오늘은 어디로 갈까...

Logging libraries : log4j 1부 본문

낙서

Logging libraries : log4j 1부

剛宇 2009. 3. 19. 17:53
 지난 시간에는 Logging Facade Libraries에 대해서 알아보았다.
 오늘은 진짜(?) Logging Libraries에 대해 알아보도록하자. 가장 유명한게 log4j와 jdk14Logger가 있겠다. 여기서는 log4j만 다루도록 하겠다.

1. log4j
 log4j는 로깅(logging)을 위한 라이브러리이다. 현재 Apache의 서브프로젝트로서, 홈페이지는 http://logging.apache.org이다.
 이 log4j의 가장 큰 특징은 계층(category) 로거라 불리우는 것인데, 로거(logger)를 사용할때 "카테고리(category)"라는 이름을 붙여서 사용한다. 이렇게함으로서 여러 소스로부터 출력되는 로거들중에 필요한 부분만을 로깅할 수가 있는것이다.
log4j의 또 하나의 특징은 로그 레벨(level)을 설정할 수 있다는것이다. FATAL/ERROR/WARN/INFO/DEBUG등으로 레벨을 나누어 필요한 레벨의 로그만을 출력할 수 있는것이다.
즉, 개발할때는 디버그 로그를 남기고, 운영할때는 디버그 로그를 출력하지 않게 할 수 있다는 것이다.
자, 그럼 log4j를 사용해보자.
일단 설치를 해야하는데 간단하다. 해당 사이트에서 log4j.jar를 다운받을 클래스패스(classpath)에 잡아주면 끝이다.(여기서는 log4j-1.2.15.jar 를 사용하겠다.) 그런 다음 log4j 설정 파일을 만들어준 다음 Logger 클래스를 이용해서 사용하면 된다.

1.1. 로그 출력 예제
- 일단 한번 로그를 출력해보자.
package test.log4j;

import org.apache.log4j.Logger;

public class TestLog4j {

	public static void main(String[] args) {
		Logger logger = Logger.getLogger(TestLog4j.class);
		
		logger.fatal("FATAL 메시지 입니다");
		logger.error("ERROR 메시지 입니다");
		logger.warn("WARN 메시지 입니다");
		logger.info("INFO 메시지 입니다");
		logger.debug("DEBUG 메시지 입니다");
		logger.trace("TRACE 메시지 입니다");
	}
}

* 실행 결과
log4j:WARN No appenders could be found for logger (test.log4j.TestLog4j).
log4j:WARN Please initialize the log4j system properly.

 Logger 클래스의 fatal(), error(), warn(), info(), debug(), trace() 메소드가 해당 로그 레벨로 출력을 담당한다.
로그 레벨은 다음과 같다. (FATAL > ERROR > WARN > INFO > DEBUG > TRACE)
fatal : 아주 심각한 에러가 발생한 상태를 나타낸다. 시스템적으로 심각한 문제가 발생해서 어플리케이션 작동이 불가능할 경우가 해당하는데, 일반적으로는 어플리케이션에서는 사용할 일이 없다.
error : 요청을 처리하는중 문제가 발생한 상태를 나타낸다.
warn  : 요청을 처리하는중 문제가 발생했지만, 불완전하게나마 처리가 가능한 상태를 나타낸다.
info : 어클리케이션이 작동할때 필요한 기본적인 정보를 나타낸다.
debug : 디버깅 즉, 문제 해결을 하기 위한 상태 정보를 나타낸다.
trace : log4j1.2.12에서 신규 추가된 레벨으로서. 디버그 레벨이 너무 광범위한것을 해결하기위해서 좀더 상세한 상태를 나타낸다.
 실행해보면 해당 로거에 Appender가 없다. log4j를 초기화 해라고 경고문이 나온다. 아직 설정파일을 만들지 않았기 때문에 이런 결과가 나온것이다.

1.2. log4j 설정파일
 - log4j는 기본적으로 클래스패스에서 log4j.xml이란 설정 파일을 먼저 검색하고 다음에 log4j.properties이란 파일을 검색한다.
 - 일단 아주 간단한 log4j.properties파일을 만들어보자.(클래스패스에 넣어주자)
### log messages to stdout ###
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target=System.out
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=[%d{HH:mm:ss.SSS}] %-5p %C{1}.%M(%F:%L) - %m%n
 
### messages to file mylog.log ###
log4j.appender.file=org.apache.log4j.FileAppender
log4j.appender.file.File=c:/mylog.log
log4j.appender.file.Append=true
log4j.appender.file.layout=org.apache.log4j.PatternLayout
log4j.appender.file.layout.ConversionPattern=[%d{HH:mm:ss.SSS}] %-5p %C{1}.%M(%F:%L) - %m%n
 
log4j.rootLogger=debug, stdout, file


 - 처음에 만든 로그 출력 클래스를 실행해보자. 원하던(?) 결과가 나올것이다.

* 실행 결과
[12:44:52.500] FATAL TestLog4j.main(TestLog4j.java:10) - FATAL 메시지 입니다
[12:44:52.500] ERROR TestLog4j.main(TestLog4j.java:11) - ERROR 메시지 입니다
[12:44:52.500] WARN  TestLog4j.main(TestLog4j.java:12) - WARN 메시지 입니다
[12:44:52.500] INFO  TestLog4j.main(TestLog4j.java:13) - INFO 메시지 입니다
[12:44:52.500] DEBUG TestLog4j.main(TestLog4j.java:14) - DEBUG 메시지 입니다


 - 그럼 설정파일을 분석해보자. 설정파일에 주의해서 봐야하는게 log4j.appender와 log4j.rootLogger 부분이다.이다.
appender는 로그 출력을 담당하는 역할을 한다. 현재는 stdout와 file이라는 이름의 두 appender를 설정하였고 stdout은 org.apache.log4j.ConsoleAppender를 사용하고, file org.apache.log4j.FileAppender를 사용한다는것이다.
rootLogger는 최상위 카테고리를 가리킨다.
즉 위의 경우, 모든 카테고리에 해당하는 DEBUG 이하의 로그를 stdout, file 두 appender를 이용해서 출력시킨다는것이다.
 - Appender
 log4j에는 기본적으로 많은 appender를 지원하고 있다. 물론 org.apache.log4j.Appender 인터페이스 구현해서 직접사용해도 된다.

 Appender  설 명  
 org.apache.log4j.AsyncAppender  비동기 출력  네트워크 전송등 조금 특수한 용도에 사용된다. 로그 이벤트를 queue에 모은후 다른 쓰레드에서 스케줄로 로그를 출력해주는것이다. 다른 Appender와 결합해서 사용한다.
 org.apache.log4j.ConsoleAppender  stdout, stderr 출력  Console
 org.apache.log4j.DailyRollingFileAppender  지정한 시간단위로 파일 출력  File
 org.apache.log4j.varia.ExternallyRolledFileAppender  외부 Roller로 출력  
 org.apache.log4j.FileAppender  파일 출력  File
 org.apache.log4j.jdbc.JDBCAppender  데이터베이스로 출력  
 org.apache.log4j.net.JMSAppender  JMS로 출력  
 org.apache.log4j.lf5.LF5Appender  LogFactor5라는 스윙 로그뷰어로 출력  
 org.apache.log4j.nt.NTEventLogAppender  Windows 이벤트 로그로 출력  
 org.apache.log4j.varia.NullAppender  아무것도 안함  
 org.apache.log4j.RollingFileAppender  파일 크기단위로 파일 출력  File
 org.apache.log4j.net.SMTPAppender  메일로 출력  
 org.apache.log4j.net.SocketAppender  외부 서버에 Socket으로 출력  
 org.apache.log4j.net.SocketHubAppende  SocketServer로서 출력  
 org.apache.log4j.net.SyslogAppender  Unix Syslog로 출력  
 org.apache.log4j.net.TelnetAppender  telnet으로 출력  

 여러가지 Appender가 있지만 가장 많이 사용하는것은 ConsoleAppender, DailyRollingFileAppender, RollingFileAppender 정도이다. 그리고 SMTPAppender와 같은 특정 Appender는 다른 라이브러리를 필요로하기도 하니 사용할때 주의해야한다.
 재미있는것은 LF5Appender라는게 존재하는데, LogFactor5라는 swing log viewer로 로그를 출력해 준다.(예전에 설명했던 chainsaw란 놈과 비슷한 놈이다.) 이 LogFactor5는 log4j.jar안에 포함되어 있다. log4j.jar의 org.apache.log4j.lf5.StartLogFactor5 가 실행클래스이다. 따로 실행할 필요 없이, 설정 파일에 LF5Appender만 추가해주면 자동(?) 실행된다. 실행되면 아래와 같은 화면을 볼 수 있다. 이벤트 단위로 처리하기 때문에 한결 보기가 쉽다.

 - Layout
 레이아웃은 로그 출력을 어떤 형식으로 할지 구체적으로 정해주는 부분이다. appender에 사용할 레이아웃 클래스와 레이아웃 클래스가 사용할 옵션을 지정할 수 있게 되어있다.
 log4j에 기본적으로 제공하는 Layout을 다음과 같다.
 Layout Class  설 명
 org.apache.log4j.SimpleLayout  기본 레이아웃이다. 아주 심플(?)하게 나온다.
 org.apache.log4j.TTCCLayout  시간 출력에 특화된 레이아웃이다.
 org.apache.log4j.HTMLLayout  HTML형식으로 출력한다. 테이블 형식으로 각각의 로그를 출력한다.
 org.apache.log4j.XMLLayout  XML 형식으로 출력한다.
 org.apache.log4j.PatternLayout  사용자 마음데로 패턴을 지정하여 출력하게 해준다.
이 Layout 중에서 가장 많이 쓰이는 것은 org.apache.log4j.PatternLayout이다. 직접 패턴을 지정할 수 있기에 많이 사랑받고 있다. 패턴은 다음과 같다.
   
 %c  카테고리 이름을 출력한다.. %c{1} 같은 형식으로 쓸 수 있다. %c{1} 이라면 최하위 레벨의 카테고리 이름을 출력한다는 뜻이다. test.log4j.TestLog4j 라면, TestLog4j만 출력된다.
 %C  로그를 생성한 클래스명(카테고리명과는 다른것이다.)을 출력한다. %C{2} 같은 형식으로 쓸 수 있다. test.log4j.TestLog4j 라면, log4j.TestLog4j만 출력된다.
 %d  날짜를 출력한다. %d{yyyy-MMM-dd HH:mm:ss,SSS} 같이 지정할수도 있고, %d{ISO8601} 처럼 쓸 수도 있다.
 %l  로그가 발생한 위치의 LocationInfo 정보를 출력한다. 아래 %F, %L, %M 정보라고 보면 되는데, JVM statck을 참조하므로, 특정 JVM에서 정상작동하지 않을수도있고, overhead가 심한편이라서 잘 사용하지 않는다.
 %F  로그가 발생한 파일명을 출력한다.
 %L  로그가 발생한 소스의 행번호를 출력한다.
 %M  로그가 발생한 메소드의 이름을 출력한다.
 %m  로그 메시지를 출력한다. 
 %n  개행 문자를 출력한다. 
 %p  로그 레벨을 출력한다.
 %r  응답 시간을 출력한다.(ms)
 %t  로그를 생성한 쓰레드명을 출력한다.
 %x  NDC의 값을 출력한다. 
 %X{key}  MDC의 key값을 출력한다
즉, 처음 실행한 결과 처럼
[%d{HH:mm:ss.SSS}] %-5p %C{1}.%M(%F:%L) - %m%n 
이렇게 지정하면
[12:44:52.500] FATAL TestLog4j.main(TestLog4j.java:10) - FATAL 메시지 입니다
이렇게 출력된다는것이다.

 - 형식 정리
간단히 log4j.properties 파일의 형식을 정리하면 다음과 같다.
# Appender 정의
log4j.appender.이름=사용할 Appender의 클래스명
log4j.appender.이름.옵션=값
log4j.appender.이름.layout=사용할 레이아웃 클래스명
log4j.appender.이름.layout.옵션=레이아웃의 옵션
 
# 카테고리 정의
log4j.logger.카테고리=로그 레벨, Appender 이름[, Appender 이름]
 
# root Looger 정의
log4j.rootLogger=로그 레벨, Appender 이름[, Appender 이름]