110 lines
2.8 KiB
Go
110 lines
2.8 KiB
Go
// Package metrics defines a concurrently-accessible metrics collector.
|
|
//
|
|
// A *metrics.M value exports methods to track integer counters and maximum
|
|
// values. A metric has a caller-assigned string name that is not interpreted
|
|
// by the collector except to locate its stored value.
|
|
package metrics
|
|
|
|
import "sync"
|
|
|
|
// An M collects counters and maximum value trackers. A nil *M is valid, and
|
|
// discards all metrics. The methods of an *M are safe for concurrent use by
|
|
// multiple goroutines.
|
|
type M struct {
|
|
mu sync.Mutex
|
|
counter map[string]int64
|
|
maxVal map[string]int64
|
|
label map[string]string
|
|
}
|
|
|
|
// New creates a new, empty metrics collector.
|
|
func New() *M {
|
|
return &M{
|
|
counter: make(map[string]int64),
|
|
maxVal: make(map[string]int64),
|
|
label: make(map[string]string),
|
|
}
|
|
}
|
|
|
|
// Count adds n to the current value of the counter named, defining the counter
|
|
// if it does not already exist.
|
|
func (m *M) Count(name string, n int64) {
|
|
if m != nil {
|
|
m.mu.Lock()
|
|
defer m.mu.Unlock()
|
|
m.counter[name] += n
|
|
}
|
|
}
|
|
|
|
// SetMaxValue sets the maximum value metric named to the greater of n and its
|
|
// current value, defining the value if it does not already exist.
|
|
func (m *M) SetMaxValue(name string, n int64) {
|
|
if m != nil {
|
|
m.mu.Lock()
|
|
defer m.mu.Unlock()
|
|
if old, ok := m.maxVal[name]; !ok || n > old {
|
|
m.maxVal[name] = n
|
|
}
|
|
}
|
|
}
|
|
|
|
// CountAndSetMax adds n to the current value of the counter named, and also
|
|
// updates a max value tracker with the same name in a single step.
|
|
func (m *M) CountAndSetMax(name string, n int64) {
|
|
if m != nil {
|
|
m.mu.Lock()
|
|
defer m.mu.Unlock()
|
|
if old, ok := m.maxVal[name]; !ok || n > old {
|
|
m.maxVal[name] = n
|
|
}
|
|
m.counter[name] += n
|
|
}
|
|
}
|
|
|
|
// SetLabel sets the specified label to value. If value == "" the label is
|
|
// removed from the set.
|
|
func (m *M) SetLabel(name, value string) {
|
|
if m != nil {
|
|
m.mu.Lock()
|
|
defer m.mu.Unlock()
|
|
if value == "" {
|
|
delete(m.label, name)
|
|
} else {
|
|
m.label[name] = value
|
|
}
|
|
}
|
|
}
|
|
|
|
// Snapshot copies an atomic snapshot of the collected metrics into the non-nil
|
|
// fields of the provided snapshot value. Only the fields of snap that are not
|
|
// nil are snapshotted.
|
|
func (m *M) Snapshot(snap Snapshot) {
|
|
if m != nil {
|
|
m.mu.Lock()
|
|
defer m.mu.Unlock()
|
|
if c := snap.Counter; c != nil {
|
|
for name, val := range m.counter {
|
|
c[name] = val
|
|
}
|
|
}
|
|
if v := snap.MaxValue; v != nil {
|
|
for name, val := range m.maxVal {
|
|
v[name] = val
|
|
}
|
|
}
|
|
if v := snap.Label; v != nil {
|
|
for name, val := range m.label {
|
|
v[name] = val
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// A Snapshot represents a point-in-time snapshot of a metrics collector. The
|
|
// fields of this type are filled in by the Snapshot method of *M.
|
|
type Snapshot struct {
|
|
Counter map[string]int64
|
|
MaxValue map[string]int64
|
|
Label map[string]string
|
|
}
|