Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 31 additions & 0 deletions docs/instrumentation-list.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -784,6 +784,37 @@ libraries:
target_versions:
javaagent:
- com.linecorp.armeria:armeria-grpc:[1.14.0,)
telemetry:
- when: default
spans:
- span_kind: CLIENT
attributes:
- name: rpc.grpc.status_code
type: LONG
- name: rpc.method
type: STRING
- name: rpc.service
type: STRING
- name: rpc.system
type: STRING
- name: server.address
type: STRING
- name: server.port
type: LONG
- span_kind: SERVER
attributes:
- name: rpc.grpc.status_code
type: LONG
- name: rpc.method
type: STRING
- name: rpc.service
type: STRING
- name: rpc.system
type: STRING
- name: server.address
type: STRING
- name: server.port
type: LONG
async:
- name: async-http-client-1.9
description: This instrumentation enables CLIENT spans and metrics for version
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
* This class is responsible for parsing metric files from the `.telemetry` directory of an
* instrumentation module and filtering them by scope.
*/
public class MetricParser {
public class MetricParser extends TelemetryParser {

/**
* Retrieves metrics for a given instrumentation module, filtered by scope.
Expand Down Expand Up @@ -109,7 +109,10 @@ public static Map<String, Map<String, AggregatedMetricInfo>> aggregateMetrics(
aggregatedMetrics.computeIfAbsent(when, k -> new HashMap<>());

for (EmittedMetrics.MetricsByScope metricsByScope : metrics.getMetricsByScope()) {
if (metricsByScope.getScope().equals(targetScopeName)) {
if (metricsByScope.getScope().equals(targetScopeName)
|| scopeAllowList
.getOrDefault(targetScopeName, Set.of())
.contains(metricsByScope.getScope())) {
for (EmittedMetrics.Metric metric : metricsByScope.getMetrics()) {
AggregatedMetricInfo aggInfo =
metricKindMap.computeIfAbsent(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
* This class is responsible for parsing span files from the `.telemetry` directory of an
* instrumentation module and filtering them by scope.
*/
public class SpanParser {
public class SpanParser extends TelemetryParser {

// We want to ignore test related attributes
private static final List<String> EXCLUDED_ATTRIBUTES =
Expand Down Expand Up @@ -87,7 +87,10 @@ public static Map<String, Map<String, Set<TelemetryAttribute>>> aggregateSpans(
aggregatedAttributes.computeIfAbsent(when, k -> new HashMap<>());

for (EmittedSpans.SpansByScope spansByScope : spans.getSpansByScope()) {
if (spansByScope.getScope().equals(targetScopeName)) {
if (spansByScope.getScope().equals(targetScopeName)
|| scopeAllowList
.getOrDefault(targetScopeName, Set.of())
.contains(spansByScope.getScope())) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd suggest not using inheritance for this

instead maybe something like (didn't think too much about names so feel free to pick others)

Suggested change
if (spansByScope.getScope().equals(targetScopeName)
|| scopeAllowList
.getOrDefault(targetScopeName, Set.of())
.contains(spansByScope.getScope())) {
if (AllowedScopes.contains(spansByScope, targetScopeName)) {

processSpansForScope(spansByScope, spanKindMap);
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/

package io.opentelemetry.instrumentation.docs.parsers;

import java.util.Map;
import java.util.Set;

abstract class TelemetryParser {

// If an instrumentation module uses an instrumenter or telemetry class from another module, it
// might report telemetry with a different scope name, resulting in us excluding it. There are
// cases where we want to include this data, so we provide this way to override that exclusion
// filter. The key is the scope of the module being analyzed, the value is a set of additional
// allowed scopes.
protected static final Map<String, Set<String>> scopeAllowList =
Map.of("io.opentelemetry.armeria-grpc-1.14", Set.of("io.opentelemetry.grpc-1.6"));
}
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,31 @@ void testPreservesMetricMetadata() {
assertThat(foundMetric.getUnit()).isEqualTo("unit");
}

@Test
void testScopeOverrideForGrpc() {
String targetScopeName = "io.opentelemetry.armeria-grpc-1.14";

EmittedMetrics.Metric metric1 =
createMetric("my.metric1", "description of my.metric1", "attr1");

EmittedMetrics.MetricsByScope targetMetricsByScope =
new EmittedMetrics.MetricsByScope("io.opentelemetry.grpc-1.6", List.of(metric1));

EmittedMetrics emittedMetrics = new EmittedMetrics("default", List.of(targetMetricsByScope));

Map<String, Map<String, MetricParser.MetricAggregator.AggregatedMetricInfo>> metrics =
MetricParser.MetricAggregator.aggregateMetrics("default", emittedMetrics, targetScopeName);

Map<String, List<EmittedMetrics.Metric>> result =
MetricParser.MetricAggregator.buildFilteredMetrics(metrics);

EmittedMetrics.Metric foundMetric = result.get("default").get(0);
assertThat(foundMetric.getName()).isEqualTo("my.metric1");
assertThat(foundMetric.getDescription()).isEqualTo("description of my.metric1");
assertThat(foundMetric.getType()).isEqualTo("gauge");
assertThat(foundMetric.getUnit()).isEqualTo("unit");
}

private static EmittedMetrics.Metric createMetric(
String name, String description, String attrName) {
return new EmittedMetrics.Metric(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -195,4 +195,70 @@ void testSpanAggregatorFiltersAndAggregatesCorrectly() {
.extracting(TelemetryAttribute::getName)
.containsExactly("my.operation");
}

@Test
void getSpansFromFilesIncludesAllowListedScopes(@TempDir Path tempDir) throws IOException {
Path telemetryDir = Files.createDirectories(tempDir.resolve(".telemetry"));

String file1Content =
"""
when: default
spans_by_scope:
- scope: io.opentelemetry.grpc-1.6
spans:
- span_kind: CLIENT
attributes:
- name: rpc.system
type: STRING
- name: rpc.grpc.status_code
type: LONG
- name: server.port
type: LONG
- name: rpc.method
type: STRING
- name: rpc.service
type: STRING
- name: server.address
type: STRING
- span_kind: SERVER
attributes:
- name: rpc.system
type: STRING
- name: rpc.grpc.status_code
type: LONG
- name: server.port
type: LONG
- name: rpc.method
type: STRING
- name: rpc.service
type: STRING
- name: server.address
type: STRING
""";

Files.writeString(telemetryDir.resolve("spans-1.yaml"), file1Content);

try (MockedStatic<FileManager> fileManagerMock = mockStatic(FileManager.class)) {
fileManagerMock
.when(() -> FileManager.readFileToString(telemetryDir.resolve("spans-1.yaml").toString()))
.thenReturn(file1Content);

Map<String, EmittedSpans> fileContents =
EmittedSpanParser.getSpansByScopeFromFiles(tempDir.toString(), "");

EmittedSpans emittedSpans = fileContents.get("default");

// Aggregate spans - only target scope should be included
Map<String, Map<String, Set<TelemetryAttribute>>> spans =
SpanParser.SpanAggregator.aggregateSpans(
"default", emittedSpans, "io.opentelemetry.armeria-grpc-1.14");

Map<String, List<EmittedSpans.Span>> result =
SpanParser.SpanAggregator.buildFilteredSpans(spans);

assertThat(result.size()).isEqualTo(1);
assertThat(result.get("default")).isNotNull();
assertThat(result.get("default").size()).isEqualTo(2);
}
}
}
Loading