Skip to content

Commit dd0b163

Browse files
committed
feat(logic): introduce telemetry to track predicate call counts
1 parent 9b72402 commit dd0b163

File tree

2 files changed

+68
-15
lines changed

2 files changed

+68
-15
lines changed

x/logic/keeper/interpreter.go

Lines changed: 11 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,7 @@ func (k Keeper) newInterpreter(ctx context.Context, params types.Params) (*prolo
105105
interpreter.WithHooks(
106106
whitelistBlacklistHookFn(whitelistPredicates, blacklistPredicates),
107107
gasMeterHookFn(sdkctx, params.GetGasPolicy()),
108+
telemetryPredicateCallCounterHookFn(),
108109
),
109110
interpreter.WithPredicates(ctx, interpreter.RegistryNames),
110111
interpreter.WithBootstrap(ctx, util.NonZeroOrDefault(interpreterParams.GetBootstrap(), bootstrap.Bootstrap())),
@@ -135,23 +136,20 @@ func whitelistBlacklistHookFn(whitelist, blacklist []string) engine.HookFunc {
135136
return nil
136137
}
137138

138-
predicateStringer, ok := operand.(fmt.Stringer)
139+
predicate, ok := stringifyOperand(operand)
139140
if !ok {
140141
return engine.SyntaxError(operand, env)
141142
}
142143

143-
predicate := predicateStringer.String()
144-
145-
if interpreter.IsRegistered(predicate) {
146-
if _, found := allowed.Get(predicate); !found {
147-
return engine.PermissionError(
148-
prolog2.AtomOperationExecute,
149-
prolog2.AtomPermissionForbiddenPredicate,
150-
engine.NewAtom(predicate),
151-
env,
152-
)
153-
}
144+
if _, found := allowed.Get(predicate); !found {
145+
return engine.PermissionError(
146+
prolog2.AtomOperationExecute,
147+
prolog2.AtomPermissionForbiddenPredicate,
148+
engine.NewAtom(predicate),
149+
env,
150+
)
154151
}
152+
155153
return nil
156154
}
157155
}
@@ -166,13 +164,11 @@ func gasMeterHookFn(ctx context.Context, gasPolicy types.GasPolicy) engine.HookF
166164
return nil
167165
}
168166

169-
operandStringer, ok := operand.(fmt.Stringer)
167+
predicate, ok := stringifyOperand(operand)
170168
if !ok {
171169
return engine.SyntaxError(operand, env)
172170
}
173171

174-
predicate := operandStringer.String()
175-
176172
cost := lookupCost(predicate,
177173
lo.CoalesceOrEmpty(gasPolicy.DefaultPredicateCost, defaultPredicateCost),
178174
gasPolicy.PredicateCosts)

x/logic/keeper/metrics.go

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
package keeper
2+
3+
import (
4+
"fmt"
5+
6+
"github.com/axone-protocol/prolog/engine"
7+
"github.com/hashicorp/go-metrics"
8+
9+
"github.com/cosmos/cosmos-sdk/telemetry"
10+
11+
"github.com/axone-protocol/axoned/v10/x/logic/interpreter"
12+
"github.com/axone-protocol/axoned/v10/x/logic/types"
13+
)
14+
15+
var (
16+
metricsKeys = []string{types.ModuleName, "vm", "predicate"}
17+
)
18+
19+
const (
20+
labelPredicate = "predicate"
21+
)
22+
23+
func telemetryPredicateCallCounterHookFn() engine.HookFunc {
24+
return func(opcode engine.Opcode, operand engine.Term, _ *engine.Env) error {
25+
if opcode != engine.OpCall {
26+
return nil
27+
}
28+
29+
predicate, ok := stringifyOperand(operand)
30+
if !ok {
31+
return nil
32+
}
33+
34+
if !interpreter.IsRegistered(predicate) {
35+
return nil
36+
}
37+
38+
telemetry.IncrCounterWithLabels(
39+
metricsKeys,
40+
1,
41+
[]metrics.Label{
42+
telemetry.NewLabel(labelPredicate, predicate),
43+
},
44+
)
45+
46+
return nil
47+
}
48+
}
49+
50+
// stringifyOperand returns the string representation of the operand if it implements fmt.Stringer.
51+
// It returns an empty string and false if the operand does not have a string representation.
52+
func stringifyOperand(operand engine.Term) (string, bool) {
53+
if stringer, ok := operand.(fmt.Stringer); ok {
54+
return stringer.String(), true
55+
}
56+
return "", false
57+
}

0 commit comments

Comments
 (0)