@@ -2,31 +2,47 @@ package metrics
2
2
3
3
import (
4
4
"fmt"
5
+ "github.com/prometheus/client_golang/prometheus/promauto"
5
6
"sync"
6
7
7
8
"github.com/prometheus/client_golang/prometheus"
8
- io_prometheus_client "github.com/prometheus/client_model/go"
9
+ "github.com/prometheus/client_model/go"
9
10
"github.com/sirupsen/logrus"
10
11
)
11
12
12
13
var (
13
14
handlerMetricsByHandlerName = & sync.Map {}
15
+ handlersResultCounter = promauto .NewCounterVec (prometheus.CounterOpts {
16
+ Namespace : grabbitPrefix ,
17
+ Subsystem : handlers ,
18
+ Name : handlerResult ,
19
+ Help : "The result of the message handler. The handler's name, message type and result are labeled" ,
20
+ }, []string {handler , messageTypeLabel , handlerResult })
21
+ handlersLatencySummary = promauto .NewSummaryVec (prometheus.SummaryOpts {
22
+ Namespace : grabbitPrefix ,
23
+ Subsystem : handlers ,
24
+ Name : handlerLatency ,
25
+ Help : "The latency of the message handler. The handler's name and message type are labeled" ,
26
+ }, []string {handler , messageTypeLabel })
14
27
)
15
28
16
29
const (
17
- failure = "failure"
18
- success = "success"
19
- handlerResult = "result"
20
- handlers = "handlers"
21
- grabbitPrefix = "grabbit"
30
+ failure = "failure"
31
+ success = "success"
32
+ handlerResult = "result"
33
+ handlers = "handlers"
34
+ grabbitPrefix = "grabbit"
35
+ messageTypeLabel = "message_type"
36
+ handlerLatency = "latency"
37
+ handler = "handler"
22
38
)
23
39
24
40
type handlerMetrics struct {
25
41
result * prometheus.CounterVec
26
42
latency prometheus.Summary
27
43
}
28
44
29
- //AddHandlerMetrics adds a handlere to be tracked with metrics
45
+ //AddHandlerMetrics adds a handler to be tracked with metrics
30
46
func AddHandlerMetrics (handlerName string ) {
31
47
handlerMetrics := newHandlerMetrics (handlerName )
32
48
_ , exists := handlerMetricsByHandlerName .LoadOrStore (handlerName , handlerMetrics )
@@ -37,29 +53,31 @@ func AddHandlerMetrics(handlerName string) {
37
53
}
38
54
39
55
//RunHandlerWithMetric runs a specific handler with metrics being collected and reported to prometheus
40
- func RunHandlerWithMetric (handleMessage func () error , handlerName string , logger logrus.FieldLogger ) error {
56
+ func RunHandlerWithMetric (handleMessage func () error , handlerName , messageType string , logger logrus.FieldLogger ) error {
41
57
handlerMetrics := GetHandlerMetrics (handlerName )
42
58
defer func () {
43
59
if p := recover (); p != nil {
44
60
if handlerMetrics != nil {
45
61
handlerMetrics .result .WithLabelValues (failure ).Inc ()
46
62
}
47
-
63
+ handlersResultCounter . With (prometheus. Labels { handler : handlerName , messageTypeLabel : messageType , handlerResult : failure }). Inc ()
48
64
panic (p )
49
65
}
50
66
}()
51
67
52
68
if handlerMetrics == nil {
53
69
logger .WithField ("handler" , handlerName ).Warn ("Running with metrics - couldn't find metrics for the given handler" )
54
- return handleMessage ( )
70
+ return trackTime ( handleMessage , handlersLatencySummary . WithLabelValues ( handlerName , messageType ) )
55
71
}
56
72
57
- err := trackTime (handleMessage , handlerMetrics .latency )
73
+ err := trackTime (handleMessage , handlerMetrics .latency , handlersLatencySummary . WithLabelValues ( handlerName , messageType ) )
58
74
59
75
if err != nil {
60
76
handlerMetrics .result .WithLabelValues (failure ).Inc ()
77
+ handlersResultCounter .With (prometheus.Labels {handler : handlerName , messageTypeLabel : messageType , handlerResult : failure }).Inc ()
61
78
} else {
62
79
handlerMetrics .result .WithLabelValues (success ).Inc ()
80
+ handlersResultCounter .With (prometheus.Labels {handler : handlerName , messageTypeLabel : messageType , handlerResult : success }).Inc ()
63
81
}
64
82
65
83
return err
@@ -95,41 +113,75 @@ func newHandlerMetrics(handlerName string) *handlerMetrics {
95
113
}
96
114
}
97
115
98
- func trackTime (functionToTrack func () error , observer prometheus.Observer ) error {
99
- timer := prometheus .NewTimer (observer )
100
- defer timer .ObserveDuration ()
116
+ func trackTime (functionToTrack func () error , observers ... prometheus.Observer ) error {
117
+ timers := make ([]* prometheus.Timer , 0 )
118
+ for _ , observer := range observers {
119
+ timers = append (timers , prometheus .NewTimer (observer ))
120
+ }
121
+
122
+ defer func () {
123
+ for _ , timer := range timers {
124
+ timer .ObserveDuration ()
125
+ }
126
+ }()
101
127
102
128
return functionToTrack ()
103
129
}
104
130
131
+ //GetSuccessCountByMessageTypeAndHandlerName gets the counter value for the successful handlers' run for a given message type and handler's name
132
+ func GetSuccessCountByMessageTypeAndHandlerName (messageType , handlerName string ) (float64 , error ) {
133
+ return getCounterValue (handlersResultCounter .With (prometheus.Labels {messageTypeLabel : messageType , handler : handlerName , handlerResult : success }))
134
+ }
135
+
136
+ //GetFailureCountByMessageTypeAndHandlerName gets the counter value for the failed handlers' run for a given message type and handler's name
137
+ func GetFailureCountByMessageTypeAndHandlerName (messageType , handlerName string ) (float64 , error ) {
138
+ return getCounterValue (handlersResultCounter .With (prometheus.Labels {messageTypeLabel : messageType , handler : handlerName , handlerResult : failure }))
139
+ }
140
+
141
+ //GetLatencySampleCountByMessageTypeAndHandlerName gets the summary sample count value for the handlers' run for a given message type and handler's name
142
+ func GetLatencySampleCountByMessageTypeAndHandlerName (messageType , handlerName string ) (* uint64 , error ) {
143
+ summary , ok := handlersLatencySummary .With (prometheus.Labels {messageTypeLabel : messageType , handler : handlerName }).(prometheus.Summary )
144
+
145
+ if ! ok {
146
+ return nil , fmt .Errorf ("couldn't find summary for event type: %s" , messageType )
147
+ }
148
+
149
+ return getSummarySampleCount (summary )
150
+ }
151
+
105
152
//GetSuccessCount gets the value of the handlers success value
106
153
func (hm * handlerMetrics ) GetSuccessCount () (float64 , error ) {
107
- return hm .getLabeledCounterValue (success )
154
+ return getCounterValue ( hm .result . WithLabelValues (success ) )
108
155
}
109
156
110
157
//GetFailureCount gets the value of the handlers failure value
111
158
func (hm * handlerMetrics ) GetFailureCount () (float64 , error ) {
112
- return hm .getLabeledCounterValue (failure )
159
+ return getCounterValue ( hm .result . WithLabelValues (failure ) )
113
160
}
114
161
115
162
//GetLatencySampleCount gets the value of the handlers latency value
116
163
func (hm * handlerMetrics ) GetLatencySampleCount () (* uint64 , error ) {
164
+ return getSummarySampleCount (hm .latency )
165
+ }
166
+
167
+ func getCounterValue (counter prometheus.Counter ) (float64 , error ) {
117
168
m := & io_prometheus_client.Metric {}
118
- err := hm .latency .Write (m )
169
+ err := counter .Write (m )
170
+
119
171
if err != nil {
120
- return nil , err
172
+ return 0 , err
121
173
}
122
174
123
- return m .GetSummary ().SampleCount , nil
175
+ return m .GetCounter ().GetValue () , nil
124
176
}
125
177
126
- func ( hm * handlerMetrics ) getLabeledCounterValue ( label string ) ( float64 , error ) {
178
+ func getSummarySampleCount ( summary prometheus. Summary ) ( * uint64 , error ) {
127
179
m := & io_prometheus_client.Metric {}
128
- err := hm . result . WithLabelValues ( label ) .Write (m )
180
+ err := summary .Write (m )
129
181
130
182
if err != nil {
131
- return 0 , err
183
+ return nil , err
132
184
}
133
185
134
- return m .GetCounter ().GetValue () , nil
186
+ return m .GetSummary ().SampleCount , nil
135
187
}
0 commit comments