Skip to content
This repository was archived by the owner on Jul 31, 2023. It is now read-only.

Commit c31d268

Browse files
paivagustavorghetia
authored andcommitted
add constant labels to gauges and cumulative metrics (#1122)
* Remove unused GetEntry. * adds support for constant labels on Gauge and CumulativeMetric * fixing format on tests. * remove unused getentry
1 parent 3e65bcb commit c31d268

File tree

4 files changed

+163
-25
lines changed

4 files changed

+163
-25
lines changed

metric/common.go

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import (
1919
"time"
2020

2121
"go.opencensus.io/internal/tagencoding"
22+
2223
"go.opencensus.io/metric/metricdata"
2324
)
2425

@@ -30,11 +31,12 @@ import (
3031
// baseMetric should not be used directly, use metric specific type such as
3132
// Float64Gauge or Int64Gauge.
3233
type baseMetric struct {
33-
vals sync.Map
34-
desc metricdata.Descriptor
35-
start time.Time
36-
keys []metricdata.LabelKey
37-
bmType baseMetricType
34+
vals sync.Map
35+
desc metricdata.Descriptor
36+
start time.Time
37+
keys []metricdata.LabelKey
38+
constLabelValues []metricdata.LabelValue
39+
bmType baseMetricType
3840
}
3941

4042
type baseMetricType int
@@ -118,6 +120,7 @@ func (bm *baseMetric) decodeLabelVals(s string) []metricdata.LabelValue {
118120
}
119121

120122
func (bm *baseMetric) entryForValues(labelVals []metricdata.LabelValue, newEntry func() baseEntry) (interface{}, error) {
123+
labelVals = append(bm.constLabelValues, labelVals...)
121124
if len(labelVals) != len(bm.keys) {
122125
return nil, errKeyValueMismatch
123126
}

metric/cumulative_test.go

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import (
1919
"time"
2020

2121
"github.com/google/go-cmp/cmp"
22+
2223
"go.opencensus.io/metric/metricdata"
2324
)
2425

@@ -83,6 +84,61 @@ func TestCumulative(t *testing.T) {
8384
}
8485
}
8586

87+
func TestCumulativeConstLabel(t *testing.T) {
88+
r := NewRegistry()
89+
90+
f, _ := r.AddFloat64Cumulative("TestCumulativeWithConstLabel",
91+
WithLabelKeys("k1"),
92+
WithConstLabel(map[metricdata.LabelKey]metricdata.LabelValue{
93+
{Key: "const"}: metricdata.NewLabelValue("same"),
94+
{Key: "const2"}: metricdata.NewLabelValue("same2"),
95+
}))
96+
97+
e, _ := f.GetEntry(metricdata.LabelValue{})
98+
e.Inc(5)
99+
e, _ = f.GetEntry(metricdata.NewLabelValue("k1v1"))
100+
e.Inc(1)
101+
m := r.Read()
102+
want := []*metricdata.Metric{
103+
{
104+
Descriptor: metricdata.Descriptor{
105+
Name: "TestCumulativeWithConstLabel",
106+
LabelKeys: []metricdata.LabelKey{
107+
{Key: "const"},
108+
{Key: "const2"},
109+
{Key: "k1"}},
110+
Type: metricdata.TypeCumulativeFloat64,
111+
},
112+
TimeSeries: []*metricdata.TimeSeries{
113+
{
114+
LabelValues: []metricdata.LabelValue{
115+
metricdata.NewLabelValue("same"),
116+
metricdata.NewLabelValue("same2"),
117+
{}},
118+
Points: []metricdata.Point{
119+
metricdata.NewFloat64Point(time.Time{}, 5),
120+
},
121+
},
122+
{
123+
LabelValues: []metricdata.LabelValue{
124+
metricdata.NewLabelValue("same"),
125+
metricdata.NewLabelValue("same2"),
126+
metricdata.NewLabelValue("k1v1"),
127+
},
128+
Points: []metricdata.Point{
129+
metricdata.NewFloat64Point(time.Time{}, 1),
130+
},
131+
},
132+
},
133+
},
134+
}
135+
canonicalize(m)
136+
canonicalize(want)
137+
if diff := cmp.Diff(m, want, cmp.Comparer(ignoreTimes)); diff != "" {
138+
t.Errorf("-got +want: %s", diff)
139+
}
140+
}
141+
86142
func TestCumulativeMetricDescriptor(t *testing.T) {
87143
r := NewRegistry()
88144

metric/gauge_test.go

Lines changed: 69 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,13 @@ package metric
1616

1717
import (
1818
"fmt"
19-
"go.opencensus.io/metric/metricdata"
2019
"sort"
2120
"testing"
2221
"time"
2322

2423
"github.com/google/go-cmp/cmp"
24+
25+
"go.opencensus.io/metric/metricdata"
2526
)
2627

2728
func TestGauge(t *testing.T) {
@@ -85,6 +86,62 @@ func TestGauge(t *testing.T) {
8586
}
8687
}
8788

89+
func TestGaugeConstLabel(t *testing.T) {
90+
r := NewRegistry()
91+
92+
f, _ := r.AddFloat64Gauge("TestGaugeWithConstLabel",
93+
WithLabelKeys("k1"),
94+
WithConstLabel(map[metricdata.LabelKey]metricdata.LabelValue{
95+
{Key: "const"}: metricdata.NewLabelValue("same"),
96+
{Key: "const2"}: metricdata.NewLabelValue("same2"),
97+
}))
98+
99+
e, _ := f.GetEntry(metricdata.LabelValue{})
100+
e.Set(5)
101+
e, _ = f.GetEntry(metricdata.NewLabelValue("k1v1"))
102+
e.Add(1)
103+
m := r.Read()
104+
want := []*metricdata.Metric{
105+
{
106+
Descriptor: metricdata.Descriptor{
107+
Name: "TestGaugeWithConstLabel",
108+
LabelKeys: []metricdata.LabelKey{
109+
{Key: "const"},
110+
{Key: "const2"},
111+
{Key: "k1"}},
112+
Type: metricdata.TypeGaugeFloat64,
113+
},
114+
TimeSeries: []*metricdata.TimeSeries{
115+
{
116+
LabelValues: []metricdata.LabelValue{
117+
metricdata.NewLabelValue("same"),
118+
metricdata.NewLabelValue("same2"),
119+
{},
120+
},
121+
Points: []metricdata.Point{
122+
metricdata.NewFloat64Point(time.Time{}, 5),
123+
},
124+
},
125+
{
126+
LabelValues: []metricdata.LabelValue{
127+
metricdata.NewLabelValue("same"),
128+
metricdata.NewLabelValue("same2"),
129+
metricdata.NewLabelValue("k1v1"),
130+
},
131+
Points: []metricdata.Point{
132+
metricdata.NewFloat64Point(time.Time{}, 1),
133+
},
134+
},
135+
},
136+
},
137+
}
138+
canonicalize(m)
139+
canonicalize(want)
140+
if diff := cmp.Diff(m, want, cmp.Comparer(ignoreTimes)); diff != "" {
141+
t.Errorf("-got +want: %s", diff)
142+
}
143+
}
144+
88145
func TestGaugeMetricDescriptor(t *testing.T) {
89146
r := NewRegistry()
90147

@@ -330,20 +387,18 @@ func canonicalize(ms []*metricdata.Metric) {
330387
for _, m := range ms {
331388
sort.Slice(m.TimeSeries, func(i, j int) bool {
332389
// sort time series by their label values
333-
iLabels := m.TimeSeries[i].LabelValues
334-
jLabels := m.TimeSeries[j].LabelValues
335-
for k := 0; k < len(iLabels); k++ {
336-
if !iLabels[k].Present {
337-
if jLabels[k].Present {
338-
return true
339-
}
340-
} else if !jLabels[k].Present {
341-
return false
342-
} else {
343-
return iLabels[k].Value < jLabels[k].Value
344-
}
390+
iStr := ""
391+
392+
for _, label := range m.TimeSeries[i].LabelValues {
393+
iStr += fmt.Sprintf("%+v", label)
345394
}
346-
panic("should have returned")
395+
396+
jStr := ""
397+
for _, label := range m.TimeSeries[j].LabelValues {
398+
jStr += fmt.Sprintf("%+v", label)
399+
}
400+
401+
return iStr < jStr
347402
})
348403
}
349404
}

metric/registry.go

Lines changed: 30 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
package metric
1616

1717
import (
18+
"sort"
1819
"sync"
1920
"time"
2021

@@ -28,11 +29,11 @@ type Registry struct {
2829
baseMetrics sync.Map
2930
}
3031

31-
//TODO: [rghetia] add constant labels.
3232
type metricOptions struct {
33-
unit metricdata.Unit
34-
labelkeys []metricdata.LabelKey
35-
desc string
33+
unit metricdata.Unit
34+
labelkeys []metricdata.LabelKey
35+
constLabels map[metricdata.LabelKey]metricdata.LabelValue
36+
desc string
3637
}
3738

3839
// Options apply changes to metricOptions.
@@ -70,6 +71,13 @@ func WithLabelKeysAndDescription(labelKeys ...metricdata.LabelKey) Options {
7071
}
7172
}
7273

74+
// WithConstLabel applies provided constant label.
75+
func WithConstLabel(constLabels map[metricdata.LabelKey]metricdata.LabelValue) Options {
76+
return func(mo *metricOptions) {
77+
mo.constLabels = constLabels
78+
}
79+
}
80+
7381
// NewRegistry initializes a new Registry.
7482
func NewRegistry() *Registry {
7583
return &Registry{}
@@ -236,12 +244,28 @@ func (r *Registry) initBaseMetric(bm *baseMetric, name string, mos ...Options) (
236244
}
237245
bm.start = time.Now()
238246
o := createMetricOption(mos...)
239-
bm.keys = o.labelkeys
247+
248+
var constLabelKeys []metricdata.LabelKey
249+
for k := range o.constLabels {
250+
constLabelKeys = append(constLabelKeys, k)
251+
}
252+
sort.Slice(constLabelKeys, func(i, j int) bool {
253+
return constLabelKeys[i].Key < constLabelKeys[j].Key
254+
})
255+
256+
var constLabelValues []metricdata.LabelValue
257+
for _, k := range constLabelKeys {
258+
constLabelValues = append(constLabelValues, o.constLabels[k])
259+
}
260+
261+
bm.keys = append(constLabelKeys, o.labelkeys...)
262+
bm.constLabelValues = constLabelValues
263+
240264
bm.desc = metricdata.Descriptor{
241265
Name: name,
242266
Description: o.desc,
243267
Unit: o.unit,
244-
LabelKeys: o.labelkeys,
268+
LabelKeys: bm.keys,
245269
Type: bmTypeToMetricType(bm),
246270
}
247271
r.baseMetrics.Store(name, bm)

0 commit comments

Comments
 (0)