Skip to content

Commit 06f22a3

Browse files
rupinder10trask
andauthored
Added setOpenTelemetry method to appender (open-telemetry#8231)
Co-authored-by: Trask Stalnaker <[email protected]>
1 parent 80d50cc commit 06f22a3

File tree

4 files changed

+301
-181
lines changed

4 files changed

+301
-181
lines changed

instrumentation/log4j/log4j-appender-2.17/library/src/main/java/io/opentelemetry/instrumentation/log4j/appender/v2_17/OpenTelemetryAppender.java

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99

1010
import com.google.errorprone.annotations.CanIgnoreReturnValue;
1111
import io.opentelemetry.api.GlobalOpenTelemetry;
12+
import io.opentelemetry.api.OpenTelemetry;
1213
import io.opentelemetry.api.logs.LogRecordBuilder;
1314
import io.opentelemetry.instrumentation.log4j.appender.v2_17.internal.ContextDataAccessor;
1415
import io.opentelemetry.instrumentation.log4j.appender.v2_17.internal.LogEventMapper;
@@ -43,6 +44,7 @@ public class OpenTelemetryAppender extends AbstractAppender {
4344
static final String PLUGIN_NAME = "OpenTelemetry";
4445

4546
private final LogEventMapper<ReadOnlyStringMap> mapper;
47+
@Nullable private OpenTelemetry openTelemetry;
4648

4749
@PluginBuilderFactory
4850
public static <B extends Builder<B>> B builder() {
@@ -57,6 +59,8 @@ public static class Builder<B extends Builder<B>> extends AbstractAppender.Build
5759
@PluginBuilderAttribute private boolean captureMarkerAttribute;
5860
@PluginBuilderAttribute private String captureContextDataAttributes;
5961

62+
@Nullable private OpenTelemetry openTelemetry;
63+
6064
/**
6165
* Sets whether experimental attributes should be set to logs. These attributes may be changed
6266
* or removed in the future, so only enable this if you know you do not require attributes
@@ -93,6 +97,12 @@ public B setCaptureContextDataAttributes(String captureContextDataAttributes) {
9397
return asBuilder();
9498
}
9599

100+
@CanIgnoreReturnValue
101+
public B setOpenTelemetry(OpenTelemetry openTelemetry) {
102+
this.openTelemetry = openTelemetry;
103+
return asBuilder();
104+
}
105+
96106
@Override
97107
public OpenTelemetryAppender build() {
98108
return new OpenTelemetryAppender(
@@ -104,7 +114,8 @@ public OpenTelemetryAppender build() {
104114
captureExperimentalAttributes,
105115
captureMapMessageAttributes,
106116
captureMarkerAttribute,
107-
captureContextDataAttributes);
117+
captureContextDataAttributes,
118+
openTelemetry);
108119
}
109120
}
110121

@@ -117,7 +128,8 @@ private OpenTelemetryAppender(
117128
boolean captureExperimentalAttributes,
118129
boolean captureMapMessageAttributes,
119130
boolean captureMarkerAttribute,
120-
String captureContextDataAttributes) {
131+
String captureContextDataAttributes,
132+
OpenTelemetry openTelemetry) {
121133

122134
super(name, filter, layout, ignoreExceptions, properties);
123135
this.mapper =
@@ -127,6 +139,7 @@ private OpenTelemetryAppender(
127139
captureMapMessageAttributes,
128140
captureMarkerAttribute,
129141
splitAndFilterBlanksAndNulls(captureContextDataAttributes));
142+
this.openTelemetry = openTelemetry;
130143
}
131144

132145
private static List<String> splitAndFilterBlanksAndNulls(String value) {
@@ -139,14 +152,23 @@ private static List<String> splitAndFilterBlanksAndNulls(String value) {
139152
.collect(Collectors.toList());
140153
}
141154

155+
public void setOpenTelemetry(OpenTelemetry openTelemetry) {
156+
this.openTelemetry = openTelemetry;
157+
}
158+
159+
private OpenTelemetry getOpenTelemetry() {
160+
return openTelemetry == null ? GlobalOpenTelemetry.get() : openTelemetry;
161+
}
162+
142163
@Override
143164
public void append(LogEvent event) {
144165
String instrumentationName = event.getLoggerName();
145166
if (instrumentationName == null || instrumentationName.isEmpty()) {
146167
instrumentationName = "ROOT";
147168
}
169+
148170
LogRecordBuilder builder =
149-
GlobalOpenTelemetry.get()
171+
getOpenTelemetry()
150172
.getLogsBridge()
151173
.loggerBuilder(instrumentationName)
152174
.build()

instrumentation/log4j/log4j-appender-2.17/library/src/test/java/io/opentelemetry/instrumentation/log4j/appender/v2_17/OpenTelemetryAppenderConfigTest.java

Lines changed: 1 addition & 178 deletions
Original file line numberDiff line numberDiff line change
@@ -5,49 +5,23 @@
55

66
package io.opentelemetry.instrumentation.log4j.appender.v2_17;
77

8-
import static io.opentelemetry.api.common.AttributeKey.stringKey;
98
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;
129

1310
import io.opentelemetry.api.GlobalOpenTelemetry;
14-
import io.opentelemetry.api.common.Attributes;
15-
import io.opentelemetry.api.logs.Severity;
16-
import io.opentelemetry.api.trace.Span;
17-
import io.opentelemetry.api.trace.SpanContext;
18-
import io.opentelemetry.context.Scope;
1911
import io.opentelemetry.sdk.OpenTelemetrySdk;
2012
import io.opentelemetry.sdk.common.InstrumentationScopeInfo;
2113
import io.opentelemetry.sdk.logs.SdkLoggerProvider;
2214
import io.opentelemetry.sdk.logs.data.LogRecordData;
2315
import io.opentelemetry.sdk.logs.export.SimpleLogRecordProcessor;
2416
import io.opentelemetry.sdk.resources.Resource;
2517
import io.opentelemetry.sdk.testing.exporter.InMemoryLogRecordExporter;
26-
import io.opentelemetry.sdk.trace.SdkTracerProvider;
27-
import io.opentelemetry.semconv.trace.attributes.SemanticAttributes;
28-
import java.time.Instant;
2918
import java.util.List;
30-
import java.util.concurrent.TimeUnit;
31-
import org.apache.logging.log4j.LogManager;
32-
import org.apache.logging.log4j.Logger;
33-
import org.apache.logging.log4j.Marker;
34-
import org.apache.logging.log4j.MarkerManager;
35-
import org.apache.logging.log4j.ThreadContext;
3619
import org.apache.logging.log4j.core.impl.Log4jLogEvent;
3720
import org.apache.logging.log4j.message.FormattedMessage;
38-
import org.apache.logging.log4j.message.StringMapMessage;
39-
import org.apache.logging.log4j.message.StructuredDataMessage;
4021
import org.junit.jupiter.api.BeforeAll;
41-
import org.junit.jupiter.api.BeforeEach;
4222
import org.junit.jupiter.api.Test;
4323

44-
class OpenTelemetryAppenderConfigTest {
45-
46-
private static final Logger logger = LogManager.getLogger("TestLogger");
47-
48-
private static InMemoryLogRecordExporter logRecordExporter;
49-
private static Resource resource;
50-
private static InstrumentationScopeInfo instrumentationScopeInfo;
24+
class OpenTelemetryAppenderConfigTest extends OpenTelemetryAppenderConfigTestBase {
5125

5226
@BeforeAll
5327
static void setupAll() {
@@ -65,12 +39,6 @@ static void setupAll() {
6539
GlobalOpenTelemetry.set(OpenTelemetrySdk.builder().setLoggerProvider(loggerProvider).build());
6640
}
6741

68-
@BeforeEach
69-
void setup() {
70-
logRecordExporter.reset();
71-
ThreadContext.clearAll();
72-
}
73-
7442
@Test
7543
void initializeWithBuilder() {
7644
OpenTelemetryAppender appender =
@@ -86,149 +54,4 @@ void initializeWithBuilder() {
8654
assertThat(logDataList)
8755
.satisfiesExactly(logRecordData -> assertThat(logDataList.get(0)).hasBody("log message 1"));
8856
}
89-
90-
@Test
91-
void logNoSpan() {
92-
logger.info("log message 1");
93-
94-
List<LogRecordData> logDataList = logRecordExporter.getFinishedLogRecordItems();
95-
assertThat(logDataList).hasSize(1);
96-
assertThat(logDataList.get(0))
97-
.hasResource(resource)
98-
.hasInstrumentationScope(instrumentationScopeInfo)
99-
.hasBody("log message 1")
100-
.hasAttributes(Attributes.empty());
101-
}
102-
103-
@Test
104-
void logWithSpan() {
105-
Span span1 = runWithSpan("span1", () -> logger.info("log message 1"));
106-
107-
logger.info("log message 2");
108-
109-
Span span2 = runWithSpan("span2", () -> logger.info("log message 3"));
110-
111-
List<LogRecordData> logDataList = logRecordExporter.getFinishedLogRecordItems();
112-
assertThat(logDataList).hasSize(3);
113-
assertThat(logDataList.get(0).getSpanContext()).isEqualTo(span1.getSpanContext());
114-
assertThat(logDataList.get(1).getSpanContext()).isEqualTo(SpanContext.getInvalid());
115-
assertThat(logDataList.get(2).getSpanContext()).isEqualTo(span2.getSpanContext());
116-
}
117-
118-
private static Span runWithSpan(String spanName, Runnable runnable) {
119-
Span span = SdkTracerProvider.builder().build().get("tracer").spanBuilder(spanName).startSpan();
120-
try (Scope ignored = span.makeCurrent()) {
121-
runnable.run();
122-
} finally {
123-
span.end();
124-
}
125-
return span;
126-
}
127-
128-
@Test
129-
void logWithExtras() {
130-
Instant start = Instant.now();
131-
logger.info("log message 1", new IllegalStateException("Error!"));
132-
133-
List<LogRecordData> logDataList = logRecordExporter.getFinishedLogRecordItems();
134-
assertThat(logDataList).hasSize(1);
135-
assertThat(logDataList.get(0))
136-
.hasResource(resource)
137-
.hasInstrumentationScope(instrumentationScopeInfo)
138-
.hasBody("log message 1")
139-
.hasSeverity(Severity.INFO)
140-
.hasSeverityText("INFO")
141-
.hasAttributesSatisfyingExactly(
142-
equalTo(SemanticAttributes.EXCEPTION_TYPE, IllegalStateException.class.getName()),
143-
equalTo(SemanticAttributes.EXCEPTION_MESSAGE, "Error!"),
144-
satisfies(SemanticAttributes.EXCEPTION_STACKTRACE, v -> v.contains("logWithExtras")));
145-
146-
assertThat(logDataList.get(0).getTimestampEpochNanos())
147-
.isGreaterThanOrEqualTo(TimeUnit.MILLISECONDS.toNanos(start.toEpochMilli()))
148-
.isLessThanOrEqualTo(TimeUnit.MILLISECONDS.toNanos(Instant.now().toEpochMilli()));
149-
}
150-
151-
@Test
152-
void logContextData() {
153-
ThreadContext.put("key1", "val1");
154-
ThreadContext.put("key2", "val2");
155-
try {
156-
logger.info("log message 1");
157-
} finally {
158-
ThreadContext.clearMap();
159-
}
160-
161-
List<LogRecordData> logDataList = logRecordExporter.getFinishedLogRecordItems();
162-
assertThat(logDataList).hasSize(1);
163-
assertThat(logDataList.get(0))
164-
.hasResource(resource)
165-
.hasInstrumentationScope(instrumentationScopeInfo)
166-
.hasBody("log message 1")
167-
.hasAttributesSatisfyingExactly(
168-
equalTo(stringKey("log4j.context_data.key1"), "val1"),
169-
equalTo(stringKey("log4j.context_data.key2"), "val2"));
170-
}
171-
172-
@Test
173-
void logStringMapMessage() {
174-
StringMapMessage message = new StringMapMessage();
175-
message.put("key1", "val1");
176-
message.put("key2", "val2");
177-
logger.info(message);
178-
179-
List<LogRecordData> logDataList = logRecordExporter.getFinishedLogRecordItems();
180-
assertThat(logDataList).hasSize(1);
181-
assertThat(logDataList.get(0))
182-
.hasResource(resource)
183-
.hasInstrumentationScope(instrumentationScopeInfo)
184-
.hasAttributesSatisfyingExactly(
185-
equalTo(stringKey("log4j.map_message.key1"), "val1"),
186-
equalTo(stringKey("log4j.map_message.key2"), "val2"));
187-
}
188-
189-
@Test
190-
void logStringMapMessageWithSpecialAttribute() {
191-
StringMapMessage message = new StringMapMessage();
192-
message.put("key1", "val1");
193-
message.put("message", "val2");
194-
logger.info(message);
195-
196-
List<LogRecordData> logDataList = logRecordExporter.getFinishedLogRecordItems();
197-
assertThat(logDataList).hasSize(1);
198-
assertThat(logDataList.get(0))
199-
.hasResource(resource)
200-
.hasInstrumentationScope(instrumentationScopeInfo)
201-
.hasBody("val2")
202-
.hasAttributesSatisfyingExactly(equalTo(stringKey("log4j.map_message.key1"), "val1"));
203-
}
204-
205-
@Test
206-
void testCaptureMarkerAttribute() {
207-
String markerName = "aMarker";
208-
Marker marker = MarkerManager.getMarker(markerName);
209-
210-
logger.info(marker, "Message");
211-
212-
List<LogRecordData> logDataList = logRecordExporter.getFinishedLogRecordItems();
213-
LogRecordData logData = logDataList.get(0);
214-
assertThat(logData.getAttributes().get(stringKey("log4j.marker"))).isEqualTo(markerName);
215-
}
216-
217-
@Test
218-
void logStructuredDataMessage() {
219-
StructuredDataMessage message = new StructuredDataMessage("an id", "a message", "a type");
220-
message.put("key1", "val1");
221-
message.put("key2", "val2");
222-
logger.info(message);
223-
224-
List<LogRecordData> logDataList = logRecordExporter.getFinishedLogRecordItems();
225-
assertThat(logDataList).hasSize(1);
226-
assertThat(logDataList.get(0))
227-
.hasResource(resource)
228-
.hasInstrumentationScope(instrumentationScopeInfo)
229-
.hasBody("a message")
230-
.hasAttributesSatisfyingExactly(
231-
equalTo(stringKey("log4j.map_message.key1"), "val1"),
232-
equalTo(stringKey("log4j.map_message.key2"), "val2"));
233-
}
23457
}

0 commit comments

Comments
 (0)