Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
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 @@ -109,7 +109,7 @@ 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 (TelemetryParser.scopeIsValid(metricsByScope.getScope(), targetScopeName)) {
for (EmittedMetrics.Metric metric : metricsByScope.getMetrics()) {
AggregatedMetricInfo aggInfo =
metricKindMap.computeIfAbsent(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ 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 (TelemetryParser.scopeIsValid(spansByScope.getScope(), targetScopeName)) {
processSpansForScope(spansByScope, spanKindMap);
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/

package io.opentelemetry.instrumentation.docs.parsers;

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

class TelemetryParser {

// Key is the scope of the module being analyzed, value is a set of additional allowed scopes.
private static final Map<String, Set<String>> scopeAllowList =
Map.of("io.opentelemetry.armeria-grpc-1.14", Set.of("io.opentelemetry.grpc-1.6"));

/**
* Checks if the given telemetry scope is valid for the specified module scope.
*
* <p>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.
*
* @param telemetryScope the scope of the telemetry signal
* @param moduleScope the scope of the module being analyzed
* @return true if the telemetry scope is valid for the module, false otherwise
*/
static boolean scopeIsValid(String telemetryScope, String moduleScope) {
return telemetryScope.equals(moduleScope)
|| scopeAllowList.getOrDefault(moduleScope, Set.of()).contains(telemetryScope);
}

private TelemetryParser() {}
}
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