Skip to content

Commit c3cdce4

Browse files
authored
Expose custom metrics functions to runtimes (heroiclabs#822)
1 parent 91f7d3e commit c3cdce4

9 files changed

+170
-19
lines changed

go.mod

+1-1
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ require (
1313
github.com/gorilla/mux v1.8.0
1414
github.com/gorilla/websocket v1.4.2
1515
github.com/grpc-ecosystem/grpc-gateway/v2 v2.7.0
16-
github.com/heroiclabs/nakama-common v1.22.1-0.20220328201422-bed57ba110d8
16+
github.com/heroiclabs/nakama-common v1.22.1-0.20220421143658-94ea09b04aff
1717
github.com/jackc/pgconn v1.10.0
1818
github.com/jackc/pgerrcode v0.0.0-20201024163028-a0d42d470451
1919
github.com/jackc/pgtype v1.8.1

go.sum

+2-2
Original file line numberDiff line numberDiff line change
@@ -255,8 +255,8 @@ github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHh
255255
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
256256
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
257257
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
258-
github.com/heroiclabs/nakama-common v1.22.1-0.20220328201422-bed57ba110d8 h1:2gUIdPre/Q57HUwd+GtbSc3CucU/wqgEVpmIF5tiSto=
259-
github.com/heroiclabs/nakama-common v1.22.1-0.20220328201422-bed57ba110d8/go.mod h1:WF4YG46afwY3ibzsXnkt3zvhQ3tBY03IYeU7xSLr8HE=
258+
github.com/heroiclabs/nakama-common v1.22.1-0.20220421143658-94ea09b04aff h1:o0b1y1lK0Vmkmta27L/2/zUzXgFcHGtgK+jatuuFWDk=
259+
github.com/heroiclabs/nakama-common v1.22.1-0.20220421143658-94ea09b04aff/go.mod h1:WF4YG46afwY3ibzsXnkt3zvhQ3tBY03IYeU7xSLr8HE=
260260
github.com/huandu/xstrings v1.3.2/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE=
261261
github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
262262
github.com/imdario/mergo v0.3.11/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA=

server/runtime_javascript.go

+3-3
Original file line numberDiff line numberDiff line change
@@ -1532,7 +1532,7 @@ func NewRuntimeProviderJS(logger, startupLogger *zap.Logger, db *sql.DB, protojs
15321532
return nil, nil
15331533
}
15341534

1535-
return NewRuntimeJavascriptMatchCore(logger, name, db, protojsonMarshaler, protojsonUnmarshaler, config, socialClient, leaderboardCache, leaderboardRankCache, localCache, leaderboardScheduler, sessionRegistry, sessionCache, matchRegistry, tracker, streamManager, router, matchProvider.CreateMatch, eventFn, id, node, stopped, mc, modCache)
1535+
return NewRuntimeJavascriptMatchCore(logger, name, db, protojsonMarshaler, protojsonUnmarshaler, config, socialClient, leaderboardCache, leaderboardRankCache, localCache, leaderboardScheduler, sessionRegistry, sessionCache, matchRegistry, tracker, metrics, streamManager, router, matchProvider.CreateMatch, eventFn, id, node, stopped, mc, modCache)
15361536
})
15371537

15381538
runtimeProviderJS.newFn = func() *RuntimeJS {
@@ -1546,7 +1546,7 @@ func NewRuntimeProviderJS(logger, startupLogger *zap.Logger, db *sql.DB, protojs
15461546
logger.Fatal("Failed to initialize JavaScript runtime", zap.Error(err))
15471547
}
15481548

1549-
nakamaModule := NewRuntimeJavascriptNakamaModule(logger, db, protojsonMarshaler, protojsonUnmarshaler, config, socialClient, leaderboardCache, leaderboardRankCache, localCache, leaderboardScheduler, sessionRegistry, sessionCache, matchRegistry, tracker, streamManager, router, eventFn, matchProvider.CreateMatch)
1549+
nakamaModule := NewRuntimeJavascriptNakamaModule(logger, db, protojsonMarshaler, protojsonUnmarshaler, config, socialClient, leaderboardCache, leaderboardRankCache, localCache, leaderboardScheduler, sessionRegistry, sessionCache, matchRegistry, tracker, metrics, streamManager, router, eventFn, matchProvider.CreateMatch)
15501550
nk := runtime.ToValue(nakamaModule.Constructor(runtime))
15511551
nkInst, err := runtime.New(nk)
15521552
if err != nil {
@@ -1935,7 +1935,7 @@ func evalRuntimeModules(rp *RuntimeProviderJS, modCache *RuntimeJSModuleCache, m
19351935
return nil, nil, err
19361936
}
19371937

1938-
nakamaModule := NewRuntimeJavascriptNakamaModule(rp.logger, rp.db, rp.protojsonMarshaler, rp.protojsonUnmarshaler, rp.config, rp.socialClient, rp.leaderboardCache, rp.leaderboardRankCache, localCache, leaderboardScheduler, rp.sessionRegistry, rp.sessionCache, rp.matchRegistry, rp.tracker, rp.streamManager, rp.router, rp.eventFn, matchProvider.CreateMatch)
1938+
nakamaModule := NewRuntimeJavascriptNakamaModule(rp.logger, rp.db, rp.protojsonMarshaler, rp.protojsonUnmarshaler, rp.config, rp.socialClient, rp.leaderboardCache, rp.leaderboardRankCache, localCache, leaderboardScheduler, rp.sessionRegistry, rp.sessionCache, rp.matchRegistry, rp.tracker, rp.metrics, rp.streamManager, rp.router, rp.eventFn, matchProvider.CreateMatch)
19391939
nk := r.ToValue(nakamaModule.Constructor(r))
19401940
nkInst, err := r.New(nk)
19411941
if err != nil {

server/runtime_javascript_match_core.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -67,15 +67,15 @@ type RuntimeJavaScriptMatchCore struct {
6767
// ctxCancelFn context.CancelFunc
6868
}
6969

70-
func NewRuntimeJavascriptMatchCore(logger *zap.Logger, module string, db *sql.DB, protojsonMarshaler *protojson.MarshalOptions, protojsonUnmarshaler *protojson.UnmarshalOptions, config Config, socialClient *social.Client, leaderboardCache LeaderboardCache, rankCache LeaderboardRankCache, localCache *RuntimeJavascriptLocalCache, leaderboardScheduler LeaderboardScheduler, sessionRegistry SessionRegistry, sessionCache SessionCache, matchRegistry MatchRegistry, tracker Tracker, streamManager StreamManager, router MessageRouter, matchCreateFn RuntimeMatchCreateFunction, eventFn RuntimeEventCustomFunction, id uuid.UUID, node string, stopped *atomic.Bool, matchHandlers *jsMatchHandlers, modCache *RuntimeJSModuleCache) (RuntimeMatchCore, error) {
70+
func NewRuntimeJavascriptMatchCore(logger *zap.Logger, module string, db *sql.DB, protojsonMarshaler *protojson.MarshalOptions, protojsonUnmarshaler *protojson.UnmarshalOptions, config Config, socialClient *social.Client, leaderboardCache LeaderboardCache, rankCache LeaderboardRankCache, localCache *RuntimeJavascriptLocalCache, leaderboardScheduler LeaderboardScheduler, sessionRegistry SessionRegistry, sessionCache SessionCache, matchRegistry MatchRegistry, tracker Tracker, metrics Metrics, streamManager StreamManager, router MessageRouter, matchCreateFn RuntimeMatchCreateFunction, eventFn RuntimeEventCustomFunction, id uuid.UUID, node string, stopped *atomic.Bool, matchHandlers *jsMatchHandlers, modCache *RuntimeJSModuleCache) (RuntimeMatchCore, error) {
7171
runtime := goja.New()
7272

7373
jsLoggerInst, err := NewJsLogger(runtime, logger)
7474
if err != nil {
7575
logger.Fatal("Failed to initialize JavaScript runtime", zap.Error(err))
7676
}
7777

78-
nakamaModule := NewRuntimeJavascriptNakamaModule(logger, db, protojsonMarshaler, protojsonUnmarshaler, config, socialClient, leaderboardCache, rankCache, localCache, leaderboardScheduler, sessionRegistry, sessionCache, matchRegistry, tracker, streamManager, router, eventFn, matchCreateFn)
78+
nakamaModule := NewRuntimeJavascriptNakamaModule(logger, db, protojsonMarshaler, protojsonUnmarshaler, config, socialClient, leaderboardCache, rankCache, localCache, leaderboardScheduler, sessionRegistry, sessionCache, matchRegistry, tracker, metrics, streamManager, router, eventFn, matchCreateFn)
7979
nk := runtime.ToValue(nakamaModule.Constructor(runtime))
8080
nkInst, err := runtime.New(nk)
8181
if err != nil {

server/runtime_javascript_nakama.go

+68-1
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@ type runtimeJavascriptNakamaModule struct {
6969
localCache *RuntimeJavascriptLocalCache
7070
leaderboardScheduler LeaderboardScheduler
7171
tracker Tracker
72+
metrics Metrics
7273
sessionRegistry SessionRegistry
7374
sessionCache SessionCache
7475
matchRegistry MatchRegistry
@@ -80,7 +81,7 @@ type runtimeJavascriptNakamaModule struct {
8081
eventFn RuntimeEventCustomFunction
8182
}
8283

83-
func NewRuntimeJavascriptNakamaModule(logger *zap.Logger, db *sql.DB, protojsonMarshaler *protojson.MarshalOptions, protojsonUnmarshaler *protojson.UnmarshalOptions, config Config, socialClient *social.Client, leaderboardCache LeaderboardCache, rankCache LeaderboardRankCache, localCache *RuntimeJavascriptLocalCache, leaderboardScheduler LeaderboardScheduler, sessionRegistry SessionRegistry, sessionCache SessionCache, matchRegistry MatchRegistry, tracker Tracker, streamManager StreamManager, router MessageRouter, eventFn RuntimeEventCustomFunction, matchCreateFn RuntimeMatchCreateFunction) *runtimeJavascriptNakamaModule {
84+
func NewRuntimeJavascriptNakamaModule(logger *zap.Logger, db *sql.DB, protojsonMarshaler *protojson.MarshalOptions, protojsonUnmarshaler *protojson.UnmarshalOptions, config Config, socialClient *social.Client, leaderboardCache LeaderboardCache, rankCache LeaderboardRankCache, localCache *RuntimeJavascriptLocalCache, leaderboardScheduler LeaderboardScheduler, sessionRegistry SessionRegistry, sessionCache SessionCache, matchRegistry MatchRegistry, tracker Tracker, metrics Metrics, streamManager StreamManager, router MessageRouter, eventFn RuntimeEventCustomFunction, matchCreateFn RuntimeMatchCreateFunction) *runtimeJavascriptNakamaModule {
8485
return &runtimeJavascriptNakamaModule{
8586
logger: logger,
8687
config: config,
@@ -93,6 +94,7 @@ func NewRuntimeJavascriptNakamaModule(logger *zap.Logger, db *sql.DB, protojsonM
9394
matchRegistry: matchRegistry,
9495
router: router,
9596
tracker: tracker,
97+
metrics: metrics,
9698
socialClient: socialClient,
9799
leaderboardCache: leaderboardCache,
98100
rankCache: rankCache,
@@ -122,6 +124,9 @@ func (n *runtimeJavascriptNakamaModule) Constructor(r *goja.Runtime) func(goja.C
122124
func (n *runtimeJavascriptNakamaModule) mappings(r *goja.Runtime) map[string]func(goja.FunctionCall) goja.Value {
123125
return map[string]func(goja.FunctionCall) goja.Value{
124126
"event": n.event(r),
127+
"metricsCounterAdd": n.metricsCounterAdd(r),
128+
"metricsGaugeSet": n.metricsGaugeSet(r),
129+
"metricsTimerRecord": n.metricsTimerRecord(r),
125130
"uuidv4": n.uuidV4(r),
126131
"cronNext": n.cronNext(r),
127132
"sqlExec": n.sqlExec(r),
@@ -340,6 +345,54 @@ func (n *runtimeJavascriptNakamaModule) event(r *goja.Runtime) func(goja.Functio
340345
}
341346
}
342347

348+
// @group metrics
349+
// @summary Add a custom metrics counter.
350+
// @param name(type=string) The name of the custom metrics counter.
351+
// @param tags(type=map[string]string) The metrics tags associated with this counter.
352+
// @param delta(type=number) An integer value to update this metric with.
353+
func (n *runtimeJavascriptNakamaModule) metricsCounterAdd(r *goja.Runtime) func(goja.FunctionCall) goja.Value {
354+
return func(f goja.FunctionCall) goja.Value {
355+
name := getJsString(r, f.Argument(0))
356+
tags := getJsStringMap(r, f.Argument(1))
357+
delta := getJsInt(r, f.Argument(2))
358+
n.metrics.CustomCounter(name, tags, delta)
359+
360+
return goja.Undefined()
361+
}
362+
}
363+
364+
// @group metrics
365+
// @summary Add a custom metrics gauge.
366+
// @param name(type=string) The name of the custom metrics gauge.
367+
// @param tags(type=map[string]string) The metrics tags associated with this gauge.
368+
// @param value(type=number) A value to update this metric with.
369+
func (n *runtimeJavascriptNakamaModule) metricsGaugeSet(r *goja.Runtime) func(goja.FunctionCall) goja.Value {
370+
return func(f goja.FunctionCall) goja.Value {
371+
name := getJsString(r, f.Argument(0))
372+
tags := getJsStringMap(r, f.Argument(1))
373+
value := getJsFloat(r, f.Argument(2))
374+
n.metrics.CustomGauge(name, tags, value)
375+
376+
return goja.Undefined()
377+
}
378+
}
379+
380+
// @group metrics
381+
// @summary Add a custom metrics timer.
382+
// @param name(type=string) The name of the custom metrics timer.
383+
// @param tags(type=map[string]string) The metrics tags associated with this timer.
384+
// @param value(type=number) An integer value to update this metric with (in nanoseconds).
385+
func (n *runtimeJavascriptNakamaModule) metricsTimerRecord(r *goja.Runtime) func(goja.FunctionCall) goja.Value {
386+
return func(f goja.FunctionCall) goja.Value {
387+
name := getJsString(r, f.Argument(0))
388+
tags := getJsStringMap(r, f.Argument(1))
389+
value := getJsInt(r, f.Argument(2))
390+
n.metrics.CustomTimer(name, tags, time.Duration(value))
391+
392+
return goja.Undefined()
393+
}
394+
}
395+
343396
// @group utils
344397
// @summary Generate a version 4 UUID in the standard 36-character string representation.
345398
// @return uuid(string) The newly generated version 4 UUID identifier string.
@@ -7489,6 +7542,20 @@ func getJsInt(r *goja.Runtime, v goja.Value) int64 {
74897542
return i
74907543
}
74917544

7545+
func getJsFloat(r *goja.Runtime, v goja.Value) float64 {
7546+
e := v.Export()
7547+
f, ok := e.(float64)
7548+
if !ok {
7549+
i, ok := e.(int64)
7550+
if ok {
7551+
return float64(i)
7552+
} else {
7553+
panic(r.NewTypeError("expects number"))
7554+
}
7555+
}
7556+
return f
7557+
}
7558+
74927559
func getJsBool(r *goja.Runtime, v goja.Value) bool {
74937560
b, ok := v.Export().(bool)
74947561
if !ok {

server/runtime_lua.go

+6-6
Original file line numberDiff line numberDiff line change
@@ -158,11 +158,11 @@ func NewRuntimeProviderLua(logger, startupLogger *zap.Logger, db *sql.DB, protoj
158158

159159
matchProvider.RegisterCreateFn("lua",
160160
func(ctx context.Context, logger *zap.Logger, id uuid.UUID, node string, stopped *atomic.Bool, name string) (RuntimeMatchCore, error) {
161-
return NewRuntimeLuaMatchCore(logger, name, db, protojsonMarshaler, protojsonUnmarshaler, config, socialClient, leaderboardCache, leaderboardRankCache, leaderboardScheduler, sessionRegistry, sessionCache, matchRegistry, tracker, streamManager, router, stdLibs, once, localCache, eventFn, nil, nil, id, node, stopped, name, matchProvider)
161+
return NewRuntimeLuaMatchCore(logger, name, db, protojsonMarshaler, protojsonUnmarshaler, config, socialClient, leaderboardCache, leaderboardRankCache, leaderboardScheduler, sessionRegistry, sessionCache, matchRegistry, tracker, metrics, streamManager, router, stdLibs, once, localCache, eventFn, nil, nil, id, node, stopped, name, matchProvider)
162162
},
163163
)
164164

165-
r, err := newRuntimeLuaVM(logger, db, protojsonMarshaler, protojsonUnmarshaler, config, socialClient, leaderboardCache, leaderboardRankCache, leaderboardScheduler, sessionRegistry, sessionCache, matchRegistry, tracker, streamManager, router, stdLibs, moduleCache, once, localCache, matchProvider.CreateMatch, eventFn, func(execMode RuntimeExecutionMode, id string) {
165+
r, err := newRuntimeLuaVM(logger, db, protojsonMarshaler, protojsonUnmarshaler, config, socialClient, leaderboardCache, leaderboardRankCache, leaderboardScheduler, sessionRegistry, sessionCache, matchRegistry, tracker, metrics, streamManager, router, stdLibs, moduleCache, once, localCache, matchProvider.CreateMatch, eventFn, func(execMode RuntimeExecutionMode, id string) {
166166
switch execMode {
167167
case RuntimeExecutionModeRPC:
168168
rpcFunctions[id] = func(ctx context.Context, headers, queryParams map[string][]string, userID, username string, vars map[string]string, expiry int64, sessionID, clientIP, clientPort, lang, payload string) (string, error, codes.Code) {
@@ -1105,7 +1105,7 @@ func NewRuntimeProviderLua(logger, startupLogger *zap.Logger, db *sql.DB, protoj
11051105
r.Stop()
11061106

11071107
runtimeProviderLua.newFn = func() *RuntimeLua {
1108-
r, err := newRuntimeLuaVM(logger, db, protojsonMarshaler, protojsonUnmarshaler, config, socialClient, leaderboardCache, leaderboardRankCache, leaderboardScheduler, sessionRegistry, sessionCache, matchRegistry, tracker, streamManager, router, stdLibs, moduleCache, once, localCache, matchProvider.CreateMatch, eventFn, nil)
1108+
r, err := newRuntimeLuaVM(logger, db, protojsonMarshaler, protojsonUnmarshaler, config, socialClient, leaderboardCache, leaderboardRankCache, leaderboardScheduler, sessionRegistry, sessionCache, matchRegistry, tracker, metrics, streamManager, router, stdLibs, moduleCache, once, localCache, matchProvider.CreateMatch, eventFn, nil)
11091109
if err != nil {
11101110
logger.Fatal("Failed to initialize Lua runtime", zap.Error(err))
11111111
}
@@ -2047,7 +2047,7 @@ func checkRuntimeLuaVM(logger *zap.Logger, config Config, stdLibs map[string]lua
20472047
vm.Push(lua.LString(name))
20482048
vm.Call(1, 0)
20492049
}
2050-
nakamaModule := NewRuntimeLuaNakamaModule(nil, nil, nil, nil, config, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil)
2050+
nakamaModule := NewRuntimeLuaNakamaModule(nil, nil, nil, nil, config, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil)
20512051
vm.PreloadModule("nakama", nakamaModule.Loader)
20522052

20532053
preload := vm.GetField(vm.GetField(vm.Get(lua.EnvironIndex), "package"), "preload")
@@ -2068,7 +2068,7 @@ func checkRuntimeLuaVM(logger *zap.Logger, config Config, stdLibs map[string]lua
20682068
return nil
20692069
}
20702070

2071-
func newRuntimeLuaVM(logger *zap.Logger, db *sql.DB, protojsonMarshaler *protojson.MarshalOptions, protojsonUnmarshaler *protojson.UnmarshalOptions, config Config, socialClient *social.Client, leaderboardCache LeaderboardCache, rankCache LeaderboardRankCache, leaderboardScheduler LeaderboardScheduler, sessionRegistry SessionRegistry, sessionCache SessionCache, matchRegistry MatchRegistry, tracker Tracker, streamManager StreamManager, router MessageRouter, stdLibs map[string]lua.LGFunction, moduleCache *RuntimeLuaModuleCache, once *sync.Once, localCache *RuntimeLuaLocalCache, matchCreateFn RuntimeMatchCreateFunction, eventFn RuntimeEventCustomFunction, announceCallbackFn func(RuntimeExecutionMode, string)) (*RuntimeLua, error) {
2071+
func newRuntimeLuaVM(logger *zap.Logger, db *sql.DB, protojsonMarshaler *protojson.MarshalOptions, protojsonUnmarshaler *protojson.UnmarshalOptions, config Config, socialClient *social.Client, leaderboardCache LeaderboardCache, rankCache LeaderboardRankCache, leaderboardScheduler LeaderboardScheduler, sessionRegistry SessionRegistry, sessionCache SessionCache, matchRegistry MatchRegistry, tracker Tracker, metrics Metrics, streamManager StreamManager, router MessageRouter, stdLibs map[string]lua.LGFunction, moduleCache *RuntimeLuaModuleCache, once *sync.Once, localCache *RuntimeLuaLocalCache, matchCreateFn RuntimeMatchCreateFunction, eventFn RuntimeEventCustomFunction, announceCallbackFn func(RuntimeExecutionMode, string)) (*RuntimeLua, error) {
20722072
vm := lua.NewState(lua.Options{
20732073
CallStackSize: config.GetRuntime().GetLuaCallStackSize(),
20742074
RegistrySize: config.GetRuntime().GetLuaRegistrySize(),
@@ -2104,7 +2104,7 @@ func newRuntimeLuaVM(logger *zap.Logger, db *sql.DB, protojsonMarshaler *protojs
21042104
callbacks.LeaderboardReset = fn
21052105
}
21062106
}
2107-
nakamaModule := NewRuntimeLuaNakamaModule(logger, db, protojsonMarshaler, protojsonUnmarshaler, config, socialClient, leaderboardCache, rankCache, leaderboardScheduler, sessionRegistry, sessionCache, matchRegistry, tracker, streamManager, router, once, localCache, matchCreateFn, eventFn, registerCallbackFn, announceCallbackFn)
2107+
nakamaModule := NewRuntimeLuaNakamaModule(logger, db, protojsonMarshaler, protojsonUnmarshaler, config, socialClient, leaderboardCache, rankCache, leaderboardScheduler, sessionRegistry, sessionCache, matchRegistry, tracker, metrics, streamManager, router, once, localCache, matchCreateFn, eventFn, registerCallbackFn, announceCallbackFn)
21082108
vm.PreloadModule("nakama", nakamaModule.Loader)
21092109
r := &RuntimeLua{
21102110
logger: logger,

0 commit comments

Comments
 (0)