github.com/moleculer-go/moleculer@v0.3.3/metrics/metrics.go (about) 1 package metrics 2 3 import ( 4 "fmt" 5 "time" 6 7 "github.com/moleculer-go/moleculer" 8 "github.com/moleculer-go/moleculer/context" 9 "github.com/moleculer-go/moleculer/middleware" 10 ) 11 12 func metricEnd(brokerContext moleculer.BrokerContext, result moleculer.Payload) { 13 ctx := brokerContext.(*context.Context) 14 if !ctx.Meta().Get("startTime").Exists() { 15 return 16 } 17 18 startTime := ctx.Meta().Get("startTime").Time() 19 payload := metricsPayload(brokerContext) 20 21 mlseconds := float64(time.Since(startTime).Nanoseconds()) / 1000000 22 payload["duration"] = mlseconds 23 payload["endTime"] = time.Now().Format(time.RFC3339) 24 if result.IsError() { 25 payload["error"] = map[string]string{ 26 "message": fmt.Sprintf("%s", result.Error()), 27 } 28 } 29 ctx.Emit("metrics.trace.span.finish", payload) 30 } 31 32 func metricStart(context moleculer.BrokerContext) { 33 meta := context.Meta().Add("startTime", time.Now()).Add("duration", 0) 34 context.UpdateMeta(meta) 35 context.Emit("metrics.trace.span.start", metricsPayload(context)) 36 } 37 38 // metricsPayload generate the payload for the metrics event 39 func metricsPayload(brokerContext moleculer.BrokerContext) map[string]interface{} { 40 rawContext := brokerContext.(*context.Context) 41 contextMap := brokerContext.AsMap() 42 if rawContext.Meta().Get("startTime").Exists() { 43 contextMap["startTime"] = rawContext.Meta().Get("startTime").Time().Format(time.RFC3339) 44 } 45 nodeID := rawContext.BrokerDelegates().LocalNode().GetID() 46 contextMap["nodeID"] = nodeID 47 if rawContext.SourceNodeID() == nodeID { 48 contextMap["remoteCall"] = false 49 } else { 50 contextMap["remoteCall"] = true 51 contextMap["callerNodeID"] = rawContext.SourceNodeID() 52 } 53 _, isAction := contextMap["action"] 54 if isAction { 55 action := contextMap["action"].(string) 56 svcs := rawContext.BrokerDelegates().ServiceForAction(action) 57 contextMap["action"] = map[string]string{"name": action} 58 contextMap["service"] = map[string]string{"name": svcs[0].Name, "version": svcs[0].Version} 59 } 60 return contextMap 61 } 62 63 // shouldMetric check if it should metric for this context. 64 func createShouldMetric(Config moleculer.Config) func(context moleculer.BrokerContext) bool { 65 var callsCount float32 = 0 66 return func(context moleculer.BrokerContext) bool { 67 if context.Meta().Get("tracing").Bool() { 68 callsCount++ 69 if callsCount*Config.MetricsRate >= 1.0 { 70 71 callsCount = 0 72 return true 73 } 74 } 75 return false 76 } 77 } 78 79 // Middleware create a metrics middleware 80 func Middlewares() moleculer.Middlewares { 81 var Config = moleculer.DefaultConfig 82 shouldMetric := createShouldMetric(Config) 83 return map[string]moleculer.MiddlewareHandler{ 84 // store the broker config 85 "Config": func(params interface{}, next func(...interface{})) { 86 Config = params.(moleculer.Config) 87 shouldMetric = createShouldMetric(Config) 88 next() 89 }, 90 "afterLocalAction": func(params interface{}, next func(...interface{})) { 91 payload := params.(middleware.AfterActionParams) 92 context := payload.BrokerContext 93 result := payload.Result 94 if shouldMetric(context) { 95 metricEnd(context, result) 96 } 97 next() 98 }, 99 "beforeLocalAction": func(params interface{}, next func(...interface{})) { 100 context := params.(moleculer.BrokerContext) 101 if shouldMetric(context) { 102 metricStart(context) 103 } 104 next() 105 }, 106 } 107 }