You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

JBoss LogManager转义Log4j2 JSON日志致格式损坏求解

问题背景

我已将日志从文件文本输出改为标准输出JSON格式,以便将可解析的JSON日志发送至带Kibana的Elastic Stack。WildFly服务器(版本22.0.1.Final或26.1.3.Final)使用的JBoss Logger也已切换为结构化可解析的JSON日志输出到标准输出。JBoss Logger会将Java应用(基于Log4j2)的日志包裹进自身日志消息,并补充额外上下文信息。

遇到的问题

当JBoss Logger和Log4j2均配置为JSON格式时,应用的JSON日志在被JBoss Logger处理前会被转义,导致JSON格式损坏,后续工作流无法解析。例如message字段中的引号会变成\"log.level\": \"INFO\",而非正常的"log.level": "INFO"。若将JBoss Logger改回文本格式,应用JSON日志格式恢复正常,但我希望同时保留JBoss日志和应用日志的JSON格式。

需求

如何在开启JBoss Logger JSON格式的前提下,禁用应用日志的转义,让应用Log4j2的JSON日志嵌套在JBoss的JSON日志中仍保持有效格式?

配置信息

WildFly/JBoss Logger配置

<subsystem xmlns="urn:jboss:domain:logging:8.0">
    <console-handler name="CONSOLE">
        <level name="INFO"/>
        <formatter>
            <named-formatter name="JSON"/>
        </formatter>
    </console-handler>
    <periodic-rotating-file-handler name="FILE" autoflush="true">
        <formatter>
            <named-formatter name="PATTERN"/>
        </formatter>
        <file relative-to="jboss.server.log.dir" path="server.log"/>
        <suffix value=".yyyy-MM-dd"/>
        <append value="true"/>
    </periodic-rotating-file-handler>
    <logger category="com.arjuna">
        <level name="WARN"/>
    </logger>
    <logger category="io.jaegertracing.Configuration">
        <level name="WARN"/>
    </logger>
    <logger category="org.jboss.as.config">
        <level name="DEBUG"/>
    </logger>
    <logger category="sun.rmi">
        <level name="WARN"/>
    </logger>
    <root-logger>
        <level name="INFO"/>
        <handlers>
            <handler name="CONSOLE"/>
            <handler name="FILE"/>
        </handlers>
    </root-logger>
    <formatter name="PATTERN">
        <pattern-formatter pattern="%d{yyyy-MM-dd HH:mm:ss,SSS} %-5p [%c] (%t) %s%e%n"/>
    </formatter>
    <formatter name="COLOR-PATTERN">
        <pattern-formatter pattern="%K{level}%d{HH:mm:ss,SSS} %-5p [%c] (%t) %s%e%n"/>
    </formatter>
    <formatter name="JSON">
        <json-formatter/>
    </formatter>
</subsystem>

Log4j2(版本2.19.0)配置

<?xml version="1.0" encoding="UTF-8"?>
<Configuration packages="org.my_project_x.logging" status="WARN" strict="true" verbose="true">
    <Appenders>
        <Console name="myConsoleLog">
            <IgnoreExceptions>false</IgnoreExceptions>
            <EcsLayout serviceName="my_project_x" serviceVersion="${serverVersion}" includeOrigin="true" eventDataset="my_project_x.log">
                <KeyValuePair key="hostname" value="%hostname"/>
                <KeyValuePair key="environment" value="develop"/>
                <KeyValuePair key="user.id" value="%userId"/>
            </EcsLayout>
        </Console>
    </Appenders>

    <Loggers>
        <Logger name="org.my_project_x">
            <Level>INFO</Level>
        </Logger>
        
        <Root>
            <AppenderRef ref="myConsoleLog"/>
            <Level>WARN</Level>
        </Root>
    </Loggers>
</Configuration>
解决方案

方案1:绕过JBoss Logger,让Log4j2直接输出原始JSON

默认情况下Log4j2的ConsoleAppender输出会被JBoss Logger捕获并二次格式化,要避免嵌套转义,可让Log4j2直接写入标准输出流,并关闭JBoss对应用日志的处理:

  1. 更新Log4j2的ConsoleAppender配置,指定输出目标为原始标准输出:
<Console name="myConsoleLog" target="SYSTEM_OUT">
    <IgnoreExceptions>false</IgnoreExceptions>
    <EcsLayout serviceName="my_project_x" serviceVersion="${serverVersion}" includeOrigin="true" eventDataset="my_project_x.log">
        <KeyValuePair key="hostname" value="%hostname"/>
        <KeyValuePair key="environment" value="develop"/>
        <KeyValuePair key="user.id" value="%userId"/>
    </EcsLayout>
</Console>
  1. 在WildFly的logging subsystem中,为应用日志类别添加use-parent-handlers="false",阻止JBoss处理这些日志:
<logger category="org.my_project_x" use-parent-handlers="false">
    <level name="INFO"/>
</logger>

此方案下应用日志直接输出原始JSON,JBoss自身日志保持JSON格式,两者互不干扰,Elastic Stack可分别解析两类日志。

方案2:配置JBoss JSON Formatter解析嵌套JSON

若希望应用日志仍被JBoss Logger包裹,但保持内部JSON有效性,可开启JBoss JSON formatter的消息解析功能,将应用日志的JSON字段合并到顶层JSON对象中:
更新JBoss的JSON formatter配置,添加parse-message="true":

<formatter name="JSON">
    <json-formatter parse-message="true"/>
</formatter>

该配置会让JBoss Logger解析应用日志的JSON内容,将其中的字段(如log.level、serviceName等)直接合并到自身生成的JSON对象里,而非将整个JSON作为转义字符串放在message字段中。注意:此功能要求应用输出的日志是严格有效的JSON,否则可能导致解析失败。

方案3:统一使用JBoss Logger处理所有日志

若无需保留Log4j2的独立格式,可移除应用中的Log4j2配置,让所有日志通过JBoss Logger输出,统一使用JBoss的JSON formatter:

  1. 移除应用中的Log4j2配置文件,或排除Log4j2依赖,让应用使用JBoss提供的日志API(SLF4J + JBoss Logger)。
  2. 在JBoss的logging subsystem中通过additional-field添加所需的自定义字段:
<formatter name="JSON">
    <json-formatter>
        <additional-field name="serviceName" value="my_project_x"/>
        <additional-field name="environment" value="develop"/>
        <additional-field name="hostname" value="${jboss.host.name}"/>
    </json-formatter>
</formatter>

此方式可完全统一日志格式,避免嵌套转义问题,但需修改应用的日志依赖和配置。


内容的提问来源于stack exchange,提问作者Ferdi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.23 12:27:54