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  }