Skip to content

Commit 4521a4f

Browse files
authored
Add timestamp to scope_info and target_info GMP metrics (#585)
* Add timestamp to scope and target_info GMP metrics * make fixtures * Use latest metric timestamp for info metrics
1 parent e22e262 commit 4521a4f

4 files changed

Lines changed: 187 additions & 21 deletions

File tree

exporter/collector/googlemanagedprometheus/extra_metrics.go

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@
1515
package googlemanagedprometheus
1616

1717
import (
18+
"time"
19+
1820
"go.opentelemetry.io/collector/pdata/pcommon"
1921
"go.opentelemetry.io/collector/pdata/pmetric"
2022
)
@@ -29,12 +31,65 @@ func AddTargetInfoMetric(m pmetric.Metrics) {
2931
for i := 0; i < rms.Len(); i++ {
3032
rm := rms.At(i)
3133

34+
// Keep track of the most recent time in this resource's metrics
35+
// Use that time for the timestamp of the new metric
36+
latestTime := time.Time{}
37+
for j := 0; j < rm.ScopeMetrics().Len(); j++ {
38+
for k := 0; k < rm.ScopeMetrics().At(j).Metrics().Len(); k++ {
39+
metric := rm.ScopeMetrics().At(j).Metrics().At(k)
40+
41+
switch metric.Type() {
42+
case pmetric.MetricTypeSum:
43+
sum := metric.Sum()
44+
points := sum.DataPoints()
45+
for x := 0; x < points.Len(); x++ {
46+
if latestTime.Before(points.At(x).Timestamp().AsTime()) {
47+
latestTime = points.At(x).Timestamp().AsTime()
48+
}
49+
}
50+
case pmetric.MetricTypeGauge:
51+
gauge := metric.Gauge()
52+
points := gauge.DataPoints()
53+
for x := 0; x < points.Len(); x++ {
54+
if latestTime.Before(points.At(x).Timestamp().AsTime()) {
55+
latestTime = points.At(x).Timestamp().AsTime()
56+
}
57+
}
58+
case pmetric.MetricTypeSummary:
59+
summary := metric.Summary()
60+
points := summary.DataPoints()
61+
for x := 0; x < points.Len(); x++ {
62+
if latestTime.Before(points.At(x).Timestamp().AsTime()) {
63+
latestTime = points.At(x).Timestamp().AsTime()
64+
}
65+
}
66+
case pmetric.MetricTypeHistogram:
67+
hist := metric.Histogram()
68+
points := hist.DataPoints()
69+
for x := 0; x < points.Len(); x++ {
70+
if latestTime.Before(points.At(x).Timestamp().AsTime()) {
71+
latestTime = points.At(x).Timestamp().AsTime()
72+
}
73+
}
74+
case pmetric.MetricTypeExponentialHistogram:
75+
eh := metric.ExponentialHistogram()
76+
points := eh.DataPoints()
77+
for x := 0; x < points.Len(); x++ {
78+
if latestTime.Before(points.At(x).Timestamp().AsTime()) {
79+
latestTime = points.At(x).Timestamp().AsTime()
80+
}
81+
}
82+
}
83+
}
84+
}
85+
3286
// create the target_info metric as a Gauge with value 1
3387
targetInfoMetric := rm.ScopeMetrics().AppendEmpty().Metrics().AppendEmpty()
3488
targetInfoMetric.SetName("target_info")
3589

3690
dataPoint := targetInfoMetric.SetEmptyGauge().DataPoints().AppendEmpty()
3791
dataPoint.SetIntValue(1)
92+
dataPoint.SetTimestamp(pcommon.NewTimestampFromTime(latestTime))
3893

3994
// copy Resource attributes to the metric except for attributes which will already be present in the MonitoredResource labels
4095
rm.Resource().Attributes().Range(func(k string, v pcommon.Value) bool {
@@ -70,6 +125,9 @@ func AddScopeInfoMetric(m pmetric.Metrics) {
70125
return true
71126
})
72127

128+
// Keep track of the most recent time in this scope's metrics
129+
// Use that time for the timestamp of the new metric
130+
latestTime := time.Time{}
73131
for k := 0; k < sm.Metrics().Len(); k++ {
74132
metric := sm.Metrics().At(k)
75133
switch metric.Type() {
@@ -80,6 +138,9 @@ func AddScopeInfoMetric(m pmetric.Metrics) {
80138
point := points.At(x)
81139
point.Attributes().PutStr("otel_scope_name", sm.Scope().Name())
82140
point.Attributes().PutStr("otel_scope_version", sm.Scope().Version())
141+
if latestTime.Before(points.At(x).Timestamp().AsTime()) {
142+
latestTime = points.At(x).Timestamp().AsTime()
143+
}
83144
}
84145
case pmetric.MetricTypeGauge:
85146
gauge := metric.Gauge()
@@ -88,6 +149,9 @@ func AddScopeInfoMetric(m pmetric.Metrics) {
88149
point := points.At(x)
89150
point.Attributes().PutStr("otel_scope_name", sm.Scope().Name())
90151
point.Attributes().PutStr("otel_scope_version", sm.Scope().Version())
152+
if latestTime.Before(points.At(x).Timestamp().AsTime()) {
153+
latestTime = points.At(x).Timestamp().AsTime()
154+
}
91155
}
92156
case pmetric.MetricTypeSummary:
93157
summary := metric.Summary()
@@ -96,6 +160,9 @@ func AddScopeInfoMetric(m pmetric.Metrics) {
96160
point := points.At(x)
97161
point.Attributes().PutStr("otel_scope_name", sm.Scope().Name())
98162
point.Attributes().PutStr("otel_scope_version", sm.Scope().Version())
163+
if latestTime.Before(points.At(x).Timestamp().AsTime()) {
164+
latestTime = points.At(x).Timestamp().AsTime()
165+
}
99166
}
100167
case pmetric.MetricTypeHistogram:
101168
hist := metric.Histogram()
@@ -104,6 +171,9 @@ func AddScopeInfoMetric(m pmetric.Metrics) {
104171
point := points.At(x)
105172
point.Attributes().PutStr("otel_scope_name", sm.Scope().Name())
106173
point.Attributes().PutStr("otel_scope_version", sm.Scope().Version())
174+
if latestTime.Before(points.At(x).Timestamp().AsTime()) {
175+
latestTime = points.At(x).Timestamp().AsTime()
176+
}
107177
}
108178
case pmetric.MetricTypeExponentialHistogram:
109179
eh := metric.ExponentialHistogram()
@@ -112,9 +182,14 @@ func AddScopeInfoMetric(m pmetric.Metrics) {
112182
point := points.At(x)
113183
point.Attributes().PutStr("otel_scope_name", sm.Scope().Name())
114184
point.Attributes().PutStr("otel_scope_version", sm.Scope().Version())
185+
if latestTime.Before(points.At(x).Timestamp().AsTime()) {
186+
latestTime = points.At(x).Timestamp().AsTime()
187+
}
115188
}
116189
}
117190
}
191+
192+
dataPoint.SetTimestamp(pcommon.NewTimestampFromTime(latestTime))
118193
}
119194
}
120195
}

exporter/collector/googlemanagedprometheus/extra_metrics_test.go

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

1717
import (
1818
"testing"
19+
"time"
1920

2021
"github.com/stretchr/testify/assert"
22+
"go.opentelemetry.io/collector/pdata/pcommon"
2123
"go.opentelemetry.io/collector/pdata/pmetric"
2224
)
2325

24-
func testMetric() pmetric.Metrics {
26+
func testMetric(timestamp time.Time) pmetric.Metrics {
2527
metrics := pmetric.NewMetrics()
2628
rm := metrics.ResourceMetrics().AppendEmpty()
2729

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

4447
func TestAddExtraMetrics(t *testing.T) {
48+
timestamp := time.Now()
4549
for _, tc := range []struct {
4650
testFunc func(pmetric.Metrics) pmetric.ResourceMetricsSlice
4751
input pmetric.Metrics
@@ -54,16 +58,17 @@ func TestAddExtraMetrics(t *testing.T) {
5458
AddTargetInfoMetric(m)
5559
return m.ResourceMetrics()
5660
},
57-
input: testMetric(),
61+
input: testMetric(timestamp),
5862
expected: func() pmetric.ResourceMetricsSlice {
59-
metrics := testMetric().ResourceMetrics()
63+
metrics := testMetric(timestamp).ResourceMetrics()
6064

6165
// Insert a new, empty ScopeMetricsSlice for this resource that will hold target_info
6266
sm := metrics.At(0).ScopeMetrics().AppendEmpty()
6367
metric := sm.Metrics().AppendEmpty()
6468
metric.SetName("target_info")
6569
metric.SetEmptyGauge().DataPoints().AppendEmpty().SetIntValue(1)
6670
metric.Gauge().DataPoints().At(0).Attributes().PutStr("foo-label", "bar")
71+
metric.Gauge().DataPoints().At(0).SetTimestamp(pcommon.NewTimestampFromTime(timestamp))
6772
return metrics
6873
}(),
6974
},
@@ -73,9 +78,9 @@ func TestAddExtraMetrics(t *testing.T) {
7378
AddScopeInfoMetric(m)
7479
return m.ResourceMetrics()
7580
},
76-
input: testMetric(),
81+
input: testMetric(timestamp),
7782
expected: func() pmetric.ResourceMetricsSlice {
78-
metrics := testMetric().ResourceMetrics()
83+
metrics := testMetric(timestamp).ResourceMetrics()
7984

8085
// Insert the scope_info metric into the existing ScopeMetricsSlice
8186
sm := metrics.At(0).ScopeMetrics().At(0)
@@ -88,6 +93,7 @@ func TestAddExtraMetrics(t *testing.T) {
8893
metric := sm.Metrics().At(i)
8994
metric.Gauge().DataPoints().At(0).Attributes().PutStr("otel_scope_name", "myscope")
9095
metric.Gauge().DataPoints().At(0).Attributes().PutStr("otel_scope_version", "v0.0.1")
96+
metric.Gauge().DataPoints().At(0).SetTimestamp(pcommon.NewTimestampFromTime(timestamp))
9197
}
9298
return metrics
9399
}(),
@@ -99,12 +105,12 @@ func TestAddExtraMetrics(t *testing.T) {
99105
return m.ResourceMetrics()
100106
},
101107
input: func() pmetric.Metrics {
102-
metrics := testMetric()
108+
metrics := testMetric(timestamp)
103109
metrics.ResourceMetrics().At(0).ScopeMetrics().At(0).Scope().Attributes().PutStr("foo_attribute", "bar")
104110
return metrics
105111
}(),
106112
expected: func() pmetric.ResourceMetricsSlice {
107-
metrics := testMetric().ResourceMetrics()
113+
metrics := testMetric(timestamp).ResourceMetrics()
108114
metrics.At(0).ScopeMetrics().At(0).Scope().Attributes().PutStr("foo_attribute", "bar")
109115

110116
// Insert the scope_info metric into the existing ScopeMetricsSlice
@@ -119,6 +125,7 @@ func TestAddExtraMetrics(t *testing.T) {
119125
metric := sm.Metrics().At(i)
120126
metric.Gauge().DataPoints().At(0).Attributes().PutStr("otel_scope_name", "myscope")
121127
metric.Gauge().DataPoints().At(0).Attributes().PutStr("otel_scope_version", "v0.0.1")
128+
scopeInfoMetric.Gauge().DataPoints().At(0).SetTimestamp(pcommon.NewTimestampFromTime(timestamp))
122129
}
123130
return metrics
124131
}(),
@@ -130,9 +137,9 @@ func TestAddExtraMetrics(t *testing.T) {
130137
AddTargetInfoMetric(m)
131138
return m.ResourceMetrics()
132139
},
133-
input: testMetric(),
140+
input: testMetric(timestamp),
134141
expected: func() pmetric.ResourceMetricsSlice {
135-
metrics := testMetric().ResourceMetrics()
142+
metrics := testMetric(timestamp).ResourceMetrics()
136143
scopeMetrics := metrics.At(0).ScopeMetrics()
137144

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

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

160169
return metrics
@@ -167,9 +176,9 @@ func TestAddExtraMetrics(t *testing.T) {
167176
AddScopeInfoMetric(m)
168177
return m.ResourceMetrics()
169178
},
170-
input: testMetric(),
179+
input: testMetric(timestamp),
171180
expected: func() pmetric.ResourceMetricsSlice {
172-
metrics := testMetric().ResourceMetrics()
181+
metrics := testMetric(timestamp).ResourceMetrics()
173182
scopeMetrics := metrics.At(0).ScopeMetrics()
174183

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

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

197208
return metrics
@@ -204,48 +215,57 @@ func TestAddExtraMetrics(t *testing.T) {
204215
return m.ResourceMetrics()
205216
},
206217
input: func() pmetric.Metrics {
207-
metrics := testMetric()
218+
metrics := testMetric(timestamp)
208219
sum := metrics.ResourceMetrics().At(0).ScopeMetrics().At(0).Metrics().AppendEmpty()
209220
sum.SetName("sum-metric")
210221
sum.SetEmptySum().DataPoints().AppendEmpty().SetIntValue(1234)
222+
sum.Sum().DataPoints().At(0).SetTimestamp(pcommon.NewTimestampFromTime(timestamp))
211223

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

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

220234
expHistogram := metrics.ResourceMetrics().At(0).ScopeMetrics().At(0).Metrics().AppendEmpty()
221235
expHistogram.SetName("exponential-histogram")
222236
expHistogram.SetEmptyExponentialHistogram().DataPoints().AppendEmpty().StartTimestamp().AsTime().Year()
237+
expHistogram.ExponentialHistogram().DataPoints().At(0).SetTimestamp(pcommon.NewTimestampFromTime(timestamp))
223238
return metrics
224239
}(),
225240
expected: func() pmetric.ResourceMetricsSlice {
226-
testMetrics := testMetric()
241+
testMetrics := testMetric(timestamp)
227242
sum := testMetrics.ResourceMetrics().At(0).ScopeMetrics().At(0).Metrics().AppendEmpty()
228243
sum.SetName("sum-metric")
229244
sum.SetEmptySum().DataPoints().AppendEmpty().SetIntValue(1234)
245+
sum.Sum().DataPoints().At(0).SetTimestamp(pcommon.NewTimestampFromTime(timestamp))
230246

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

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

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

243262
metrics := testMetrics.ResourceMetrics()
244263
// Insert the scope_info metric into the existing ScopeMetricsSlice
245264
sm := metrics.At(0).ScopeMetrics().At(0)
246265
scopeInfoMetric := sm.Metrics().AppendEmpty()
247266
scopeInfoMetric.SetName("otel_scope_info")
248267
scopeInfoMetric.SetEmptyGauge().DataPoints().AppendEmpty().SetIntValue(1)
268+
scopeInfoMetric.Gauge().DataPoints().At(0).SetTimestamp(pcommon.NewTimestampFromTime(timestamp))
249269

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

exporter/collector/integrationtest/testcases/testcases_metrics.go

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ package testcases
1717
import (
1818
"strings"
1919

20+
"go.opentelemetry.io/collector/pdata/pmetric"
2021
"go.opentelemetry.io/otel/attribute"
2122
"go.opentelemetry.io/otel/sdk/metric/metricdata"
2223

@@ -133,12 +134,11 @@ var MetricsTestCases = []TestCase{
133134
cfg.MetricConfig.SkipCreateMetricDescriptor = true
134135
cfg.MetricConfig.GetMetricName = googlemanagedprometheus.GetMetricName
135136
cfg.MetricConfig.MapMonitoredResource = googlemanagedprometheus.MapToPrometheusTarget
136-
// TODO(#584): re-enable this portion of the test.
137-
// cfg.MetricConfig.ExtraMetrics = func(m pmetric.Metrics) pmetric.ResourceMetricsSlice {
138-
// googlemanagedprometheus.AddScopeInfoMetric(m)
139-
// googlemanagedprometheus.AddTargetInfoMetric(m)
140-
// return m.ResourceMetrics()
141-
// }
137+
cfg.MetricConfig.ExtraMetrics = func(m pmetric.Metrics) pmetric.ResourceMetricsSlice {
138+
googlemanagedprometheus.AddScopeInfoMetric(m)
139+
googlemanagedprometheus.AddTargetInfoMetric(m)
140+
return m.ResourceMetrics()
141+
}
142142
cfg.MetricConfig.InstrumentationLibraryLabels = false
143143
cfg.MetricConfig.ServiceResourceLabels = false
144144
cfg.MetricConfig.EnableSumOfSquaredDeviation = true

0 commit comments

Comments
 (0)