Skip to content

Commit 6aa55ae

Browse files
committed
Migrate annotation instrumentation to declarative config API
1 parent 7b81e9f commit 6aa55ae

7 files changed

Lines changed: 97 additions & 8 deletions

File tree

instrumentation/opentelemetry-extension-annotations-1.0/javaagent/build.gradle.kts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,4 +39,16 @@ tasks {
3939
test {
4040
jvmArgs("-Dotel.instrumentation.opentelemetry-annotations.exclude-methods=io.opentelemetry.test.annotation.TracedWithSpan[ignored]")
4141
}
42+
43+
val testDeclarativeConfig by registering(Test::class) {
44+
testClassesDirs = sourceSets.test.get().output.classesDirs
45+
classpath = sourceSets.test.get().runtimeClasspath
46+
jvmArgs(
47+
"-Dotel.experimental.config.file=$projectDir/src/test/resources/declarative-config.yaml"
48+
)
49+
}
50+
51+
check {
52+
dependsOn(testDeclarativeConfig)
53+
}
4254
}

instrumentation/opentelemetry-extension-annotations-1.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/extensionannotations/WithSpanInstrumentation.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
import io.opentelemetry.context.Scope;
2323
import io.opentelemetry.instrumentation.api.annotation.support.async.AsyncOperationEndSupport;
2424
import io.opentelemetry.instrumentation.api.incubator.config.internal.DeclarativeConfigUtil;
25+
import io.opentelemetry.instrumentation.api.incubator.config.internal.ExtendedDeclarativeConfigProperties;
2526
import io.opentelemetry.instrumentation.api.instrumenter.Instrumenter;
2627
import io.opentelemetry.javaagent.extension.instrumentation.TypeInstrumentation;
2728
import io.opentelemetry.javaagent.extension.instrumentation.TypeTransformer;
@@ -97,10 +98,9 @@ static ElementMatcher.Junction<MethodDescription> configureExcludedMethods() {
9798
ElementMatcher.Junction<MethodDescription> result = none();
9899

99100
Map<String, Set<String>> excludedMethods =
100-
MethodsConfigurationParser.parse(
101+
MethodsConfigurationParser.parseExcludeMethods(
101102
DeclarativeConfigUtil.getInstrumentationConfig(
102-
GlobalOpenTelemetry.get(), "opentelemetry_extension_annotations")
103-
.getString("exclude_methods"));
103+
GlobalOpenTelemetry.get(), "opentelemetry_extension_annotations"));
104104
for (Map.Entry<String, Set<String>> entry : excludedMethods.entrySet()) {
105105
String className = entry.getKey();
106106
ElementMatcher.Junction<ByteCodeElement> matcher =
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
file_format: "1.0-rc.1"
2+
instrumentation/development:
3+
java:
4+
opentelemetry_extension_annotations:
5+
exclude_methods:
6+
- class: io.opentelemetry.test.annotation.TracedWithSpan
7+
methods:
8+
- ignored

instrumentation/opentelemetry-instrumentation-annotations-1.16/javaagent/build.gradle.kts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,4 +41,16 @@ tasks {
4141
test {
4242
jvmArgs("-Dotel.instrumentation.opentelemetry-instrumentation-annotations.exclude-methods=io.opentelemetry.test.annotation.TracedWithSpan[ignored]")
4343
}
44+
45+
val testDeclarativeConfig by registering(Test::class) {
46+
testClassesDirs = sourceSets.test.get().output.classesDirs
47+
classpath = sourceSets.test.get().runtimeClasspath
48+
jvmArgs(
49+
"-Dotel.experimental.config.file=$projectDir/src/test/resources/declarative-config.yaml"
50+
)
51+
}
52+
53+
check {
54+
dependsOn(testDeclarativeConfig)
55+
}
4456
}

instrumentation/opentelemetry-instrumentation-annotations-1.16/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/instrumentationannotations/AnnotationExcludedMethods.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111

1212
import io.opentelemetry.api.GlobalOpenTelemetry;
1313
import io.opentelemetry.instrumentation.api.incubator.config.internal.DeclarativeConfigUtil;
14+
import io.opentelemetry.instrumentation.api.incubator.config.internal.ExtendedDeclarativeConfigProperties;
1415
import io.opentelemetry.javaagent.tooling.config.MethodsConfigurationParser;
1516
import java.util.Map;
1617
import java.util.Set;
@@ -29,10 +30,9 @@ public static ElementMatcher.Junction<MethodDescription> configureExcludedMethod
2930
ElementMatcher.Junction<MethodDescription> result = none();
3031

3132
Map<String, Set<String>> excludedMethods =
32-
MethodsConfigurationParser.parse(
33+
MethodsConfigurationParser.parseExcludeMethods(
3334
DeclarativeConfigUtil.getInstrumentationConfig(
34-
GlobalOpenTelemetry.get(), "opentelemetry_instrumentation_annotations")
35-
.getString("exclude_methods"));
35+
GlobalOpenTelemetry.get(), "opentelemetry_instrumentation_annotations"));
3636
for (Map.Entry<String, Set<String>> entry : excludedMethods.entrySet()) {
3737
String className = entry.getKey();
3838
ElementMatcher.Junction<ByteCodeElement> matcher =
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
file_format: "1.0-rc.1"
2+
instrumentation/development:
3+
java:
4+
opentelemetry_instrumentation_annotations:
5+
exclude_methods:
6+
- class: io.opentelemetry.test.annotation.TracedWithSpan
7+
methods:
8+
- ignored

javaagent-tooling/src/main/java/io/opentelemetry/javaagent/tooling/config/MethodsConfigurationParser.java

Lines changed: 51 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,20 @@
55

66
package io.opentelemetry.javaagent.tooling.config;
77

8+
import static java.util.Collections.emptyList;
9+
import static java.util.Collections.emptyMap;
810
import static java.util.logging.Level.WARNING;
911

12+
import io.opentelemetry.api.incubator.config.DeclarativeConfigProperties;
13+
import io.opentelemetry.instrumentation.api.incubator.config.internal.ExtendedDeclarativeConfigProperties;
1014
import java.util.Collections;
1115
import java.util.HashMap;
1216
import java.util.HashSet;
17+
import java.util.List;
1318
import java.util.Map;
1419
import java.util.Set;
1520
import java.util.logging.Logger;
21+
import java.util.stream.Collectors;
1622

1723
public final class MethodsConfigurationParser {
1824

@@ -23,6 +29,49 @@ public final class MethodsConfigurationParser {
2329
private static final String CONFIG_FORMAT =
2430
PACKAGE_CLASS_NAME_REGEX + "(?:\\[" + METHOD_LIST_REGEX + "])?";
2531

32+
/**
33+
* Parse exclude methods configuration from declarative config.
34+
*
35+
* <p>First tries structured declarative config (YAML format), then falls back to old string/list
36+
* property format for backward compatibility.
37+
*
38+
* <p>Example YAML structure:
39+
*
40+
* <pre>{@code
41+
* exclude_methods:
42+
* - class: com.example.MyClass
43+
* methods: [method1, method2]
44+
* - class: com.example.AnotherClass
45+
* methods: [someMethod]
46+
* }</pre>
47+
*/
48+
public static Map<String, Set<String>> parseExcludeMethods(
49+
ExtendedDeclarativeConfigProperties config) {
50+
// First try structured declarative config (YAML format)
51+
List<DeclarativeConfigProperties> excludeList = config.getStructuredList("exclude_methods");
52+
if (excludeList != null) {
53+
return excludeList.stream()
54+
.filter(
55+
entry -> {
56+
String className = entry.getString("class");
57+
return className != null && !className.isEmpty();
58+
})
59+
.collect(
60+
Collectors.toMap(
61+
entry -> entry.getString("class"),
62+
entry ->
63+
new HashSet<>(entry.getScalarList("methods", String.class, emptyList()))));
64+
}
65+
66+
// Fall back to old string property format for backward compatibility
67+
String excludeMethodsString = config.getString("exclude_methods");
68+
if (excludeMethodsString != null) {
69+
return parse(excludeMethodsString);
70+
}
71+
72+
return emptyMap();
73+
}
74+
2675
/**
2776
* This method takes a string in a form of {@code
2877
* "io.package.ClassName[method1,method2];my.example[someMethodName];"} and returns a map where
@@ -32,13 +81,13 @@ public final class MethodsConfigurationParser {
3281
*/
3382
public static Map<String, Set<String>> parse(String configString) {
3483
if (configString == null || configString.trim().isEmpty()) {
35-
return Collections.emptyMap();
84+
return emptyMap();
3685
} else if (!validateConfigString(configString)) {
3786
logger.log(
3887
WARNING,
3988
"Invalid trace method config \"{0}\". Must match 'package.Class$Name[method1,method2];*'.",
4089
configString);
41-
return Collections.emptyMap();
90+
return emptyMap();
4291
} else {
4392
Map<String, Set<String>> toTrace = new HashMap<>();
4493
String[] classMethods = configString.split(";", -1);

0 commit comments

Comments
 (0)