Skip to content

Commit ad077ae

Browse files
philsttrtraskotelbot[bot]laurit
authored
Capture event name in logback/log4j/jboss-logmanager instrumentation (#14649)
Co-authored-by: Trask Stalnaker <[email protected]> Co-authored-by: otelbot <[email protected]> Co-authored-by: Lauri Tulmin <[email protected]>
1 parent 64be6da commit ad077ae

File tree

26 files changed

+397
-281
lines changed

26 files changed

+397
-281
lines changed
Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
# Settings for the JBoss Log Manager instrumentation
22

3-
| System property | Type | Default | Description |
4-
|-----------------------------------------------------------------------------|---------|---------|--------------------------------------------------------------------------------------------------------------|
5-
| `otel.instrumentation.jboss-logmanager.experimental-log-attributes` | Boolean | `false` | Enable the capture of experimental log attributes `thread.name` and `thread.id`. |
6-
| `otel.instrumentation.jboss-logmanager.experimental.capture-mdc-attributes` | String | | Comma separated list of MDC attributes to capture. Use the wildcard character `*` to capture all attributes. |
3+
| System property | Type | Default | Description |
4+
|-----------------------------------------------------------------------------|---------|---------|------------------------------------------------------------------------------------------------------------------------------------|
5+
| `otel.instrumentation.jboss-logmanager.experimental-log-attributes` | Boolean | `false` | Enable the capture of experimental log attributes `thread.name` and `thread.id`. |
6+
| `otel.instrumentation.jboss-logmanager.experimental.capture-mdc-attributes` | String | | Comma separated list of MDC attributes to capture. Use the wildcard character `*` to capture all attributes. |
7+
| `otel.instrumentation.jboss-logmanager.experimental.capture-event-name` | Boolean | `false` | Enable moving the `event.name` attribute (captured by one of the other mechanisms of capturing attributes) to the log event name. |

instrumentation/jboss-logmanager/jboss-logmanager-appender-1.1/javaagent/build.gradle.kts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ if (latestDepTest) {
3333
tasks.withType<Test>().configureEach {
3434
// TODO run tests both with and without experimental log attributes
3535
jvmArgs("-Dotel.instrumentation.jboss-logmanager.experimental.capture-mdc-attributes=*")
36+
jvmArgs("-Dotel.instrumentation.jboss-logmanager.experimental.capture-event-name=true")
3637
jvmArgs("-Dotel.instrumentation.jboss-logmanager.experimental-log-attributes=true")
3738
jvmArgs("-Dotel.instrumentation.java-util-logging.experimental-log-attributes=true")
3839
}

instrumentation/jboss-logmanager/jboss-logmanager-appender-1.1/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jbosslogmanager/appender/v1_1/LoggingEventMapper.java

Lines changed: 25 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,6 @@
1010

1111
import io.opentelemetry.api.GlobalOpenTelemetry;
1212
import io.opentelemetry.api.common.AttributeKey;
13-
import io.opentelemetry.api.common.Attributes;
14-
import io.opentelemetry.api.common.AttributesBuilder;
1513
import io.opentelemetry.api.incubator.logs.ExtendedLogRecordBuilder;
1614
import io.opentelemetry.api.logs.LogRecordBuilder;
1715
import io.opentelemetry.api.logs.Severity;
@@ -32,6 +30,9 @@ public final class LoggingEventMapper {
3230

3331
private static final Cache<String, AttributeKey<String>> mdcAttributeKeys = Cache.bounded(100);
3432

33+
// copied from EventIncubatingAttributes
34+
private static final AttributeKey<String> EVENT_NAME = AttributeKey.stringKey("event.name");
35+
3536
private final List<String> captureMdcAttributes;
3637

3738
private static final boolean captureExperimentalAttributes =
@@ -41,6 +42,11 @@ public final class LoggingEventMapper {
4142
// cached as an optimization
4243
private final boolean captureAllMdcAttributes;
4344

45+
private final boolean captureEventName =
46+
AgentInstrumentationConfig.get()
47+
.getBoolean(
48+
"otel.instrumentation.jboss-logmanager.experimental.capture-event-name", false);
49+
4450
private LoggingEventMapper() {
4551
this.captureMdcAttributes =
4652
AgentInstrumentationConfig.get()
@@ -75,55 +81,59 @@ public void capture(Logger logger, ExtLogRecord record) {
7581
builder.setSeverityText(level.toString());
7682
}
7783

78-
AttributesBuilder attributes = Attributes.builder();
79-
8084
Throwable throwable = record.getThrown();
8185
if (throwable != null) {
8286
// this cast is safe within java agent instrumentation
8387
((ExtendedLogRecordBuilder) builder).setException(throwable);
8488
}
85-
captureMdcAttributes(attributes);
89+
captureMdcAttributes(builder);
8690

8791
if (captureExperimentalAttributes) {
8892
Thread currentThread = Thread.currentThread();
89-
attributes.put(ThreadIncubatingAttributes.THREAD_NAME, currentThread.getName());
90-
attributes.put(ThreadIncubatingAttributes.THREAD_ID, currentThread.getId());
93+
builder.setAttribute(ThreadIncubatingAttributes.THREAD_NAME, currentThread.getName());
94+
builder.setAttribute(ThreadIncubatingAttributes.THREAD_ID, currentThread.getId());
9195
}
9296

93-
builder.setAllAttributes(attributes.build());
94-
9597
builder.setContext(Context.current());
9698

9799
builder.setTimestamp(record.getMillis(), MILLISECONDS);
98100
builder.emit();
99101
}
100102

101-
private void captureMdcAttributes(AttributesBuilder attributes) {
103+
private void captureMdcAttributes(LogRecordBuilder builder) {
102104

103105
Map<String, String> context = MDC.copy();
104106

105107
if (captureAllMdcAttributes) {
106108
if (context != null) {
107109
for (Map.Entry<String, String> entry : context.entrySet()) {
108-
attributes.put(
109-
getMdcAttributeKey(String.valueOf(entry.getKey())), String.valueOf(entry.getValue()));
110+
setAttributeOrEventName(builder, getMdcAttributeKey(entry.getKey()), entry.getValue());
110111
}
111112
}
112113
return;
113114
}
114115

115116
for (String key : captureMdcAttributes) {
116117
Object value = context.get(key);
117-
if (value != null) {
118-
attributes.put(key, value.toString());
119-
}
118+
setAttributeOrEventName(builder, getMdcAttributeKey(key), value);
120119
}
121120
}
122121

123122
public static AttributeKey<String> getMdcAttributeKey(String key) {
124123
return mdcAttributeKeys.computeIfAbsent(key, AttributeKey::stringKey);
125124
}
126125

126+
private void setAttributeOrEventName(
127+
LogRecordBuilder builder, AttributeKey<String> key, Object value) {
128+
if (value != null) {
129+
if (captureEventName && key.equals(EVENT_NAME)) {
130+
builder.setEventName(value.toString());
131+
} else {
132+
builder.setAttribute(key, value.toString());
133+
}
134+
}
135+
}
136+
127137
private static Severity levelToSeverity(java.util.logging.Level level) {
128138
int levelInt = level.intValue();
129139
if (levelInt >= Level.FATAL.intValue()) {

instrumentation/jboss-logmanager/jboss-logmanager-appender-1.1/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/jbosslogmanager/appender/v1_1/JbossLogmanagerTest.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -202,11 +202,13 @@ private static void performLogging(
202202
void testMdc() {
203203
MDC.put("key1", "val1");
204204
MDC.put("key2", "val2");
205+
MDC.put("event.name", "MyEventName");
205206
try {
206207
logger.info("xyz");
207208
} finally {
208209
MDC.remove("key1");
209210
MDC.remove("key2");
211+
MDC.remove("event.name");
210212
}
211213

212214
testing.waitAndAssertLogRecords(
@@ -216,6 +218,7 @@ void testMdc() {
216218
.hasInstrumentationScope(InstrumentationScopeInfo.builder("abc").build())
217219
.hasSeverity(Severity.INFO)
218220
.hasSeverityText("INFO")
221+
.hasEventName("MyEventName")
219222
.hasAttributesSatisfyingExactly(
220223
equalTo(AttributeKey.stringKey("key1"), "val1"),
221224
equalTo(AttributeKey.stringKey("key2"), "val2"),

instrumentation/log4j/log4j-appender-1.2/javaagent/README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,5 +5,6 @@
55
| `otel.instrumentation.log4j-appender.experimental-log-attributes` | Boolean | `false` | Enable the capture of experimental log attributes `thread.name` and `thread.id`. |
66
| `otel.instrumentation.log4j-appender.experimental.capture-code-attributes` | Boolean | `false` | Enable the capture of [source code attributes]. Note that capturing source code attributes at logging sites might add a performance overhead. |
77
| `otel.instrumentation.log4j-appender.experimental.capture-mdc-attributes` | String | | Comma separated list of context data attributes to capture. Use the wildcard character `*` to capture all attributes. |
8+
| `otel.instrumentation.log4j-appender.experimental.capture-event-name` | Boolean | `false` | Enable moving the `event.name` attribute (captured by one of the other mechanisms of capturing attributes) to the log event name. |
89

910
[source code attributes]: https://github.com/open-telemetry/semantic-conventions/blob/main/docs/general/attributes.md#source-code-attributes

instrumentation/log4j/log4j-appender-1.2/javaagent/build.gradle.kts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ tasks.withType<Test>().configureEach {
3535
// TODO run tests both with and without experimental log attributes
3636
jvmArgs("-Dotel.instrumentation.log4j-appender.experimental.capture-mdc-attributes=*")
3737
jvmArgs("-Dotel.instrumentation.log4j-appender.experimental.capture-code-attributes=true")
38-
jvmArgs("-Dotel.instrumentation.log4j-appender.experimental-log-attributes=true")
38+
jvmArgs("-Dotel.instrumentation.log4j-appender.experimental.capture-event-name=true")
3939
jvmArgs("-Dotel.instrumentation.log4j-appender.experimental-log-attributes=true")
4040
jvmArgs("-Dotel.instrumentation.common.experimental.controller-telemetry.enabled=true")
4141
}

instrumentation/log4j/log4j-appender-1.2/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/log4j/appender/v1_2/LogEventMapper.java

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

1010
import io.opentelemetry.api.GlobalOpenTelemetry;
1111
import io.opentelemetry.api.common.AttributeKey;
12-
import io.opentelemetry.api.common.Attributes;
13-
import io.opentelemetry.api.common.AttributesBuilder;
1412
import io.opentelemetry.api.incubator.logs.ExtendedLogRecordBuilder;
1513
import io.opentelemetry.api.logs.LogRecordBuilder;
1614
import io.opentelemetry.api.logs.Severity;
@@ -44,6 +42,8 @@ public final class LogEventMapper {
4442
private static final AttributeKey<Long> CODE_LINENO = AttributeKey.longKey("code.lineno");
4543
private static final AttributeKey<String> CODE_NAMESPACE =
4644
AttributeKey.stringKey("code.namespace");
45+
// copied from EventIncubatingAttributes
46+
private static final AttributeKey<String> EVENT_NAME = AttributeKey.stringKey("event.name");
4747
// copied from org.apache.log4j.Level because it was only introduced in 1.2.12
4848
private static final int TRACE_INT = 5000;
4949

@@ -56,6 +56,10 @@ public final class LogEventMapper {
5656
// cached as an optimization
5757
private final boolean captureAllMdcAttributes;
5858

59+
private final boolean captureEventName =
60+
AgentInstrumentationConfig.get()
61+
.getBoolean("otel.instrumentation.log4j-appender.experimental.capture-event-name", false);
62+
5963
private LogEventMapper() {
6064
List<String> captureMdcAttributes =
6165
AgentInstrumentationConfig.get()
@@ -98,49 +102,47 @@ public void capture(
98102
builder.setSeverityText(level.toString());
99103
}
100104

101-
AttributesBuilder attributes = Attributes.builder();
102-
103105
// throwable
104106
if (throwable != null) {
105107
if (builder instanceof ExtendedLogRecordBuilder) {
106108
((ExtendedLogRecordBuilder) builder).setException(throwable);
107109
} else {
108-
attributes.put(ExceptionAttributes.EXCEPTION_TYPE, throwable.getClass().getName());
109-
attributes.put(ExceptionAttributes.EXCEPTION_MESSAGE, throwable.getMessage());
110+
builder.setAttribute(ExceptionAttributes.EXCEPTION_TYPE, throwable.getClass().getName());
111+
builder.setAttribute(ExceptionAttributes.EXCEPTION_MESSAGE, throwable.getMessage());
110112
StringWriter writer = new StringWriter();
111113
throwable.printStackTrace(new PrintWriter(writer));
112-
attributes.put(ExceptionAttributes.EXCEPTION_STACKTRACE, writer.toString());
114+
builder.setAttribute(ExceptionAttributes.EXCEPTION_STACKTRACE, writer.toString());
113115
}
114116
}
115117

116-
captureMdcAttributes(attributes);
118+
captureMdcAttributes(builder);
117119

118120
if (captureExperimentalAttributes) {
119121
Thread currentThread = Thread.currentThread();
120-
attributes.put(ThreadIncubatingAttributes.THREAD_NAME, currentThread.getName());
121-
attributes.put(ThreadIncubatingAttributes.THREAD_ID, currentThread.getId());
122+
builder.setAttribute(ThreadIncubatingAttributes.THREAD_NAME, currentThread.getName());
123+
builder.setAttribute(ThreadIncubatingAttributes.THREAD_ID, currentThread.getId());
122124
}
123125

124126
if (captureCodeAttributes) {
125127
LocationInfo locationInfo = new LocationInfo(new Throwable(), fqcn);
126128
String fileName = locationInfo.getFileName();
127129
if (fileName != null) {
128130
if (SemconvStability.isEmitStableCodeSemconv()) {
129-
attributes.put(CodeAttributes.CODE_FILE_PATH, fileName);
131+
builder.setAttribute(CodeAttributes.CODE_FILE_PATH, fileName);
130132
}
131133
if (SemconvStability.isEmitOldCodeSemconv()) {
132-
attributes.put(CODE_FILEPATH, fileName);
134+
builder.setAttribute(CODE_FILEPATH, fileName);
133135
}
134136
}
135137

136138
if (SemconvStability.isEmitStableCodeSemconv()) {
137-
attributes.put(
139+
builder.setAttribute(
138140
CodeAttributes.CODE_FUNCTION_NAME,
139141
locationInfo.getClassName() + "." + locationInfo.getMethodName());
140142
}
141143
if (SemconvStability.isEmitOldCodeSemconv()) {
142-
attributes.put(CODE_NAMESPACE, locationInfo.getClassName());
143-
attributes.put(CODE_FUNCTION, locationInfo.getMethodName());
144+
builder.setAttribute(CODE_NAMESPACE, locationInfo.getClassName());
145+
builder.setAttribute(CODE_FUNCTION, locationInfo.getMethodName());
144146
}
145147

146148
String lineNumber = locationInfo.getLineNumber();
@@ -154,49 +156,56 @@ public void capture(
154156
}
155157
if (codeLineNo >= 0) {
156158
if (SemconvStability.isEmitStableCodeSemconv()) {
157-
attributes.put(CodeAttributes.CODE_LINE_NUMBER, codeLineNo);
159+
builder.setAttribute(CodeAttributes.CODE_LINE_NUMBER, (long) codeLineNo);
158160
}
159161
if (SemconvStability.isEmitOldCodeSemconv()) {
160-
attributes.put(CODE_LINENO, codeLineNo);
162+
builder.setAttribute(CODE_LINENO, (long) codeLineNo);
161163
}
162164
}
163165
}
164166

165-
builder.setAllAttributes(attributes.build());
166-
167167
// span context
168168
builder.setContext(Context.current());
169169

170170
builder.setTimestamp(Instant.now());
171171
builder.emit();
172172
}
173173

174-
private void captureMdcAttributes(AttributesBuilder attributes) {
174+
private void captureMdcAttributes(LogRecordBuilder builder) {
175175

176176
Hashtable<?, ?> context = MDC.getContext();
177177

178178
if (captureAllMdcAttributes) {
179179
if (context != null) {
180180
for (Map.Entry<?, ?> entry : context.entrySet()) {
181-
attributes.put(
182-
getMdcAttributeKey(String.valueOf(entry.getKey())), String.valueOf(entry.getValue()));
181+
setAttributeOrEventName(
182+
builder, getMdcAttributeKey(String.valueOf(entry.getKey())), entry.getValue());
183183
}
184184
}
185185
return;
186186
}
187187

188188
for (Map.Entry<String, AttributeKey<String>> entry : captureMdcAttributes.entrySet()) {
189189
Object value = context.get(entry.getKey());
190-
if (value != null) {
191-
attributes.put(entry.getValue(), value.toString());
192-
}
190+
setAttributeOrEventName(builder, entry.getValue(), value);
193191
}
194192
}
195193

196194
private static AttributeKey<String> getMdcAttributeKey(String key) {
197195
return mdcAttributeKeys.computeIfAbsent(key, AttributeKey::stringKey);
198196
}
199197

198+
private void setAttributeOrEventName(
199+
LogRecordBuilder builder, AttributeKey<String> key, Object value) {
200+
if (value != null) {
201+
if (captureEventName && key.equals(EVENT_NAME)) {
202+
builder.setEventName(value.toString());
203+
} else {
204+
builder.setAttribute(key, value.toString());
205+
}
206+
}
207+
}
208+
200209
private static Severity levelToSeverity(Priority level) {
201210
int lev = level.toInt();
202211
if (lev <= TRACE_INT) {

instrumentation/log4j/log4j-appender-1.2/javaagent/src/test/java/io/opentelemetry/instrumentation/log4j/appender/v1_2/Log4j1Test.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -176,11 +176,13 @@ private static void test(
176176
void testMdc() {
177177
MDC.put("key1", "val1");
178178
MDC.put("key2", "val2");
179+
MDC.put("event.name", "MyEventName");
179180
try {
180181
logger.info("xyz");
181182
} finally {
182183
MDC.remove("key1");
183184
MDC.remove("key2");
185+
MDC.remove("event.name");
184186
}
185187

186188
List<AttributeAssertion> assertions =
@@ -195,6 +197,7 @@ void testMdc() {
195197
logRecord ->
196198
logRecord
197199
.hasBody("xyz")
200+
.hasEventName("MyEventName")
198201
.hasInstrumentationScope(InstrumentationScopeInfo.builder("abc").build())
199202
.hasSeverity(Severity.INFO)
200203
.hasSeverityText("INFO")

instrumentation/log4j/log4j-appender-2.17/javaagent/README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,5 +7,6 @@
77
| `otel.instrumentation.log4j-appender.experimental.capture-map-message-attributes` | Boolean | `false` | Enable the capture of `MapMessage` attributes. |
88
| `otel.instrumentation.log4j-appender.experimental.capture-marker-attribute` | Boolean | `false` | Enable the capture of Log4j markers as attributes. |
99
| `otel.instrumentation.log4j-appender.experimental.capture-mdc-attributes` | String | | Comma separated list of context data attributes to capture. Use the wildcard character `*` to capture all attributes. |
10+
| `otel.instrumentation.log4j-appender.experimental.capture-event-name` | Boolean | `false` | Enable moving the `event.name` attribute (captured by one of the other mechanisms of capturing attributes) to the log event name. |
1011

1112
[source code attributes]: https://github.com/open-telemetry/semantic-conventions/blob/main/docs/general/attributes.md#source-code-attributes

instrumentation/log4j/log4j-appender-2.17/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/log4j/appender/v2_17/Log4jHelper.java

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,9 @@ public final class Log4jHelper {
5252
List<String> captureContextDataAttributes =
5353
config.getList(
5454
"otel.instrumentation.log4j-appender.experimental.capture-mdc-attributes", emptyList());
55+
boolean captureEventName =
56+
config.getBoolean(
57+
"otel.instrumentation.log4j-appender.experimental.capture-event-name", false);
5558

5659
mapper =
5760
new LogEventMapper<>(
@@ -60,7 +63,8 @@ public final class Log4jHelper {
6063
captureCodeAttributes,
6164
captureMapMessageAttributes,
6265
captureMarkerAttribute,
63-
captureContextDataAttributes);
66+
captureContextDataAttributes,
67+
captureEventName);
6468
}
6569

6670
public static void capture(

0 commit comments

Comments
 (0)