Skip to content

Commit 559ea1f

Browse files
authored
Support counter metrics with the _total suffix. (#146)
1 parent 0e6fe9e commit 559ea1f

File tree

3 files changed

+144
-3
lines changed

3 files changed

+144
-3
lines changed

retrieval/series_cache.go

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -391,8 +391,8 @@ func (c *seriesCache) refresh(ctx context.Context, ref uint64) error {
391391
return errors.Wrap(err, "get metadata")
392392
}
393393
if metadata == nil {
394-
// The full name didn't turn anything up. Check again in case it's a summary or histogram without
395-
// the metric name suffix.
394+
// The full name didn't turn anything up. Check again in case it's a summary,
395+
// histogram, or counter without the metric name suffix.
396396
var ok bool
397397
if baseMetricName, suffix, ok = stripComplexMetricSuffix(metricName); ok {
398398
metadata, err = c.metadata.Get(ctx, job, instance, baseMetricName)
@@ -429,6 +429,9 @@ func (c *seriesCache) refresh(ctx context.Context, ref uint64) error {
429429
case textparse.MetricTypeCounter:
430430
ts.MetricKind = metric_pb.MetricDescriptor_CUMULATIVE
431431
ts.ValueType = metric_pb.MetricDescriptor_DOUBLE
432+
if baseMetricName != "" && suffix == metricSuffixTotal {
433+
ts.Metric.Type = c.getMetricType(c.metricsPrefix, baseMetricName)
434+
}
432435
case textparse.MetricTypeGauge, textparse.MetricTypeUnknown:
433436
ts.MetricKind = metric_pb.MetricDescriptor_GAUGE
434437
ts.ValueType = metric_pb.MetricDescriptor_DOUBLE

retrieval/transform.go

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -132,9 +132,10 @@ const (
132132
metricSuffixBucket = "_bucket"
133133
metricSuffixSum = "_sum"
134134
metricSuffixCount = "_count"
135+
metricSuffixTotal = "_total"
135136
)
136137

137-
func stripComplexMetricSuffix(name string) (string, string, bool) {
138+
func stripComplexMetricSuffix(name string) (prefix string, suffix string, ok bool) {
138139
if strings.HasSuffix(name, metricSuffixBucket) {
139140
return name[:len(name)-len(metricSuffixBucket)], metricSuffixBucket, true
140141
}
@@ -144,6 +145,9 @@ func stripComplexMetricSuffix(name string) (string, string, bool) {
144145
if strings.HasSuffix(name, metricSuffixSum) {
145146
return name[:len(name)-len(metricSuffixSum)], metricSuffixSum, true
146147
}
148+
if strings.HasSuffix(name, metricSuffixTotal) {
149+
return name[:len(name)-len(metricSuffixTotal)], metricSuffixTotal, true
150+
}
147151
return name, "", false
148152
}
149153

retrieval/transform_test.go

Lines changed: 134 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -626,6 +626,140 @@ func TestSampleBuilder(t *testing.T) {
626626
},
627627
},
628628
},
629+
// Any counter metric with the _total suffix should be treated as normal if metadata
630+
// can be found for the original metric name.
631+
{
632+
series: seriesMap{
633+
1: labels.FromStrings("job", "job1", "instance", "instance1", "a", "1", "__name__", "metric1_total"),
634+
},
635+
targets: targetMap{
636+
"job1/instance1": &targets.Target{
637+
Labels: promlabels.FromStrings("job", "job1", "instance", "instance1"),
638+
DiscoveredLabels: promlabels.FromStrings("__resource_a", "resource2_a"),
639+
},
640+
},
641+
metadata: metadataMap{
642+
"job1/instance1/metric1_total": &scrape.MetricMetadata{Type: textparse.MetricTypeCounter, Metric: "metric1_total"},
643+
},
644+
metricPrefix: "test.googleapis.com",
645+
input: []tsdb.RefSample{
646+
{Ref: 1, T: 2000, V: 5.5},
647+
{Ref: 1, T: 3000, V: 8},
648+
},
649+
result: []*monitoring_pb.TimeSeries{
650+
nil, // Skipped by reset timestamp handling.
651+
{
652+
Resource: &monitoredres_pb.MonitoredResource{
653+
Type: "resource2",
654+
Labels: map[string]string{"resource_a": "resource2_a"},
655+
},
656+
Metric: &metric_pb.Metric{
657+
Type: "test.googleapis.com/metric1_total",
658+
Labels: map[string]string{"a": "1"},
659+
},
660+
MetricKind: metric_pb.MetricDescriptor_CUMULATIVE,
661+
ValueType: metric_pb.MetricDescriptor_DOUBLE,
662+
Points: []*monitoring_pb.Point{{
663+
Interval: &monitoring_pb.TimeInterval{
664+
StartTime: &timestamp_pb.Timestamp{Seconds: 2},
665+
EndTime: &timestamp_pb.Timestamp{Seconds: 3},
666+
},
667+
Value: &monitoring_pb.TypedValue{
668+
Value: &monitoring_pb.TypedValue_DoubleValue{2.5},
669+
},
670+
}},
671+
},
672+
},
673+
},
674+
// Any counter metric with the _total suffix should fail over to the metadata for
675+
// the metric with the _total suffix removed while reporting the metric with the
676+
// _total suffix removed in the metric name as well.
677+
{
678+
series: seriesMap{
679+
1: labels.FromStrings("job", "job1", "instance", "instance1", "a", "1", "__name__", "metric1_total"),
680+
},
681+
targets: targetMap{
682+
"job1/instance1": &targets.Target{
683+
Labels: promlabels.FromStrings("job", "job1", "instance", "instance1"),
684+
DiscoveredLabels: promlabels.FromStrings("__resource_a", "resource2_a"),
685+
},
686+
},
687+
metadata: metadataMap{
688+
"job1/instance1/metric1": &scrape.MetricMetadata{Type: textparse.MetricTypeCounter, Metric: "metric1"},
689+
},
690+
metricPrefix: "test.googleapis.com",
691+
input: []tsdb.RefSample{
692+
{Ref: 1, T: 2000, V: 5.5},
693+
{Ref: 1, T: 3000, V: 8},
694+
},
695+
result: []*monitoring_pb.TimeSeries{
696+
nil, // Skipped by reset timestamp handling.
697+
{
698+
Resource: &monitoredres_pb.MonitoredResource{
699+
Type: "resource2",
700+
Labels: map[string]string{"resource_a": "resource2_a"},
701+
},
702+
Metric: &metric_pb.Metric{
703+
Type: "test.googleapis.com/metric1",
704+
Labels: map[string]string{"a": "1"},
705+
},
706+
MetricKind: metric_pb.MetricDescriptor_CUMULATIVE,
707+
ValueType: metric_pb.MetricDescriptor_DOUBLE,
708+
Points: []*monitoring_pb.Point{{
709+
Interval: &monitoring_pb.TimeInterval{
710+
StartTime: &timestamp_pb.Timestamp{Seconds: 2},
711+
EndTime: &timestamp_pb.Timestamp{Seconds: 3},
712+
},
713+
Value: &monitoring_pb.TypedValue{
714+
Value: &monitoring_pb.TypedValue_DoubleValue{2.5},
715+
},
716+
}},
717+
},
718+
},
719+
},
720+
// Any non-counter metric with the _total suffix should fail over to the metadata
721+
// for the metric with the _total suffix removed while reporting the metric with
722+
// the original name.
723+
{
724+
series: seriesMap{
725+
1: labels.FromStrings("job", "job1", "instance", "instance1", "a", "1", "__name__", "metric1_total"),
726+
},
727+
targets: targetMap{
728+
"job1/instance1": &targets.Target{
729+
Labels: promlabels.FromStrings("job", "job1", "instance", "instance1"),
730+
DiscoveredLabels: promlabels.FromStrings("__resource_a", "resource2_a"),
731+
},
732+
},
733+
metadata: metadataMap{
734+
"job1/instance1/metric1": &scrape.MetricMetadata{Type: textparse.MetricTypeGauge, Metric: "metric1"},
735+
},
736+
metricPrefix: "test.googleapis.com",
737+
input: []tsdb.RefSample{
738+
{Ref: 1, T: 3000, V: 8},
739+
},
740+
result: []*monitoring_pb.TimeSeries{
741+
{
742+
Resource: &monitoredres_pb.MonitoredResource{
743+
Type: "resource2",
744+
Labels: map[string]string{"resource_a": "resource2_a"},
745+
},
746+
Metric: &metric_pb.Metric{
747+
Type: "test.googleapis.com/metric1_total",
748+
Labels: map[string]string{"a": "1"},
749+
},
750+
MetricKind: metric_pb.MetricDescriptor_GAUGE,
751+
ValueType: metric_pb.MetricDescriptor_DOUBLE,
752+
Points: []*monitoring_pb.Point{{
753+
Interval: &monitoring_pb.TimeInterval{
754+
EndTime: &timestamp_pb.Timestamp{Seconds: 3},
755+
},
756+
Value: &monitoring_pb.TypedValue{
757+
Value: &monitoring_pb.TypedValue_DoubleValue{8},
758+
},
759+
}},
760+
},
761+
},
762+
},
629763
}
630764
ctx, cancel := context.WithCancel(context.Background())
631765
defer cancel()

0 commit comments

Comments
 (0)