Log4j 2 JSON 模式布局 + 日志记录 JSON 有效负载

2022-09-04 03:09:14

我正在使用ELK堆栈以及通过sl4j的log4j 2以及json模式布局来记录消息。我的所有日志都记录为消息。同样在我的一个日志中,我正在尝试记录从第三方服务收到的响应。但是这个响应体没有附加到结构中。但它更像是一个包含转义字符的字符串。jsonjsonjsonjson

如何注销最终日志。

 {
    "timeMillis": 1471862316416,
    "thread": "FioranoMQ Pubsub Session Thread",
    "level": "INFO",
    "loggerName": "com.mlp.eventing.bridge.fiorano.TopicMessageListener",
    "message": "{\"Msgtype\":\"SentToRabbitMqTest\",\"MessageData\":\"10\",\"opration\":\"devide\"}",
    "endOfBatch": false,
    "loggerFqcn": "org.apache.logging.slf4j.Log4jLogger",
    "threadId": 28,
    "threadPriority": 5
}

在上面的消息段中,作为转义字符串而不是整个结构追加。我预期的出局应该是json

{
    "timeMillis": 1471862316416,
    "thread": "FioranoMQ Pubsub Session Thread",
    "level": "INFO",
    "loggerName": "com.mlp.eventing.bridge.fiorano.TopicMessageListener",
    "message": {
        "Msgtype": "SentToRabbitMqTest",
        "MessageData": "10",
        "opration": "devide"
    },
    "endOfBatch": false,
    "loggerFqcn": "org.apache.logging.slf4j.Log4jLogger",
    "threadId": 28,
    "threadPriority": 5
}

我希望使用 grok 过滤器提取消息段中的字段jsonshipper.conf

以下是我的配置:- log4j2.xml

<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="info"> <!-- log4j internals tracing -->
    <properties>
        <property name="pattern">%d{yyyy-MM-dd HH:mm:ss.SSS} | %-5.5p | %-20.20C:%-5.5L | %msg%n</property>
        <property name="filePath">/opt/mlp/logs</property> 
        <property name="fileName">logs</property>
    </properties>
    <Appenders>
        <RollingFile name="RollingFile" fileName="${filePath}/${fileName}.log"
                     filePattern="${filePath}/${fileName}-%d{yyyy-MM-dd}-%i.log" append="true">
            <JSONLayout complete="false" compact="true" eventEol="true" />  
            <PatternLayout>
                <pattern>${pattern}</pattern>
            </PatternLayout>
            <Policies>
                <SizeBasedTriggeringPolicy size="1000 KB"/> 
            </Policies>l
        </RollingFile>
        <Console name="STDOUT" target="SYSTEM_OUT">
            <PatternLayout>
                <pattern>${pattern}</pattern>
            </PatternLayout>
        </Console>
    </Appenders>
    <Loggers>
        <Root level="debug">
            <AppenderRef ref="RollingFile"/>
            <AppenderRef ref="STDOUT"/>
        </Root>
    </Loggers>
</Configuration>

示例代码片段

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

class A {
private static final Logger LOG = LoggerFactory.getLogger(Main.class);

public void testMethod()  {

JSONObject responseJson = callService();// json simple object
LOG.info(responseJson);

}

}

maven dependencies

<dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-api</artifactId>
            <version>1.7.21</version>
        </dependency>

        <dependency>
            <groupId>org.apache.logging.log4j</groupId>
            <artifactId>log4j-slf4j-impl</artifactId>
            <version>2.6.2</version>
        </dependency>

        <!-- end adding sl4j 2 for the message bridge -->

        <dependency>
            <groupId>org.apache.logging.log4j</groupId>
            <artifactId>log4j-api</artifactId>
            <version>2.6.2</version>
        </dependency>

        <dependency>
            <groupId>org.apache.logging.log4j</groupId>
            <artifactId>log4j-core</artifactId>
            <version>2.6.2</version>
        </dependency>

        <!--
        to enable json support for log4j enable following libraries
        -->

        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-core</artifactId>
            <version>2.7.5</version>
        </dependency>

        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
            <version>2.7.5</version>
        </dependency>

        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-annotations</artifactId>
            <version>2.7.5</version>
        </dependency>

答案 1

为了能够记录未转义的 JSON,您应该使用 Log4j2 logger 而不是 Slf4j。此功能从 Log4j 2.11 开始可用。

Log4j记录器能够记录,这将被转换为嵌套的JSON。 构造函数接受 Map,因此 JSONObject 必须转换为 map(例如,在 Jackson 的帮助下)。ObjectMessageObjectMessageObjectMapper

在布局配置中添加:objectMessageAsJsonObject="true"

<JSONLayout complete="false" compact="true" eventEol="true" objectMessageAsJsonObject="true" />

完整的工作示例:

import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.message.ObjectMessage;
import org.json.JSONObject;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

public class test {

    public static void main(String[] args) throws IOException {
        HashMap<Object, Object> map = new HashMap<>();
        map.put("foo", "bar");
        JSONObject jsonObject = new JSONObject(map);

        Map<String, Object> newMap = new ObjectMapper().readValue(jsonObject.toString(), new TypeReference<Map<String, Object>>() {});

        Logger log4jLogger = LogManager.getLogger("mainLogger");
        log4jLogger.info(new ObjectMessage(newMap));
    }
}

这将产生:

{"thread":"main","level":"INFO","loggerName":"mainLogger","message":{"foo":"bar"},"endOfBatch":false,"loggerFqcn":"org.apache.logging.log4j.spi.AbstractLogger","instant":{"epochSecond":1548434758,"nanoOfSecond":572000000},"threadId":1,"threadPriority":5}

答案 2