Skip to content

Commit 9427f79

Browse files
committed
Add unit and integration tests for FaaS exception event extractor
1 parent eae016b commit 9427f79

4 files changed

Lines changed: 137 additions & 13 deletions

File tree

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
/*
2+
* Copyright The OpenTelemetry Authors
3+
* SPDX-License-Identifier: Apache-2.0
4+
*/
5+
6+
package io.opentelemetry.instrumentation.api.incubator.semconv.faas.internal;
7+
8+
import static io.opentelemetry.instrumentation.api.internal.SemconvExceptionSignal.emitExceptionAsLogs;
9+
import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.assertThat;
10+
import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.equalTo;
11+
import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.satisfies;
12+
import static io.opentelemetry.semconv.ExceptionAttributes.EXCEPTION_MESSAGE;
13+
import static io.opentelemetry.semconv.ExceptionAttributes.EXCEPTION_STACKTRACE;
14+
import static io.opentelemetry.semconv.ExceptionAttributes.EXCEPTION_TYPE;
15+
16+
import io.opentelemetry.api.logs.Severity;
17+
import io.opentelemetry.context.Context;
18+
import io.opentelemetry.instrumentation.api.instrumenter.Instrumenter;
19+
import io.opentelemetry.instrumentation.api.instrumenter.InstrumenterBuilder;
20+
import io.opentelemetry.sdk.logs.data.LogRecordData;
21+
import io.opentelemetry.sdk.testing.junit5.OpenTelemetryExtension;
22+
import java.util.List;
23+
import org.assertj.core.api.AbstractAssert;
24+
import org.junit.jupiter.api.Test;
25+
import org.junit.jupiter.api.extension.RegisterExtension;
26+
27+
class FaasExceptionEventExtractorsTest {
28+
29+
@RegisterExtension
30+
static final OpenTelemetryExtension otelTesting = OpenTelemetryExtension.create();
31+
32+
@Test
33+
void faasInvocationExceptionLog() {
34+
InstrumenterBuilder<String, String> builder =
35+
Instrumenter.builder(otelTesting.getOpenTelemetry(), "test", unused -> "span");
36+
FaasExceptionEventExtractors.setFaasInvocationExceptionEventExtractor(builder);
37+
Instrumenter<String, String> instrumenter = builder.buildInstrumenter();
38+
39+
Context context = instrumenter.start(Context.root(), "request");
40+
IllegalStateException error = new IllegalStateException("test");
41+
instrumenter.end(context, "request", "response", error);
42+
43+
List<LogRecordData> logs = otelTesting.getLogRecords();
44+
if (emitExceptionAsLogs()) {
45+
assertThat(logs).hasSize(1);
46+
assertThat(logs.get(0))
47+
.hasSeverity(Severity.ERROR)
48+
.hasEventName("faas.invocation.exception")
49+
.hasAttributesSatisfyingExactly(
50+
equalTo(EXCEPTION_TYPE, "java.lang.IllegalStateException"),
51+
equalTo(EXCEPTION_MESSAGE, "test"),
52+
satisfies(EXCEPTION_STACKTRACE, AbstractAssert::isNotNull));
53+
} else {
54+
assertThat(logs).isEmpty();
55+
}
56+
}
57+
}

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

Lines changed: 23 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -20,11 +20,28 @@ dependencies {
2020
testImplementation(project(":instrumentation:aws-lambda:aws-lambda-core-1.0:testing"))
2121
}
2222

23-
tasks.test {
24-
// required on jdk17
25-
jvmArgs("--add-opens=java.base/java.lang=ALL-UNNAMED")
26-
jvmArgs("--add-opens=java.base/java.util=ALL-UNNAMED")
27-
jvmArgs("-XX:+IgnoreUnrecognizedVMOptions")
23+
tasks {
24+
withType<Test>().configureEach {
25+
// required on jdk17
26+
jvmArgs("--add-opens=java.base/java.lang=ALL-UNNAMED")
27+
jvmArgs("--add-opens=java.base/java.util=ALL-UNNAMED")
28+
jvmArgs("-XX:+IgnoreUnrecognizedVMOptions")
2829

29-
systemProperty("collectMetadata", otelProps.collectMetadata)
30+
systemProperty("collectMetadata", otelProps.collectMetadata)
31+
}
32+
33+
val testExceptionSignalLogs by registering(Test::class) {
34+
testClassesDirs = sourceSets.test.get().output.classesDirs
35+
classpath = sourceSets.test.get().runtimeClasspath
36+
37+
filter {
38+
includeTestsMatching("AwsLambdaTest")
39+
}
40+
jvmArgs("-Dotel.semconv.exception.signal.preview=logs")
41+
systemProperty("metadataConfig", "otel.semconv.exception.signal.preview=logs")
42+
}
43+
44+
check {
45+
dependsOn(testExceptionSignalLogs)
46+
}
3047
}

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

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,3 +34,19 @@ tasks.withType<Test>().configureEach {
3434
jvmArgs("--add-opens=java.base/java.util=ALL-UNNAMED")
3535
jvmArgs("-XX:+IgnoreUnrecognizedVMOptions")
3636
}
37+
38+
tasks {
39+
val testExceptionSignalLogs by registering(Test::class) {
40+
testClassesDirs = sourceSets.test.get().output.classesDirs
41+
classpath = sourceSets.test.get().runtimeClasspath
42+
43+
filter {
44+
includeTestsMatching("AwsLambdaTest")
45+
}
46+
jvmArgs("-Dotel.semconv.exception.signal.preview=logs")
47+
}
48+
49+
check {
50+
dependsOn(testExceptionSignalLogs)
51+
}
52+
}

instrumentation/aws-lambda/aws-lambda-core-1.0/testing/src/main/java/io/opentelemetry/instrumentation/awslambdacore/v1_0/AbstractAwsLambdaTest.java

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

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

8+
import static io.opentelemetry.instrumentation.api.internal.SemconvExceptionSignal.emitExceptionAsLogs;
9+
import static io.opentelemetry.instrumentation.api.internal.SemconvExceptionSignal.emitExceptionAsSpanEvents;
810
import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.assertThat;
911
import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.equalTo;
12+
import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.satisfies;
13+
import static io.opentelemetry.semconv.ExceptionAttributes.EXCEPTION_MESSAGE;
14+
import static io.opentelemetry.semconv.ExceptionAttributes.EXCEPTION_STACKTRACE;
15+
import static io.opentelemetry.semconv.ExceptionAttributes.EXCEPTION_TYPE;
1016
import static io.opentelemetry.semconv.incubating.FaasIncubatingAttributes.FAAS_INVOCATION_ID;
17+
import static java.util.stream.Collectors.toList;
1118
import static org.assertj.core.api.Assertions.catchThrowable;
1219
import static org.mockito.Mockito.when;
1320

1421
import com.amazonaws.services.lambda.runtime.Context;
1522
import com.amazonaws.services.lambda.runtime.RequestHandler;
23+
import io.opentelemetry.api.logs.Severity;
1624
import io.opentelemetry.api.trace.SpanKind;
1725
import io.opentelemetry.instrumentation.testing.junit.InstrumentationExtension;
26+
import io.opentelemetry.sdk.logs.data.LogRecordData;
1827
import io.opentelemetry.sdk.trace.data.StatusData;
28+
import java.util.List;
29+
import org.awaitility.Awaitility;
1930
import org.junit.jupiter.api.AfterEach;
2031
import org.junit.jupiter.api.BeforeEach;
2132
import org.junit.jupiter.api.Test;
@@ -80,13 +91,36 @@ void handlerTracedWithException() {
8091
.waitAndAssertTraces(
8192
trace ->
8293
trace.hasSpansSatisfyingExactly(
83-
span ->
84-
span.hasName("my_function")
85-
.hasKind(SpanKind.SERVER)
86-
.hasStatus(StatusData.error())
87-
.hasException(thrown)
88-
.hasAttributesSatisfyingExactly(
89-
equalTo(FAAS_INVOCATION_ID, "1-22-333"))));
94+
span -> {
95+
span.hasName("my_function")
96+
.hasKind(SpanKind.SERVER)
97+
.hasStatus(StatusData.error())
98+
.hasAttributesSatisfyingExactly(equalTo(FAAS_INVOCATION_ID, "1-22-333"));
99+
span.hasException(emitExceptionAsSpanEvents() ? thrown : null);
100+
}));
101+
102+
if (emitExceptionAsLogs()) {
103+
assertInvocationExceptionLog();
104+
}
105+
}
106+
107+
private void assertInvocationExceptionLog() {
108+
Awaitility.await()
109+
.untilAsserted(
110+
() -> {
111+
List<LogRecordData> logs =
112+
testing().logRecords().stream()
113+
.filter(log -> "faas.invocation.exception".equals(log.getEventName()))
114+
.collect(toList());
115+
assertThat(logs).hasSize(1);
116+
assertThat(logs.get(0))
117+
.hasSeverity(Severity.ERROR)
118+
.hasEventName("faas.invocation.exception")
119+
.hasAttributesSatisfyingExactly(
120+
satisfies(EXCEPTION_TYPE, val -> val.isNotNull()),
121+
satisfies(EXCEPTION_MESSAGE, val -> val.isNotNull()),
122+
satisfies(EXCEPTION_STACKTRACE, val -> val.isNotNull()));
123+
});
90124
}
91125

92126
/**

0 commit comments

Comments
 (0)