Skip to content

Commit dd476de

Browse files
committed
Unify logback appender javaagent and library tests
1 parent 1aaa090 commit dd476de

File tree

8 files changed

+392
-221
lines changed

8 files changed

+392
-221
lines changed

instrumentation/logback/logback-appender-1.0/javaagent/build.gradle.kts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ dependencies {
4646

4747
implementation(project(":instrumentation:logback:logback-appender-1.0:library"))
4848

49+
testImplementation(project(":instrumentation:logback:logback-appender-1.0:testing"))
4950
testImplementation("org.awaitility:awaitility")
5051
}
5152

instrumentation/logback/logback-appender-1.0/javaagent/src/test/java/io/opentelemetry/instrumentation/logback/appender/v1_0/LogbackTest.java

Lines changed: 11 additions & 221 deletions
Original file line numberDiff line numberDiff line change
@@ -5,247 +5,37 @@
55

66
package io.opentelemetry.instrumentation.logback.appender.v1_0;
77

8-
import static io.opentelemetry.instrumentation.testing.junit.code.SemconvCodeStabilityUtil.codeFileAndLineAssertions;
9-
import static io.opentelemetry.instrumentation.testing.junit.code.SemconvCodeStabilityUtil.codeFunctionAssertions;
10-
import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.assertThat;
118
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;
169

17-
import io.opentelemetry.api.common.AttributeKey;
18-
import io.opentelemetry.api.logs.Severity;
19-
import io.opentelemetry.api.trace.SpanContext;
2010
import io.opentelemetry.instrumentation.testing.junit.AgentInstrumentationExtension;
2111
import io.opentelemetry.instrumentation.testing.junit.InstrumentationExtension;
22-
import io.opentelemetry.sdk.common.InstrumentationScopeInfo;
2312
import io.opentelemetry.sdk.testing.assertj.AttributeAssertion;
2413
import io.opentelemetry.semconv.incubating.ThreadIncubatingAttributes;
25-
import java.util.ArrayList;
2614
import java.util.Arrays;
27-
import java.util.Collections;
2815
import java.util.List;
29-
import java.util.stream.Stream;
30-
import org.junit.jupiter.api.Test;
3116
import org.junit.jupiter.api.extension.RegisterExtension;
32-
import org.junit.jupiter.params.ParameterizedTest;
33-
import org.junit.jupiter.params.provider.Arguments;
34-
import org.junit.jupiter.params.provider.MethodSource;
35-
import org.slf4j.Logger;
36-
import org.slf4j.LoggerFactory;
37-
import org.slf4j.MDC;
38-
import org.slf4j.Marker;
39-
import org.slf4j.MarkerFactory;
4017

41-
class LogbackTest {
18+
class LogbackTest extends AbstractLogbackTest {
4219

4320
@RegisterExtension
4421
static final InstrumentationExtension testing = AgentInstrumentationExtension.create();
4522

46-
private static final Logger abcLogger = LoggerFactory.getLogger("abc");
47-
private static final Logger defLogger = LoggerFactory.getLogger("def");
48-
49-
private static Stream<Arguments> provideParameters() {
50-
return Stream.of(
51-
Arguments.of(false, false),
52-
Arguments.of(false, true),
53-
Arguments.of(true, false),
54-
Arguments.of(true, true));
55-
}
56-
57-
@ParameterizedTest
58-
@MethodSource("provideParameters")
59-
public void test(boolean logException, boolean withParent) throws InterruptedException {
60-
test(abcLogger, Logger::debug, Logger::debug, logException, withParent, null, null, null);
61-
testing.clearData();
62-
test(
63-
abcLogger,
64-
Logger::info,
65-
Logger::info,
66-
logException,
67-
withParent,
68-
"abc",
69-
Severity.INFO,
70-
"INFO");
71-
testing.clearData();
72-
test(
73-
abcLogger,
74-
Logger::warn,
75-
Logger::warn,
76-
logException,
77-
withParent,
78-
"abc",
79-
Severity.WARN,
80-
"WARN");
81-
testing.clearData();
82-
test(
83-
abcLogger,
84-
Logger::error,
85-
Logger::error,
86-
logException,
87-
withParent,
88-
"abc",
89-
Severity.ERROR,
90-
"ERROR");
91-
testing.clearData();
92-
test(defLogger, Logger::debug, Logger::debug, logException, withParent, null, null, null);
93-
testing.clearData();
94-
test(defLogger, Logger::info, Logger::info, logException, withParent, null, null, null);
95-
testing.clearData();
96-
test(
97-
defLogger,
98-
Logger::warn,
99-
Logger::warn,
100-
logException,
101-
withParent,
102-
"def",
103-
Severity.WARN,
104-
"WARN");
105-
testing.clearData();
106-
test(
107-
defLogger,
108-
Logger::error,
109-
Logger::error,
110-
logException,
111-
withParent,
112-
"def",
113-
Severity.ERROR,
114-
"ERROR");
115-
testing.clearData();
23+
@Override
24+
protected InstrumentationExtension testing() {
25+
return testing;
11626
}
11727

118-
private static void test(
119-
Logger logger,
120-
OneArgLoggerMethod oneArgLoggerMethod,
121-
TwoArgLoggerMethod twoArgLoggerMethod,
122-
boolean logException,
123-
boolean withParent,
124-
String expectedLoggerName,
125-
Severity expectedSeverity,
126-
String expectedSeverityText)
127-
throws InterruptedException {
128-
129-
// when
130-
if (withParent) {
131-
testing.runWithSpan(
132-
"parent",
133-
() -> performLogging(logger, oneArgLoggerMethod, twoArgLoggerMethod, logException));
134-
} else {
135-
performLogging(logger, oneArgLoggerMethod, twoArgLoggerMethod, logException);
136-
}
137-
138-
// then
139-
if (withParent) {
140-
testing.waitForTraces(1);
141-
}
142-
143-
if (expectedSeverity != null) {
144-
testing.waitAndAssertLogRecords(
145-
logRecord -> {
146-
logRecord
147-
.hasBody("xyz: 123")
148-
.hasInstrumentationScope(
149-
InstrumentationScopeInfo.builder(expectedLoggerName).build())
150-
.hasSeverity(expectedSeverity)
151-
.hasSeverityText(expectedSeverityText)
152-
.hasSpanContext(
153-
withParent
154-
? testing.spans().get(0).getSpanContext()
155-
: SpanContext.getInvalid());
156-
157-
List<AttributeAssertion> attributeAsserts = new ArrayList<>(threadAssertions());
158-
159-
attributeAsserts.addAll(codeFunctionAssertions(LogbackTest.class, "performLogging"));
160-
attributeAsserts.addAll(codeFileAndLineAssertions("LogbackTest.java"));
161-
162-
if (logException) {
163-
attributeAsserts.addAll(
164-
Arrays.asList(
165-
equalTo(EXCEPTION_TYPE, IllegalStateException.class.getName()),
166-
equalTo(EXCEPTION_MESSAGE, "hello"),
167-
satisfies(
168-
EXCEPTION_STACKTRACE, v -> v.contains(LogbackTest.class.getName()))));
169-
}
170-
logRecord.hasAttributesSatisfyingExactly(attributeAsserts);
171-
});
172-
} else {
173-
Thread.sleep(500); // sleep a bit just to make sure no log is captured
174-
assertThat(testing.logRecords()).isEmpty();
175-
}
176-
}
177-
178-
@Test
179-
void testMdc() {
180-
MDC.put("key1", "val1");
181-
MDC.put("key2", "val2");
182-
try {
183-
abcLogger.info("xyz: {}", 123);
184-
} finally {
185-
MDC.clear();
186-
}
187-
188-
List<AttributeAssertion> assertions = new ArrayList<>();
189-
assertions.addAll(threadAssertions());
190-
assertions.addAll(codeFileAndLineAssertions("LogbackTest.java"));
191-
assertions.addAll(codeFunctionAssertions(LogbackTest.class, "testMdc"));
192-
assertions.add(equalTo(AttributeKey.stringKey("key1"), "val1"));
193-
assertions.add(equalTo(AttributeKey.stringKey("key2"), "val2"));
194-
195-
testing.waitAndAssertLogRecords(
196-
logRecord ->
197-
logRecord
198-
.hasBody("xyz: 123")
199-
.hasInstrumentationScope(InstrumentationScopeInfo.builder("abc").build())
200-
.hasSeverity(Severity.INFO)
201-
.hasSeverityText("INFO")
202-
.hasAttributesSatisfyingExactly(assertions));
203-
}
204-
205-
@Test
206-
public void testMarker() {
207-
208-
String markerName = "aMarker";
209-
Marker marker = MarkerFactory.getMarker(markerName);
210-
211-
abcLogger.info(marker, "Message");
212-
213-
List<AttributeAssertion> assertions = codeFunctionAssertions(LogbackTest.class, "testMarker");
214-
assertions.addAll(threadAssertions());
215-
assertions.addAll(codeFileAndLineAssertions("LogbackTest.java"));
216-
assertions.add(
217-
equalTo(
218-
AttributeKey.stringArrayKey("logback.marker"), Collections.singletonList(markerName)));
219-
220-
testing.waitAndAssertLogRecords(
221-
logRecord -> logRecord.hasAttributesSatisfyingExactly(assertions));
222-
}
223-
224-
private static List<AttributeAssertion> threadAssertions() {
28+
@Override
29+
protected List<AttributeAssertion> threadAssertions() {
22530
return Arrays.asList(
22631
equalTo(ThreadIncubatingAttributes.THREAD_NAME, Thread.currentThread().getName()),
22732
equalTo(ThreadIncubatingAttributes.THREAD_ID, Thread.currentThread().getId()));
22833
}
22934

230-
private static void performLogging(
231-
Logger logger,
232-
OneArgLoggerMethod oneArgLoggerMethod,
233-
TwoArgLoggerMethod twoArgLoggerMethod,
234-
boolean logException) {
235-
if (logException) {
236-
twoArgLoggerMethod.call(logger, "xyz: {}", 123, new IllegalStateException("hello"));
237-
} else {
238-
oneArgLoggerMethod.call(logger, "xyz: {}", 123);
239-
}
240-
}
241-
242-
@FunctionalInterface
243-
interface OneArgLoggerMethod {
244-
void call(Logger logger, String msg, Object arg);
245-
}
246-
247-
@FunctionalInterface
248-
interface TwoArgLoggerMethod {
249-
void call(Logger logger, String msg, Object arg1, Object arg2);
35+
@Override
36+
protected boolean expectEventName() {
37+
// TODO support event name in the agent once the attribute name is decided
38+
// see https://github.com/open-telemetry/semantic-conventions/issues/2913
39+
return false;
25040
}
25141
}

instrumentation/logback/logback-appender-1.0/library/build.gradle.kts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ dependencies {
4040
}
4141
}
4242

43+
testImplementation(project(":instrumentation:logback:logback-appender-1.0:testing"))
4344
testImplementation("io.opentelemetry:opentelemetry-sdk-testing")
4445
}
4546

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
/*
2+
* Copyright The OpenTelemetry Authors
3+
* SPDX-License-Identifier: Apache-2.0
4+
*/
5+
6+
package io.opentelemetry.instrumentation.logback.appender.v1_0;
7+
8+
import io.opentelemetry.instrumentation.testing.junit.InstrumentationExtension;
9+
import io.opentelemetry.instrumentation.testing.junit.LibraryInstrumentationExtension;
10+
import org.junit.jupiter.api.extension.RegisterExtension;
11+
12+
class LogbackTest extends AbstractLogbackTest {
13+
14+
@RegisterExtension
15+
private static final LibraryInstrumentationExtension testing =
16+
LibraryInstrumentationExtension.create();
17+
18+
@Override
19+
protected InstrumentationExtension testing() {
20+
return testing;
21+
}
22+
23+
@Override
24+
protected void beforeEachTest() {
25+
OpenTelemetryAppender.install(testing.getOpenTelemetry());
26+
}
27+
28+
@Override
29+
protected void afterEachTest() {
30+
OpenTelemetryAppender.install(null);
31+
}
32+
}

instrumentation/logback/logback-appender-1.0/library/src/test/resources/logback-test.xml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,9 @@
1919
<captureEventName>true</captureEventName>
2020
</appender>
2121

22+
<logger name="abc" level="INFO"/>
23+
<logger name="def" level="WARN"/>
24+
2225
<root level="INFO">
2326
<appender-ref ref="console"/>
2427
<appender-ref ref="OpenTelemetry"/>
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
plugins {
2+
id("otel.java-conventions")
3+
}
4+
5+
dependencies {
6+
api(project(":testing-common"))
7+
api("io.opentelemetry:opentelemetry-sdk-testing")
8+
9+
api("ch.qos.logback:logback-classic:1.0.0")
10+
api("org.slf4j:slf4j-api:1.7.36")
11+
}

0 commit comments

Comments
 (0)