如何修改log4j JsonLayout字段名

zy1mlcev  于 2023-05-23  发布在  其他
关注(0)|答案(5)|浏览(164)

我已经用这个配置文件配置了log4j 2,将我的MapMessage写入控制台:

<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="ERROR">
    <Properties>
        <Property name="disableThreadContext">true</Property>
        <Property name="disableThreadContextStack">true</Property>
        <Property name="disableThreadContextMap">true</Property>
        <Property name="log4j2.disable.jmx">true</Property>
    </Properties>
    <Appenders>
        <Console name="CONSOLE" target="SYSTEM_OUT">
            <JsonLayout locationInfo="true" complete="false" />
        </Console>
    </Appenders>
    <Loggers>
        <logger name="ir.cvas.logger" level="info" />
        <Root level="warn">
            <AppenderRef ref="CONSOLE"/>
        </Root>
    </Loggers>
</Configuration>

此配置的输出如下所示:

{
  "timeMillis" : 1404902036494,
  "thread" : "main",
  "level" : "ERROR",
  "loggerName" : "ir.cvas.log4j.json.Main",
  "message" : "description=\"I'm so fucked...\" id=\"12312312312312321\"",
  "endOfBatch" : false,
  "loggerFqcn" : "org.apache.logging.log4j.spi.AbstractLogger",
  "source" : {
    "class" : "ir.cvas.log4j.json.Main",
    "method" : "main",
    "file" : "Main.java",
    "line" : 24
  }
}

1.我需要从输出中删除一些字段,如endOfBatchloggerFqcn。这可能吗?
1.我不太喜欢MapMessage的转换方式。我想要像Json对象那样的东西,而不是单个字符串,像这样的东西:"message": { "description"="I'm so fucked...", "id"="12312312312312321" }或至少展平MapMessage字段以记录消息。
1.我想把时间戳字段转换为unix时间与毫秒删除。
有人能帮忙吗?

mzsu5hc0

mzsu5hc01#

用户JsonTemplateLayout

Pom.xml:

<dependency>
    <groupId>org.apache.logging.log4j</groupId>
    <artifactId>log4j-layout-template-json</artifactId>
    <version>2.14.1</version>
</dependency>

log4j2.xml:

<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="INFO">
    <Appenders>
        <Console name="console" target="SYSTEM_OUT">
            <JsonTemplateLayout eventTemplateUri="classpath:JsonTemplateLayout.json" />
        </Console>
    </Appenders>
    <Loggers>
        <Logger name="com.logging.a.b" level="error" additivity="false">
            <AppenderRef ref="console" />
        </Logger>
    </Loggers>
</Configuration>

src/main/resources/JsonTemplateLayout.json:

{
    "version": "1.1",
    "hostName": "${hostName}",
    "field1": "${env:JAVA_HOME}",
    "field2": "${sys:os.name}",
    "time": {
        "$resolver": "timestamp",
        "pattern": {
            "format": "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'",
            "timeZone": "UTC"
        }
    },
    "level": {
        "$resolver": "level",
        "field": "name"
    },
    "loggerName": {
        "$resolver": "logger",
        "field": "name"
    },
    "message": {
        "$resolver": "message",
        "stringified": true
    },
    "source": {
        "class": {
            "$resolver": "source",
            "field": "className"
        },
        "method": {
            "$resolver": "source",
            "field": "methodName"
        },
        "file": {
            "$resolver": "source",
            "field": "fileName"
        },
        "line": {
            "$resolver": "source",
            "field": "lineNumber"
        }
    },
}

您可以添加和删除字段,或通过更改上述模板文件来更改字段名称。查看更多示例:json template file

6kkfgxo0

6kkfgxo02#

您可以自定义JacksonFactory类,以便在日志条目中仅包含您想要的字段名称。JacksonFactory中的默认实现只从日志条目中排除两个字段,它们是location和properties(也基于参数、属性和源)。但如果你想排除更多的字段,你可以添加更多的字段名称排除在一组属性排除,这里是例子

ObjectWriter newWriter(final boolean locationInfo, final boolean properties, final boolean compact) {
        final SimpleFilterProvider filters = new SimpleFilterProvider();
        final Set<String> except = new HashSet<>(5);
        if (!locationInfo) {
            except.add(this.getPropertNameForSource());
        }
        if (!properties) {
            except.add(this.getPropertNameForContextMap());
    }

    except.add(this.getPropertNameForNanoTime());

    except.add("loggerFqcn");
    except.add("endOfBatch");
    filters.addFilter(Log4jLogEvent.class.getName(), SimpleBeanPropertyFilter.serializeAllExcept(except));

    final ObjectWriter writer = this.newObjectMapper().writer(compact ? this.newCompactPrinter() : this.newPrettyPrinter());

    return writer.with(filters);
}
v6ylcynt

v6ylcynt3#

我的回答基于this manual reference
1)显然,JSONLayout只接受charset、compact、complete、properties和locationInfo参数。不幸的是,根据我有限的研究,删除endOfBatch和loggerFqcn似乎不可能。(然而,这很奇怪,因为参考手册中的示例输出不包括这些字段。)
2)这几乎肯定是不可能的。log4j中的日志条目的概念涉及到一个字符串消息,可能是一个throwable,一个日志级别,以及一些其他的静态内容。如果不编写自定义类,自定义字段是不可能的。This SO question描述了如何做到这一点,尽管出于该问题的目的,最后使用了MDC。MDC不能满足您的需要,因为您希望在每个条目中都有不同的自定义字段。我不太明白你说的“压扁”是什么意思
3)不幸的是,这看起来也不像是可用的。PatternLayout的可定制性要好得多; AFAIK你必须自己定制JSONLayout。

0s7z1bwu

0s7z1bwu4#

可以使用Log4j扩展来实现这一点。参见https://github.com/metamx/sumologic-log4j2-appender/blob/master/src/main/java/com/sumologic/log4j/core/SumoJsonLayout.java#L117-L237以获取示例。基本上,您可以使用任何Jackson注解来扩展LogEvent,以自定义如何打印输出内容,但是您需要某种布局,以便将事件强制到自定义字段命名的事件对象中。

1cosmwyk

1cosmwyk5#

您可以使用下面链接中的解决方案来自定义这些属性。
https://stackoverflow.com/a/76303815/11092008

相关问题