logback:合并控制台和logstash json的键/值

mlmc2os5  于 2023-01-19  发布在  Logstash
关注(0)|答案(1)|浏览(162)

在JVM项目中,我们使用logstash在生产服务器上记录包含附加JSON数据的消息。
问题是JSON很难在控制台中读取,所以我尝试更改为本地(dev)配置以使用PatternLayoutEncoder,并在本地有良好的、干净的日志。
我发现这个问题:https://github.com/logstash/logstash-logback-encoder/issues/136
结论是,使用logstashlogbackencoder5.0,我们现在可以用结构化参数统一键/值对。
我这样做了,效果很好,但我遇到的问题是,现在在logstash上,这些对在消息和JSON中都重复。

  • 对于控制台,我使用ch.qos.logback.classic.encoder.PatternLayoutEncoder
  • 对于JSON,我使用net.logstash.logback.encoder.LogstashEncoder
    要么我这么做
LOGGER.info("Some message", kv("user_id", 1));

logstash json如下所示:

{  message: "Some message", user_id: 1 }

但是控制台日志没有参数:

2018-04-10 08:38:38,042 INFO - Some message

否则我就这么做

LOGGER.info("Some message {}", kv("user_id", 1));

logstash json有重复的信息(不好):

{  message: "Some message user_id=1", user_id: 1 }

而控制台日志正是我所需要的:

2018-04-10 08:38:38,042 INFO - Some message user_id=1

"所以我的问题是"
我如何配置我的日志,以便以一种干净的方式在控制台中获得额外的信息,而不是在JSON中复制它们?

qyyhg6bp

qyyhg6bp1#

ArrayList<Object> argumentList = new ArrayList<>();
argumentList.add(StructuredArguments.kv("system", "MySystem"));
argumentList.add(StructuredArguments.kv("id", 1234L));
argumentList.add(StructuredArguments.kv("method", "MyMethod"));
log.info("some message", argumentList.toArray());

参数数组转换器:

import ch.qos.logback.classic.pattern.ClassicConverter;
import ch.qos.logback.classic.spi.ILoggingEvent;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import static java.util.Arrays.stream;
import static java.util.Optional.ofNullable;

public class ArgumentArrayConverter extends ClassicConverter {
    @Override
    public String convert(ILoggingEvent iLoggingEvent) {
        List<String> allArgs = new ArrayList<>();
        ofNullable(iLoggingEvent.getArgumentArray()).ifPresent(a -> 
            stream(a)
            .forEach(o -> allArgs.add(o.toString())));
        stream(iLoggingEvent.getMDCPropertyMap()
             .entrySet()
             .toArray())
             .forEach(o -> allArgs.add(o.toString()));
        Collections.sort(allArgs);
        return !allArgs.isEmpty() ? allArgs.toString() : "";
}

}
本地回登录配置:

<include resource="org/springframework/boot/logging/logback/defaults.xml"/>
        <conversionRule conversionWord="argumentArray" converterClass="com.nordea.swo.digi.ncr.config.logging.ArgumentArrayConverter" />
        <appender name="console" class="ch.qos.logback.core.ConsoleAppender">
            <withJansi>true</withJansi>
            <encoder class="ch.qos.logback.core.encoder.LayoutWrappingEncoder">
                <layout class="ch.qos.logback.classic.PatternLayout">
                    <Pattern> %date{"yyyy-MM-dd'T'HH:mm:ss,SSSZ", CET} %clr(%-5level) --- [%15.-15t] %cyan(%-40.40logger{39}) : %msg%argumentArray\r\n</Pattern>
                </layout>
            </encoder>
        </appender>
        <root level="info">
            <appender-ref ref="console"/>
        </root>
    </configuration>

回登录配置其他环境:

<configuration>
    <include resource="org/springframework/boot/logging/logback/defaults.xml"/>
    <appender name="console" class="ch.qos.logback.core.ConsoleAppender">
        <encoder class="ch.qos.logback.core.encoder.LayoutWrappingEncoder">
            <layout class="ch.qos.logback.contrib.json.classic.JsonLayout">
                <timestampFormat>yyyy-MM-dd'T'HH:mm:ss.SSSX</timestampFormat>
                <timestampFormatTimezoneId>Etc/UTC</timestampFormatTimezoneId>
                <jsonFormatter class="ch.qos.logback.contrib.jackson.JacksonJsonFormatter">
                    <prettyPrint>false</prettyPrint>
                </jsonFormatter>
                <appendLineSeparator>true</appendLineSeparator>
            </layout>
        </encoder>
    </appender>
    <root level="info">
        <appender-ref ref="console"/>
    </root>
</configuration>

本地输出:

some message[id=1234, method=MyMethod, system=MySystem]

输出其他环境:

{with timestamp and other thingies as well. . ." id":"1234", "method":"MyMethod", "system":"MySystem"}

相关问题