Java 自定义log4j日志管理器,以便在所有日志中包含前缀
在我的项目中,我有各种不同的模块,对于所有日志记录,它们在消息中配置一个前缀以进行隔离。比如说 私有静态最终记录器log=LogManager.getLogger(MethodHandles.lookup().lookupClass()) 项目1所有日志:Java 自定义log4j日志管理器,以便在所有日志中包含前缀,java,logging,log4j2,Java,Logging,Log4j2,在我的项目中,我有各种不同的模块,对于所有日志记录,它们在消息中配置一个前缀以进行隔离。比如说 私有静态最终记录器log=LogManager.getLogger(MethodHandles.lookup().lookupClass()) 项目1所有日志: log.info("{} my message my args{}", Project1.KEY, args); log.info("{} my message my args{}", Project2.KEY, args); 项目2所有
log.info("{} my message my args{}", Project1.KEY, args);
log.info("{} my message my args{}", Project2.KEY, args);
项目2所有日志:
log.info("{} my message my args{}", Project1.KEY, args);
log.info("{} my message my args{}", Project2.KEY, args);
每个模块如何配置LogManager
,以使密钥前缀自动附加到每条消息中,而不是手动提供密钥
我通过扩展AbstractMessageFactory
解决了这个问题,这种方法需要在每个模块中重复大量相同的代码
public class CustomLogManager extends LogManager {
private static final class CustomMessageFactory extends AbstractMessageFactory {
public static final CustomMessageFactory INSTANCE = new CustomMessageFactory();
private String messageWithPrefix(String message) {
return prefix + SEPARATOR + message;
}
@Override
public Message newMessage(String message, Object... params) {
return new ParameterizedMessage(messageWithPrefix(message), params);
}
@Override
public Message newMessage(final String message, final Object p0) {
return new ParameterizedMessage(messageWithPrefix(message), p0);
}
... other overloads ...
}
private static final Prefix prefix = Prefix.one;
public static Logger getLogger(final Class<?> clazz) {
return getLogger(clazz, CustomMessageFactory.INSTANCE);
}
}
公共类CustomLogManager扩展LogManager{
私有静态最终类CustomMessageFactory扩展了AbstractMessageFactory{
公共静态最终CustomMessageFactory实例=新建CustomMessageFactory();
私有字符串消息WithPrefix(字符串消息){
返回前缀+分隔符+消息;
}
@凌驾
公共消息newMessage(字符串消息、对象…参数){
返回新的参数化消息(messageWithPrefix(message),params);
}
@凌驾
公共消息newMessage(最终字符串消息,最终对象p0){
返回新的参数化消息(messageWithPrefix(message),p0);
}
…其他重载。。。
}
私有静态最终前缀前缀=Prefix.one;
公共静态记录器getLogger(最终类clazz){
返回getLogger(clazz,CustomMessageFactory.INSTANCE);
}
}
定制
ParameterizedMessageFactory
以仅包含前缀字符串是否可行?根据您的情况,我将创建一个界面,其中包含您正在查找的信息以及一个键—可能是每个jar特有的包名(我希望您不要在jar之间混合包名)。然后,我将在每个jar中创建该接口的实例,并按照java.util.ServiceLoader将其注册为服务
然后,我将创建一个Log4j2查找,它使用ServiceLoader查找所有实例,并在初始化期间将它们添加到映射中。然后,我会在我的Log4j配置中使用该查找来使用LogEvent中的Logger查找适当的值(假设Logger遵循使用类名作为名称的惯例)。您的问题的挑战是“什么是模块”?它是一个简单的jar文件,与所有其他jar都在同一个类加载器中吗?它是Java平台模块系统中的Java模块吗?它是某种其他插件吗?Log4j有几种方法可以做到这一点,但如果不了解如何确定哪个模块处于“活动”状态,则很难回答。@rgoers它们在gradle设置中是不同的项目。看见每个项目都在定义自己的
build.gradle
Ok。因此,我假设这与maven多模块项目相同,并且您正在生成多个JAR。是的,正确。所有这些都是作为单个jar生成的,我认为我不能定制log4j2.xml,因为它是在公共框架中构建的。