/
metrics.go
187 lines (160 loc) · 4.54 KB
/
metrics.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
/**
* @Author: steven
* @Description:
* @File: metrics
* @Date: 18/12/23 00.54
*/
package telemetry
import (
"errors"
"github.com/evorts/kevlars/logger"
"time"
)
type MetricPushAction interface {
Push(tags ...string)
}
type metricActionNoop struct {
log logger.Manager
}
func (m *metricActionNoop) Push(_ ...string) {
m.log.Debug("metric action push noop triggered")
}
type metricPushAction struct {
name string
tags []string
startAt time.Time
metrics []Metric
log logger.Manager
}
func (m *metricPushAction) appendTags(tags ...string) {
m.tags = append(m.tags, tags...)
}
func (m *metricPushAction) Push(tags ...string) {
m.appendTags(tags...)
for _, metric := range m.metrics {
m.log.InfoWithProps(map[string]interface{}{
"name": m.name,
"tags": tags,
}, "sending metrics")
metric.Count(m.name, 1, m.tags)
elapsedTime := time.Since(m.startAt).Milliseconds()
metric.Histogram(m.name+".histogram", float64(elapsedTime), m.tags)
}
}
func (m *metricPushAction) addMetrics(metrics ...Metric) MetricPushAction {
m.metrics = append(m.metrics, metrics...)
return m
}
func NewMetricActionNoop(log logger.Manager) MetricPushAction {
return &metricActionNoop{log: log}
}
func newMetricPushAction(log logger.Manager, name string, metrics []Metric, tags ...string) MetricPushAction {
return &metricPushAction{
name: name,
tags: tags,
startAt: time.Now(),
metrics: metrics,
log: log,
}
}
type MetricsManager interface {
StartBy(provider, name string) MetricPushAction
Start(name string) MetricPushAction
StartDefault(name string) MetricPushAction
Enabled() bool
MetricActions
MustInit() MetricsManager
}
type metricsManager struct {
enabled bool
env string
serviceName string
metrics map[string]Metric
log logger.Manager
}
var defaultProvider = MetricDatadog
func (m *metricsManager) getProvider(name string) (Metric, error) {
if p, ok := m.metrics[name]; ok {
return p, nil
}
return nil, errors.New("metric provider not found")
}
func (m *metricsManager) execBy(provider string, run func(metric Metric)) {
if p, err := m.getProvider(provider); err == nil {
run(p)
}
}
func (m *metricsManager) execAll(run func(metric Metric)) {
for _, mt := range m.metrics {
run(mt)
}
}
func (m *metricsManager) Enabled() bool {
return m.enabled
}
func (m *metricsManager) Count(metricName string, value int64, tags []string) {
m.execAll(func(metric Metric) {
metric.Count(metricName, value, tags)
})
}
func (m *metricsManager) Gauge(metricName string, value float64, tags []string) {
m.execAll(func(metric Metric) {
metric.Gauge(metricName, value, tags)
})
}
func (m *metricsManager) Histogram(metricName string, value float64, tags []string) {
m.execAll(func(metric Metric) {
metric.Histogram(metricName, value, tags)
})
}
func (m *metricsManager) Distribution(metricName string, value float64, tags []string) {
m.execAll(func(metric Metric) {
metric.Distribution(metricName, value, tags)
})
}
// StartBy specific metric provider only
func (m *metricsManager) StartBy(provider, name string) MetricPushAction {
p, err := m.getProvider(provider)
if !m.enabled || err != nil {
return NewMetricActionNoop(m.log)
}
actionName := m.serviceName + "." + name
tags := []string{"src_env:" + m.env, "name:" + actionName}
return newMetricPushAction(m.log, actionName, []Metric{p}, tags...)
}
// StartDefault using default metric provider
func (m *metricsManager) StartDefault(name string) MetricPushAction {
p, err := m.getProvider(defaultProvider.String())
if !m.enabled || err != nil {
return NewMetricActionNoop(m.log)
}
actionName := m.serviceName + "." + name
tags := []string{"src_env:" + m.env, "name:" + actionName}
return newMetricPushAction(m.log, actionName, []Metric{p}, tags...)
}
// Start using all instantiated providers
func (m *metricsManager) Start(name string) MetricPushAction {
if !m.enabled {
return NewMetricActionNoop(m.log)
}
actionName := m.serviceName + "." + name
tags := []string{"src_env:" + m.env, "name:" + actionName}
metrics := make([]Metric, 0)
for _, metric := range m.metrics {
metrics = append(metrics, metric)
}
return newMetricPushAction(m.log, actionName, metrics, tags...)
}
func (m *metricsManager) MustInit() MetricsManager {
if len(m.metrics) > 0 {
m.enabled = true
}
return m
}
func NewMetricsManager(log logger.Manager, serviceName string, metrics ...Metric) MetricsManager {
m := make(map[string]Metric)
for _, metric := range metrics {
m[metric.Key()] = metric
}
return &metricsManager{metrics: m, serviceName: serviceName, log: log}
}