如何使用Log4j2 xml重写附加程序在登录文件之前修改LogEvent

 攻玉是我_944 发布于 2023-01-19 17:21

我想在log4j2.xml文件中使用重写追加程序,以便在记录之前可以修改日志。我没有从Google获得太多帮助。根据log4j2文档,Rewrite是具有重写方法的接口,而MapRewritePolicy是实现类,当我运行该类时,我可以看到我的web3.log文件正在生成,但是看不到日志内容的任何修改。我看到了MapRewritePolicy源代码,并在我的项目中将本地实现类创建为MapRewritePolicyImpl.java,并放置了一些System.out来查看代码流从log4j2.xml文件进入此类。我已经修改了log4j2.xml以使用MapRewritePolicyImpl.java,但是代码流没有进入MapRewritePolicyImpl.java类。


            
             
                
             
        



    
        
            
                
                
                    
                    

                
            
            
                
                 
                    
                 
            
    
    
        
            
            
        
    

Frederic Lei.. 5

解决方案1:使用RewriteAppender

您的示例似乎几乎是正确的。如@Remko Popma所述,您选择的Rewrite实现不适合您的用例。

如果您使用自己的Rewriter实现,则可以使其生效。

我在这里找到了一个很好的示例:RewriteAppender示例

该示例包含log4j2.xml和RewriteAppender的实现。在RewriteAppender(此处称为MarkerInjectorRewritePolicy)中,您可以修改事件以适合您的需求。在示例中,作者注入了一些标记数据,您将不需要该部分。

解决方案2:使用LogEventFactory

解决方案1具有一些缺点。假设您有100个记录器和50个Appender。现在,尝试实施解决方案1时,您最终会得到另外50个RewriteAppender声明以及对所有记录器的调整,以使用重定向记录器而不是实际的目标Appender。这可能非常繁琐且容易出错。

一个更简单的解决方案是:

// Do this somewhere before using the logger
System.setProperty(Constants.LOG4J_LOG_EVENT_FACTORY, MyLogEventFactory.class.getName());

或使用start参数进行设置:

-DLog4jLogEventFactory=my.package.MyLogEventFactory

编辑:更好:设置此功能的更强大的方法是使用log4j2.component.properties

创建一个名为的文本文件log4j2.component.properties,并将其放在您的类路径中。

将以下代码放入其中: Log4jLogEventFactory = my.package.MyLogEventFactory

该文件由log4j自动加载,并用于配置多个核心设置。使用该文件,您不必每次都传递起始参数,而且您也不会遇到类初始化排序问题的潜在问题(例如使用时System.setProperty())。

LogEventFactory实现非常简单:

public class MyLogEventFactory implements LogEventFactory {

    @Override
    public LogEvent createEvent(String loggerName, Marker marker, String fqcn, Level level, Message message,
            List properties, Throwable t) {
        { // In my case i wanted "log.error(new Exception(msg))"
          // to pass the exception properly to the event,
          // as if "log.error(msg, new Exception(msg))" was called.
            if (t == null && message instanceof ObjectMessage) {
                ObjectMessage msg = (ObjectMessage) message;
                t = msg.getThrowable();
            }
        }
        // XXX do your adjustments here
        return new Log4jLogEvent(loggerName, marker, fqcn, level, message, properties, t);
    }

}

LogEventFactory被用于创建LogEvents。因此,我们不再去侦听和操纵它们,而是直接前往源代码并在此处进行工作。

有了这个我们得到所有事件!

祝好运!玩得开心!

1 个回答
  • 解决方案1:使用RewriteAppender

    您的示例似乎几乎是正确的。如@Remko Popma所述,您选择的Rewrite实现不适合您的用例。

    如果您使用自己的Rewriter实现,则可以使其生效。

    我在这里找到了一个很好的示例:RewriteAppender示例

    该示例包含log4j2.xml和RewriteAppender的实现。在RewriteAppender(此处称为MarkerInjectorRewritePolicy)中,您可以修改事件以适合您的需求。在示例中,作者注入了一些标记数据,您将不需要该部分。

    解决方案2:使用LogEventFactory

    解决方案1具有一些缺点。假设您有100个记录器和50个Appender。现在,尝试实施解决方案1时,您最终会得到另外50个RewriteAppender声明以及对所有记录器的调整,以使用重定向记录器而不是实际的目标Appender。这可能非常繁琐且容易出错。

    一个更简单的解决方案是:

    // Do this somewhere before using the logger
    System.setProperty(Constants.LOG4J_LOG_EVENT_FACTORY, MyLogEventFactory.class.getName());
    

    或使用start参数进行设置:

    -DLog4jLogEventFactory=my.package.MyLogEventFactory
    

    编辑:更好:设置此功能的更强大的方法是使用log4j2.component.properties

    创建一个名为的文本文件log4j2.component.properties,并将其放在您的类路径中。

    将以下代码放入其中: Log4jLogEventFactory = my.package.MyLogEventFactory

    该文件由log4j自动加载,并用于配置多个核心设置。使用该文件,您不必每次都传递起始参数,而且您也不会遇到类初始化排序问题的潜在问题(例如使用时System.setProperty())。

    LogEventFactory实现非常简单:

    public class MyLogEventFactory implements LogEventFactory {
    
        @Override
        public LogEvent createEvent(String loggerName, Marker marker, String fqcn, Level level, Message message,
                List<Property> properties, Throwable t) {
            { // In my case i wanted "log.error(new Exception(msg))"
              // to pass the exception properly to the event,
              // as if "log.error(msg, new Exception(msg))" was called.
                if (t == null && message instanceof ObjectMessage) {
                    ObjectMessage msg = (ObjectMessage) message;
                    t = msg.getThrowable();
                }
            }
            // XXX do your adjustments here
            return new Log4jLogEvent(loggerName, marker, fqcn, level, message, properties, t);
        }
    
    }
    

    LogEventFactory被用于创建LogEvents。因此,我们不再去侦听和操纵它们,而是直接前往源代码并在此处进行工作。

    有了这个我们得到所有事件!

    祝好运!玩得开心!

    2023-01-19 17:23 回答
撰写答案
今天,你开发时遇到什么问题呢?
立即提问
热门标签
PHP1.CN | 中国最专业的PHP中文社区 | PNG素材下载 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有