如何在LOG4J模式上有条件地添加MDC中的文本?

r1zhe5dt  于 2023-03-02  发布在  其他
关注(0)|答案(4)|浏览(159)

如何仅在MDC上设置了值的情况下打印log4j条目上的键/值对?
例如,我目前有以下模式:

%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - client=%X{client} %m%n

我只想在MDC上有这个键的值时打印“client=”部分。
例如,当启动我的程序时,没有客户端登录,因此将使用以下模式记录日志:

%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - %m%n

但是,在客户端登录之后(并且在我使用“client”键设置MDC之后),我需要使用以下命令打印它:

%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - client=%X{client} %m%n

log4j上有这样的“条件模式”吗?
谢谢

yqkkidmi

yqkkidmi1#

Log4j2中有一个%notEmpty模式,它允许您准确地实现这一点。

%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - %notEmpty{client=%X{client} }%m%n
siv3szwd

siv3szwd2#

我最终采纳了xav的建议。
我从log4j模式中删除了“client=”字符串,并在每次向MDC添加条目时附加它。这不是最漂亮的解决方案,但它工作得很好!
例如,如果我不使用

MDC.put("client", client.getId());

我现在使用:

MDC.put("client", "client="+client.getId().toString());
pu82cl6c

pu82cl6c3#

建议的hack将键的值作为MDC值,这有助于将键名绑定到代码中的某个常量。但这对微服务不好,例如标头被重新发送到其他服务,键名被复制

有一种简洁的SLF4J模式逻辑解决方案可以实现这一点:

%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - %replace( client=%mdc{client}){' client=$', ''} %m%n
bt1cpqcv

bt1cpqcv4#

我最近有一个类似的需求,虽然其他解决方案在很多情况下可以达到这个目的,但有时需要更多的控制。例如,我必须生成这样的东西:A:B,C,其中AB都是可选的。我无法找到一个解决方案,只使用一个模式就不会在C前面留下逗号。所以我最终创建了一个自定义转换器。
在OP的例子中,我们可以在模式中引入一个新的标记,例如%client(假设Log4j2)。

@Plugin(name = "ClientConverter", category = PatternConverter.CATEGORY)
@ConverterKeys({ "client" })
public class ClientConverter extends LogEventPatternConverter {

    private static final ClientConverter INSTANCE = new ClientConverter();

    private ClientConverter() {
        super("ClientConverter", null);
    }

    public static ClientConverter newInstance(String[] options) {
        return INSTANCE;
    }

    @Override
    public void format(LogEvent event, StringBuilder toAppendTo) {
        var context = event.getContextData();
        Optional.ofNullable(context.getValue("client"))
            .ifPresent(client -> toAppendTo.append("client=").append(client));

    }

}

相关问题