[原]如何在程序运行时修改log4j日志文件名

最近在项目的开发过程中,遇到了一个问题:

由于整个系统的存储是基于NAS结构(如下图),因此在集群中,由于各个结点的机器状态相同,在记录日志文件的时候,不同节点的同一个logger会向NAS系统中的同一个文件写入日志。

这样就有一个问题:当多个进程同时操作一个文件的时候,不光IO操作可能会出现阻塞,日志文件格式是否被打乱也是个未知的情况。

况且,同一个日志文件记录了多台主机的日志,也不便于统计分析。因此,需要从文件目录和文件名上对不同主机的不用业务进行区分。

目前我们的日志系统是apache log4j,使用了DailyRollingFileAppender来记录日志。但是DailyRollingFileAppender在文件名的操作上,只能按日期区分,没法做更多的操作。有的同事提出每一台服务器的log4j配置文件都针对本机进行特有的log4j配置,这样虽然能够解决问题,但是这样带来的后果就是集群中的每一台机器都处于一个独立的状态,在机器书目庞大的时候,不便于管理于故障恢复。因此,我考虑在代码中修改log4j的日志文件目录和文件名,这样能够保证集群中的每一台机器都互为镜像。

我的log4j配置文件的片段是这样的:

log4j.appender.RING=org.apache.log4j.DailyRollingFileAppender

log4j.appender.RING.file=Behavior

log4j.appender.RING.DatePattern=’-‘yyyy-MM-dd’.log’

log4j.appender.RING.layout=org.apache.log4j.PatternLayout

log4j.appender.RING.layout.ConversionPattern= %m%n

上面定义了一个叫做RING的appender,它负责每天生成一个日志文件。

然后,log4j.logger.com.xxxxsoft.ns.search.advice.SearchBehaviorAdvice=INFO, RING

声明了类SearchBehaviorAdvice使用RING这个appender来记录日志。

在类SearchBehaviorAdvice中,我做了如下操作:

    private static final Logger logger = Logger.getLogger(SearchBehaviorAdvice.class);

   

    static{

        Appender appender = logger.getAppender("RING");

        if(appender instanceof FileAppender){

            FileAppender fappender = (FileAppender)appender;

            if(!fappender.getFile().startsWith("App1")){

                fappender.setFile("App1"+fappender.getFile());

                fappender.activateOptions();

            }

        }

    }

在初始化logger后,我通过获取logger的appender,来修改appender写入文件的文件名,再为该文件名添加一个前缀。这里直接硬编码为app1,将来可能就是ip地址+主机名+应用名等较为复杂的命名规则。

通过调用appender的activateOptions方法来激活针对appender的修改,之后的日志就记录在新的日志文件中了。

加载评论框需要翻墙