0

我们在生产环境中面临一个问题,在某些情况下日志文件没有得到翻转。我们正在使用 Log4j 版本 1.2.17 以及 apache.commons-logging。创建自定义附加程序以滚动文件。appender 扩展了 Log4j 的 FileAppender。下面是 subAppend(LoggingEvent event) 方法的算法:

long n = System.currentTimeMillis();
// Has the time come to roll the log file?
if (n >= nextCheck)
{
 now.setTime(n);
    nextCheck = rc.getNextCheckMillis(now);

    rollOver();
    reachedMaxSize = false;

 else
 {
     File f = new File(getFile());

     // Has the log file has exceeded its maximum size?
     if (!reachedMaxSize && f.length() > maxFileSize)
     {
         // Log file has reached it maximum size.
         reachedMaxSize = true;

         // Log one last message to the file stating the max has been reached.
         LoggingEvent exeededEvent = new LoggingEvent(
                      getClass().getName(),
                      Logger.getLogger(getClass().getName()),
                      Priority.ERROR,
                      "Maximum log file size has been reached ("+maxFileSize/1024+"KB)",
                      null);
       super.subAppend(exeededEvent);
     }

 // If the log has not reached its max size, write it. Otherwise,
 // send log event to stdout.
 if (!reachedMaxSize)
 {
     super.subAppend(event);
 }
 else
 {
     System.out.println(event.getRenderedMessage());
 }

这是 Log4j.properties 文件

log4j.rootLogger=INFO,RCFLog

log4j.appender.RCFLog=com.ge.medit.util.logging.MaxFileSizeRollingFileAppender
log4j.appender.RCFLog.File=runtime/logs/rcf.log
log4j.appender.RCFLog.DatePattern=yyyyMMdd'_'{0}
log4j.appender.RCFLog.Encoding=UTF-8
log4j.appender.RCFLog.Append=true

log4j.appender.ConsoleLog=org.apache.log4j.ConsoleAppender
log4j.appender.ConsoleLog.layout=org.apache.log4j.PatternLayout
log4j.appender.ConsoleLog.layout.ConversionPattern=%p [%t] %c{1}: %m%n

log4j.appender.RCFLog.layout=org.apache.log4j.PatternLayout
log4j.appender.RCFLog.layout.ConversionPattern=@%d{yyyyMMdd HH:mm:ss.SSS}@ %p {%t} %c{1}: %m%n

log4j.logger.GUIEVT=INFO

根据观察,系统上的日期发生了变化。日期设置为当前日期前 3 个月。

Current Date- 10th May 2018
nextCheck - 11th May 2018 00:00
Changed Date- 10th March 2018
No backup is created as a condition at line 3 failed.

5 月 11 日再次经过 12 小时后,日期更改为当前日期。到那时,文件的时间戳已更改为 3 月 10 日。由于没有 RollOver,下一次检查仍然是 2018 年 5 月 11 日 00:00。但是在 5 月 12 日 00:00,文件应该已经按照第 3 行的条件翻转,并且应该创建了一个新文件,但没有发生。此外,该文件已达到最大大小。从那时起,在系统重新启动之前没有日志。

Java 版本是java8u162。虽然我找不到任何说明它是否与 java 相关的帖子。

我试图在测试环境中重现相同的场景,但一切都按预期工作。

有没有人在使用 Log4j 时遇到过这样的问题?请分享您的意见。提前致谢。

4

2 回答 2

0

我得到了文件未备份的原因。有多个日期更改。据观察,日期首先更改为 10/05/2036,然后更改为 2021 年并更改回 10/03/2018,之后我们最终将日期更改为当前日期 11/05/2018。

因此,当日期更改为未来日期 2036 年 10 月 5 日。nextCheck 日期已更新为 2036 年 11 月 5 日。再次将日期更改回当前日期时,如果条件失败(现在(11/05/2018 >= 11/05/2036)。因此,仅当日期更改为 11/05/ 时才会进行备份2036 或更多。

需要将条件 if (n >= nextCheck) 更改为 if (n >= nextCheck || nextCheck - n > TimeConstants.MILLISECONDS_PER_DAY。此更改尚待测试。

感谢@Mark Bramnik 的快速回复。

于 2018-05-30T09:13:52.603 回答
0

我相信最好的方法就是调试代码,log4j 可以像其他任何代码一样调试,没有这个我们只能推测。

我从您的配置中看到,您使用com.ge.medit.util.logging.MaxFileSizeRollingFileAppender 的不是 log4j 的标准滚动文件附加程序(可能是您公司的自定义附加程序,可能有问题)。

如果您无法调试它,我只能提供一些提示,希望能有所帮助。

  1. 修改 appender 并用于org.apache.log4j.helpers.LogLog打印有关 appender 本身工作的一些信息,就像“在 log4j 中记录” - 根据严重性级别进入 System.out/System.err

  2. 通常翻转(参见“翻转”功能)是作为文件的一系列“重命名”来实现的。我曾经见过(再次,只是推测)这种方法只有在以下情况下才有效:

    • 你对文件有权限
    • 您的应用程序拥有文件中的唯一句柄(尤其与 Windows 操作系统相关)。

在调试中很容易跟踪,因为从技术上讲,重命名可能是通过java.io.File#renameTo返回真/假来完成的,具体取决于重命名操作是成功还是失败。

为了模拟这种情况,您可以部署“隐藏”代码,该代码只是用消息“淹没”日志(您可以使用 JMX,内部 Web servlet/消息处理程序 - 任何您想要的,但其中可以包含过多的在循环中记录消息(假),如下所示:

class MyHiddenMBean {
    Logger logger = ...
    public void doLogManyTimes(int times) {
         for(int i = 0; i < times; i++) {
             logger.info("Artificial Logging Message : " + i);
         }
    } 
}

您将立即达到最大文件(当然,您可以故意将其设置得非常小以更快地模拟),然后您将能够看到为什么renameTo不起作用

于 2018-05-28T12:24:44.517 回答