2012-11-14 3 views
4

이것은 약간 이상하지만, 로깅 패키지 및 속성 사용에 익숙하지 않습니다. 인터넷 검색으로 찾을 수있는 모든 질문은 "로깅을 여러 파일을 여는 방법"입니다. 하지만 오늘 내 질문은 그것을 만드는 방법입니다 여러 파일을 동시에하고 중지하십시오. 여기에 우리가 간다 ...Java 로그 오프닝 "too many"로그 파일

첫 번째 사항 :이 프로젝트는 java.util.logging을 사용하여 제한되며, 아니요 log4j 또는 다른 타사 패키지로 전환 할 수 없습니다. 그렇습니다. 더 굉장해.

import java.util.logging.Logger; 
import java.util.logging.LogManager; 

// in startup routine: 
LogManager.getLogManager().readConfiguration(
    this.getClass().getResourceAsStream("/logging.properties")); 

작동하는 그들을 속성은 JAR에서 파일을 꺼내와 적용이 애플릿이 시작되면 :-)

그래서, 그것은 코드의이 비트를 실행합니다. readConfiguration()은 VM 시작에서 모든 기존 설정을 다시 설정해야합니다. 프로젝트의 나머지 부분은

private final static Logger LOGGER = Logger.getLogger(NameOfClass.class.getName()); 

과 같은 라인을 가지고 있습니다. 나는 꽤 표준이라고 생각합니다. 모든 클래스는 동일한 패키지 (예 : TheProject)에 있고, 펑키 로깅 이름/속성 계층 구조는 java.util.logging이 롤백하는 것을 좋아하기 때문에 동일한 규칙을 따릅니다.

logging.properties 파일은 Java 6 SE JRE와 함께 제공된 파일의 복사본으로 시작한 다음 수정되었습니다. 이제 다음과 같이 보입니다 :

handlers=java.util.logging.FileHandler,java.util.logging.ConsoleHandler 

# Default global logging level. 
.level=INFO 

# Loggers 
# ------------------------------------------ 
# Loggers are usually attached to packages. 
# Here, the level for each package is specified. 
# The global level is used by default, so levels 
# specified here simply act as an override. 
java.level = INFO 
javax.swing.level = INFO 
sun.awt.level = INFO 
theproject.level = ALL 

# Handlers 
# ----------------------------------------- 
theproject.handlers=java.util.logging.FileHandler 

# Override of global logging level 
java.util.logging.FileHandler.level=ALL 

# Naming style for the output file: 
java.util.logging.FileHandler.pattern=/path/to/logfiles/TheProject%u.%g.log 

로그 메시지가 Java 콘솔에 표시되고 디스크 파일에도 표시된다는 점에서 모두 "작동"합니다. 애플릿이 실행 되 자마자 두 개의 파일이 동시에 열립니다 (TheProject0.0.log 및 TheProject1.0.log). 로그 메시지가 시작되면 두 파일에 동시에 표시됩니다. 두 파일 모두 최대 크기에 도달했을 때를 포함하여 항상 서로의 정확한 사본입니다 (모두!).

한 번에 하나의 JRE VM 만 실행 중입니다.

언제든지 두 파일 중 하나를 열거 나 두 파일을 모두 닫은 다음 확인했습니다. 하나가 다른 것보다 더 오랜 시간이나 더 짧은 시간 동안 열려있는 것과는 다릅니다.

두 파일 이름 사이에 다른 % u 토큰은 로그 파일이 이미 다른 프로세스에서 열려있는 경우 "충돌을 해결할 고유 번호"로 문서화되어 있지만 으로 생각합니다. 두 로그 동일한 데이터를 가져오고 있으며 다른 어떤 것도 파일을 열지 않습니다. (증거 : Windows는 VM이 ​​실행 중일 때 두 파일을 삭제할 수 없지만 일단 VM이 종료되면 VM이 종료됩니다.)

속성 파일에서 무언가를하고 있거나 속성을 올바르게로드하는 방법을 잘못 이해하고 있습니까? , 또는 ...?

+1

'theproject.handlers = ... '를 주석 처리 해 보셨습니까? –

+0

게시 한 내용에 문제가없는 것 같습니다. LogManager.getLogManager(). getLogger (NameOfClass.class.getName()). javaHandler (new FileHandler ("/ path/to /logfiles/TheProject%u.%g.log "));'). 그것이 내가 그것을 재현 할 수있는 유일한 방법이었습니다. –

답변

1

@Joop (답변으로 표시 할 수없는 설명에서). 핸들러를 설정하는 것은 덧셈 프로세스이므로 이전 설정을 덮어 쓰는 것이 아닙니다. 그것은 나에게 정말로 직관적이지는 않지만 java.util.logging for ya ... 그 밖의 모든 속성을 그대로두고 핸들러 할당을 제거하는 것은 길이었습니다.

@jschoen이 제안한 reset() 호출도 사용하기에 현명한 선택입니다.

여러분 모두에게 감사드립니다. 나는이 모든 것을 "닫힌"것으로 표시하는 방법을 확신하지 못한다.

3

나는 readConfiguration()이 생각하는대로 작동하지 않는다고 생각합니다.

다시 초기화 로깅 특성 및 java.util.Properties 형식이어야 지정된 스트림으로부터 기록 구성을 다시 읽고 다음의 JavaDoc을 형성한다. 속성을 읽은 후 PropertyChangeEvent가 발생합니다 ( ).

대상 로거가있는 경우 Logger.setLevel()을 사용하여 새 구성 파일의 모든 로그 수준 정의가 적용됩니다 ( ).

실제로 로깅 구성을 재설정할지 여부 또는 단순히 현재 구성을 추가/업데이트하는 경우 확실하지 않습니다.

readConfiguration()으로 전화하기 전에 reset()으로 전화해야한다고 생각합니다.

로깅 구성을 재설정하십시오.

모든 명명 된 로거의 경우 reset 작업은 모든 처리기를 제거하고 닫고 (루트 로거 제외) 수준을 null로 설정합니다. 루트 로거 레벨이 Level.INFO로 설정됩니다.

편집 :은 그냥 당신의 등록 정보 파일에 문제가 아니라는 것을 보여주기 위해, 아래처럼 theproject 패키지에 테스트라는 클래스를 생성하고 실행할 수 있습니다. 기존 로그 파일을 삭제하면 실행될 때 생성되는 로그 파일의 수를 알 수 있습니다.

package theproject; 

import java.util.logging.FileHandler; 
import java.util.logging.Level; 
import java.util.logging.LogManager; 
import java.util.logging.Logger; 
public class Test { 

    private final static Logger LOGGER = Logger.getLogger(Test.class.getName()); 

    public static void main(String[] args) throws Exception { 
     LogManager.getLogManager().readConfiguration(
        Test.class.getResourceAsStream("/logging.properties")); 
//  The only way I could get it to create two log files was to uncomment the line below that 
//  adds another FileHandler to the root logger. 
//  LogManager.getLogManager().getLogger("").addHandler(new FileHandler("/path/to/logfiles/TheProject%u.%g.log")); 
     Test test = new Test(); 
    } 

    public Test(){ 
     LOGGER.log(Level.INFO, "Info"); 
    } 

} 
+0

잘 잡으세요! 나는 코드를 변경하여'LogManager LM = LogManager.getLogManager(); LM.reset(); LM.readConfiguration (....);'불행하게도, 이것은 전혀 효과가 없었습니다. 재설정 전, 재설정 후, readConfig 후에 LogManager의 getLoggerNames를 사용하여 일부 덤프 코드를 추가했으며 세 개의 출력이 모두 동일했습니다. –

+0

@TiStrga'getLoggerNames'가 당신이 찾고자하는 것이 아니라, 각각의 로거에서'getHandlers()'가 들어 있는지 확신 할 수 없습니다. 그들은 어떻게 든 두 개의'FileHandler'를 첨부 한 것 같습니다. 두 번째 FileHandler를 코드에서 로거에 추가했는지 확인 했습니까? –