-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmetric.go
148 lines (122 loc) · 3.02 KB
/
metric.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
package stats
import (
"sync/atomic"
)
// Metric is a general interface for stats.
type Metric interface {
Name() string
TagExtractedName() string
Tags() []*Tag
IsUsed() bool
}
var (
_ Metric = new(Gauge)
_ Metric = new(Histogram)
_ Metric = new(Counter)
)
type metric struct {
name string
tagExtractedName string
tags []*Tag
isUsed int32
}
func newMetric(name, tagExtractedName string, tags []*Tag) metric {
return metric{
name: name,
tagExtractedName: tagExtractedName,
tags: tags,
}
}
func (m *metric) Name() string {
return m.name
}
func (m *metric) TagExtractedName() string {
return m.tagExtractedName
}
func (m *metric) Tags() []*Tag {
return m.tags
}
func (m *metric) IsUsed() bool {
return atomic.LoadInt32(&m.isUsed) == 1
}
func (m *metric) markUsed() {
atomic.StoreInt32(&m.isUsed, 1)
}
// Gauge is a Metric that represents a single numerical value that can
// arbitrarily go up and down.
type Gauge struct {
metric
val uint64
}
// NewGauge creates a gauge with given params.
// NOTE: It should only be used in unit tests.
func NewGauge(name, tagExtractedName string, tags []*Tag) *Gauge {
return &Gauge{
metric: newMetric(name, tagExtractedName, tags),
}
}
// Set sets the gauge to an arbitrary value.
func (g *Gauge) Set(val uint64) {
atomic.StoreUint64(&g.val, val)
g.markUsed()
}
// Add adds the given value to the Gauge.
func (g *Gauge) Add(amount uint64) {
atomic.AddUint64(&g.val, amount)
g.markUsed()
}
// Sub subtracts the given value from the Gauge.
func (g *Gauge) Sub(amount uint64) {
atomic.AddUint64(&g.val, ^uint64(amount-1))
g.markUsed()
}
// Inc increments the Gauge by 1.
func (g *Gauge) Inc() {
g.Add(1)
}
// Dec decrements the Gauge by 1.
func (g *Gauge) Dec() {
g.Sub(1)
}
// Value returns the Gauge value.
func (g *Gauge) Value() uint64 {
return atomic.LoadUint64(&g.val)
}
// Counter is a Metric that represents a single numerical value
// that only ever goes up. Each increment is added both to a global
// counter as well as periodic counter.
type Counter struct {
metric
val uint64
pendingIncr uint64
intervalVal uint64
}
// NewCounter creates a counter with given params.
// NOTE: It should only be used in unit tests.
func NewCounter(name, tagExtractedName string, tags []*Tag) *Counter {
return &Counter{metric: newMetric(name, tagExtractedName, tags)}
}
// Add adds the given value to the counter.
func (c *Counter) Add(amount uint64) {
atomic.AddUint64(&c.val, amount)
atomic.AddUint64(&c.pendingIncr, amount)
c.markUsed()
}
// Inc icrements the counter by 1.
func (c *Counter) Inc() {
c.Add(1)
}
// Latch returns the periodic counter value and clears it.
func (c *Counter) Latch() uint64 {
val := atomic.SwapUint64(&c.pendingIncr, 0)
c.intervalVal = val
return val
}
// IntervalValue returns the lastest periodic counter value.
func (c *Counter) IntervalValue() uint64 {
return c.intervalVal
}
// Value returns the global counter value.
func (c *Counter) Value() uint64 {
return atomic.LoadUint64(&c.val)
}