Tizen_4.0 base
[platform/upstream/docker-engine.git] / vendor / github.com / grpc-ecosystem / go-grpc-prometheus / server_reporter.go
1 // Copyright 2016 Michal Witkowski. All Rights Reserved.
2 // See LICENSE for licensing terms.
3
4 package grpc_prometheus
5
6 import (
7         "time"
8
9         "google.golang.org/grpc/codes"
10
11         prom "github.com/prometheus/client_golang/prometheus"
12         "google.golang.org/grpc"
13 )
14
15 type grpcType string
16
17 const (
18         Unary        grpcType = "unary"
19         ClientStream grpcType = "client_stream"
20         ServerStream grpcType = "server_stream"
21         BidiStream   grpcType = "bidi_stream"
22 )
23
24 var (
25         serverStartedCounter = prom.NewCounterVec(
26                 prom.CounterOpts{
27                         Namespace: "grpc",
28                         Subsystem: "server",
29                         Name:      "started_total",
30                         Help:      "Total number of RPCs started on the server.",
31                 }, []string{"grpc_type", "grpc_service", "grpc_method"})
32
33         serverHandledCounter = prom.NewCounterVec(
34                 prom.CounterOpts{
35                         Namespace: "grpc",
36                         Subsystem: "server",
37                         Name:      "handled_total",
38                         Help:      "Total number of RPCs completed on the server, regardless of success or failure.",
39                 }, []string{"grpc_type", "grpc_service", "grpc_method", "grpc_code"})
40
41         serverStreamMsgReceived = prom.NewCounterVec(
42                 prom.CounterOpts{
43                         Namespace: "grpc",
44                         Subsystem: "server",
45                         Name:      "msg_received_total",
46                         Help:      "Total number of RPC stream messages received on the server.",
47                 }, []string{"grpc_type", "grpc_service", "grpc_method"})
48
49         serverStreamMsgSent = prom.NewCounterVec(
50                 prom.CounterOpts{
51                         Namespace: "grpc",
52                         Subsystem: "server",
53                         Name:      "msg_sent_total",
54                         Help:      "Total number of gRPC stream messages sent by the server.",
55                 }, []string{"grpc_type", "grpc_service", "grpc_method"})
56
57         serverHandledHistogramEnabled = false
58         serverHandledHistogramOpts    = prom.HistogramOpts{
59                 Namespace: "grpc",
60                 Subsystem: "server",
61                 Name:      "handling_seconds",
62                 Help:      "Histogram of response latency (seconds) of gRPC that had been application-level handled by the server.",
63                 Buckets:   prom.DefBuckets,
64         }
65         serverHandledHistogram *prom.HistogramVec
66 )
67
68 func init() {
69         prom.MustRegister(serverStartedCounter)
70         prom.MustRegister(serverHandledCounter)
71         prom.MustRegister(serverStreamMsgReceived)
72         prom.MustRegister(serverStreamMsgSent)
73 }
74
75 type HistogramOption func(*prom.HistogramOpts)
76
77 // WithHistogramBuckets allows you to specify custom bucket ranges for histograms if EnableHandlingTimeHistogram is on.
78 func WithHistogramBuckets(buckets []float64) HistogramOption {
79         return func(o *prom.HistogramOpts) { o.Buckets = buckets }
80 }
81
82 // EnableHandlingTimeHistogram turns on recording of handling time of RPCs for server-side interceptors.
83 // Histogram metrics can be very expensive for Prometheus to retain and query.
84 func EnableHandlingTimeHistogram(opts ...HistogramOption) {
85         for _, o := range opts {
86                 o(&serverHandledHistogramOpts)
87         }
88         if !serverHandledHistogramEnabled {
89                 serverHandledHistogram = prom.NewHistogramVec(
90                         serverHandledHistogramOpts,
91                         []string{"grpc_type", "grpc_service", "grpc_method"},
92                 )
93                 prom.Register(serverHandledHistogram)
94         }
95         serverHandledHistogramEnabled = true
96 }
97
98 type serverReporter struct {
99         rpcType     grpcType
100         serviceName string
101         methodName  string
102         startTime   time.Time
103 }
104
105 func newServerReporter(rpcType grpcType, fullMethod string) *serverReporter {
106         r := &serverReporter{rpcType: rpcType}
107         if serverHandledHistogramEnabled {
108                 r.startTime = time.Now()
109         }
110         r.serviceName, r.methodName = splitMethodName(fullMethod)
111         serverStartedCounter.WithLabelValues(string(r.rpcType), r.serviceName, r.methodName).Inc()
112         return r
113 }
114
115 func (r *serverReporter) ReceivedMessage() {
116         serverStreamMsgReceived.WithLabelValues(string(r.rpcType), r.serviceName, r.methodName).Inc()
117 }
118
119 func (r *serverReporter) SentMessage() {
120         serverStreamMsgSent.WithLabelValues(string(r.rpcType), r.serviceName, r.methodName).Inc()
121 }
122
123 func (r *serverReporter) Handled(code codes.Code) {
124         serverHandledCounter.WithLabelValues(string(r.rpcType), r.serviceName, r.methodName, code.String()).Inc()
125         if serverHandledHistogramEnabled {
126                 serverHandledHistogram.WithLabelValues(string(r.rpcType), r.serviceName, r.methodName).Observe(time.Since(r.startTime).Seconds())
127         }
128 }
129
130 // preRegisterMethod is invoked on Register of a Server, allowing all gRPC services labels to be pre-populated.
131 func preRegisterMethod(serviceName string, mInfo *grpc.MethodInfo) {
132         methodName := mInfo.Name
133         methodType := string(typeFromMethodInfo(mInfo))
134         // These are just references (no increments), as just referencing will create the labels but not set values.
135         serverStartedCounter.GetMetricWithLabelValues(methodType, serviceName, methodName)
136         serverStreamMsgReceived.GetMetricWithLabelValues(methodType, serviceName, methodName)
137         serverStreamMsgSent.GetMetricWithLabelValues(methodType, serviceName, methodName)
138         if serverHandledHistogramEnabled {
139                 serverHandledHistogram.GetMetricWithLabelValues(methodType, serviceName, methodName)
140         }
141         for _, code := range allCodes {
142                 serverHandledCounter.GetMetricWithLabelValues(methodType, serviceName, methodName, code.String())
143         }
144 }
145
146 func typeFromMethodInfo(mInfo *grpc.MethodInfo) grpcType {
147         if mInfo.IsClientStream == false && mInfo.IsServerStream == false {
148                 return Unary
149         }
150         if mInfo.IsClientStream == true && mInfo.IsServerStream == false {
151                 return ClientStream
152         }
153         if mInfo.IsClientStream == false && mInfo.IsServerStream == true {
154                 return ServerStream
155         }
156         return BidiStream
157 }