Log4J2 JSONLAYOUT How to add custom Parameters

2020-06-25 04:18发布

How to add customized parameters to Log4j2’s JSONLAYOUT?

Also is there a way to add pattern to the JSONLAYOUT’s message element?

I have tried the options listed here ->
logging.apache.org/log4j/2.x/manual/layouts.html#JSONLayout

Please help!

标签: log4j2
2条回答
神经病院院长
2楼-- · 2020-06-25 05:03

As I understand it you're looking for a way to customize the format of the JSON output from the JSONLayout in a manner similar to how you can customize the PatternLayout by specifying "Conversion Patterns".

I believe the answer is that you can't customize the JSONLayout in the same manner. You can select the various pieces of information you want to be included in the message. For example, the documentation shows parameters like properties:

If true, the appender includes the thread context map in the generated JSON. Defaults to false.

So you can set various parameters to include certain kinds of information, but you don't have the direct control over the specific items that are included.

What you could do instead is to use ObjectMessage along with a JSON library to generate a JSON message. However, this would generate JSON within JSON (assuming you still wish to use JSONLayout with this approach). Here is some sample code to illustrate:

A class with a main method to generate a log message:

package example;

import java.util.HashMap;
import java.util.Map;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.json.JSONObject;

public class JsonMessageExample {

    private static final Logger log = LogManager.getLogger();
    
    public static void main(String[] args) {
        Map<String,String> msgMap = new HashMap<>();
        msgMap.put("myKey", "myValue");
        JSONObject message = new JSONObject(msgMap);
        log.info(message);
    }
}

The log4j2.xml config file:

<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="WARN">
    <Appenders>
        <Console name="Console" target="SYSTEM_OUT">
            <JSONLayout/>
        </Console>

    </Appenders>

    <Loggers>
        <Root level="debug">
            <AppenderRef ref="Console"/>
        </Root>
    </Loggers>
</Configuration>

The output from the above:

{
  "timeMillis" : 1510429852038,
  "thread" : "main",
  "level" : "INFO",
  "loggerName" : "example.JsonMessageExample",
  "message" : "{\"myKey\":\"myValue\"}",
  "endOfBatch" : false,
  "loggerFqcn" : "org.apache.logging.log4j.spi.AbstractLogger",
  "threadId" : 1,
  "threadPriority" : 5
}

As you can see, the message name value pair has a value that is a JSON string. In order to parse this you would have to parse the outer object as JSON, pull the message field and then parse its value as JSON as well.

However, if you use a different layout such as a very basic PatternLayout like this: <PatternLayout pattern="%m%n"/>

You will be able to generate just one level of JSON output and therefore only have to parse once. However, you would have to write your logic to obtain all of the data that you need in your message and stuff it into your map (and JSON object) because now you're simply dumping the contents of the map.

Sample output using same java code with the layout changed to PatternLayout as described above:

{"myKey":"myValue"}

EDIT:

You could even do something like the following if you want to use the "Conversion Patterns" of PatternLayout, output logs in JSON format, and not have to write the logic to obtain some of the specifics:

<PatternLayout>
    <pattern>{"timeMillis":"%d{UNIX_MILLIS}","thread":"%t","level":"%p","loggerName":"%c","message":%m}%n</pattern>
</PatternLayout>

Sample output:

{"timeMillis":"1510455694601","thread":"main","level":"INFO","loggerName":"example.JsonMessageExample","message":{"myKey":"myValue"}}
查看更多
家丑人穷心不美
3楼-- · 2020-06-25 05:10

Solution is to explicitly add log4j2’s 2.10.0 version. This version supports custom parameter in JSONLayout!

<Appenders>

    <Console name="Console" target="SYSTEM_OUT">
        <JSONLayout compact="true" eventEol="true">
            <KeyValuePair key="application" value="${sys:com.example.appname}"/>
        </JSONLayout>
    </Console>
    <Async name="AsyncAppender" bufferSize="80">
        <AppenderRef ref="Console"/>
    </Async>

</Appenders>
查看更多
登录 后发表回答