Skip to content

Commit b6b334f

Browse files
authored
Metadata Telemetry scope allowlist (#14413)
1 parent 909bd48 commit b6b334f

File tree

6 files changed

+159
-2
lines changed

6 files changed

+159
-2
lines changed

docs/instrumentation-list.yaml

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -784,6 +784,37 @@ libraries:
784784
target_versions:
785785
javaagent:
786786
- com.linecorp.armeria:armeria-grpc:[1.14.0,)
787+
telemetry:
788+
- when: default
789+
spans:
790+
- span_kind: CLIENT
791+
attributes:
792+
- name: rpc.grpc.status_code
793+
type: LONG
794+
- name: rpc.method
795+
type: STRING
796+
- name: rpc.service
797+
type: STRING
798+
- name: rpc.system
799+
type: STRING
800+
- name: server.address
801+
type: STRING
802+
- name: server.port
803+
type: LONG
804+
- span_kind: SERVER
805+
attributes:
806+
- name: rpc.grpc.status_code
807+
type: LONG
808+
- name: rpc.method
809+
type: STRING
810+
- name: rpc.service
811+
type: STRING
812+
- name: rpc.system
813+
type: STRING
814+
- name: server.address
815+
type: STRING
816+
- name: server.port
817+
type: LONG
787818
async:
788819
- name: async-http-client-1.9
789820
description: This instrumentation enables CLIENT spans and metrics for version

instrumentation-docs/src/main/java/io/opentelemetry/instrumentation/docs/parsers/MetricParser.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,7 @@ public static Map<String, Map<String, AggregatedMetricInfo>> aggregateMetrics(
109109
aggregatedMetrics.computeIfAbsent(when, k -> new HashMap<>());
110110

111111
for (EmittedMetrics.MetricsByScope metricsByScope : metrics.getMetricsByScope()) {
112-
if (metricsByScope.getScope().equals(targetScopeName)) {
112+
if (TelemetryParser.scopeIsValid(metricsByScope.getScope(), targetScopeName)) {
113113
for (EmittedMetrics.Metric metric : metricsByScope.getMetrics()) {
114114
AggregatedMetricInfo aggInfo =
115115
metricKindMap.computeIfAbsent(

instrumentation-docs/src/main/java/io/opentelemetry/instrumentation/docs/parsers/SpanParser.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ public static Map<String, Map<String, Set<TelemetryAttribute>>> aggregateSpans(
8787
aggregatedAttributes.computeIfAbsent(when, k -> new HashMap<>());
8888

8989
for (EmittedSpans.SpansByScope spansByScope : spans.getSpansByScope()) {
90-
if (spansByScope.getScope().equals(targetScopeName)) {
90+
if (TelemetryParser.scopeIsValid(spansByScope.getScope(), targetScopeName)) {
9191
processSpansForScope(spansByScope, spanKindMap);
9292
}
9393
}
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
/*
2+
* Copyright The OpenTelemetry Authors
3+
* SPDX-License-Identifier: Apache-2.0
4+
*/
5+
6+
package io.opentelemetry.instrumentation.docs.parsers;
7+
8+
import java.util.Map;
9+
import java.util.Set;
10+
11+
class TelemetryParser {
12+
13+
// Key is the scope of the module being analyzed, value is a set of additional allowed scopes.
14+
private static final Map<String, Set<String>> scopeAllowList =
15+
Map.of("io.opentelemetry.armeria-grpc-1.14", Set.of("io.opentelemetry.grpc-1.6"));
16+
17+
/**
18+
* Checks if the given telemetry scope is valid for the specified module scope.
19+
*
20+
* <p>If an instrumentation module uses an instrumenter or telemetry class from another module, it
21+
* might report telemetry with a different scope name, resulting in us excluding it. There are
22+
* cases where we want to include this data, so we provide this way to override that exclusion
23+
* filter.
24+
*
25+
* @param telemetryScope the scope of the telemetry signal
26+
* @param moduleScope the scope of the module being analyzed
27+
* @return true if the telemetry scope is valid for the module, false otherwise
28+
*/
29+
static boolean scopeIsValid(String telemetryScope, String moduleScope) {
30+
return telemetryScope.equals(moduleScope)
31+
|| scopeAllowList.getOrDefault(moduleScope, Set.of()).contains(telemetryScope);
32+
}
33+
34+
private TelemetryParser() {}
35+
}

instrumentation-docs/src/test/java/io/opentelemetry/instrumentation/docs/parsers/MetricParserTest.java

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,31 @@ void testPreservesMetricMetadata() {
107107
assertThat(foundMetric.getUnit()).isEqualTo("unit");
108108
}
109109

110+
@Test
111+
void testScopeOverrideForGrpc() {
112+
String targetScopeName = "io.opentelemetry.armeria-grpc-1.14";
113+
114+
EmittedMetrics.Metric metric1 =
115+
createMetric("my.metric1", "description of my.metric1", "attr1");
116+
117+
EmittedMetrics.MetricsByScope targetMetricsByScope =
118+
new EmittedMetrics.MetricsByScope("io.opentelemetry.grpc-1.6", List.of(metric1));
119+
120+
EmittedMetrics emittedMetrics = new EmittedMetrics("default", List.of(targetMetricsByScope));
121+
122+
Map<String, Map<String, MetricParser.MetricAggregator.AggregatedMetricInfo>> metrics =
123+
MetricParser.MetricAggregator.aggregateMetrics("default", emittedMetrics, targetScopeName);
124+
125+
Map<String, List<EmittedMetrics.Metric>> result =
126+
MetricParser.MetricAggregator.buildFilteredMetrics(metrics);
127+
128+
EmittedMetrics.Metric foundMetric = result.get("default").get(0);
129+
assertThat(foundMetric.getName()).isEqualTo("my.metric1");
130+
assertThat(foundMetric.getDescription()).isEqualTo("description of my.metric1");
131+
assertThat(foundMetric.getType()).isEqualTo("gauge");
132+
assertThat(foundMetric.getUnit()).isEqualTo("unit");
133+
}
134+
110135
private static EmittedMetrics.Metric createMetric(
111136
String name, String description, String attrName) {
112137
return new EmittedMetrics.Metric(

instrumentation-docs/src/test/java/io/opentelemetry/instrumentation/docs/parsers/SpanParserTest.java

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -195,4 +195,70 @@ void testSpanAggregatorFiltersAndAggregatesCorrectly() {
195195
.extracting(TelemetryAttribute::getName)
196196
.containsExactly("my.operation");
197197
}
198+
199+
@Test
200+
void getSpansFromFilesIncludesAllowListedScopes(@TempDir Path tempDir) throws IOException {
201+
Path telemetryDir = Files.createDirectories(tempDir.resolve(".telemetry"));
202+
203+
String file1Content =
204+
"""
205+
when: default
206+
spans_by_scope:
207+
- scope: io.opentelemetry.grpc-1.6
208+
spans:
209+
- span_kind: CLIENT
210+
attributes:
211+
- name: rpc.system
212+
type: STRING
213+
- name: rpc.grpc.status_code
214+
type: LONG
215+
- name: server.port
216+
type: LONG
217+
- name: rpc.method
218+
type: STRING
219+
- name: rpc.service
220+
type: STRING
221+
- name: server.address
222+
type: STRING
223+
- span_kind: SERVER
224+
attributes:
225+
- name: rpc.system
226+
type: STRING
227+
- name: rpc.grpc.status_code
228+
type: LONG
229+
- name: server.port
230+
type: LONG
231+
- name: rpc.method
232+
type: STRING
233+
- name: rpc.service
234+
type: STRING
235+
- name: server.address
236+
type: STRING
237+
""";
238+
239+
Files.writeString(telemetryDir.resolve("spans-1.yaml"), file1Content);
240+
241+
try (MockedStatic<FileManager> fileManagerMock = mockStatic(FileManager.class)) {
242+
fileManagerMock
243+
.when(() -> FileManager.readFileToString(telemetryDir.resolve("spans-1.yaml").toString()))
244+
.thenReturn(file1Content);
245+
246+
Map<String, EmittedSpans> fileContents =
247+
EmittedSpanParser.getSpansByScopeFromFiles(tempDir.toString(), "");
248+
249+
EmittedSpans emittedSpans = fileContents.get("default");
250+
251+
// Aggregate spans - only target scope should be included
252+
Map<String, Map<String, Set<TelemetryAttribute>>> spans =
253+
SpanParser.SpanAggregator.aggregateSpans(
254+
"default", emittedSpans, "io.opentelemetry.armeria-grpc-1.14");
255+
256+
Map<String, List<EmittedSpans.Span>> result =
257+
SpanParser.SpanAggregator.buildFilteredSpans(spans);
258+
259+
assertThat(result.size()).isEqualTo(1);
260+
assertThat(result.get("default")).isNotNull();
261+
assertThat(result.get("default").size()).isEqualTo(2);
262+
}
263+
}
198264
}

0 commit comments

Comments
 (0)