Log4j:事件出现在错误的日志文件中

时间:2009-08-28 09:10:52

标签: java file events log4j logging

为了能够记录和跟踪某些事件,我在我的java项目中添加了一个LoggingHandler类。在这个类中,我使用两个不同的log4j记录器实例 - 一个用于记录事件,另一个用于将事件跟踪到不同的文件中。该类的初始化块如下所示:

public void initialize()
{
    System.out.print("starting logging server ...");

    // create logger instances
    logLogger = Logger.getLogger("log");
    traceLogger = Logger.getLogger("trace");

    // create pattern layout
    String conversionPattern = "%c{2} %d{ABSOLUTE} %r %p %m%n";
    try
    {
        patternLayout = new PatternLayout();
        patternLayout.setConversionPattern(conversionPattern);
    }
    catch (Exception e)
    {
        System.out.println("error: could not create logger layout pattern");
        System.out.println(e);
        System.exit(1);
    }

    // add pattern to file appender
    try
    {
        logFileAppender = new FileAppender(patternLayout, logFilename, false);
        traceFileAppender = new FileAppender(patternLayout, traceFilename, false);
    }
    catch (IOException e)
    {
        System.out.println("error: could not add logger layout pattern to corresponding appender");
        System.out.println(e);
        System.exit(1);
    }

    // add appenders to loggers
    logLogger.addAppender(logFileAppender);
    traceLogger.addAppender(traceFileAppender);

    // set logger level
    logLogger.setLevel(Level.INFO);
    traceLogger.setLevel(Level.INFO);

    // start logging server
    loggingServer = new LoggingServer(logLogger, traceLogger, serverPort, this);
    loggingServer.start();

    System.out.println(" done");
}

为了确保只有一个线程正在使用记录器实例的功能,同时每个日志记录/跟踪方法在synchronized块中调用记录方法.info()。一个例子如下:

    public void logMessage(String message)
{
    synchronized (logLogger)
    {
        if (logLogger.isInfoEnabled() && logFileAppender != null)
        {
            logLogger.info(instanceName + ": " + message);
        }
    }
} 

如果我查看日志文件,我发现有时会在错误的文件中出现一个事件。一个例子:

trace 10:41:30,773 11080 INFO masterControl(192.168.2.21): string broadcast message was  pushed from 1267093 to vehicle 1055293 (slaveControl 1)
trace 10:41:30,784 11091 INFO masterControl(192.168.2.21): string broadcast message was pushed from 1156513 to vehicle 1105792 (slaveControl 1)
trace 10:41:30,796 11103 INFO masterControl(192.168.2.21): string broadcast message was pushed from 1104306 to vehicle 1055293 (slaveControl 1)
trace 10:41:30,808 11115 INFO masterControl(192.168.2.21): vehicle 1327879 was pushed to slave control 1
10:41:30,808 11115 INFO masterControl(192.168.2.21): string broadcast message was pushed from 1101572 to vehicle 106741 (slaveControl 1)
trace 10:41:30,820 11127 INFO masterControl(192.168.2.21): string broadcast message was pushed from 1055293 to vehicle 1104306 (slaveControl 1)

我认为每次发生两件事时都会出现问题(这里:10:41:30,808)。有人知道如何解决我的问题吗?我已经尝试在方法调用之后添加一个sleep(),但这没有帮助......

BR,

马库斯

编辑:

logtrace  11:16:07,75511:16:07,755  1129711297  INFOINFO  masterControl(192.168.2.21): string broadcast message was pushed from 1291400 to vehicle 1138272 (slaveControl 1)masterControl(192.168.2.21): vehicle 1333770 was added to slave control 1

log 11:16:08,562 12104 INFO 11:16:08,562 masterControl(192.168.2.21): string broadcast message was pushed from 117772 to vehicle 1217744 (slaveControl 1)

12104 INFO masterControl(192.168.2.21):车辆1169775被推到奴隶控制1

编辑2:

似乎问题只发生在从RMI线程内部调用日志记录方法时(我的客户端/服务器使用RMI连接交换信息)。 ...

编辑3:

我自己解决了这个问题:看起来log4j并不是完全线程保存的。使用单独的对象同步所有日志/跟踪方法后,一切正常。也许lib在将消息写入文件之前将消息写入线程不安全的缓冲区?

3 个答案:

答案 0 :(得分:0)

您不需要在记录器上同步,而是在输出流上进行同步。

如果使用log4j,则应正确同步输出。获得所见的唯一方法是两个线程同时写入同一个文件。

您是否可以使用相同的输出文件配置两个appender?不要那样做;每个appender都必须拥有自己独特的文件名。

如果您100%确定每个appender都写入不同的文件,那么剩下的唯一选择就是您有时使用了错误的记录器。

答案 1 :(得分:0)

可能是因为某种方式多次调用initialize方法?每次调用都会添加两个新的appender,这些appender会写入与现有appender相同的文件中。

答案 2 :(得分:0)

这个问题是4岁但是我在2013年遇到了同样的问题,我想我已经通过为每个Appender创建一个新的PatternLayout来修复它。希望将来能帮助其他人解决同样的问题。