-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathvec.go
More file actions
151 lines (133 loc) · 3.92 KB
/
vec.go
File metadata and controls
151 lines (133 loc) · 3.92 KB
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
// Copyright 2026 The Cockroach Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
package goodhistogram
import (
"fmt"
"strings"
"sync"
"github.com/prometheus/client_golang/prometheus"
prometheusgo "github.com/prometheus/client_model/go"
)
// HistogramVec is a collection of Histograms partitioned by label values.
// It implements prometheus.Collector so the entire vec can be registered
// with a Prometheus registry. Recording is done on the individual
// *Histogram returned by WithLabelValues.
type HistogramVec struct {
params Params
desc *prometheus.Desc
labelNames []string
mu struct {
sync.RWMutex
histograms map[string]*labeledHistogram
}
}
type labeledHistogram struct {
h *Histogram
labelPairs []*prometheusgo.LabelPair
}
// NewHistogramVec creates a new HistogramVec. All child histograms share the
// same Params. The desc is created internally from name, help, and labelNames.
func NewHistogramVec(p Params, name, help string, labelNames []string) *HistogramVec {
v := &HistogramVec{
params: p,
desc: prometheus.NewDesc(name, help, labelNames, nil),
labelNames: labelNames,
}
v.mu.histograms = make(map[string]*labeledHistogram)
return v
}
// WithLabelValues returns the Histogram for the given label values,
// creating it if it doesn't exist. Panics if the number of values
// doesn't match the number of label names.
func (v *HistogramVec) WithLabelValues(lvs ...string) *Histogram {
if len(lvs) != len(v.labelNames) {
panic(fmt.Sprintf(
"goodhistogram: expected %d label values, got %d",
len(v.labelNames), len(lvs),
))
}
key := strings.Join(lvs, "\xff")
v.mu.RLock()
if lh, ok := v.mu.histograms[key]; ok {
v.mu.RUnlock()
return lh.h
}
v.mu.RUnlock()
v.mu.Lock()
defer v.mu.Unlock()
if lh, ok := v.mu.histograms[key]; ok {
return lh.h
}
h := New(v.params)
v.mu.histograms[key] = &labeledHistogram{
h: h,
labelPairs: makeLabelPairs(v.labelNames, lvs),
}
return h
}
// DeleteLabelValues removes the Histogram for the given label values.
// Returns true if the entry existed. Panics if the number of values
// doesn't match the number of label names.
func (v *HistogramVec) DeleteLabelValues(lvs ...string) bool {
if len(lvs) != len(v.labelNames) {
panic(fmt.Sprintf(
"goodhistogram: expected %d label values, got %d",
len(v.labelNames), len(lvs),
))
}
key := strings.Join(lvs, "\xff")
v.mu.Lock()
defer v.mu.Unlock()
_, ok := v.mu.histograms[key]
delete(v.mu.histograms, key)
return ok
}
// Reset removes all child histograms.
func (v *HistogramVec) Reset() {
v.mu.Lock()
defer v.mu.Unlock()
v.mu.histograms = make(map[string]*labeledHistogram)
}
// Describe implements prometheus.Collector.
func (v *HistogramVec) Describe(ch chan<- *prometheus.Desc) {
ch <- v.desc
}
// Collect implements prometheus.Collector.
func (v *HistogramVec) Collect(ch chan<- prometheus.Metric) {
v.mu.RLock()
defer v.mu.RUnlock()
for _, lh := range v.mu.histograms {
ch <- &histogramMetric{
desc: v.desc,
h: lh.h,
labelPairs: lh.labelPairs,
}
}
}
// histogramMetric implements prometheus.Metric for a single labeled histogram.
type histogramMetric struct {
desc *prometheus.Desc
h *Histogram
labelPairs []*prometheusgo.LabelPair
}
func (m *histogramMetric) Desc() *prometheus.Desc { return m.desc }
func (m *histogramMetric) Write(out *prometheusgo.Metric) error {
snap := m.h.Snapshot()
out.Histogram = snap.ToPrometheusHistogram()
out.Label = m.labelPairs
return nil
}
func makeLabelPairs(names, values []string) []*prometheusgo.LabelPair {
pairs := make([]*prometheusgo.LabelPair, len(names))
for i := range names {
n := names[i]
v := values[i]
pairs[i] = &prometheusgo.LabelPair{Name: &n, Value: &v}
}
return pairs
}