2009-08-28 4 views
0

일부 이벤트를 로깅하고 추적 할 수 있도록 Java 프로젝트에 LoggingHandler 클래스를 추가했습니다. 이 클래스에서는 두 개의 서로 다른 log4j 로거 인스턴스를 사용합니다. 하나는 이벤트를 로깅하고 다른 하나는 이벤트를 다른 파일로 추적하는 인스턴스입니다. 클래스의 초기화 블록은 다음과 같습니다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"); 
} 

은 단지 스레드가 동시에 각각의 기록에 로거 인스턴스의 기능을 사용하고 있는지 확인하려면/방법을 추적하는 것은 내부) (.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) 

나는 문제가 매번 두 개의 이벤트가 동시에 발생 occures 생각 (현재 : 10 : 41 : 30,808). 아무도 내 문제를 해결하는 방법을 알고 있습니까?

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 

또는

: ...

BR,

마르쿠스

편집을 이미 메서드 호출 후 잠을()를 추가하려하지만 도움이되지 않습니다

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 정보 masterControl (192.168.2.21) : 차량 1169775가 슬레이브 컨트롤 1에 푸시되었습니다.

편집 2 : 로깅 방법은 RMI 스레드 내부에서 호출하는 경우 문제는 (내 클라이언트/서버 정보를 교환은 RMI 연결을 사용하여) 발생과 같은

보인다. ...

편집 3 :

은 나 자신에 의해 문제를 해결 : 그것은 완전히 스레드 저장 아닙니다의 log4j처럼 보인다. 별도의 객체를 사용하여 모든 로그/추적 메소드를 동기화 한 후에 모든 것이 잘 작동합니다. 어쩌면 lib 디렉토리에 파일을 쓰기 전에 스레드가 안전하지 않은 버퍼에 메시지를 쓰고 있습니까?

답변

0

로거에서 동기화 할 필요없이 출력 스트림에서 동기화 할 수 있습니다.

log4j를 사용하는 경우 출력이 올바르게 동기화되어야합니다. 보이는 것을 얻는 유일한 방법은 두 개의 스레드가 동시에 같은 파일에 쓰는 것입니다.

출력 파일이 동일한 두 개의 appender를 구성 할 수 있습니까? 그렇게하지 마라. 모든 appender는 고유 한 고유 한 파일 이름을 가져야합니다.

모든 appender가 다른 파일에 쓰는 것을 100 % 확신하는 경우 남은 유일한 옵션은 때때로 잘못된 로거를 사용하는 것입니다.

+0

출력 스트림에서 appender를 의미하는 경우 appender는 threadsafe입니다. 'doAppend' 메소드는'동기화 됨 '입니다. –

+0

fileAppeners에서 동기화 한 후에도 문제가 계속 발생합니다 (예제 위쪽 참조). 어쩌면 로거 인스턴스를 다른 스레드에 넣어야합니까? – Markus

+0

아니요, 초기화 메소드에서 볼 수 있듯이 두 애 퍼더가 서로 다른 파일 (logFilename 및 traceFilename)에 바인딩되지만 동일한 patternLayout을 사용하고 있습니다. 일부 분 agao 나는 로깅/추적을 다른 스레드로 옮기려고했지만이 역시 도움이되지 못했습니다. – Markus

0

어떻게 든 initialize 메서드가 두 번 이상 호출 될 수 있습니까? 모든 호출은 기존 appender와 동일한 파일에 기록하는 두 개의 새로운 appender를 추가합니다.

+0

나는 완전히 확신하지 못한다. 이클립스 디버거를 사용하여 확인합니다 ... – Markus

0

이 질문은 4 살이지만 2013 년에도 똑같은 문제가 발생했습니다. 각 Appender에 대해 새로운 PatternLayout을 작성하여 해결했다고 생각합니다. 희망이 다른 사람이 같은 문제가 미래에 도움이됩니다.

관련 문제