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

LOG4J Json-Template-Layout如何仅添加指定HTTP头至headers对象?

解决Log4j Json-Template-Layout生成指定HTTP头的headers对象问题

方案一:使用MapMessage传递指定字段

直接通过MapMessage构造仅包含目标HTTP头的消息体,日志模板直接提取该消息的内容作为headers对象,完全避免MDC无关内容的混入。

代码示例(Java)

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.message.MapMessage;
import javax.servlet.http.HttpServletRequest;
import java.util.HashMap;
import java.util.Map;

public class RequestLogger {
    private static final Logger logger = LogManager.getLogger(RequestLogger.class);

    public void logRequest(HttpServletRequest request) {
        // 仅收集需要的HTTP头/请求字段
        Map<String, String> targetHeaders = new HashMap<>();
        targetHeaders.put("host", request.getHeader("Host"));
        targetHeaders.put("method", request.getMethod());
        targetHeaders.put("user_agent", request.getHeader("User-Agent"));
        // 可按需添加其他字段

        // 用MapMessage输出日志
        logger.info(new MapMessage(targetHeaders));
    }
}

Log4j2配置(XML示例)

<Configuration status="WARN">
    <Appenders>
        <Console name="Console" target="SYSTEM_OUT">
            <JsonTemplateLayout>
                <Template>
                    {
                        "timestamp": "$${date:yyyy-MM-dd'T'HH:mm:ss.SSSXXX}",
                        "level": "$${level}",
                        "logger_name": "$${loggerName}",
                        "headers": "$${map:}"
                    }
                </Template>
            </JsonTemplateLayout>
        </Console>
    </Appenders>
    <Loggers>
        <Root level="info">
            <AppenderRef ref="Console"/>
        </Root>
    </Loggers>
</Configuration>

${map:}会直接提取MapMessage中的所有键值对,作为headers对象的内容,确保只包含你指定的字段。

方案二:用Map Resolver从MDC筛选指定字段

如果已经将HTTP头存入MDC(但不想输出所有MDC内容),可以通过Map Resolver的构建器语法,仅提取需要的MDC键,构造headers对象。

步骤1:将指定头存入MDC

import org.apache.logging.log4j.ThreadContext;
import javax.servlet.http.HttpServletRequest;

public class RequestMDCInitializer {
    public void initMDC(HttpServletRequest request) {
        // 仅存入需要的字段到MDC
        ThreadContext.put("http_host", request.getHeader("Host"));
        ThreadContext.put("http_method", request.getMethod());
        ThreadContext.put("http_user_agent", request.getHeader("User-Agent"));
    }
}

步骤2:配置Json-Template-Layout筛选字段

<Configuration status="WARN">
    <Appenders>
        <Console name="Console" target="SYSTEM_OUT">
            <JsonTemplateLayout>
                <Template>
                    {
                        "timestamp": "$${date:yyyy-MM-dd'T'HH:mm:ss.SSSXXX}",
                        "level": "$${level}",
                        "logger_name": "$${loggerName}",
                        "headers": "$${map:builder:put('host', mdc('http_host')):put('method', mdc('http_method')):put('user_agent', mdc('http_user_agent')):build()}"
                    }
                </Template>
            </JsonTemplateLayout>
        </Console>
    </Appenders>
    <Loggers>
        <Root level="info">
            <AppenderRef ref="Console"/>
        </Root>
    </Loggers>
</Configuration>

这里通过map:builder逐个添加需要的键值对,每个值从MDC中读取指定的键,最终构建出仅包含目标字段的headers对象,不会混入其他MDC元素。

方案对比

  • MapMessage方案:无需依赖MDC,日志内容更独立,适合单次日志输出指定字段的场景;
  • Map Resolver+MDC方案:适合需要在多个日志中复用同一批HTTP头字段的场景,只需初始化一次MDC即可。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.07 13:05:23