Skip to content

Commit 023f30c

Browse files
Save ILoggingEvent.getArgumentArray() arguments from Logback (#11865)
Co-authored-by: Lauri Tulmin <[email protected]>
1 parent dee515d commit 023f30c

File tree

7 files changed

+91
-5
lines changed

7 files changed

+91
-5
lines changed

instrumentation/logback/logback-appender-1.0/javaagent/README.md

+1
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
| `otel.instrumentation.logback-appender.experimental.capture-marker-attribute` | Boolean | `false` | Enable the capture of Logback markers as attributes. |
88
| `otel.instrumentation.logback-appender.experimental.capture-key-value-pair-attributes` | Boolean | `false` | Enable the capture of Logback key value pairs as attributes. |
99
| `otel.instrumentation.logback-appender.experimental.capture-logger-context-attributes` | Boolean | `false` | Enable the capture of Logback logger context properties as attributes. |
10+
| `otel.instrumentation.logback-appender.experimental.capture-arguments` | Boolean | `false` | Enable the capture of Logback logger arguments. |
1011
| `otel.instrumentation.logback-appender.experimental.capture-mdc-attributes` | String | | Comma separated list of MDC attributes to capture. Use the wildcard character `*` to capture all attributes. |
1112

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

instrumentation/logback/logback-appender-1.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/logback/appender/v1_0/LogbackSingletons.java

+4
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,9 @@ public final class LogbackSingletons {
3636
config.getBoolean(
3737
"otel.instrumentation.logback-appender.experimental.capture-logger-context-attributes",
3838
false);
39+
boolean captureArguments =
40+
config.getBoolean(
41+
"otel.instrumentation.logback-appender.experimental.capture-arguments", false);
3942
List<String> captureMdcAttributes =
4043
config.getList(
4144
"otel.instrumentation.logback-appender.experimental.capture-mdc-attributes",
@@ -49,6 +52,7 @@ public final class LogbackSingletons {
4952
.setCaptureMarkerAttribute(captureMarkerAttribute)
5053
.setCaptureKeyValuePairAttributes(captureKeyValuePairAttributes)
5154
.setCaptureLoggerContext(captureLoggerContext)
55+
.setCaptureArguments(captureArguments)
5256
.build();
5357
}
5458

instrumentation/logback/logback-appender-1.0/library/README.md

+1
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,7 @@ The available settings are:
100100
| `captureMarkerAttribute` | Boolean | `false` | Enable the capture of Logback markers as attributes. |
101101
| `captureKeyValuePairAttributes` | Boolean | `false` | Enable the capture of Logback key value pairs as attributes. |
102102
| `captureLoggerContext` | Boolean | `false` | Enable the capture of Logback logger context properties as attributes. |
103+
| `captureArguments` | Boolean | `false` | Enable the capture of Logback logger arguments. |
103104
| `captureMdcAttributes` | String | | Comma separated list of MDC attributes to capture. Use the wildcard character `*` to capture all attributes. |
104105
| `numLogsCapturedBeforeOtelInstall` | Integer | 1000 | Log telemetry is emitted after the initialization of the OpenTelemetry Logback appender with an OpenTelemetry object. This setting allows you to modify the size of the cache used to replay the first logs. thread.id attribute is not captured. |
105106

instrumentation/logback/logback-appender-1.0/library/src/main/java/io/opentelemetry/instrumentation/logback/appender/v1_0/OpenTelemetryAppender.java

+11
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ public class OpenTelemetryAppender extends UnsynchronizedAppenderBase<ILoggingEv
3333
private boolean captureMarkerAttribute = false;
3434
private boolean captureKeyValuePairAttributes = false;
3535
private boolean captureLoggerContext = false;
36+
private boolean captureArguments = true;
3637
private List<String> captureMdcAttributes = emptyList();
3738

3839
private volatile OpenTelemetry openTelemetry;
@@ -79,6 +80,7 @@ public void start() {
7980
.setCaptureMarkerAttribute(captureMarkerAttribute)
8081
.setCaptureKeyValuePairAttributes(captureKeyValuePairAttributes)
8182
.setCaptureLoggerContext(captureLoggerContext)
83+
.setCaptureArguments(captureArguments)
8284
.build();
8385
eventsToReplay = new ArrayBlockingQueue<>(numLogsCapturedBeforeOtelInstall);
8486
super.start();
@@ -164,6 +166,15 @@ public void setCaptureLoggerContext(boolean captureLoggerContext) {
164166
this.captureLoggerContext = captureLoggerContext;
165167
}
166168

169+
/**
170+
* Sets whether the arguments should be set to logs.
171+
*
172+
* @param captureArguments To enable or disable capturing logger arguments
173+
*/
174+
public void setCaptureArguments(boolean captureArguments) {
175+
this.captureArguments = captureArguments;
176+
}
177+
167178
/** Configures the {@link MDC} attributes that will be copied to logs. */
168179
public void setCaptureMdcAttributes(String attributes) {
169180
if (attributes != null) {

instrumentation/logback/logback-appender-1.0/library/src/main/java/io/opentelemetry/instrumentation/logback/appender/v1_0/internal/LoggingEventMapper.java

+34-5
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,11 @@
2424
import java.io.PrintWriter;
2525
import java.io.StringWriter;
2626
import java.util.ArrayList;
27+
import java.util.Arrays;
2728
import java.util.List;
2829
import java.util.Map;
2930
import java.util.concurrent.TimeUnit;
31+
import java.util.stream.Collectors;
3032
import org.slf4j.Marker;
3133
import org.slf4j.event.KeyValuePair;
3234

@@ -53,6 +55,10 @@ public final class LoggingEventMapper {
5355

5456
private static final AttributeKey<List<String>> LOG_MARKER =
5557
AttributeKey.stringArrayKey("logback.marker");
58+
private static final AttributeKey<String> LOG_BODY_TEMPLATE =
59+
AttributeKey.stringKey("log.body.template");
60+
private static final AttributeKey<List<String>> LOG_BODY_PARAMETERS =
61+
AttributeKey.stringArrayKey("log.body.parameters");
5662

5763
private final boolean captureExperimentalAttributes;
5864
private final List<String> captureMdcAttributes;
@@ -61,6 +67,7 @@ public final class LoggingEventMapper {
6167
private final boolean captureMarkerAttribute;
6268
private final boolean captureKeyValuePairAttributes;
6369
private final boolean captureLoggerContext;
70+
private final boolean captureArguments;
6471

6572
private LoggingEventMapper(Builder builder) {
6673
this.captureExperimentalAttributes = builder.captureExperimentalAttributes;
@@ -69,6 +76,7 @@ private LoggingEventMapper(Builder builder) {
6976
this.captureMarkerAttribute = builder.captureMarkerAttribute;
7077
this.captureKeyValuePairAttributes = builder.captureKeyValuePairAttributes;
7178
this.captureLoggerContext = builder.captureLoggerContext;
79+
this.captureArguments = builder.captureArguments;
7280
this.captureAllMdcAttributes =
7381
builder.captureMdcAttributes.size() == 1 && builder.captureMdcAttributes.get(0).equals("*");
7482
}
@@ -173,6 +181,12 @@ private void mapLoggingEvent(
173181
captureLoggerContext(attributes, loggingEvent.getLoggerContextVO().getPropertyMap());
174182
}
175183

184+
if (captureArguments
185+
&& loggingEvent.getArgumentArray() != null
186+
&& loggingEvent.getArgumentArray().length > 0) {
187+
captureArguments(attributes, loggingEvent.getMessage(), loggingEvent.getArgumentArray());
188+
}
189+
176190
builder.setAllAttributes(attributes.build());
177191

178192
// span context
@@ -218,6 +232,13 @@ void captureMdcAttributes(AttributesBuilder attributes, Map<String, String> mdcP
218232
}
219233
}
220234

235+
void captureArguments(AttributesBuilder attributes, String message, Object[] arguments) {
236+
attributes.put(LOG_BODY_TEMPLATE, message);
237+
attributes.put(
238+
LOG_BODY_PARAMETERS,
239+
Arrays.stream(arguments).map(String::valueOf).collect(Collectors.toList()));
240+
}
241+
221242
public static AttributeKey<String> getMdcAttributeKey(String key) {
222243
return mdcAttributeKeys.computeIfAbsent(key, AttributeKey::stringKey);
223244
}
@@ -258,19 +279,20 @@ private static void captureKeyValuePairAttributes(
258279
if (keyValuePairs != null) {
259280
for (KeyValuePair keyValuePair : keyValuePairs) {
260281
Object value = keyValuePair.value;
261-
if (keyValuePair.value != null) {
282+
if (value != null) {
283+
String key = keyValuePair.key;
262284
// preserve type for boolean and numeric values, everything else is converted to String
263285
if (value instanceof Boolean) {
264-
attributes.put(keyValuePair.key, (Boolean) keyValuePair.value);
286+
attributes.put(key, (Boolean) value);
265287
} else if (value instanceof Byte
266288
|| value instanceof Integer
267289
|| value instanceof Long
268290
|| value instanceof Short) {
269-
attributes.put(keyValuePair.key, ((Number) keyValuePair.value).longValue());
291+
attributes.put(key, ((Number) value).longValue());
270292
} else if (value instanceof Double || value instanceof Float) {
271-
attributes.put(keyValuePair.key, ((Number) keyValuePair.value).doubleValue());
293+
attributes.put(key, ((Number) value).doubleValue());
272294
} else {
273-
attributes.put(getAttributeKey(keyValuePair.key), keyValuePair.value.toString());
295+
attributes.put(getAttributeKey(key), value.toString());
274296
}
275297
}
276298
}
@@ -358,6 +380,7 @@ public static final class Builder {
358380
private boolean captureMarkerAttribute;
359381
private boolean captureKeyValuePairAttributes;
360382
private boolean captureLoggerContext;
383+
private boolean captureArguments;
361384

362385
Builder() {}
363386

@@ -397,6 +420,12 @@ public Builder setCaptureLoggerContext(boolean captureLoggerContext) {
397420
return this;
398421
}
399422

423+
@CanIgnoreReturnValue
424+
public Builder setCaptureArguments(boolean captureArguments) {
425+
this.captureArguments = captureArguments;
426+
return this;
427+
}
428+
400429
public LoggingEventMapper build() {
401430
return new LoggingEventMapper(this);
402431
}

instrumentation/logback/logback-appender-1.0/library/src/slf4j2ApiTest/java/io/opentelemetry/instrumentation/logback/appender/v1_0/Slf4j2Test.java

+39
Original file line numberDiff line numberDiff line change
@@ -112,4 +112,43 @@ void multipleMarkers() {
112112
AttributeKey.stringArrayKey("logback.marker"),
113113
value -> assertThat(value).isEqualTo(Arrays.asList(markerName1, markerName2)));
114114
}
115+
116+
@Test
117+
void arguments() {
118+
logger
119+
.atInfo()
120+
.setMessage("log message {} and {}, bool {}, long {}")
121+
.addArgument("'world'")
122+
.addArgument(Math.PI)
123+
.addArgument(true)
124+
.addArgument(Long.MAX_VALUE)
125+
.log();
126+
127+
List<LogRecordData> logDataList = logRecordExporter.getFinishedLogRecordItems();
128+
assertThat(logDataList).hasSize(1);
129+
LogRecordData logData = logDataList.get(0);
130+
131+
assertThat(logData.getResource()).isEqualTo(resource);
132+
assertThat(logData.getInstrumentationScopeInfo()).isEqualTo(instrumentationScopeInfo);
133+
assertThat(logData.getBody().asString())
134+
.isEqualTo(
135+
"log message 'world' and 3.141592653589793, bool true, long 9223372036854775807");
136+
assertThat(logData.getAttributes().size()).isEqualTo(6);
137+
assertThat(logData.getAttributes())
138+
.hasEntrySatisfying(
139+
AttributeKey.stringArrayKey("log.body.parameters"),
140+
value ->
141+
assertThat(value)
142+
.isEqualTo(
143+
Arrays.asList(
144+
"'world'",
145+
String.valueOf(Math.PI),
146+
String.valueOf(true),
147+
String.valueOf(Long.MAX_VALUE))));
148+
assertThat(logData)
149+
.hasAttributesSatisfying(
150+
equalTo(
151+
AttributeKey.stringKey("log.body.template"),
152+
"log message {} and {}, bool {}, long {}"));
153+
}
115154
}

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

+1
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
<captureCodeAttributes>true</captureCodeAttributes>
1515
<captureMarkerAttribute>true</captureMarkerAttribute>
1616
<captureKeyValuePairAttributes>true</captureKeyValuePairAttributes>
17+
<captureArguments>true</captureArguments>
1718
<captureMdcAttributes>*</captureMdcAttributes>
1819
</appender>
1920

0 commit comments

Comments
 (0)