Skip to content

Commit 96beabd

Browse files
authored
Fix duplicate metrics in timeseries (#231)
* Fixes export error due to multiple metric points in TimeSeries * Cleanup debug statements * Fix formatting * Refactor: removes duplicate code * Updates test with expected instrumentation labels * Refactor: extract label values to final constants
1 parent e7876f0 commit 96beabd

File tree

2 files changed

+60
-39
lines changed

2 files changed

+60
-39
lines changed

exporters/metrics/src/main/java/com/google/cloud/opentelemetry/metric/AggregateByLabelMetricTimeSeriesBuilder.java

Lines changed: 54 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -22,17 +22,22 @@
2222
import static com.google.cloud.opentelemetry.metric.ResourceTranslator.mapResource;
2323

2424
import com.google.api.MetricDescriptor;
25+
import com.google.monitoring.v3.Point;
2526
import com.google.monitoring.v3.TimeSeries;
2627
import com.google.monitoring.v3.TypedValue;
28+
import io.opentelemetry.api.common.AttributeKey;
2729
import io.opentelemetry.api.common.Attributes;
30+
import io.opentelemetry.sdk.common.InstrumentationScopeInfo;
2831
import io.opentelemetry.sdk.metrics.data.DoublePointData;
2932
import io.opentelemetry.sdk.metrics.data.HistogramPointData;
3033
import io.opentelemetry.sdk.metrics.data.LongPointData;
3134
import io.opentelemetry.sdk.metrics.data.MetricData;
35+
import io.opentelemetry.sdk.metrics.data.PointData;
3236
import java.util.Collection;
3337
import java.util.HashMap;
3438
import java.util.List;
3539
import java.util.Map;
40+
import java.util.Objects;
3641
import java.util.stream.Collectors;
3742

3843
/**
@@ -41,6 +46,9 @@
4146
*/
4247
public final class AggregateByLabelMetricTimeSeriesBuilder implements MetricTimeSeriesBuilder {
4348

49+
public static final String LABEL_INSTRUMENTATION_LIBRARY_NAME = "instrumentation_source";
50+
public static final String LABEL_INSTRUMENTATION_LIBRARY_VERSION = "instrumentation_version";
51+
4452
private final Map<String, MetricDescriptor> descriptors = new HashMap<>();
4553
private final Map<MetricWithLabels, TimeSeries.Builder> pendingTimeSeries = new HashMap<>();
4654
private final String projectId;
@@ -52,58 +60,53 @@ public AggregateByLabelMetricTimeSeriesBuilder(String projectId, String prefix)
5260
}
5361

5462
@Override
55-
public void recordPoint(MetricData metric, LongPointData point) {
56-
MetricDescriptor descriptor = mapMetricDescriptor(this.prefix, metric, point);
57-
if (descriptor == null) {
58-
// Unsupported type.
59-
return;
60-
}
61-
descriptors.putIfAbsent(descriptor.getType(), descriptor);
62-
MetricWithLabels key = new MetricWithLabels(descriptor.getType(), point.getAttributes());
63-
// TODO: Check lastExportTime and ensure we don't send too often...
64-
pendingTimeSeries
65-
.computeIfAbsent(key, k -> makeTimeSeriesHeader(metric, point.getAttributes(), descriptor))
66-
.addPoints(
67-
com.google.monitoring.v3.Point.newBuilder()
68-
.setValue(TypedValue.newBuilder().setInt64Value(point.getValue()))
69-
.setInterval(mapInterval(point, metric))
70-
.build());
63+
public void recordPoint(MetricData metricData, LongPointData pointData) {
64+
recordPoint(
65+
metricData,
66+
pointData,
67+
Point.newBuilder()
68+
.setValue(TypedValue.newBuilder().setInt64Value(pointData.getValue()))
69+
.setInterval(mapInterval(pointData, metricData))
70+
.build());
7171
}
7272

7373
@Override
74-
public void recordPoint(MetricData metric, DoublePointData point) {
75-
MetricDescriptor descriptor = mapMetricDescriptor(this.prefix, metric, point);
76-
if (descriptor == null) {
77-
// Unsupported type.
78-
return;
79-
}
80-
descriptors.putIfAbsent(descriptor.getType(), descriptor);
81-
MetricWithLabels key = new MetricWithLabels(descriptor.getType(), point.getAttributes());
82-
// TODO: Check lastExportTime and ensure we don't send too often...
83-
pendingTimeSeries
84-
.computeIfAbsent(key, k -> makeTimeSeriesHeader(metric, point.getAttributes(), descriptor))
85-
.addPoints(
86-
com.google.monitoring.v3.Point.newBuilder()
87-
.setValue(TypedValue.newBuilder().setDoubleValue(point.getValue()))
88-
.setInterval(mapInterval(point, metric)));
74+
public void recordPoint(MetricData metricData, DoublePointData pointData) {
75+
recordPoint(
76+
metricData,
77+
pointData,
78+
Point.newBuilder()
79+
.setValue(TypedValue.newBuilder().setDoubleValue(pointData.getValue()))
80+
.setInterval(mapInterval(pointData, metricData))
81+
.build());
8982
}
9083

9184
@Override
92-
public void recordPoint(MetricData metric, HistogramPointData point) {
85+
public void recordPoint(MetricData metricData, HistogramPointData pointData) {
86+
recordPoint(
87+
metricData,
88+
pointData,
89+
Point.newBuilder()
90+
.setValue(
91+
TypedValue.newBuilder().setDistributionValue(mapDistribution(pointData, projectId)))
92+
.setInterval(mapInterval(pointData, metricData))
93+
.build());
94+
}
95+
96+
private void recordPoint(MetricData metric, PointData point, Point builtPoint) {
9397
MetricDescriptor descriptor = mapMetricDescriptor(this.prefix, metric, point);
9498
if (descriptor == null) {
9599
// Unsupported type.
96100
return;
97101
}
98102
descriptors.putIfAbsent(descriptor.getType(), descriptor);
99-
MetricWithLabels key = new MetricWithLabels(descriptor.getType(), point.getAttributes());
103+
Attributes metricAttributes =
104+
attachInstrumentationLibraryLabels(
105+
point.getAttributes(), metric.getInstrumentationScopeInfo());
106+
MetricWithLabels key = new MetricWithLabels(descriptor.getType(), metricAttributes);
100107
pendingTimeSeries
101-
.computeIfAbsent(key, k -> makeTimeSeriesHeader(metric, point.getAttributes(), descriptor))
102-
.addPoints(
103-
com.google.monitoring.v3.Point.newBuilder()
104-
.setValue(
105-
TypedValue.newBuilder().setDistributionValue(mapDistribution(point, projectId)))
106-
.setInterval(mapInterval(point, metric)));
108+
.computeIfAbsent(key, k -> makeTimeSeriesHeader(metric, metricAttributes, descriptor))
109+
.addPoints(builtPoint);
107110
}
108111

109112
private TimeSeries.Builder makeTimeSeriesHeader(
@@ -114,6 +117,18 @@ private TimeSeries.Builder makeTimeSeriesHeader(
114117
.setResource(mapResource(metric.getResource()));
115118
}
116119

120+
private Attributes attachInstrumentationLibraryLabels(
121+
Attributes attributes, InstrumentationScopeInfo instrumentationScopeInfo) {
122+
return attributes.toBuilder()
123+
.put(
124+
AttributeKey.stringKey(LABEL_INSTRUMENTATION_LIBRARY_NAME),
125+
instrumentationScopeInfo.getName())
126+
.put(
127+
AttributeKey.stringKey(LABEL_INSTRUMENTATION_LIBRARY_VERSION),
128+
Objects.requireNonNullElse(instrumentationScopeInfo.getVersion(), ""))
129+
.build();
130+
}
131+
117132
@Override
118133
public Collection<MetricDescriptor> getDescriptors() {
119134
return descriptors.values();

exporters/metrics/src/test/java/com/google/cloud/opentelemetry/metric/GoogleCloudMetricExporterTest.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@
1515
*/
1616
package com.google.cloud.opentelemetry.metric;
1717

18+
import static com.google.cloud.opentelemetry.metric.AggregateByLabelMetricTimeSeriesBuilder.LABEL_INSTRUMENTATION_LIBRARY_NAME;
19+
import static com.google.cloud.opentelemetry.metric.AggregateByLabelMetricTimeSeriesBuilder.LABEL_INSTRUMENTATION_LIBRARY_VERSION;
1820
import static com.google.cloud.opentelemetry.metric.FakeData.aCloudZone;
1921
import static com.google.cloud.opentelemetry.metric.FakeData.aDoubleSummaryPoint;
2022
import static com.google.cloud.opentelemetry.metric.FakeData.aFakeCredential;
@@ -190,6 +192,8 @@ public void testExportSucceeds() {
190192
.setType(expectedDescriptor.getType())
191193
.putLabels("label1", "value1")
192194
.putLabels("label2", "false")
195+
.putLabels(LABEL_INSTRUMENTATION_LIBRARY_NAME, "instrumentName")
196+
.putLabels(LABEL_INSTRUMENTATION_LIBRARY_VERSION, "0")
193197
.build())
194198
.addPoints(expectedPoint)
195199
.setMetricKind(expectedDescriptor.getMetricKind())
@@ -294,6 +298,8 @@ public void testExportWithHistogram_Succeeds() {
294298
Metric.newBuilder()
295299
.setType(expectedDescriptor.getType())
296300
.putLabels("test", "one")
301+
.putLabels("instrumentation_source", "instrumentName")
302+
.putLabels("instrumentation_version", "0")
297303
.build())
298304
.addPoints(expectedPoint)
299305
.setMetricKind(expectedDescriptor.getMetricKind())

0 commit comments

Comments
 (0)