[펌] Log4J 사용하기

프로그래밍/Library 2007. 11. 28. 09:36 Posted by galad
1. 서언
이 문서는 GPL을 따릅니다. 편의상 경어는 생략합니다. 이 문서에서 다루고 있는 범위는 Log4J의 설치 및 환경설정, 그리고 간단한 예제 프로그램의 구동까지입니다. 추가의 내용을 원하시는 분은 Log4J의 홈페이지에 가셔서 보면 Log4J에 대한 책을 소개하고 있으니 참고하시기 바랍니다.

2. Context
Log4J는 Jakarta 프로젝트의 Sub Project로 자바에서 손쉽게 로그를 만들 수 있도록 해 준다. 일반적으로 디버깅을 위해서는 System.out.println을 사용하게 된다. 아니면 자체적으로 로그 기능을 담당하는 간단한 로그 클래스를 작성하기도 한다. 하지만 오픈소스로 만들어진 다양한 기능을 제공하고 퍼포먼스도 빠른 로그 시스템인 Log4J를 사용한다면 개발자들은 로그 보다는 좀 더 비즈니스 로직에 충실할 수 있게된다.
이에 Log4J를 설치하고 사용해 보고 그 설정 및 샘플을 남겨 보았다.

Log4J에 대한 소개는 http://jakarta.apache-korea.org/log4j/index.html에 있으니 자세한 내용을 보길 원한다면 위 페이지를 참고한다. 위 페이지는 한글로 번역된 페이지라 읽기에 부담없으리라 생각한다.

3. Install & Configuration
먼저 Log4J를 다운 받는다. Log4J는 http://jakarta.apache.org/log4j/docs/download.html에서 최신 버전을 다운로드 받을 수 있다. 이 글을 쓰는 시점에서 최신 버전은 1.2.7이다.
파일을 다운로드 받은 다음에 적절한 디렉토리에 압축을 푼다. 여기서는 압축을 푼 디렉토리를 $LOG4J_HOME이라 하겠다. $LOG4J_HOME에 보면 INSTALL 이라는 파일이 존재한다. 반드시 이 파일을 먼저 읽어 보길 권한다.
이 파일에는 Log4J를 어떻게 설치하고 테스트하는지 잘 설명이 되어 있다. 또한 이 글에서는 언급하고 있지 않는 Dependency부분들을 설명하고 있으니 JDK버전이 다른 사람들은 반드시 읽고 Dependency를 체크해 보길 바란다.
$LOG4J_HOMEdistlib에 보면 log4j-1.2.7.jar 파일이 존재한다. 이 파일을 CLASSPATH에 추가를 한다.

자바로 개발을 하다 보면 이것저것 툴도 설치하는 것도 많고 여러 Jar파일들도 CLASSPATH에 추가해야 하는 경우가 많다. 이러한 모든 Jar파일들을 시스템 환경변수나 사용자 환경변수의 CLASSPATH에 추가하게 되면 나중에 CLASSPATH때문에 고생하는 경우가 발생된다. 따라서 이런 방법보다는 cmd파일 또는 sh파일에 환경 변수를 셋팅하는 Script를 만들어 두고 사용하는 것을 추천한다.

이제 클래스패스에 log4j-1.2.7.jar를 추가했으면 다음의 프로그램을 통해서 제대로 셋팅이 되었는지 체크해
보도록 하자.
############################## Test Program ##############################
import org.apache.log4j.Logger;
import org.apache.log4j.BasicConfigurator;

public class Hello {

  static Logger logger = Logger.getLogger(Hello.class);

  public
  static
  void main(String argv[]) {
  BasicConfigurator.configure();
  logger.debug("Hello world.");
  logger.info("What a beatiful day.");
  }
}
##############################  End of Program ##############################
위의 Hello.java를 컴파일을 하고 실행을 시켜본다.
만일 Exception in thread "main" java.lang.NoClassDefFoundError: Hello 이라는 메시지가 나온다면 클래스 패스에 현재 디렉토리(.)를 추가한다. 실행을 시켰을때,

10 [main] DEBUG Hello  - Hello world.
20 [main] INFO Hello  - What a beatiful day.

이런 Output이 나온다면 제대로 셋팅이 된 것이다.

4. Sample Program
이제 Log4J를 이용한 간단한 로그를 남기는 예제를 만들어보자. 이 예제는 3가지 종류의 로그를 남기는 아주 간단한 프로그램이다.
첫번째 로그는 파일로 로그를 남기면서 그 파일의 크기가 10KB 이상이면 백업으로 보관하고
새로운 파일에 로그를 작성하게 된다.
두번째 로그는 파일로 로그를 남기지만 날짜별로 백업을 남기게 된다.
세번째는 Project 전체에 대한 로그를 파일로 남기게 된다.

먼저 프로그램 코드를 보도록 하자.

############################## Sample Program ############################## import org.apache.log4j.*;

public class TestLogging {
  static Logger esoLogger = Logger.getLogger("posdata.log.esourcing");
  static Logger bidLogger = Logger.getLogger("posdata.log.ebidding");
  public static void main(String[] args) {

    esoLogger.debug("ESO Debug");
    bidLogger.debug("BID Debug");
    esoLogger.info("ESO INFO");
    bidLogger.info("BID info");
    esoLogger.warn("ESO WARN");
    bidLogger.warn("BID WARN");
    esoLogger.error("ESO ERROR");
    bidLogger.error("BID ERROR");
    init();
    property();
  }

  public static void init() {
    Logger hr = Logger.getLogger("posdata.log.hr");
    hr.debug("HR debug");
    hr.info("HR Info");
    hr.warn("HR Warn");
    hr.error("HR Error");
  }

  private static void property() {
    java.util.Properties props = System.getProperties();
    java.util.Enumeration enum = props.propertyNames();
    String key = null;
    while(enum.hasMoreElements()) {
      key = (String)enum.nextElement();
      bidLogger.info(key + " : " + props.getProperty(key));
    }
  }
}
############################## End of Program ##############################

다음은 위 프로그램의 로그설정을 가지고 있는 log4j.properties 파일이다. '#'표시는 주석문이 된다. ESO_Appender의 설정은 로그 파일의 크기가 10KB이상이 되면 백업으로 남기게 하는 설정이고, BIS_Appender의 설정은 날짜별로 백업을 남기게 되는 설정이다. 만일 여기에 설정된 Appener이외에 다른 것을 Logger를 사용 했다면 ROOT_Appender를 통해서 로그를 남기게 된다. 이 Properties 파일은 반드시 Classpath에 포함되어 있어야 한다.

############################## log4j.properties ##############################
log4j.rootCategory=DEBUG, ROOT_Appender
log4j.category.posdata.log.esourcing=INFO, ESO_Appender
log4j.category.posdata.log.ebidding=INFO, BID_Appender
log4j.additivity.posdata.log.ebidding=false
log4j.additivity.posdata.log.esourcing=false

# Set ESO_Appender specific options.
# log4j.appender.ESO_Appender=org.apache.log4j.ConsoleAppender
log4j.appender.ESO_Appender=org.apache.log4j.RollingFileAppender
log4j.appender.ESO_Appender.File=./eso.log
log4j.appender.ESO_Appender.Append=true
log4j.appender.ESO_Appender.MaxFileSize=10KB
log4j.appender.ESO_Appender.MaxBackupIndex=12
log4j.appender.ESO_Appender.layout=org.apache.log4j.PatternLayout
log4j.appender.ESO_Appender.layout.ConversionPattern=%d{<yyyy-MM-dd HH:mm:ss>} <%-5p> <%l>: %m%n

# Set BID_Appender specific options.
log4j.appender.BID_Appender=org.apache.log4j.DailyRollingFileAppender
log4j.appender.BID_Appender.ImmediateFlush=true
log4j.appender.BID_Appender.File=./bid.log
log4j.appender.BID_Appender.Append=true
log4j.appender.BID_Appneder.DatePattern='.'yyyy-MM-dd
# log4j.appender.BID_Appender.MaxFileSize=10KB
# log4j.appender.BID_Appender.MaxBackupIndex=9
log4j.appender.BID_Appender.layout=org.apache.log4j.PatternLayout
log4j.appender.BID_Appender.layout.ConversionPattern=%d{<yyyy-MM-dd HH:mm:ss>} <%-5p> <%-l>: %m%n
# log4j.appender.BID_Appender.layout.ConversionPattern=%d{<yyyy-MM-dd HH:mm:ss>} %-15.15t %-8.8p %-30.30c %x: %m%n

# Set ROOT_Appender specific options.
log4j.appender.ROOT_Appender=org.apache.log4j.RollingFileAppender
log4j.appender.ROOT_Appender.File=./project.log
log4j.appender.ROOT_Appender.Append=true
log4j.appender.ROOT_Appender.MaxFileSize=10kb
log4j.appender.ROOT_Appender.MaxBackupIndex=9
log4j.appender.ROOT_Appender.layout=org.apache.log4j.PatternLayout
log4j.appender.ROOT_Appender.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %-15.15t %-8.8p %-30.30c %x %C %F %l %L %M: %m%n
############################ End of Properties File ############################

응용프로그램을 개발하다 보면 많은 System.out.println()을 남발하게 된다. 개발된 프로그램을 테스트하고 가동에 들어가면 System.out.println()문을 지우던가 아니면 지저분하게 두어야 하는 문제가 발생한다. 하지만 위와 같이 Log4J를 사용하면 개발과 테스트시에는 DEBUG 레벨로 두고 운영시에는 좀 더 레벨을 올려서 설정할 수 있게 되기에 좀 더 시스템 개발과 운영에 있어서 깔끔하게 된다. 또한 레벨별로 로그를 남길 수 있고 운영 중에도 동적으로 설정을 바꿀 수 있고, 로그를 남기는 형식 또한 다이나믹하게 지원하기 때문에 그 유용성이 크다고 볼 수 있다.

마지막으로 위에서 사용된 각 Pattern들의 인자값은
http://www.vipan.com/htdocs/log4jhelp.html에서 찾아볼 수 있다. 참고하길 바란다(단 해당문서가 Log4J Version 1.1을 기준으로 한거 같으니 잘 구별해서 사용하길 바란다).