본문 바로가기

Dev.../웹서비스

[펌] Log4j 사용법...

출처:http://network.hanbitbook.co.kr/view_news.htm?serial=565

 

Log4J

Log4J 의 문서에도 있듯이, log4j 객체를 생성해서 main 메소드가 있는 클래스에 public static으로 선언해 놓고 사용하는 것이 가장 보편적이다. 우선적으로 log4j에는 기본적인 3가지 Logger, Appender, Layout 클래스가 있는데 각 클래스들의 연관관계는 아래와 같이 간단하게 이야기할 수 있다.

"Logger 는 Appender 가 지정한 곳에 Layout 형식으로 로그를 기록한다"
Logger

Log4j 패키지의 핵심클래스이다. 설정을 제외한 대부분의 로깅작업을 수행한다. 로깅작업은 Category에 있는 debug, info, warn, error, fatal의 다섯 가지 메소드를 이용해서 수행할 수 있다. Log4j의 최신문서를 보면 Logger의 parent class인 Category는 deprecated 되었고 Logger 클래스로 대치되었으며 호환성을 위해 2003년 중반까지는 API에서 제거하지 않는다고 되어 있으나 앞으로 없어질 클래스이므로 Category를 사용하지 말고 Logger 클래스의 메소드들을 사용하기 바란다. (이전에 나온, 혹은 최근에 나온 몇몇 how-to 문서들을 보면 여전히 Category를 쓰는 코드를 볼 수 있는데 빠른 시일 내에 모두 수정되어야 할 것이다)

로그레벨 지정하기

앞에서도 언급했듯이 log4j에서는 기본적으로 debug, info, warn, error, fatal의 다섯 가지 로그레벨이 있다. 각각은 메소드 debug(), info(), warn(), error(), fatal()라는 5가지 메소드를 이용해서 로그를 남길 수 있다. 다만 이때 Logger의 setLevel에서 지정된 로그레벨이 있다면 지정된 로그레벨 이하의 로깅이벤트는 무시된다. 따라서 로그도 남지 않는다. 즉, 아래와 같이
logger.setLevel(Level.INFO); 
코드내에 지정되어 있다면, 다음의 세 코드 중
logger.debug("debug 로그");logger.info("info 로그");logger.warn("warning 로그");
debug 로그는 남지 않고 info 와 warn 로그만 남는다. 자바에서는 C와 같이 전처리기의 기능이 없기 때문에 #ifdef DEBUG와 같은 형태와 같이 디버깅 때와 릴리즈 때의 디버깅코드를 각각 별도로 생성할 수가 없다. 따라서 log4j의 이러한 기능은 로그관리에 있어서 상당히 편리하다.

Appender

log4j 의 api를 보면 실로 다양한 로그방식을 지원한다. 가장 단순한 Console부터 시작해서 파일, SMTP, 기타 등등… 의 방식들을 지원하는데 이들은 log4j 객체에 Appender의 객체로서 할당된다.
  • ConsoleAppender: 콘솔화면으로 출력하기 위한 appender이다.
  • FileAppender: FileAppender는 로깅을 파일에 하고 싶을 때 사용한다.
  • RollingFileAppender: FileAppender는 지정한 파일에 로그가 계속 남으므로 한 파일의 크기가 지나치게 커질 수 있으며, 계획적인 로그관리가 불가능해진다. RollingFileAppender는 파일의 크기 또는 파일백업인덱스 등의 지정을 통해서 특정크기 이상 파일의 크기가 커지게 되면 기존파일을 백업파일로 바꾸고, 다시 처음부터 로깅을 시작한다.
  • DailyRollingFileAppender: 설정한 날짜 또는 조건에 맞춰 로깅을 수행한다. 생성자 DailyRollingFileAppender(Layout layout, String filename, String datePattern);를 이용해서 객체의 생성과 함께 log가 roll 되는 시간을 지정해줄 수도 있고 기본 생성자로 생성 후 setDatePattern()을 이용해서 지정해 줄 수도 있다. DatePattern의 몇 가지 포맷은 다음과 같다.
    '.'yyyy-MM: 매달 첫번째날에 로그파일을 변경한다.'.'yyyy-ww: 매주의 시작싱 로그파일을 변경한다.'.'yyyy-MM-dd: 매일 자정에 로그파일을 변경한다. (필자는 주로 이 옵션을 이용한다)'.'yyyy-MM-dd-a: 자정과 정오에 로그파일을 변경한다.'.'yyyy-MM-dd-HH: 매 시간의 시작마다 로그파일을 변경한다.'.'yyyy-MM-dd-HH-mm: 매분마다 로그파일을 변경한다.
    보다 자세한 내용은 아파치 api 문서를 참고하기 바란다.
Layout

로그를 어떤 포맷의 형태로 남길 것인가? 단순히 메시지 외에도 현재 로그하는 대상의 스레드명, 로그시간 등등 많은 정보를 조합할 수 있다. Layout에는 HTMLLayout, PatternLayout, SimpleLayout, XMLLayout 등이 있다. SimpleLayout과 XMLLayout 등도 많이 사용할 수 있겠지만, 아무래도 자신이 원하는 스타일의 로그메세지를 남기기 불편한 면이 있다. 필자가 자주 사용하는 레이아웃은 PatternLayout으로서, c 함수의 printf처럼 다양한 로그 메시지 조합을 만들어 낼 수가 있다.

%p : debug, info, warn, error, fatal 등의 priority 가 출력된다.
%m : debug(), info(), warn(), error(), fatal() 등의 함수로 지정한 로그내용이 출력된다.
%d : 로깅 이벤트가 발생한 시간을 기록한다. 출력포멧은 %d후의 브레이스내에 지정된 형태를 따른다. %d{HH:mm:ss, SSS}라든가 %d{yyyy MMM dd HH:mm:ss, SSS}와 같은 형태로 사용하면 된다. Java 의 SimpleDateFormat 의 형식대로 사용하면 된다.
%t : 로그이벤트가 발생된 쓰레드의 이름이 출력된다.
%% : % 표시를 출력하기 위해 사용한다.
%n : 플랫폼 종속적인 개행문자가 출력된다. \r\n 또는 \n 일것이다.


기타 자세한 내용은 log4j 홈페이지 또는 api 문서를 참고하길 바란다.

예제

다음은 log4j를 활용하는 간단한 예이다. 별도의 configuration 파일을 이용해서 log4j의 값을 세팅하는 방법도 있으나 지면 관계상 실행가능한 간단한 예제 하나로 대신할까 한다.

아래 예제는 DailyRollingFileAppender를 이용해서 분당 하나의 로깅파일을 만들어내도록 했으며, 5초마다 Hello, DEBUG와 Hello, INFO 그리고 Hello, WARN을 출력하도록 되어 있다. 그리고 화면으로도 로그결과를 확인하기 위해서 ConsoleAppender도 추가하였다. 기본적인 priority 모드는 INFO로 설정되어 있다. 각각 어떤 값들이 로그에 남고 DailyRollingFileAppender가 어떻게 동작하는지, 그리고 각각의 파라미터들을 어떻게 세팅하였는지 등을 중심으로 코드를 보기 바란다.

Log4j 역시 다운로드받은 후 ant를 이용해서 빌드해서 사용해야 한다.
import java.io.*;import org.apache.log4j.*;public class Test {    public Test(){        initLog();    }        public void initLog(){        /////////////////////////////////////////        // log4j 설정        logger.setLevel(Level.INFO);        DailyRollingFileAppender appender = null;        Appender consoleAppender = null;                try {            String logPattern = "%r [%t] %-5p %c %x - %m %d{yyyy MMM dd HH:mm:ss, SSS} \n";            appender = new DailyRollingFileAppender( new PatternLayout(logPattern), "syslog.log", "'.'yyyy-MM-dd-HH-mm" );            consoleAppender = new ConsoleAppender(new PatternLayout(logPattern));        }        catch(IOException e){            e.printStackTrace();            System.out.println("로그설정에 문제가 있습니다. 실행권한 체크등을 해보길 바랍니다.");            System.exit(-1);        }                logger.addAppender(appender);        logger.addAppender(consoleAppender);        logger = Logger.getRootLogger();                logger.debug("LBSGateway 객체 생성");        /////////////////////////////////////////    }        public static Logger logger = Logger.getRootLogger();        public void go(){        for ( int I = 0; I < 3; I++)            new testThread().start();    }        public static void main(String[] args){        Test t = new Test();        t.go();    }}class testThread extends Thread {    public void run(){        while ( true )            {Test.logger.debug("Hello, DEBUG");            Test.logger.info("Hello, INFO");            Test.logger.warn("Hello, WARN");                        Thread.sleep(5000);        }    }}
참고자료

Log4J 프로젝트 홈페이지는 http://jakarta.apache.org/log4j이다.