我将显示log4j2,其中JSONLayout与消息上的对象相同。 例如我的配置是:
cat log4j2.xml
<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="INFO">
<Appenders>
<Console name="Console" target="SYSTEM_OUT">
<PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/>
</Console>
<File name="Json" fileName="/home/jeus/log/loggerjson/main.log" bufferedIO="true" advertiseURI="file://home/jeus/log/loggerjson/main1.log" advertise="true">
<JSONLayout compact="true" locationInfo="true" complete="false" eventEol="true" properties="true" propertiesAsList="true"/>
</File>
</Appenders>
<Loggers>
<Root level="info">
<AppenderRef ref="Json"/>
</Root>
</Loggers>
我输出输出:
cat /home/jeus/log/loggerjson/main.log
{
"timeMillis":1502359773290,
"thread":"main",
"level":"INFO",
"loggerName":"com.jeus.logger.json.loggerjson.Main",
"message":"This message is a raw",
"endOfBatch":false,
"loggerFqcn":"org.apache.logging.log4j.spi.AbstractLogger",
"contextMap":[ ],
"threadId":1,
"threadPriority":5,
"source":{
"class":"com.jeus.logger.json.loggerjson.Main",
"method":"main",
"file":"Main.java",
"line":61
}
}
我添加了一个json对象来记录,但没有在消息中显示json对象,并用 \&#34; charecter
显示JSON对象:
{"line_id": 12,"play_name":"Jeus"}
我的日志代码:
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
public class Main {
private static final Logger LOGGER = LogManager.getLogger(Main.class);
public static void main(String[] args) {
String message = "{\"line_id\": 12,\"play_name\": \"Jeus\"}";
LOGGER.info(message);
}
}
输出是:
{
"timeMillis":1502361394238,
"thread":"main",
"level":"INFO",
"loggerName":"com.jeus.logger.json.loggerjson.Main",
"message":"{\"line_id\": 12,\"play_name\": \"Jeus\"}",
"endOfBatch":false,
"loggerFqcn":"org.apache.logging.log4j.spi.AbstractLogger",
"contextMap":[
],
"threadId":1,
"threadPriority":5,
"source":{
"class":"com.jeus.logger.json.loggerjson.Main",
"method":"main",
"file":"Main.java",
"line":62
}
}
但我会将消息显示为json对象同样如下:
"message":{"line_id": 12,"play_name":"Jeus"},
答案 0 :(得分:1)
这似乎与内置的JsonLayout无关。无论我尝试什么,只需在字段上执行toString而不是正确序列化。
一种解决方案是使用PatternLayout并将其格式化为JSON。
log4j.appender.frontEndAudit.layout=org.apache.log4j.PatternLayout
log4j.appender.frontEndAudit.layout.ConversionPattern={"timestamp":
"%d{MM/dd/yyyy HH:mm:ss:SSSS}", "class": "%C", "file": "%F", "level" :
"%5p", "line_number" : "%L", "logger_name": "frontEndAuditLog", "mdc":
"ipAddress": "%X{ipAddress}", "requestId":"%X{requestId}",
"sessionId":"%X{sessionId}"}, "message": %m, "method": "%M",
"source_host":"%X{sourceHost}", "thread_name": "%t" }%n
这是针对log4j1的,但同样的概念适用于log4j2
答案 1 :(得分:0)
事实证明,LogstashLayout是可以解决问题的自定义布局。
"message": "${json:message:json}"
文件中写入LogstashJsonEventLayoutV1.json
。MultiformatMessage
的Java对象,并以getFromattedMessage
方法返回JSON字符串。getMessageFormats()
方法还必须返回JSON
。答案 2 :(得分:0)
log4j-layout-template-json 在 2.14.0 版本中可用,并且可以完美地使用 MapMessage。如果使用 gradle,只需添加以下 gradle 依赖项
compile 'org.apache.logging.log4j:log4j-api:2.14.0'
compile 'org.apache.logging.log4j:log4j-core:2.14.0'
compile 'org.apache.logging.log4j:log4j-layout-template-json:2.14.0'
compile 'com.fasterxml.jackson.dataformat:jackson-dataformat-yaml:2.10.0'
compile 'com.fasterxml.jackson.dataformat:jackson-databind:2.10.0'
log4j2.yaml 看起来像
Configuration:
name: Default
Appenders:
Console:
name: LogToConsole
target: SYSTEM_OUT
JsonTemplateLayout:
eventTemplateUri: "classpath:LogstashJsonEventLayoutV1.json"
Loggers:
AsyncRoot:
level: info
additivity: false
AppenderRef:
- ref: LogToConsole
然后为您要记录和使用的对象(MyMapMessage)扩展 MapMessage
private static final org.apache.logging.log4j.Logger LOGGER = LogManager.getLogger(YourClass.class);
LOGGER.error(myMapMessage.getData());
答案 3 :(得分:0)
• 在 log4j2.xml 中,设置 objectMessageAsJsonObject 选项:
<JSONLayout objectMessageAsJsonObject="true" [...] />
• 使用 ObjectMessage(示例代码,与 jackson):
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.node.JsonNodeFactory;
import org.apache.logging.log4j.*;
import org.apache.logging.log4j.message.ObjectMessage;
JsonNodeFactory f = JsonNodeFactory.instance;
JsonNode event = f.objectNode()
.put("eventName", "abc")
.set("person", f.objectNode()
.put("firstName", "John")
.put("lastName", "Doe")
);
// "message":{"eventName":"abc","person":{"firstName":"John","lastName":"Doe"}}
logger.info(new ObjectMessage(event));
// "message":"{\"eventName\":\"abc\",\"person\":{\"firstName\":\"John\",\"lastName\":\"Doe\"}}"
logger.info(new ObjectMessage(event.toString()));