diff --git a/x/logic/keeper/interpreter.go b/x/logic/keeper/interpreter.go index 4737771c..6894de5b 100644 --- a/x/logic/keeper/interpreter.go +++ b/x/logic/keeper/interpreter.go @@ -106,6 +106,7 @@ func (k Keeper) newInterpreter(ctx context.Context, params types.Params) (*prolo whitelistBlacklistHookFn(whitelistPredicates, blacklistPredicates), gasMeterHookFn(sdkctx, params.GetGasPolicy()), telemetryPredicateCallCounterHookFn(), + telemetryPredicateDurationHookFn(), ), interpreter.WithPredicates(ctx, interpreter.RegistryNames), interpreter.WithBootstrap(ctx, util.NonZeroOrDefault(interpreterParams.GetBootstrap(), bootstrap.Bootstrap())), diff --git a/x/logic/keeper/metrics.go b/x/logic/keeper/metrics.go index 2f74fde8..41e30b30 100644 --- a/x/logic/keeper/metrics.go +++ b/x/logic/keeper/metrics.go @@ -2,6 +2,7 @@ package keeper import ( "fmt" + "time" "github.com/axone-protocol/prolog/engine" "github.com/hashicorp/go-metrics" @@ -45,6 +46,30 @@ func telemetryPredicateCallCounterHookFn() engine.HookFunc { } } +func telemetryPredicateDurationHookFn() engine.HookFunc { + var predicate string + var start time.Time + return func(opcode engine.Opcode, operand engine.Term, _ *engine.Env) error { + if opcode != engine.OpCall { + if predicate != "" { + telemetry.MeasureSince(start, append(metricsKeys, predicate)...) + predicate = "" + start = time.Time{} + } + return nil + } + + var ok bool + if predicate, ok = stringifyOperand(operand); !ok { + return nil + } + + start = telemetry.Now() + + return nil + } +} + // stringifyOperand returns the string representation of the operand if it implements fmt.Stringer. // It returns an empty string and false if the operand does not have a string representation. func stringifyOperand(operand engine.Term) (string, bool) {