diff --git a/receiver/statsdreceiver/protocol/metric_translator.go b/receiver/statsdreceiver/protocol/metric_translator.go index 84236145e609..cf6c4ca1c8b5 100644 --- a/receiver/statsdreceiver/protocol/metric_translator.go +++ b/receiver/statsdreceiver/protocol/metric_translator.go @@ -21,7 +21,7 @@ import ( "go.opentelemetry.io/collector/model/pdata" ) -func buildCounterMetric(parsedMetric statsDMetric, isMonotonicCounter bool, timeNow time.Time) pdata.InstrumentationLibraryMetrics { +func buildCounterMetric(parsedMetric statsDMetric, isMonotonicCounter bool, timeNow, lastIntervalTime time.Time) pdata.InstrumentationLibraryMetrics { ilm := pdata.NewInstrumentationLibraryMetrics() nm := ilm.Metrics().AppendEmpty() nm.SetName(parsedMetric.description.name) @@ -31,14 +31,11 @@ func buildCounterMetric(parsedMetric statsDMetric, isMonotonicCounter bool, time nm.SetDataType(pdata.MetricDataTypeSum) nm.Sum().SetAggregationTemporality(pdata.MetricAggregationTemporalityDelta) - if isMonotonicCounter { - nm.Sum().SetAggregationTemporality(pdata.MetricAggregationTemporalityCumulative) - } - - nm.Sum().SetIsMonotonic(true) + nm.Sum().SetIsMonotonic(isMonotonicCounter) dp := nm.Sum().DataPoints().AppendEmpty() dp.SetIntVal(parsedMetric.counterValue()) + dp.SetStartTimestamp(pdata.NewTimestampFromTime(lastIntervalTime)) dp.SetTimestamp(pdata.NewTimestampFromTime(timeNow)) for i, key := range parsedMetric.labelKeys { dp.Attributes().InsertString(key, parsedMetric.labelValues[i]) diff --git a/receiver/statsdreceiver/protocol/metric_translator_test.go b/receiver/statsdreceiver/protocol/metric_translator_test.go index 94206226d65e..c5587a804960 100644 --- a/receiver/statsdreceiver/protocol/metric_translator_test.go +++ b/receiver/statsdreceiver/protocol/metric_translator_test.go @@ -24,6 +24,7 @@ import ( func TestBuildCounterMetric(t *testing.T) { timeNow := time.Now() + lastUpdateInterval := timeNow.Add(-1 * time.Minute) metricDescription := statsDMetricdescription{ name: "testCounter", } @@ -35,16 +36,17 @@ func TestBuildCounterMetric(t *testing.T) { labelValues: []string{"myvalue"}, } isMonotonicCounter := false - metric := buildCounterMetric(parsedMetric, isMonotonicCounter, timeNow) + metric := buildCounterMetric(parsedMetric, isMonotonicCounter, timeNow, lastUpdateInterval) expectedMetrics := pdata.NewInstrumentationLibraryMetrics() expectedMetric := expectedMetrics.Metrics().AppendEmpty() expectedMetric.SetName("testCounter") expectedMetric.SetUnit("meter") expectedMetric.SetDataType(pdata.MetricDataTypeSum) expectedMetric.Sum().SetAggregationTemporality(pdata.MetricAggregationTemporalityDelta) - expectedMetric.Sum().SetIsMonotonic(true) + expectedMetric.Sum().SetIsMonotonic(isMonotonicCounter) dp := expectedMetric.Sum().DataPoints().AppendEmpty() dp.SetIntVal(32) + dp.SetStartTimestamp(pdata.NewTimestampFromTime(lastUpdateInterval)) dp.SetTimestamp(pdata.NewTimestampFromTime(timeNow)) dp.Attributes().InsertString("mykey", "myvalue") assert.Equal(t, metric, expectedMetrics) diff --git a/receiver/statsdreceiver/protocol/statsd_parser.go b/receiver/statsdreceiver/protocol/statsd_parser.go index 19ab3522600f..6b18ecbb6293 100644 --- a/receiver/statsdreceiver/protocol/statsd_parser.go +++ b/receiver/statsdreceiver/protocol/statsd_parser.go @@ -72,6 +72,7 @@ type StatsDParser struct { isMonotonicCounter bool observeTimer ObserverType observeHistogram ObserverType + lastIntervalTime time.Time } type summaryMetric struct { @@ -113,6 +114,7 @@ func (t MetricType) FullName() TypeName { } func (p *StatsDParser) Initialize(enableMetricType bool, isMonotonicCounter bool, sendTimerHistogram []TimerHistogramMapping) error { + p.lastIntervalTime = timeNowFunc() p.gauges = make(map[statsDMetricdescription]pdata.InstrumentationLibraryMetrics) p.counters = make(map[statsDMetricdescription]pdata.InstrumentationLibraryMetrics) p.timersAndDistributions = make([]pdata.InstrumentationLibraryMetrics, 0) @@ -157,6 +159,7 @@ func (p *StatsDParser) GetMetrics() pdata.Metrics { ) } + p.lastIntervalTime = timeNowFunc() p.gauges = make(map[statsDMetricdescription]pdata.InstrumentationLibraryMetrics) p.counters = make(map[statsDMetricdescription]pdata.InstrumentationLibraryMetrics) p.timersAndDistributions = make([]pdata.InstrumentationLibraryMetrics, 0) @@ -201,7 +204,7 @@ func (p *StatsDParser) Aggregate(line string) error { case CounterType: _, ok := p.counters[parsedMetric.description] if !ok { - p.counters[parsedMetric.description] = buildCounterMetric(parsedMetric, p.isMonotonicCounter, timeNowFunc()) + p.counters[parsedMetric.description] = buildCounterMetric(parsedMetric, p.isMonotonicCounter, timeNowFunc(), p.lastIntervalTime) } else { point := p.counters[parsedMetric.description].Metrics().At(0).Sum().DataPoints().At(0) point.SetIntVal(point.IntVal() + parsedMetric.counterValue()) diff --git a/receiver/statsdreceiver/protocol/statsd_parser_test.go b/receiver/statsdreceiver/protocol/statsd_parser_test.go index bdb1f29ceb7e..37d10aec4f90 100644 --- a/receiver/statsdreceiver/protocol/statsd_parser_test.go +++ b/receiver/statsdreceiver/protocol/statsd_parser_test.go @@ -592,9 +592,9 @@ func TestStatsDParser_Aggregate(t *testing.T) { expectedGauges: map[statsDMetricdescription]pdata.InstrumentationLibraryMetrics{}, expectedCounters: map[statsDMetricdescription]pdata.InstrumentationLibraryMetrics{ testDescription("statsdTestMetric1", "c", - []string{"mykey"}, []string{"myvalue"}): buildCounterMetric(testStatsDMetric("statsdTestMetric1", 7000, false, "c", 0, []string{"mykey"}, []string{"myvalue"}), false, time.Unix(711, 0)), + []string{"mykey"}, []string{"myvalue"}): buildCounterMetric(testStatsDMetric("statsdTestMetric1", 7000, false, "c", 0, []string{"mykey"}, []string{"myvalue"}), false, time.Unix(711, 0), time.Unix(611, 0)), testDescription("statsdTestMetric2", "c", - []string{"mykey"}, []string{"myvalue"}): buildCounterMetric(testStatsDMetric("statsdTestMetric2", 50, false, "c", 0, []string{"mykey"}, []string{"myvalue"}), false, time.Unix(711, 0)), + []string{"mykey"}, []string{"myvalue"}): buildCounterMetric(testStatsDMetric("statsdTestMetric2", 50, false, "c", 0, []string{"mykey"}, []string{"myvalue"}), false, time.Unix(711, 0), time.Unix(611, 0)), }, expectedTimer: []pdata.InstrumentationLibraryMetrics{}, }, @@ -617,9 +617,9 @@ func TestStatsDParser_Aggregate(t *testing.T) { }, expectedCounters: map[statsDMetricdescription]pdata.InstrumentationLibraryMetrics{ testDescription("statsdTestMetric1", "c", - []string{"mykey"}, []string{"myvalue"}): buildCounterMetric(testStatsDMetric("statsdTestMetric1", 7000, false, "c", 0, []string{"mykey"}, []string{"myvalue"}), false, time.Unix(711, 0)), + []string{"mykey"}, []string{"myvalue"}): buildCounterMetric(testStatsDMetric("statsdTestMetric1", 7000, false, "c", 0, []string{"mykey"}, []string{"myvalue"}), false, time.Unix(711, 0), time.Unix(611, 0)), testDescription("statsdTestMetric2", "c", - []string{"mykey"}, []string{"myvalue"}): buildCounterMetric(testStatsDMetric("statsdTestMetric2", 50, false, "c", 0, []string{"mykey"}, []string{"myvalue"}), false, time.Unix(711, 0)), + []string{"mykey"}, []string{"myvalue"}): buildCounterMetric(testStatsDMetric("statsdTestMetric2", 50, false, "c", 0, []string{"mykey"}, []string{"myvalue"}), false, time.Unix(711, 0), time.Unix(611, 0)), }, expectedTimer: []pdata.InstrumentationLibraryMetrics{}, }, @@ -645,9 +645,9 @@ func TestStatsDParser_Aggregate(t *testing.T) { }, expectedCounters: map[statsDMetricdescription]pdata.InstrumentationLibraryMetrics{ testDescription("statsdTestMetric1", "c", - []string{"mykey"}, []string{"myvalue"}): buildCounterMetric(testStatsDMetric("statsdTestMetric1", 215, false, "c", 0, []string{"mykey"}, []string{"myvalue"}), false, time.Unix(711, 0)), + []string{"mykey"}, []string{"myvalue"}): buildCounterMetric(testStatsDMetric("statsdTestMetric1", 215, false, "c", 0, []string{"mykey"}, []string{"myvalue"}), false, time.Unix(711, 0), time.Unix(611, 0)), testDescription("statsdTestMetric2", "c", - []string{"mykey"}, []string{"myvalue"}): buildCounterMetric(testStatsDMetric("statsdTestMetric2", 75, false, "c", 0, []string{"mykey"}, []string{"myvalue"}), false, time.Unix(711, 0)), + []string{"mykey"}, []string{"myvalue"}): buildCounterMetric(testStatsDMetric("statsdTestMetric2", 75, false, "c", 0, []string{"mykey"}, []string{"myvalue"}), false, time.Unix(711, 0), time.Unix(611, 0)), }, expectedTimer: []pdata.InstrumentationLibraryMetrics{}, }, @@ -674,6 +674,7 @@ func TestStatsDParser_Aggregate(t *testing.T) { var err error p := &StatsDParser{} p.Initialize(false, false, []TimerHistogramMapping{{StatsdType: "timer", ObserverType: "gauge"}, {StatsdType: "histogram", ObserverType: "gauge"}}) + p.lastIntervalTime = time.Unix(611, 0) for _, line := range tt.input { err = p.Aggregate(line) } @@ -731,9 +732,9 @@ func TestStatsDParser_AggregateWithMetricType(t *testing.T) { expectedGauges: map[statsDMetricdescription]pdata.InstrumentationLibraryMetrics{}, expectedCounters: map[statsDMetricdescription]pdata.InstrumentationLibraryMetrics{ testDescription("statsdTestMetric1", "c", - []string{"mykey", "metric_type"}, []string{"myvalue", "counter"}): buildCounterMetric(testStatsDMetric("statsdTestMetric1", 7000, false, "c", 0, []string{"mykey", "metric_type"}, []string{"myvalue", "counter"}), false, time.Unix(711, 0)), + []string{"mykey", "metric_type"}, []string{"myvalue", "counter"}): buildCounterMetric(testStatsDMetric("statsdTestMetric1", 7000, false, "c", 0, []string{"mykey", "metric_type"}, []string{"myvalue", "counter"}), false, time.Unix(711, 0), time.Unix(611, 0)), testDescription("statsdTestMetric2", "c", - []string{"mykey", "metric_type"}, []string{"myvalue", "counter"}): buildCounterMetric(testStatsDMetric("statsdTestMetric2", 50, false, "c", 0, []string{"mykey", "metric_type"}, []string{"myvalue", "counter"}), false, time.Unix(711, 0)), + []string{"mykey", "metric_type"}, []string{"myvalue", "counter"}): buildCounterMetric(testStatsDMetric("statsdTestMetric2", 50, false, "c", 0, []string{"mykey", "metric_type"}, []string{"myvalue", "counter"}), false, time.Unix(711, 0), time.Unix(611, 0)), }, }, } @@ -742,6 +743,7 @@ func TestStatsDParser_AggregateWithMetricType(t *testing.T) { var err error p := &StatsDParser{} p.Initialize(true, false, []TimerHistogramMapping{{StatsdType: "timer", ObserverType: "gauge"}, {StatsdType: "histogram", ObserverType: "gauge"}}) + p.lastIntervalTime = time.Unix(611, 0) for _, line := range tt.input { err = p.Aggregate(line) } @@ -778,9 +780,9 @@ func TestStatsDParser_AggregateWithIsMonotonicCounter(t *testing.T) { expectedGauges: map[statsDMetricdescription]pdata.InstrumentationLibraryMetrics{}, expectedCounters: map[statsDMetricdescription]pdata.InstrumentationLibraryMetrics{ testDescription("statsdTestMetric1", "c", - []string{"mykey"}, []string{"myvalue"}): buildCounterMetric(testStatsDMetric("statsdTestMetric1", 7000, false, "c", 0, []string{"mykey"}, []string{"myvalue"}), true, time.Unix(711, 0)), + []string{"mykey"}, []string{"myvalue"}): buildCounterMetric(testStatsDMetric("statsdTestMetric1", 7000, false, "c", 0, []string{"mykey"}, []string{"myvalue"}), true, time.Unix(711, 0), time.Unix(611, 0)), testDescription("statsdTestMetric2", "c", - []string{"mykey"}, []string{"myvalue"}): buildCounterMetric(testStatsDMetric("statsdTestMetric2", 50, false, "c", 0, []string{"mykey"}, []string{"myvalue"}), true, time.Unix(711, 0)), + []string{"mykey"}, []string{"myvalue"}): buildCounterMetric(testStatsDMetric("statsdTestMetric2", 50, false, "c", 0, []string{"mykey"}, []string{"myvalue"}), true, time.Unix(711, 0), time.Unix(611, 0)), }, }, } @@ -789,6 +791,7 @@ func TestStatsDParser_AggregateWithIsMonotonicCounter(t *testing.T) { var err error p := &StatsDParser{} p.Initialize(false, true, []TimerHistogramMapping{{StatsdType: "timer", ObserverType: "gauge"}, {StatsdType: "histogram", ObserverType: "gauge"}}) + p.lastIntervalTime = time.Unix(611, 0) for _, line := range tt.input { err = p.Aggregate(line) }