// Copyright 2016 Michal Witkowski. All Rights Reserved. // See LICENSE for licensing terms. package grpc_prometheus import ( "time" "google.golang.org/grpc/codes" prom "github.com/prometheus/client_golang/prometheus" ) var ( clientStartedCounter = prom.NewCounterVec( prom.CounterOpts{ Namespace: "grpc", Subsystem: "client", Name: "started_total", Help: "Total number of RPCs started on the client.", }, []string{"grpc_type", "grpc_service", "grpc_method"}) clientHandledCounter = prom.NewCounterVec( prom.CounterOpts{ Namespace: "grpc", Subsystem: "client", Name: "handled_total", Help: "Total number of RPCs completed by the client, regardless of success or failure.", }, []string{"grpc_type", "grpc_service", "grpc_method", "grpc_code"}) clientStreamMsgReceived = prom.NewCounterVec( prom.CounterOpts{ Namespace: "grpc", Subsystem: "client", Name: "msg_received_total", Help: "Total number of RPC stream messages received by the client.", }, []string{"grpc_type", "grpc_service", "grpc_method"}) clientStreamMsgSent = prom.NewCounterVec( prom.CounterOpts{ Namespace: "grpc", Subsystem: "client", Name: "msg_sent_total", Help: "Total number of gRPC stream messages sent by the client.", }, []string{"grpc_type", "grpc_service", "grpc_method"}) clientHandledHistogramEnabled = false clientHandledHistogramOpts = prom.HistogramOpts{ Namespace: "grpc", Subsystem: "client", Name: "handling_seconds", Help: "Histogram of response latency (seconds) of the gRPC until it is finished by the application.", Buckets: prom.DefBuckets, } clientHandledHistogram *prom.HistogramVec ) func init() { prom.MustRegister(clientStartedCounter) prom.MustRegister(clientHandledCounter) prom.MustRegister(clientStreamMsgReceived) prom.MustRegister(clientStreamMsgSent) } // EnableClientHandlingTimeHistogram turns on recording of handling time of RPCs. // Histogram metrics can be very expensive for Prometheus to retain and query. func EnableClientHandlingTimeHistogram(opts ...HistogramOption) { for _, o := range opts { o(&clientHandledHistogramOpts) } if !clientHandledHistogramEnabled { clientHandledHistogram = prom.NewHistogramVec( clientHandledHistogramOpts, []string{"grpc_type", "grpc_service", "grpc_method"}, ) prom.Register(clientHandledHistogram) } clientHandledHistogramEnabled = true } type clientReporter struct { rpcType grpcType serviceName string methodName string startTime time.Time } func newClientReporter(rpcType grpcType, fullMethod string) *clientReporter { r := &clientReporter{rpcType: rpcType} if clientHandledHistogramEnabled { r.startTime = time.Now() } r.serviceName, r.methodName = splitMethodName(fullMethod) clientStartedCounter.WithLabelValues(string(r.rpcType), r.serviceName, r.methodName).Inc() return r } func (r *clientReporter) ReceivedMessage() { clientStreamMsgReceived.WithLabelValues(string(r.rpcType), r.serviceName, r.methodName).Inc() } func (r *clientReporter) SentMessage() { clientStreamMsgSent.WithLabelValues(string(r.rpcType), r.serviceName, r.methodName).Inc() } func (r *clientReporter) Handled(code codes.Code) { clientHandledCounter.WithLabelValues(string(r.rpcType), r.serviceName, r.methodName, code.String()).Inc() if clientHandledHistogramEnabled { clientHandledHistogram.WithLabelValues(string(r.rpcType), r.serviceName, r.methodName).Observe(time.Since(r.startTime).Seconds()) } }