Skip to content

Commit 0de1dcf

Browse files
laurittrask
andauthored
Fail test if advice threw an exception (#9654)
Co-authored-by: Trask Stalnaker <[email protected]>
1 parent b7df46d commit 0de1dcf

File tree

10 files changed

+52
-8
lines changed

10 files changed

+52
-8
lines changed

instrumentation/aws-lambda/aws-lambda-core-1.0/javaagent/build.gradle.kts

-1
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@ dependencies {
1919
library("com.amazonaws:aws-lambda-java-core:1.0.0")
2020

2121
testImplementation(project(":instrumentation:aws-lambda:aws-lambda-core-1.0:testing"))
22-
testInstrumentation(project(":instrumentation:aws-lambda:aws-lambda-events-2.2:javaagent"))
2322
}
2423

2524
tasks.withType<Test>().configureEach {

instrumentation/aws-lambda/aws-lambda-core-1.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/awslambdacore/v1_0/AwsLambdaInstrumentationModule.java

+9
Original file line numberDiff line numberDiff line change
@@ -5,19 +5,28 @@
55

66
package io.opentelemetry.javaagent.instrumentation.awslambdacore.v1_0;
77

8+
import static io.opentelemetry.javaagent.extension.matcher.AgentElementMatchers.hasClassesNamed;
89
import static java.util.Collections.singletonList;
10+
import static net.bytebuddy.matcher.ElementMatchers.not;
911

1012
import com.google.auto.service.AutoService;
1113
import io.opentelemetry.javaagent.extension.instrumentation.InstrumentationModule;
1214
import io.opentelemetry.javaagent.extension.instrumentation.TypeInstrumentation;
1315
import java.util.List;
16+
import net.bytebuddy.matcher.ElementMatcher;
1417

1518
@AutoService(InstrumentationModule.class)
1619
public class AwsLambdaInstrumentationModule extends InstrumentationModule {
1720
public AwsLambdaInstrumentationModule() {
1821
super("aws-lambda-core", "aws-lambda-core-1.0", "aws-lambda");
1922
}
2023

24+
@Override
25+
public ElementMatcher.Junction<ClassLoader> classLoaderMatcher() {
26+
// aws-lambda-events-2.2 is used when SQSEvent is present
27+
return not(hasClassesNamed("com.amazonaws.services.lambda.runtime.events.SQSEvent"));
28+
}
29+
2130
@Override
2231
public boolean isHelperClass(String className) {
2332
return className.startsWith("io.opentelemetry.contrib.awsxray.");

instrumentation/kafka/kafka-clients/kafka-clients-0.11/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/kafkaclients/v0_11/KafkaConsumerInstrumentation.java

+7-1
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
import io.opentelemetry.javaagent.extension.instrumentation.TypeInstrumentation;
2525
import io.opentelemetry.javaagent.extension.instrumentation.TypeTransformer;
2626
import java.time.Duration;
27+
import java.util.HashMap;
2728
import java.util.Map;
2829
import java.util.Properties;
2930
import net.bytebuddy.asm.Advice;
@@ -61,7 +62,12 @@ public void transform(TypeTransformer transformer) {
6162
public static class ConstructorMapAdvice {
6263

6364
@Advice.OnMethodEnter(suppress = Throwable.class)
64-
public static void onEnter(@Advice.Argument(0) Map<String, Object> config) {
65+
public static void onEnter(
66+
@Advice.Argument(value = 0, readOnly = false) Map<String, Object> config) {
67+
// ensure config is a mutable map
68+
if (config.getClass() != HashMap.class) {
69+
config = new HashMap<>(config);
70+
}
6571
enhanceConfig(config);
6672
}
6773
}

instrumentation/kafka/kafka-clients/kafka-clients-0.11/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/kafkaclients/v0_11/KafkaProducerInstrumentation.java

+7-1
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
import io.opentelemetry.javaagent.bootstrap.Java8BytecodeBridge;
2121
import io.opentelemetry.javaagent.extension.instrumentation.TypeInstrumentation;
2222
import io.opentelemetry.javaagent.extension.instrumentation.TypeTransformer;
23+
import java.util.HashMap;
2324
import java.util.Map;
2425
import java.util.Properties;
2526
import net.bytebuddy.asm.Advice;
@@ -57,7 +58,12 @@ public void transform(TypeTransformer transformer) {
5758
public static class ConstructorMapAdvice {
5859

5960
@Advice.OnMethodEnter(suppress = Throwable.class)
60-
public static void onEnter(@Advice.Argument(0) Map<String, Object> config) {
61+
public static void onEnter(
62+
@Advice.Argument(value = 0, readOnly = false) Map<String, Object> config) {
63+
// ensure config is a mutable map
64+
if (config.getClass() != HashMap.class) {
65+
config = new HashMap<>(config);
66+
}
6167
enhanceConfig(config);
6268
}
6369
}

instrumentation/netty/netty-4-common/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/netty/v4/common/AbstractNettyChannelPipelineInstrumentation.java

+12-4
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,9 @@ public static void removeHandler(
7171
VirtualField.find(ChannelHandler.class, ChannelHandler.class);
7272
ChannelHandler ourHandler = virtualField.get(handler);
7373
if (ourHandler != null) {
74-
pipeline.remove(ourHandler);
74+
if (pipeline.context(ourHandler) != null) {
75+
pipeline.remove(ourHandler);
76+
}
7577
virtualField.set(handler, null);
7678
}
7779
}
@@ -92,7 +94,9 @@ public static void removeHandler(
9294
VirtualField.find(ChannelHandler.class, ChannelHandler.class);
9395
ChannelHandler ourHandler = virtualField.get(handler);
9496
if (ourHandler != null) {
95-
pipeline.remove(ourHandler);
97+
if (pipeline.context(ourHandler) != null) {
98+
pipeline.remove(ourHandler);
99+
}
96100
virtualField.set(handler, null);
97101
}
98102
}
@@ -114,7 +118,9 @@ public static void removeHandler(
114118
VirtualField.find(ChannelHandler.class, ChannelHandler.class);
115119
ChannelHandler ourHandler = virtualField.get(handler);
116120
if (ourHandler != null) {
117-
pipeline.remove(ourHandler);
121+
if (pipeline.context(ourHandler) != null) {
122+
pipeline.remove(ourHandler);
123+
}
118124
virtualField.set(handler, null);
119125
}
120126
}
@@ -130,7 +136,9 @@ public static void removeHandler(
130136
VirtualField.find(ChannelHandler.class, ChannelHandler.class);
131137
ChannelHandler ourHandler = virtualField.get(handler);
132138
if (ourHandler != null) {
133-
pipeline.remove(ourHandler);
139+
if (pipeline.context(ourHandler) != null) {
140+
pipeline.remove(ourHandler);
141+
}
134142
virtualField.set(handler, null);
135143
}
136144
}

instrumentation/servlet/servlet-2.2/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/servlet/v2_2/Servlet2SpanNameExtractor.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ public String extract(ServletRequestContext<REQUEST> requestContext) {
3232
if (!knownMethods.contains(method)) {
3333
method = "HTTP";
3434
}
35-
if (servletPath.isEmpty()) {
35+
if (servletPath == null || servletPath.isEmpty()) {
3636
return method;
3737
}
3838
String contextPath = accessor.getRequestContextPath(request);

javaagent-bootstrap/src/main/java/io/opentelemetry/javaagent/bootstrap/ExceptionLogger.java

+8
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77

88
import static java.util.logging.Level.FINE;
99

10+
import java.util.concurrent.atomic.AtomicInteger;
1011
import java.util.logging.Logger;
1112

1213
/**
@@ -17,11 +18,18 @@
1718
public final class ExceptionLogger {
1819

1920
private static final Logger logger = Logger.getLogger(ExceptionLogger.class.getName());
21+
private static final AtomicInteger counter = new AtomicInteger();
2022

2123
/** See {@code io.opentelemetry.javaagent.tooling.ExceptionHandlers} for usages. */
2224
@SuppressWarnings("unused")
2325
public static void logSuppressedError(String message, Throwable error) {
2426
logger.log(FINE, message, error);
27+
counter.incrementAndGet();
28+
}
29+
30+
// only used by tests
31+
public static int getAndReset() {
32+
return counter.getAndSet(0);
2533
}
2634

2735
private ExceptionLogger() {}

testing-common/build.gradle.kts

+1
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ dependencies {
4646
api("org.slf4j:slf4j-api")
4747

4848
compileOnly(project(":testing:armeria-shaded-for-testing", configuration = "shadow"))
49+
compileOnly(project(":javaagent-bootstrap"))
4950

5051
compileOnly("com.google.auto.value:auto-value-annotations")
5152
annotationProcessor("com.google.auto.value:auto-value")

testing-common/src/main/java/io/opentelemetry/instrumentation/testing/AgentTestRunner.java

+2
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,8 @@ public void afterTestClass() {
5555
assert TestAgentListenerAccess.getInstrumentationErrorCount() == 0
5656
: TestAgentListenerAccess.getInstrumentationErrorCount()
5757
+ " Instrumentation errors during test";
58+
int adviceFailureCount = TestAgentListenerAccess.getAndResetAdviceFailureCount();
59+
assert adviceFailureCount == 0 : adviceFailureCount + " Advice failures during test";
5860
int muzzleFailureCount = TestAgentListenerAccess.getAndResetMuzzleFailureCount();
5961
assert muzzleFailureCount == 0 : muzzleFailureCount + " Muzzle failures during test";
6062
// additional library ignores are ignored during tests, because they can make it really

testing-common/src/main/java/io/opentelemetry/javaagent/testing/common/TestAgentListenerAccess.java

+5
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77

88
import static java.lang.invoke.MethodType.methodType;
99

10+
import io.opentelemetry.javaagent.bootstrap.ExceptionLogger;
1011
import java.lang.invoke.MethodHandle;
1112
import java.lang.invoke.MethodHandles;
1213
import java.util.List;
@@ -105,5 +106,9 @@ public static void addSkipErrorCondition(BiFunction<String, Throwable, Boolean>
105106
}
106107
}
107108

109+
public static int getAndResetAdviceFailureCount() {
110+
return ExceptionLogger.getAndReset();
111+
}
112+
108113
private TestAgentListenerAccess() {}
109114
}

0 commit comments

Comments
 (0)