Skip to content

Commit 44b28c8

Browse files
committed
cleanup
1 parent 5d4095b commit 44b28c8

File tree

2 files changed

+146
-160
lines changed

2 files changed

+146
-160
lines changed

exporters/prometheus/src/main/java/io/opentelemetry/exporter/prometheus/Otel2PrometheusConverter.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -672,7 +672,8 @@ private static String toLabelValue(AttributeType type, Object attributeValue) {
672672

673673
public static String toJsonStr(List<?> attributeValue) {
674674
StringJoiner joiner = new StringJoiner(",", "[", "]");
675-
for (Object value : attributeValue) {
675+
for (int i = 0; i < attributeValue.size(); i++) {
676+
Object value = attributeValue.get(i);
676677
joiner.add(value instanceof String ? toJsonValidStr((String) value) : String.valueOf(value));
677678
}
678679
return joiner.toString();

exporters/prometheus/src/test/java/io/opentelemetry/exporter/prometheus/Otel2PrometheusConverterTest.java

Lines changed: 144 additions & 159 deletions
Original file line numberDiff line numberDiff line change
@@ -91,165 +91,6 @@ void metricMetadata(
9191
assertThat(matcher.group("metricName")).isEqualTo(expectedMetricName);
9292
}
9393

94-
@ParameterizedTest
95-
@MethodSource("resourceAttributesAdditionArgs")
96-
void resourceAttributesAddition(
97-
MetricData metricData,
98-
@Nullable Predicate<String> allowedResourceAttributesFilter,
99-
String metricName,
100-
String expectedMetricLabels)
101-
throws IOException {
102-
103-
Otel2PrometheusConverter converter =
104-
new Otel2PrometheusConverter(true, allowedResourceAttributesFilter);
105-
106-
ByteArrayOutputStream out = new ByteArrayOutputStream();
107-
MetricSnapshots snapshots = converter.convert(Collections.singletonList(metricData));
108-
ExpositionFormats.init().getPrometheusTextFormatWriter().write(out, snapshots);
109-
String expositionFormat = new String(out.toByteArray(), StandardCharsets.UTF_8);
110-
111-
// extract the only metric line
112-
List<String> metricLines =
113-
Arrays.stream(expositionFormat.split("\n"))
114-
.filter(line -> line.startsWith(metricName))
115-
.collect(Collectors.toList());
116-
assertThat(metricLines).hasSize(1);
117-
String metricLine = metricLines.get(0);
118-
119-
String metricLabels =
120-
metricLine.substring(metricLine.indexOf("{") + 1, metricLine.indexOf("}"));
121-
assertThat(metricLabels).isEqualTo(expectedMetricLabels);
122-
}
123-
124-
@Test
125-
void prometheusNameCollisionTest_Issue6277() {
126-
// NOTE: Metrics with the same resolved prometheus name should merge. However,
127-
// Otel2PrometheusConverter is not responsible for merging individual series, so the merge will
128-
// fail if the two different metrics contain overlapping series. Users should deal with this by
129-
// adding a view that renames one of the two metrics such that the conflict does not occur.
130-
MetricData dotName =
131-
createSampleMetricData(
132-
"my.metric",
133-
"units",
134-
MetricDataType.LONG_SUM,
135-
Attributes.builder().put("key", "a").build(),
136-
Resource.create(Attributes.empty()));
137-
MetricData underscoreName =
138-
createSampleMetricData(
139-
"my_metric",
140-
"units",
141-
MetricDataType.LONG_SUM,
142-
Attributes.builder().put("key", "b").build(),
143-
Resource.create(Attributes.empty()));
144-
145-
List<MetricData> metricData = new ArrayList<>();
146-
metricData.add(dotName);
147-
metricData.add(underscoreName);
148-
149-
assertThatCode(() -> converter.convert(metricData)).doesNotThrowAnyException();
150-
}
151-
152-
@ParameterizedTest
153-
@MethodSource("labelValueSerializationArgs")
154-
void labelValueSerialization(Attributes attributes) {
155-
MetricData metricData =
156-
createSampleMetricData("sample", "1", MetricDataType.LONG_SUM, attributes, null);
157-
158-
MetricSnapshots snapshots = converter.convert(Collections.singletonList(metricData));
159-
160-
Labels labels = snapshots.get(0).getDataPoints().get(0).getLabels();
161-
attributes.forEach(
162-
(key, value) -> {
163-
String labelValue = labels.get(key.getKey());
164-
try {
165-
String expectedValue =
166-
key.getType() == AttributeType.STRING
167-
? (String) value
168-
: OBJECT_MAPPER.writeValueAsString(value);
169-
assertThat(labelValue).isEqualTo(expectedValue);
170-
} catch (JsonProcessingException e) {
171-
throw new RuntimeException(e);
172-
}
173-
});
174-
}
175-
176-
@Test
177-
void labelValueSerialization_Should_Handle_All_AttributeTypes() {
178-
assertThat(Stream.of(AttributeType.values()).map(Enum::name))
179-
.isEqualTo(
180-
Arrays.asList(
181-
"STRING",
182-
"BOOLEAN",
183-
"LONG",
184-
"DOUBLE",
185-
"STRING_ARRAY",
186-
"BOOLEAN_ARRAY",
187-
"LONG_ARRAY",
188-
"DOUBLE_ARRAY"));
189-
}
190-
191-
private static Stream<Arguments> resourceAttributesAdditionArgs() {
192-
List<Arguments> arguments = new ArrayList<>();
193-
194-
for (MetricDataType metricDataType : MetricDataType.values()) {
195-
// Check that resource attributes are added as labels, according to allowed pattern
196-
arguments.add(
197-
Arguments.of(
198-
createSampleMetricData(
199-
"my.metric",
200-
"units",
201-
metricDataType,
202-
Attributes.of(stringKey("foo1"), "bar1", stringKey("foo2"), "bar2"),
203-
Resource.create(
204-
Attributes.of(
205-
stringKey("host"), "localhost", stringKey("cluster"), "mycluster"))),
206-
/* allowedResourceAttributesFilter= */ Predicates.startsWith("clu"),
207-
metricDataType == MetricDataType.SUMMARY
208-
|| metricDataType == MetricDataType.HISTOGRAM
209-
|| metricDataType == MetricDataType.EXPONENTIAL_HISTOGRAM
210-
? "my_metric_units_count"
211-
: "my_metric_units",
212-
213-
// "cluster" attribute is added (due to reg expr specified) and only it
214-
"cluster=\"mycluster\",foo1=\"bar1\",foo2=\"bar2\",otel_scope_name=\"scope\""));
215-
}
216-
217-
// Resource attributes which also exists in the metric labels are not added twice
218-
arguments.add(
219-
Arguments.of(
220-
createSampleMetricData(
221-
"my.metric",
222-
"units",
223-
MetricDataType.LONG_SUM,
224-
Attributes.of(stringKey("cluster"), "mycluster2", stringKey("foo2"), "bar2"),
225-
Resource.create(
226-
Attributes.of(
227-
stringKey("host"), "localhost", stringKey("cluster"), "mycluster"))),
228-
/* allowedResourceAttributesFilter= */ Predicates.startsWith("clu"),
229-
"my_metric_units",
230-
231-
// "cluster" attribute is present only once and the value is taken
232-
// from the metric attributes and not the resource attributes
233-
"cluster=\"mycluster2\",foo2=\"bar2\",otel_scope_name=\"scope\""));
234-
235-
// Empty attributes
236-
arguments.add(
237-
Arguments.of(
238-
createSampleMetricData(
239-
"my.metric",
240-
"units",
241-
MetricDataType.LONG_SUM,
242-
Attributes.empty(),
243-
Resource.create(
244-
Attributes.of(
245-
stringKey("host"), "localhost", stringKey("cluster"), "mycluster"))),
246-
/* allowedResourceAttributesFilter= */ Predicates.startsWith("clu"),
247-
"my_metric_units",
248-
"cluster=\"mycluster\",otel_scope_name=\"scope\""));
249-
250-
return arguments.stream();
251-
}
252-
25394
private static Stream<Arguments> metricMetadataArgs() {
25495
return Stream.of(
25596
// the unity unit "1" is translated to "ratio"
@@ -345,6 +186,150 @@ private static Stream<Arguments> metricMetadataArgs() {
345186
"_metric_name_bytes_count"));
346187
}
347188

189+
@ParameterizedTest
190+
@MethodSource("resourceAttributesAdditionArgs")
191+
void resourceAttributesAddition(
192+
MetricData metricData,
193+
@Nullable Predicate<String> allowedResourceAttributesFilter,
194+
String metricName,
195+
String expectedMetricLabels)
196+
throws IOException {
197+
198+
Otel2PrometheusConverter converter =
199+
new Otel2PrometheusConverter(true, allowedResourceAttributesFilter);
200+
201+
ByteArrayOutputStream out = new ByteArrayOutputStream();
202+
MetricSnapshots snapshots = converter.convert(Collections.singletonList(metricData));
203+
ExpositionFormats.init().getPrometheusTextFormatWriter().write(out, snapshots);
204+
String expositionFormat = new String(out.toByteArray(), StandardCharsets.UTF_8);
205+
206+
// extract the only metric line
207+
List<String> metricLines =
208+
Arrays.stream(expositionFormat.split("\n"))
209+
.filter(line -> line.startsWith(metricName))
210+
.collect(Collectors.toList());
211+
assertThat(metricLines).hasSize(1);
212+
String metricLine = metricLines.get(0);
213+
214+
String metricLabels =
215+
metricLine.substring(metricLine.indexOf("{") + 1, metricLine.indexOf("}"));
216+
assertThat(metricLabels).isEqualTo(expectedMetricLabels);
217+
}
218+
219+
private static Stream<Arguments> resourceAttributesAdditionArgs() {
220+
List<Arguments> arguments = new ArrayList<>();
221+
222+
for (MetricDataType metricDataType : MetricDataType.values()) {
223+
// Check that resource attributes are added as labels, according to allowed pattern
224+
arguments.add(
225+
Arguments.of(
226+
createSampleMetricData(
227+
"my.metric",
228+
"units",
229+
metricDataType,
230+
Attributes.of(stringKey("foo1"), "bar1", stringKey("foo2"), "bar2"),
231+
Resource.create(
232+
Attributes.of(
233+
stringKey("host"), "localhost", stringKey("cluster"), "mycluster"))),
234+
/* allowedResourceAttributesFilter= */ Predicates.startsWith("clu"),
235+
metricDataType == MetricDataType.SUMMARY
236+
|| metricDataType == MetricDataType.HISTOGRAM
237+
|| metricDataType == MetricDataType.EXPONENTIAL_HISTOGRAM
238+
? "my_metric_units_count"
239+
: "my_metric_units",
240+
241+
// "cluster" attribute is added (due to reg expr specified) and only it
242+
"cluster=\"mycluster\",foo1=\"bar1\",foo2=\"bar2\",otel_scope_name=\"scope\""));
243+
}
244+
245+
// Resource attributes which also exists in the metric labels are not added twice
246+
arguments.add(
247+
Arguments.of(
248+
createSampleMetricData(
249+
"my.metric",
250+
"units",
251+
MetricDataType.LONG_SUM,
252+
Attributes.of(stringKey("cluster"), "mycluster2", stringKey("foo2"), "bar2"),
253+
Resource.create(
254+
Attributes.of(
255+
stringKey("host"), "localhost", stringKey("cluster"), "mycluster"))),
256+
/* allowedResourceAttributesFilter= */ Predicates.startsWith("clu"),
257+
"my_metric_units",
258+
259+
// "cluster" attribute is present only once and the value is taken
260+
// from the metric attributes and not the resource attributes
261+
"cluster=\"mycluster2\",foo2=\"bar2\",otel_scope_name=\"scope\""));
262+
263+
// Empty attributes
264+
arguments.add(
265+
Arguments.of(
266+
createSampleMetricData(
267+
"my.metric",
268+
"units",
269+
MetricDataType.LONG_SUM,
270+
Attributes.empty(),
271+
Resource.create(
272+
Attributes.of(
273+
stringKey("host"), "localhost", stringKey("cluster"), "mycluster"))),
274+
/* allowedResourceAttributesFilter= */ Predicates.startsWith("clu"),
275+
"my_metric_units",
276+
"cluster=\"mycluster\",otel_scope_name=\"scope\""));
277+
278+
return arguments.stream();
279+
}
280+
281+
@Test
282+
void prometheusNameCollisionTest_Issue6277() {
283+
// NOTE: Metrics with the same resolved prometheus name should merge. However,
284+
// Otel2PrometheusConverter is not responsible for merging individual series, so the merge will
285+
// fail if the two different metrics contain overlapping series. Users should deal with this by
286+
// adding a view that renames one of the two metrics such that the conflict does not occur.
287+
MetricData dotName =
288+
createSampleMetricData(
289+
"my.metric",
290+
"units",
291+
MetricDataType.LONG_SUM,
292+
Attributes.builder().put("key", "a").build(),
293+
Resource.create(Attributes.empty()));
294+
MetricData underscoreName =
295+
createSampleMetricData(
296+
"my_metric",
297+
"units",
298+
MetricDataType.LONG_SUM,
299+
Attributes.builder().put("key", "b").build(),
300+
Resource.create(Attributes.empty()));
301+
302+
List<MetricData> metricData = new ArrayList<>();
303+
metricData.add(dotName);
304+
metricData.add(underscoreName);
305+
306+
assertThatCode(() -> converter.convert(metricData)).doesNotThrowAnyException();
307+
}
308+
309+
@ParameterizedTest
310+
@MethodSource("labelValueSerializationArgs")
311+
void labelValueSerialization(Attributes attributes) {
312+
MetricData metricData =
313+
createSampleMetricData("sample", "1", MetricDataType.LONG_SUM, attributes, null);
314+
315+
MetricSnapshots snapshots = converter.convert(Collections.singletonList(metricData));
316+
317+
Labels labels = snapshots.get(0).getDataPoints().get(0).getLabels();
318+
attributes.forEach(
319+
(key, value) -> {
320+
String labelValue = labels.get(key.getKey());
321+
try {
322+
String expectedValue =
323+
key.getType() == AttributeType.STRING
324+
? (String) value
325+
: OBJECT_MAPPER.writeValueAsString(value);
326+
assertThat(labelValue).isEqualTo(expectedValue);
327+
} catch (JsonProcessingException e) {
328+
throw new RuntimeException(e);
329+
}
330+
});
331+
}
332+
348333
private static Stream<Arguments> labelValueSerializationArgs() {
349334
return Stream.of(
350335
Arguments.of(Attributes.of(stringKey("key"), "stringValue")),

0 commit comments

Comments
 (0)