如何修改log4j JsonLayout字段名称

时间:2014-07-09 11:10:52

标签: java json log4j

我已使用此配置文件配置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。有可能吗?
  2. 我真的不喜欢MapMessage的转换方式。我想要像Json对象而不是单个字符串,像这样:"message": { "description"="I'm so fucked...", "id"="12312312312312321" }或者至少压平MapMessage个字段来记录消息。
  3. 我想将timestamp字段转换为unix时间,并删除毫秒。
  4. 有人可以帮忙吗?

4 个答案:

答案 0 :(得分:2)

您可以自定义JacksonFactory类,以便仅包含日志条目中所需的字段名称。 JacksonFactory中的默认实现仅排除日志条目中的两个字段,即位置和属性(也基于参数属性和源)。但是,如果要排除更多字段,可以添加更多字段名称以排除要排除的属性集,以下是示例

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);
}

答案 1 :(得分:0)

我的回答基于this manual reference

1)显然,JSONLayout采用的唯一参数是charset,compact,complete,properties和locationInfo。不幸的是,根据我的有限研究,删除endOfBatch和loggerFqcn似乎不可行。 (但这很奇怪,因为参考手册中的示例输出不包括这些字段。)

2)这几乎肯定不可能。 log4j中的日志条目的概念涉及字符串消息,可能是throwable,日志级别和一些其他静态事物。如果不编写自定义类,则无法使用自定义字段。 This SO question描述了这样做,尽管出于该问题的目的,最终使用了MDC。由于您希望每个条目中的自定义字段不同,因此MDC无法满足您的需求。我不确定你的意思是“扁平化”。

3)不幸的是,它看起来并不像它可用。 PatternLayout更加可定制; AFAIK你必须自己定制JSONLayout。

答案 2 :(得分:0)

可以使用Log4j扩展名执行此操作。有关示例,请参阅https://github.com/metamx/sumologic-log4j2-appender/blob/master/src/main/java/com/sumologic/log4j/core/SumoJsonLayout.java#L117-L237。基本上,您可以使用任何杰克逊注释来扩展LogEvent,以便自定义打印出来的内容,但是您需要某种布局才能将事件强制转换为自定义字段命名的事件对象。

答案 3 :(得分:0)

用户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