/
metrics.go
119 lines (102 loc) · 1.99 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
package statsd
import (
"math"
"sync"
"sync/atomic"
)
/*
Those are metrics type that can be aggregated on the client side:
- Gauge
- Count
- Set
*/
type countMetric struct {
value int64
name string
tags []string
}
func newCountMetric(name string, value int64, tags []string) *countMetric {
return &countMetric{
value: value,
name: name,
tags: tags,
}
}
func (c *countMetric) sample(v int64) {
atomic.AddInt64(&c.value, v)
}
func (c *countMetric) flushUnsafe() metric {
return metric{
metricType: count,
name: c.name,
tags: c.tags,
rate: 1,
ivalue: c.value,
}
}
// Gauge
type gaugeMetric struct {
value uint64
name string
tags []string
}
func newGaugeMetric(name string, value float64, tags []string) *gaugeMetric {
return &gaugeMetric{
value: math.Float64bits(value),
name: name,
tags: tags,
}
}
func (g *gaugeMetric) sample(v float64) {
atomic.StoreUint64(&g.value, math.Float64bits(v))
}
func (g *gaugeMetric) flushUnsafe() metric {
return metric{
metricType: gauge,
name: g.name,
tags: g.tags,
rate: 1,
fvalue: math.Float64frombits(g.value),
}
}
// Set
type setMetric struct {
data map[string]struct{}
name string
tags []string
sync.Mutex
}
func newSetMetric(name string, value string, tags []string) *setMetric {
set := &setMetric{
data: map[string]struct{}{},
name: name,
tags: tags,
}
set.data[value] = struct{}{}
return set
}
func (s *setMetric) sample(v string) {
s.Lock()
defer s.Unlock()
s.data[v] = struct{}{}
}
// Sets are aggregated on the agent side too. We flush the keys so a set from
// multiple application can be correctly aggregated on the agent side.
func (s *setMetric) flushUnsafe() []metric {
if len(s.data) == 0 {
return nil
}
metrics := make([]metric, len(s.data))
i := 0
for value := range s.data {
metrics[i] = metric{
metricType: set,
name: s.name,
tags: s.tags,
rate: 1,
svalue: value,
}
i++
}
return metrics
}