Skip to content

Commit a439e4b

Browse files
lauritzeitlinger
authored andcommitted
Method instrumentation
1 parent 64a18fe commit a439e4b

File tree

3 files changed

+39
-31
lines changed

3 files changed

+39
-31
lines changed

instrumentation/methods/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/methods/MethodInstrumentation.java

Lines changed: 22 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -23,19 +23,19 @@
2323
import io.opentelemetry.instrumentation.api.incubator.semconv.util.ClassAndMethod;
2424
import io.opentelemetry.javaagent.extension.instrumentation.TypeInstrumentation;
2525
import io.opentelemetry.javaagent.extension.instrumentation.TypeTransformer;
26+
import java.util.Collection;
2627
import java.util.Map;
2728
import net.bytebuddy.asm.Advice;
2829
import net.bytebuddy.description.enumeration.EnumerationDescription;
2930
import net.bytebuddy.description.type.TypeDescription;
3031
import net.bytebuddy.implementation.bytecode.assign.Assigner;
3132
import net.bytebuddy.matcher.ElementMatcher;
3233

33-
@SuppressWarnings("EnumOrdinal")
3434
public class MethodInstrumentation implements TypeInstrumentation {
3535
private final String className;
36-
private final Map<String, SpanKind> methodNames;
36+
private final Map<SpanKind, Collection<String>> methodNames;
3737

38-
public MethodInstrumentation(String className, Map<String, SpanKind> methodNames) {
38+
public MethodInstrumentation(String className, Map<SpanKind, Collection<String>> methodNames) {
3939
this.className = className;
4040
this.methodNames = methodNames;
4141
}
@@ -63,36 +63,37 @@ public ElementMatcher<TypeDescription> typeMatcher() {
6363

6464
@Override
6565
public void transform(TypeTransformer transformer) {
66-
transformer.applyAdviceToMethod(
67-
namedOneOf(methodNames.keySet().toArray(new String[0])).and(isMethod()),
68-
mapping ->
69-
mapping
70-
.bind(
71-
MethodReturnType.class,
72-
(instrumentedType, instrumentedMethod, assigner, argumentHandler, sort) ->
73-
Advice.OffsetMapping.Target.ForStackManipulation.of(
74-
instrumentedMethod.getReturnType().asErasure()))
75-
.bind(
76-
SpanKindOrdinal.class,
77-
(instrumentedType, instrumentedMethod, assigner, argumentHandler, sort) ->
78-
Advice.OffsetMapping.Target.ForStackManipulation.of(
79-
new EnumerationDescription.ForLoadedEnumeration(
80-
methodNames.get(instrumentedMethod.getName())))),
81-
MethodInstrumentation.class.getName() + "$MethodAdvice");
66+
for (Map.Entry<SpanKind, Collection<String>> entry : methodNames.entrySet()) {
67+
SpanKind spanKind = entry.getKey();
68+
Collection<String> names = entry.getValue();
69+
transformer.applyAdviceToMethod(
70+
namedOneOf(names.toArray(new String[0])).and(isMethod()),
71+
mapping ->
72+
mapping
73+
.bind(
74+
MethodReturnType.class,
75+
(instrumentedType, instrumentedMethod, assigner, argumentHandler, sort) ->
76+
Advice.OffsetMapping.Target.ForStackManipulation.of(
77+
instrumentedMethod.getReturnType().asErasure()))
78+
.bind(
79+
MethodSpanKind.class,
80+
new EnumerationDescription.ForLoadedEnumeration(spanKind)),
81+
MethodInstrumentation.class.getName() + "$MethodAdvice");
82+
}
8283
}
8384

8485
// custom annotation that represents the return type of the method
8586
@interface MethodReturnType {}
8687

8788
// custom annotation that represents the SpanKind of the method
88-
@interface SpanKindOrdinal {}
89+
@interface MethodSpanKind {}
8990

9091
@SuppressWarnings("unused")
9192
public static class MethodAdvice {
9293

9394
@Advice.OnMethodEnter(suppress = Throwable.class)
9495
public static void onEnter(
95-
@SpanKindOrdinal SpanKind spanKind,
96+
@MethodSpanKind SpanKind spanKind,
9697
@Advice.Origin("#t") Class<?> declaringClass,
9798
@Advice.Origin("#m") String methodName,
9899
@Advice.Local("otelMethod") MethodAndType classAndMethod,

instrumentation/methods/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/methods/MethodInstrumentationModule.java

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,17 @@
55

66
package io.opentelemetry.javaagent.instrumentation.methods;
77

8+
import static java.util.Collections.emptyList;
9+
import static java.util.Collections.singletonList;
10+
import static java.util.Collections.singletonMap;
11+
812
import com.google.auto.service.AutoService;
913
import io.opentelemetry.api.incubator.config.DeclarativeConfigProperties;
1014
import io.opentelemetry.api.trace.SpanKind;
1115
import io.opentelemetry.javaagent.bootstrap.internal.AgentInstrumentationConfig;
1216
import io.opentelemetry.javaagent.extension.instrumentation.InstrumentationModule;
1317
import io.opentelemetry.javaagent.extension.instrumentation.TypeInstrumentation;
1418
import io.opentelemetry.javaagent.tooling.config.MethodsConfigurationParser;
15-
import java.util.Collections;
1619
import java.util.List;
1720
import java.util.Map;
1821
import java.util.Set;
@@ -35,8 +38,11 @@ private static List<TypeInstrumentation> createInstrumentations() {
3538
AgentInstrumentationConfig.get().getDeclarativeConfig("methods");
3639
List<TypeInstrumentation> list =
3740
methods != null ? MethodsConfig.parseDeclarativeConfig(methods) : parseConfigProperties();
41+
// ensure that there is at least one instrumentation so that muzzle reference collection could
42+
// work
3843
if (list.isEmpty()) {
39-
return Collections.singletonList(new MethodInstrumentation(null, Collections.emptyMap()));
44+
return singletonList(
45+
new MethodInstrumentation(null, singletonMap(SpanKind.INTERNAL, emptyList())));
4046
}
4147
return list;
4248
}
@@ -51,11 +57,7 @@ private static List<TypeInstrumentation> parseConfigProperties() {
5157
.map(
5258
e ->
5359
new MethodInstrumentation(
54-
e.getKey(),
55-
e.getValue().stream()
56-
.collect(
57-
Collectors.toMap(
58-
methodName -> methodName, ignore -> SpanKind.INTERNAL))))
60+
e.getKey(), singletonMap(SpanKind.INTERNAL, e.getValue())))
5961
.collect(Collectors.toList());
6062
}
6163

instrumentation/methods/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/methods/MethodsConfig.java

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,9 @@
1010
import io.opentelemetry.api.incubator.config.DeclarativeConfigProperties;
1111
import io.opentelemetry.api.trace.SpanKind;
1212
import io.opentelemetry.javaagent.extension.instrumentation.TypeInstrumentation;
13-
import java.util.LinkedHashMap;
13+
import java.util.ArrayList;
14+
import java.util.Collection;
15+
import java.util.EnumMap;
1416
import java.util.List;
1517
import java.util.Locale;
1618
import java.util.Map;
@@ -39,7 +41,7 @@ private static Stream<MethodInstrumentation> parseMethodInstrumentation(
3941
return Stream.empty();
4042
}
4143

42-
Map<String, SpanKind> methodNames = new LinkedHashMap<>();
44+
Map<SpanKind, Collection<String>> methodNames = new EnumMap<>(SpanKind.class);
4345
for (DeclarativeConfigProperties method : config.getStructuredList("methods", emptyList())) {
4446
String methodName = method.getString("name");
4547
if (isNullOrEmpty(methodName)) {
@@ -49,7 +51,10 @@ private static Stream<MethodInstrumentation> parseMethodInstrumentation(
4951
}
5052
String spanKind = method.getString("span_kind", "INTERNAL");
5153
try {
52-
methodNames.put(methodName, SpanKind.valueOf(spanKind.toUpperCase(Locale.ROOT)));
54+
methodNames
55+
.computeIfAbsent(
56+
SpanKind.valueOf(spanKind.toUpperCase(Locale.ROOT)), unused -> new ArrayList<>())
57+
.add(methodName);
5358
} catch (IllegalArgumentException e) {
5459
logger.log(
5560
Level.WARNING,

0 commit comments

Comments
 (0)