You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@logging.apache.org by "Volkan Yazici (Jira)" <ji...@apache.org> on 2022/01/21 13:22:00 UTC
[jira] [Commented] (LOG4J2-3358) 2.17.1: JsonLayout Context no longer working.
[ https://issues.apache.org/jira/browse/LOG4J2-3358?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=17480069#comment-17480069 ]
Volkan Yazici commented on LOG4J2-3358:
---------------------------------------
For one, I strongly recommend you to use [JSON Template Layout|https://logging.apache.org/log4j/2.x/manual/json-template-layout.html] instead, which is the successor to JSON Layout. I would personally refrain from lookups depending on the user-provided (i.e., {{LogEvent}}) data. Using {{mdc}} resolver of JSON Template Layout, you can have your configuration as follows:
{code:java}
JsonTemplateLayout layout = JsonTemplateLayout
.newBuilder()
.setConfiguration(new DefaultConfiguration())
.setEventTemplateUri("classpath:JsonLayout.json")
.setStackTraceEnabled(true)
.setLocationInfoEnabled(true)
.setEventTemplateAdditionalFields(new EventTemplateAdditionalField[] {
EventTemplateAdditionalField
.newBuilder()
.setFormat(EventTemplateAdditionalField.Format.JSON)
.setKey("who")
.setValue("{'$resolver': 'mdc', 'key': 'WHO', 'stringified': true}".replaceAll("'", "\""))
.build(),
EventTemplateAdditionalField
.newBuilder()
.setFormat(EventTemplateAdditionalField.Format.JSON)
.setKey("what")
.setValue("{'$resolver': 'mdc', 'key': 'WHAT', 'stringified': true}".replaceAll("'", "\""))
.build(),
EventTemplateAdditionalField
.newBuilder()
.setFormat(EventTemplateAdditionalField.Format.JSON)
.setKey("method")
.setValue("{'$resolver': 'mdc', 'key': 'METHOD', 'stringified': true}".replaceAll("'", "\""))
.build(),
EventTemplateAdditionalField
.newBuilder()
.setFormat(EventTemplateAdditionalField.Format.JSON)
.setKey("parameters")
.setValue("{'$resolver': 'mdc', 'key': 'PARAMETERS', 'stringified': true}".replaceAll("'", "\""))
.build(),
})
.build();
{code}
That said, I can indeed reproduce the issue. The following test passes on 2.17.0 and fails on 2.17.1:
{code:java}
@Test
public void jsonLayout_should_substitute_lookups() {
// Create the layout.
KeyValuePair[] additionalFields = {
KeyValuePair
.newBuilder()
.setKey("who")
.setValue("${ctx:WHO}")
.build()
};
JsonLayout layout = JsonLayout
.newBuilder()
.setConfiguration(new DefaultConfiguration())
.setAdditionalFields(additionalFields)
.build();
// Create a log event containing `WHO` key in MDC.
StringMap contextData = ContextDataFactory.createContextData();
contextData.putValue("WHO", "mduft");
LogEvent logEvent = Log4jLogEvent
.newBuilder()
.setContextData(contextData)
.build();
// Verify the `WHO` key.
String serializedLogEvent = layout.toSerializable(logEvent);
assertThat(serializedLogEvent).contains("\"who\": \"mduft\"");
}
{code}
I will try to figure out what is going on.
> 2.17.1: JsonLayout Context no longer working.
> ---------------------------------------------
>
> Key: LOG4J2-3358
> URL: https://issues.apache.org/jira/browse/LOG4J2-3358
> Project: Log4j 2
> Issue Type: Bug
> Components: Layouts
> Affects Versions: 2.17.1
> Reporter: Markus Duft
> Priority: Major
>
> We're creating a RollingFileAppender programmatically using a JsonLayout. This uses fields using ${ctx:...} expansion. This stopped working when upgrading from 2.17.0 to 2.17.1.
> The code is as follows:
> {code:java}
> /**
> * Creates a rolling file appender that write audit entries to a programmatically readable JSON file.
> */
> private RollingFileAppender createJsonAppender(Path logDir) {
> List<KeyValuePair> fields = new ArrayList<>();
> fields.add(KeyValuePair.newBuilder().setKey("who").setValue("${ctx:WHO}").build());
> fields.add(KeyValuePair.newBuilder().setKey("what").setValue("${ctx:WHAT}").build());
> fields.add(KeyValuePair.newBuilder().setKey("method").setValue("${ctx:METHOD}").build());
> fields.add(KeyValuePair.newBuilder().setKey("parameters").setValue("${ctx:PARAMETERS}").build());
> RollingFileAppender.Builder<?> builder = RollingFileAppender.newBuilder();
> builder.setName("auditJsonLogger");
> builder.withFileName(logDir.resolve(LOG_JSON_FILENAME).toString());
> builder.withFilePattern(logDir.resolve(LOG_JSON_FILEPATTERN).toString());
> builder.withPolicy(SizeBasedTriggeringPolicy.createPolicy("10M"));
> builder.setLayout(JsonLayout.newBuilder().setCompact(true).setEventEol(true).setConfiguration(new DefaultConfiguration())
> .setAdditionalFields(fields.toArray(new KeyValuePair[0])).build());
> builder.withStrategy(
> DefaultRolloverStrategy.newBuilder().withCompressionLevelStr(String.valueOf(Deflater.DEFAULT_COMPRESSION))
> .withMax(Integer.toString(LOG_MAX_INDEX)).withFileIndex("min").build());
> return builder.build();
> } {code}
> We also tried to use %X\{...} as well as $${ctx:...} expansions instead to no avail. The log file always contains the *literal* string we use in .setValue(), i.e. lines like this:
> {noformat}
> {"instant":{"epochSecond":1642756242,"nanoOfSecond":271091900},"thread":"hive/fsck","level":"INFO","message":"Execute","endOfBatch":false,"threadId":65,"threadPriority":5,"who":"${ctx:WHO}","what":"${ctx:WHAT}","method":"${ctx:METHOD}","parameters":"${ctx:PARAMETERS}"}{noformat}
> Reverting to 2.17.0 will correctly give lines like this in the JSON file:
> {noformat}
> {"instant":{"epochSecond":1642756430,"nanoOfSecond":923210700},"thread":"hive/fsck","level":"INFO","message":"Execute","endOfBatch":false,"threadId":62,"threadPriority":5,"who":"marku","what":"ObjectConsistencyCheckOperation","method":"-","parameters":"{dryRun=false, roots=[io.bdeploy/demo/client-app/linux:1.0.0, io.bdeploy/demo/client-app/linux:2.0.0, io.bdeploy/demo/client-app/windows:1.0.0, ...]}"}{noformat}
--
This message was sent by Atlassian Jira
(v8.20.1#820001)