Skip to content

Commit

Permalink
Use latest metric timestamp for info metrics
Browse files Browse the repository at this point in the history
  • Loading branch information
damemi committed Feb 7, 2023
1 parent 1d67a5a commit 61a5514
Show file tree
Hide file tree
Showing 2 changed files with 106 additions and 15 deletions.
75 changes: 73 additions & 2 deletions exporter/collector/googlemanagedprometheus/extra_metrics.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,13 +31,65 @@ func AddTargetInfoMetric(m pmetric.Metrics) {
for i := 0; i < rms.Len(); i++ {
rm := rms.At(i)

// Keep track of the most recent time in this resource's metrics
// Use that time for the timestamp of the new metric
latestTime := time.Time{}
for j := 0; j < rm.ScopeMetrics().Len(); j++ {
for k := 0; k < rm.ScopeMetrics().At(j).Metrics().Len(); k++ {
metric := rm.ScopeMetrics().At(j).Metrics().At(k)

switch metric.Type() {
case pmetric.MetricTypeSum:
sum := metric.Sum()
points := sum.DataPoints()
for x := 0; x < points.Len(); x++ {
if latestTime.Before(points.At(x).Timestamp().AsTime()) {
latestTime = points.At(x).Timestamp().AsTime()
}
}
case pmetric.MetricTypeGauge:
gauge := metric.Gauge()
points := gauge.DataPoints()
for x := 0; x < points.Len(); x++ {
if latestTime.Before(points.At(x).Timestamp().AsTime()) {
latestTime = points.At(x).Timestamp().AsTime()
}
}
case pmetric.MetricTypeSummary:
summary := metric.Summary()
points := summary.DataPoints()
for x := 0; x < points.Len(); x++ {
if latestTime.Before(points.At(x).Timestamp().AsTime()) {
latestTime = points.At(x).Timestamp().AsTime()
}
}
case pmetric.MetricTypeHistogram:
hist := metric.Histogram()
points := hist.DataPoints()
for x := 0; x < points.Len(); x++ {
if latestTime.Before(points.At(x).Timestamp().AsTime()) {
latestTime = points.At(x).Timestamp().AsTime()
}
}
case pmetric.MetricTypeExponentialHistogram:
eh := metric.ExponentialHistogram()
points := eh.DataPoints()
for x := 0; x < points.Len(); x++ {
if latestTime.Before(points.At(x).Timestamp().AsTime()) {
latestTime = points.At(x).Timestamp().AsTime()
}
}
}
}
}

// create the target_info metric as a Gauge with value 1
targetInfoMetric := rm.ScopeMetrics().AppendEmpty().Metrics().AppendEmpty()
targetInfoMetric.SetName("target_info")

dataPoint := targetInfoMetric.SetEmptyGauge().DataPoints().AppendEmpty()
dataPoint.SetIntValue(1)
dataPoint.SetTimestamp(pcommon.NewTimestampFromTime(time.Now()))
dataPoint.SetTimestamp(pcommon.NewTimestampFromTime(latestTime))

// copy Resource attributes to the metric except for attributes which will already be present in the MonitoredResource labels
rm.Resource().Attributes().Range(func(k string, v pcommon.Value) bool {
Expand Down Expand Up @@ -68,12 +120,14 @@ func AddScopeInfoMetric(m pmetric.Metrics) {
scopeInfoMetric.SetName("otel_scope_info")
dataPoint := scopeInfoMetric.SetEmptyGauge().DataPoints().AppendEmpty()
dataPoint.SetIntValue(1)
dataPoint.SetTimestamp(pcommon.NewTimestampFromTime(time.Now()))
sm.Scope().Attributes().Range(func(k string, v pcommon.Value) bool {
dataPoint.Attributes().PutStr(k, v.AsString())
return true
})

// Keep track of the most recent time in this scope's metrics
// Use that time for the timestamp of the new metric
latestTime := time.Time{}
for k := 0; k < sm.Metrics().Len(); k++ {
metric := sm.Metrics().At(k)
switch metric.Type() {
Expand All @@ -84,6 +138,9 @@ func AddScopeInfoMetric(m pmetric.Metrics) {
point := points.At(x)
point.Attributes().PutStr("otel_scope_name", sm.Scope().Name())
point.Attributes().PutStr("otel_scope_version", sm.Scope().Version())
if latestTime.Before(points.At(x).Timestamp().AsTime()) {
latestTime = points.At(x).Timestamp().AsTime()
}
}
case pmetric.MetricTypeGauge:
gauge := metric.Gauge()
Expand All @@ -92,6 +149,9 @@ func AddScopeInfoMetric(m pmetric.Metrics) {
point := points.At(x)
point.Attributes().PutStr("otel_scope_name", sm.Scope().Name())
point.Attributes().PutStr("otel_scope_version", sm.Scope().Version())
if latestTime.Before(points.At(x).Timestamp().AsTime()) {
latestTime = points.At(x).Timestamp().AsTime()
}
}
case pmetric.MetricTypeSummary:
summary := metric.Summary()
Expand All @@ -100,6 +160,9 @@ func AddScopeInfoMetric(m pmetric.Metrics) {
point := points.At(x)
point.Attributes().PutStr("otel_scope_name", sm.Scope().Name())
point.Attributes().PutStr("otel_scope_version", sm.Scope().Version())
if latestTime.Before(points.At(x).Timestamp().AsTime()) {
latestTime = points.At(x).Timestamp().AsTime()
}
}
case pmetric.MetricTypeHistogram:
hist := metric.Histogram()
Expand All @@ -108,6 +171,9 @@ func AddScopeInfoMetric(m pmetric.Metrics) {
point := points.At(x)
point.Attributes().PutStr("otel_scope_name", sm.Scope().Name())
point.Attributes().PutStr("otel_scope_version", sm.Scope().Version())
if latestTime.Before(points.At(x).Timestamp().AsTime()) {
latestTime = points.At(x).Timestamp().AsTime()
}
}
case pmetric.MetricTypeExponentialHistogram:
eh := metric.ExponentialHistogram()
Expand All @@ -116,9 +182,14 @@ func AddScopeInfoMetric(m pmetric.Metrics) {
point := points.At(x)
point.Attributes().PutStr("otel_scope_name", sm.Scope().Name())
point.Attributes().PutStr("otel_scope_version", sm.Scope().Version())
if latestTime.Before(points.At(x).Timestamp().AsTime()) {
latestTime = points.At(x).Timestamp().AsTime()
}
}
}
}

dataPoint.SetTimestamp(pcommon.NewTimestampFromTime(latestTime))
}
}
}
Expand Down
46 changes: 33 additions & 13 deletions exporter/collector/googlemanagedprometheus/extra_metrics_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,14 @@ package googlemanagedprometheus

import (
"testing"
"time"

"github.com/stretchr/testify/assert"
"go.opentelemetry.io/collector/pdata/pcommon"
"go.opentelemetry.io/collector/pdata/pmetric"
)

func testMetric() pmetric.Metrics {
func testMetric(timestamp time.Time) pmetric.Metrics {
metrics := pmetric.NewMetrics()
rm := metrics.ResourceMetrics().AppendEmpty()

Expand All @@ -38,10 +40,12 @@ func testMetric() pmetric.Metrics {
metric := sm.Metrics().AppendEmpty()
metric.SetName("baz-metric")
metric.SetEmptyGauge().DataPoints().AppendEmpty().SetIntValue(2112)
metric.Gauge().DataPoints().At(0).SetTimestamp(pcommon.NewTimestampFromTime(timestamp))
return metrics
}

func TestAddExtraMetrics(t *testing.T) {
timestamp := time.Now()
for _, tc := range []struct {
testFunc func(pmetric.Metrics) pmetric.ResourceMetricsSlice
input pmetric.Metrics
Expand All @@ -54,16 +58,17 @@ func TestAddExtraMetrics(t *testing.T) {
AddTargetInfoMetric(m)
return m.ResourceMetrics()
},
input: testMetric(),
input: testMetric(timestamp),
expected: func() pmetric.ResourceMetricsSlice {
metrics := testMetric().ResourceMetrics()
metrics := testMetric(timestamp).ResourceMetrics()

// Insert a new, empty ScopeMetricsSlice for this resource that will hold target_info
sm := metrics.At(0).ScopeMetrics().AppendEmpty()
metric := sm.Metrics().AppendEmpty()
metric.SetName("target_info")
metric.SetEmptyGauge().DataPoints().AppendEmpty().SetIntValue(1)
metric.Gauge().DataPoints().At(0).Attributes().PutStr("foo-label", "bar")
metric.Gauge().DataPoints().At(0).SetTimestamp(pcommon.NewTimestampFromTime(timestamp))
return metrics
}(),
},
Expand All @@ -73,9 +78,9 @@ func TestAddExtraMetrics(t *testing.T) {
AddScopeInfoMetric(m)
return m.ResourceMetrics()
},
input: testMetric(),
input: testMetric(timestamp),
expected: func() pmetric.ResourceMetricsSlice {
metrics := testMetric().ResourceMetrics()
metrics := testMetric(timestamp).ResourceMetrics()

// Insert the scope_info metric into the existing ScopeMetricsSlice
sm := metrics.At(0).ScopeMetrics().At(0)
Expand All @@ -88,6 +93,7 @@ func TestAddExtraMetrics(t *testing.T) {
metric := sm.Metrics().At(i)
metric.Gauge().DataPoints().At(0).Attributes().PutStr("otel_scope_name", "myscope")
metric.Gauge().DataPoints().At(0).Attributes().PutStr("otel_scope_version", "v0.0.1")
metric.Gauge().DataPoints().At(0).SetTimestamp(pcommon.NewTimestampFromTime(timestamp))
}
return metrics
}(),
Expand All @@ -99,12 +105,12 @@ func TestAddExtraMetrics(t *testing.T) {
return m.ResourceMetrics()
},
input: func() pmetric.Metrics {
metrics := testMetric()
metrics := testMetric(timestamp)
metrics.ResourceMetrics().At(0).ScopeMetrics().At(0).Scope().Attributes().PutStr("foo_attribute", "bar")
return metrics
}(),
expected: func() pmetric.ResourceMetricsSlice {
metrics := testMetric().ResourceMetrics()
metrics := testMetric(timestamp).ResourceMetrics()
metrics.At(0).ScopeMetrics().At(0).Scope().Attributes().PutStr("foo_attribute", "bar")

// Insert the scope_info metric into the existing ScopeMetricsSlice
Expand All @@ -119,6 +125,7 @@ func TestAddExtraMetrics(t *testing.T) {
metric := sm.Metrics().At(i)
metric.Gauge().DataPoints().At(0).Attributes().PutStr("otel_scope_name", "myscope")
metric.Gauge().DataPoints().At(0).Attributes().PutStr("otel_scope_version", "v0.0.1")
scopeInfoMetric.Gauge().DataPoints().At(0).SetTimestamp(pcommon.NewTimestampFromTime(timestamp))
}
return metrics
}(),
Expand All @@ -130,9 +137,9 @@ func TestAddExtraMetrics(t *testing.T) {
AddTargetInfoMetric(m)
return m.ResourceMetrics()
},
input: testMetric(),
input: testMetric(timestamp),
expected: func() pmetric.ResourceMetricsSlice {
metrics := testMetric().ResourceMetrics()
metrics := testMetric(timestamp).ResourceMetrics()
scopeMetrics := metrics.At(0).ScopeMetrics()

// Insert a new, empty ScopeMetricsSlice for this resource that will hold target_info
Expand All @@ -141,6 +148,7 @@ func TestAddExtraMetrics(t *testing.T) {
metric.SetName("target_info")
metric.SetEmptyGauge().DataPoints().AppendEmpty().SetIntValue(1)
metric.Gauge().DataPoints().At(0).Attributes().PutStr("foo-label", "bar")
metric.Gauge().DataPoints().At(0).SetTimestamp(pcommon.NewTimestampFromTime(timestamp))

// Insert the scope_info metric into the existing ScopeMetricsSlice
sm = scopeMetrics.At(0)
Expand All @@ -155,6 +163,7 @@ func TestAddExtraMetrics(t *testing.T) {
metric := sm.Metrics().At(i)
metric.Gauge().DataPoints().At(0).Attributes().PutStr("otel_scope_name", "myscope")
metric.Gauge().DataPoints().At(0).Attributes().PutStr("otel_scope_version", "v0.0.1")
metric.Gauge().DataPoints().At(0).SetTimestamp(pcommon.NewTimestampFromTime(timestamp))
}

return metrics
Expand All @@ -167,9 +176,9 @@ func TestAddExtraMetrics(t *testing.T) {
AddScopeInfoMetric(m)
return m.ResourceMetrics()
},
input: testMetric(),
input: testMetric(timestamp),
expected: func() pmetric.ResourceMetricsSlice {
metrics := testMetric().ResourceMetrics()
metrics := testMetric(timestamp).ResourceMetrics()
scopeMetrics := metrics.At(0).ScopeMetrics()

// Insert a new, empty ScopeMetricsSlice for this resource that will hold target_info
Expand All @@ -178,6 +187,7 @@ func TestAddExtraMetrics(t *testing.T) {
metric.SetName("target_info")
metric.SetEmptyGauge().DataPoints().AppendEmpty().SetIntValue(1)
metric.Gauge().DataPoints().At(0).Attributes().PutStr("foo-label", "bar")
metric.Gauge().DataPoints().At(0).SetTimestamp(pcommon.NewTimestampFromTime(timestamp))

// Insert the scope_info metric into the existing ScopeMetricsSlice
sm = scopeMetrics.At(0)
Expand All @@ -192,6 +202,7 @@ func TestAddExtraMetrics(t *testing.T) {
metric := sm.Metrics().At(i)
metric.Gauge().DataPoints().At(0).Attributes().PutStr("otel_scope_name", "myscope")
metric.Gauge().DataPoints().At(0).Attributes().PutStr("otel_scope_version", "v0.0.1")
metric.Gauge().DataPoints().At(0).SetTimestamp(pcommon.NewTimestampFromTime(timestamp))
}

return metrics
Expand All @@ -204,48 +215,57 @@ func TestAddExtraMetrics(t *testing.T) {
return m.ResourceMetrics()
},
input: func() pmetric.Metrics {
metrics := testMetric()
metrics := testMetric(timestamp)
sum := metrics.ResourceMetrics().At(0).ScopeMetrics().At(0).Metrics().AppendEmpty()
sum.SetName("sum-metric")
sum.SetEmptySum().DataPoints().AppendEmpty().SetIntValue(1234)
sum.Sum().DataPoints().At(0).SetTimestamp(pcommon.NewTimestampFromTime(timestamp))

summary := metrics.ResourceMetrics().At(0).ScopeMetrics().At(0).Metrics().AppendEmpty()
summary.SetName("summary-metric")
summary.SetEmptySummary().DataPoints().AppendEmpty().SetSum(float64(1.0))
summary.Summary().DataPoints().At(0).SetTimestamp(pcommon.NewTimestampFromTime(timestamp))

histogram := metrics.ResourceMetrics().At(0).ScopeMetrics().At(0).Metrics().AppendEmpty()
histogram.SetName("histogram-metric")
histogram.SetEmptyHistogram().DataPoints().AppendEmpty().StartTimestamp().AsTime().Year()
histogram.Histogram().DataPoints().At(0).SetTimestamp(pcommon.NewTimestampFromTime(timestamp))

expHistogram := metrics.ResourceMetrics().At(0).ScopeMetrics().At(0).Metrics().AppendEmpty()
expHistogram.SetName("exponential-histogram")
expHistogram.SetEmptyExponentialHistogram().DataPoints().AppendEmpty().StartTimestamp().AsTime().Year()
expHistogram.ExponentialHistogram().DataPoints().At(0).SetTimestamp(pcommon.NewTimestampFromTime(timestamp))
return metrics
}(),
expected: func() pmetric.ResourceMetricsSlice {
testMetrics := testMetric()
testMetrics := testMetric(timestamp)
sum := testMetrics.ResourceMetrics().At(0).ScopeMetrics().At(0).Metrics().AppendEmpty()
sum.SetName("sum-metric")
sum.SetEmptySum().DataPoints().AppendEmpty().SetIntValue(1234)
sum.Sum().DataPoints().At(0).SetTimestamp(pcommon.NewTimestampFromTime(timestamp))

summary := testMetrics.ResourceMetrics().At(0).ScopeMetrics().At(0).Metrics().AppendEmpty()
summary.SetName("summary-metric")
summary.SetEmptySummary().DataPoints().AppendEmpty().SetSum(float64(1.0))
summary.Summary().DataPoints().At(0).SetTimestamp(pcommon.NewTimestampFromTime(timestamp))

histogram := testMetrics.ResourceMetrics().At(0).ScopeMetrics().At(0).Metrics().AppendEmpty()
histogram.SetName("histogram-metric")
histogram.SetEmptyHistogram().DataPoints().AppendEmpty().StartTimestamp().AsTime().Year()
histogram.Histogram().DataPoints().At(0).SetTimestamp(pcommon.NewTimestampFromTime(timestamp))

expHistogram := testMetrics.ResourceMetrics().At(0).ScopeMetrics().At(0).Metrics().AppendEmpty()
expHistogram.SetName("exponential-histogram")
expHistogram.SetEmptyExponentialHistogram().DataPoints().AppendEmpty().StartTimestamp().AsTime().Year()
expHistogram.ExponentialHistogram().DataPoints().At(0).SetTimestamp(pcommon.NewTimestampFromTime(timestamp))

metrics := testMetrics.ResourceMetrics()
// Insert the scope_info metric into the existing ScopeMetricsSlice
sm := metrics.At(0).ScopeMetrics().At(0)
scopeInfoMetric := sm.Metrics().AppendEmpty()
scopeInfoMetric.SetName("otel_scope_info")
scopeInfoMetric.SetEmptyGauge().DataPoints().AppendEmpty().SetIntValue(1)
scopeInfoMetric.Gauge().DataPoints().At(0).SetTimestamp(pcommon.NewTimestampFromTime(timestamp))

// add otel_scope_* attributes to all metrics in this scope (including otel_scope_info)
for i := 0; i < sm.Metrics().Len(); i++ {
Expand Down

0 comments on commit 61a5514

Please sign in to comment.