My work space/JSP/Servlet

Log4j 사용법 로깅-Log4J

schpritz 2008. 9. 8. 15:07

Log4j 사용법 <?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />

 

Log4j 상세 설명 및 예제 프로그램

 

 

 

 

 

 

 

작성자:          <?xml:namespace prefix = st1 ns = "urn:schemas-microsoft-com:office:smarttags" />홍혜성 hicomet@nate.com

작성일:          200613

 

Log4j 사용 예제 프로그램(1)

[1] Log4jTest.java

 

import org.apache.log4j.Logger;

              

public class Log4jTest

{

        protected static final Logger logger = Logger.getLogger(Log4jTest.class);

              

        public static void main(String[] args)

        {

               if (logger.isDebugEnabled()) {

                       logger.debug("프로그램 DEBUG");

               }

               if (logger.isInfoEnabled()) {

                       logger.info("프로그램 INFO");

               }

                logger.warn("프로그램 WARN");

               logger.error("프로그램 ERROR");

               logger.fatal("프로그램 FATAL");

        }

}      

 

[2] log4j.properties

 

## info 이상만 출력 허용 (debug Priority은 출력되지 않음)

## ROOT appender R 로 지정함

log4j.rootCategory=info, R

              

## 콘솔에 출력

log4j.appender.R=org.apache.log4j.ConsoleAppender

              

## 패턴 : 날짜출력 Priority출력 클래스명출력 - 메시지출력 개행

log4j.appender.R.layout=org.apache.log4j.PatternLayout

log4j.appender.R.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss,SSS} %-5p %c{2} %x - %m%n

 

[3] 결과

 

D:\study\log4j>javac Log4jTest.java

D:\study\log4j>java Log4jTest

2006-01-02 16:19:18,671 INFO  Log4jTest  - 프로그램 INFO

2006-01-02 16:19:18,671 WARN  Log4jTest  - 프로그램 WARN

2006-01-02 16:19:18,671 ERROR Log4jTest  - 프로그램 ERROR

2006-01-02 16:19:18,671 FATAL Log4jTest  - 프로그램 FATAL

 

Log4j 사용 예제 프로그램 (2)

 [1] Log4jTest.java

 

import org.apache.log4j.Logger;

import org.apache.log4j.PropertyConfigurator;

              

public class Log4jTest

{

        public static void main(String[] args)

        {

               // ROOT

               Logger rootLogger = Logger.getRootLogger();

               rootLogger.info("프로그램 시작");

              

               // Logger1

               Logger logger1 = Logger.getLogger("com.search1");

               if (logger1.isDebugEnabled()) {

                       logger1.debug("프로그램 DEBUG");

               }

               if (logger1.isInfoEnabled()) {

                       logger1.info("프로그램 INFO");

               }

               logger1.warn("프로그램 WARN");

               logger1.error("프로그램 ERROR");

               logger1.fatal("프로그램 FATAL");

                             

               // Logger2

               Logger Logger2 = Logger.getLogger("com.search2");

               if (Logger2.isDebugEnabled()) {

                       Logger2.debug("프로그램 DEBUG");

               }

               if (Logger2.isInfoEnabled()) {

                       Logger2.info("프로그램 INFO");

               }

               Logger2.warn("프로그램 WARN");

               Logger2.error("프로그램 ERROR");

               Logger2.fatal("프로그램 FATAL");

              

               // ROOT

               rootLogger.info("프로그램 끝");      

        }

}

 

[2] log4j.properties

 

## info 이상만 출력 허용 (debug Priority은 출력되지 않음)

## ROOT appender R 로 지정함

log4j.rootCategory=info, R

 

## com.search1 패키지의 로깅에는 warn 이상만 출력

## additivity = false 로 지정했으므로 log4j.search1.log 에만 출력됨

## additivity = true 로 지정하면 log4j.log, log4j.search1.log 모두에 출력됨

log4j.category.com.search1=warn, search1

log4j.additivity.com.search1=false

 

## com.search2 패키지의 로깅에는 info 이상만 출력

log4j.category.com.search2=info, search2

log4j.additivity.com.search2=false

 

## DailyRollingFileAppender 는 파일 교체주기를 월, , , 하루 2, 시간, 분 별로 정할수 있는 Appender

log4j.appender.R=org.apache.log4j.DailyRollingFileAppender

 

## priority 설정, 만약 Threshold=fatal 을 설정하면

## log4j.category.com.search1=warn, search1 를 설정했더라고 fatal 이상만 출력 된다.

log4j.appender.R.Threshold=debug

 

## ImmediateFlush 기본값은 true. 로그메세지들이 전혀 버퍼되지 않는 것을 의미

log4j.appender.R.ImmediateFlush=true

 

## log4j.log 파일에 출력 (디렉토리는 미리생성해 놓아야 에러 나지 않음)

log4j.appender.R.File=/study/log4j/log/log4j.log

 

## 기본값은 true이며 파일 끝에 추가하는 것을 의미한다.

## false 는 각각의 프로그램이 시작할때 파일에 덮어씌운다.

log4j.appender.R.Append=true

 

## 교체주기를 월, , , 하루 2, 시간, 분 별로 정할수 있다.

## 형식은 SimpleDateFormat 을 따른다. (":" 문자는 사용 금지)

log4j.appender.R.DatePattern='.'yyyyMMdd

 

## 패턴 : 날짜출력 Priority출력 클래스명출력 - 메시지출력 개행

log4j.appender.R.layout=org.apache.log4j.PatternLayout

log4j.appender.R.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss,SSS} %-5p %c{2} %x - %m%n

 

log4j.appender.search1=org.apache.log4j.DailyRollingFileAppender

log4j.appender.search1.Threshold=debug

log4j.appender.search1.ImmediateFlush=true

log4j.appender.search1.File=/study/log4j/log/log4j.search1.log

log4j.appender.search1.Append=true

log4j.appender.search1.DatePattern='.'yyyyMMdd

log4j.appender.search1.layout=org.apache.log4j.PatternLayout

log4j.appender.search1.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss,SSS} %m%n

              

log4j.appender.search2=org.apache.log4j.DailyRollingFileAppender

log4j.appender.search2.Threshold=debug

log4j.appender.search2.ImmediateFlush=true

log4j.appender.search2.File=/study/log4j/log/log4j.search2.log

log4j.appender.search2.Append=true

log4j.appender.search2.DatePattern='.'yyyyMMdd

log4j.appender.search2.layout=org.apache.log4j.PatternLayout

log4j.appender.search2.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss,SSS} %m%n

 

[3] 결과

 

(1) log4j.log

        2006-01-02 16:29:35,984 INFO  root  - 프로그램 시작

        2006-01-02 16:29:35,984 INFO  root  - 프로그램 끝

 

(2) log4j.search1.log

        2006-01-02 16:29:35,984 프로그램 WARN

        2006-01-02 16:29:35,984 프로그램 ERROR

        2006-01-02 16:29:35,984 프로그램 FATAL

 

(3) log4j.search2.log

        2006-01-02 16:29:35,984 프로그램 INFO

        2006-01-02 16:29:35,984 프로그램 WARN

        2006-01-02 16:29:35,984 프로그램 ERROR

        2006-01-02 16:29:35,984 프로그램 FATAL

Log4j 상세 설명

org.apache.log4j.Logger 사용

 

n         Category extends 받은 Logger 클래스 사용

ü        org.apache.log4j.Logger extends org.apache.log4j.Category)

ü        Category.getInstance() 방식은 deprecated .
대신 Logger.getLogger() 방식으로 대체됨

 

      public static Logger getLogger(String name);

      public static Logger getLogger(Class clazz);

      public static Logger getRootLogger();

      public static Logger getLogger(String name, LoggerFactory factory);

 

주요 컴포넌트

 

n         Categories

n         appenders

ü        콘솔, 텍스트파일, html 파일, xml 파일, 소켓, Windows NT Event Log, 이메일 전송 가능

ü        ConsoleAppender, FileAppender, SMTPAppender, SocketAppender, NTEventLogAppender, SyslogAppender, JMSAppender, AsyncAppender, NullAppender

n         layouts : 메시지 형식

 

Priority(우선권)

 

      debug : 디버깅 메세지

      info : verbose 모드에서 출력될만한 메세지

      warn : 이상없이 계속 실행될 수 있는 정도의 경고메세지

      error : 그럭저럭 돌아갈만한 정도의 에러메세지

      fatal : 비정상적으로 종료될 치명적인 메시지

 

Appender 옵션

 

전체 옵션

log4j.configuration=app_config.properties

log4j.debug=true

log4j.disable=INFO

log4j.additivity.your.category.name=false

log4j.defaultInitOverride=false

log4j.disableOverride=false

ConsoleAppender

Threadhold=WARN

ImmediateFlush=true

Target=System.err

FileAppender

Threadhold=WARN

ImmediateFlush=true

File=mylog.txt

Append=false

RollingFileAppender

Threadhold=WARN

ImmediateFlush=true

File=mylog.txt

Append=false

MaxFileSize=100KB

MaxBackupIndex=2

DailyRollingFileAppender

Threadhold=WARN

ImmediateFlush=true

File=mylog.txt

Append=false

DatePattern='.'yyyy-ww

 

n         log4j.configuration=app_config.properties

ü        ex> java –Dlog4j.configuration= app_config.properties … 형식으로 속성 파일 설정

n         log4j.debug=true

ü        기본값은 false. log4j 를 설정하는 상세 정보를 출력

n         Log4j.disable=INFO

ü        모든 category에서 여기 지정한 priority 보다 같거나 낮은 priority 메세지는 로깅하지 않는다. (log4j.disableOverride=false 일때에만 동작)

n         log4j.additivity.your.category.name=false

ü        기본값은 true. appender ancestor(조상)으로부터 쌓이게 할지(true) 그렇게 하지 않을지(false)를 지정한다.

n         log4j.defaultInitOverride=false

ü        Category.getRoot() Category.getInstance(...) 메소드를 처음으로 호출하여   Log4j 의 초기화 과정을 마친다.("log4j.debug=true" 로 지정하여 초기화가 일어나는 것을 볼 수 있다) 초기화되는 동안 Log4j 는 어플리케이션의 클래스패스에서 "log4j.properties" 파일이나 "log4j.configuration=app_config.properties" 프로퍼티를 통해 지정한 파일을 찾는다. 만약 이것(프로퍼티를 통해 지정한 환경파일을 찾는 것)을 원하지 않는다면 이 프로퍼티를 true 로 세팅하라.

ü        이것을 시스템 property로 설정할 필요가 있다. 예를 들어 다음과 같이 프로그램을 구동한다. java -Dlog4j.defaultInitOverride=true ...   왜냐하면 설정파일에 세팅했다면 이미 너무 늦기 때문이다.Log4j는 이미 그 파일을 읽기위해 시작되었을 것이다.

n         log4j.disableOverride=false

ü        기본값은 false. 가끔 true로 설정하여 log.disable 프로퍼티를 무시할 수 있다.

n         Threadhold=WARN

ü        appender category priority가 더 낮게 지정되어 있다고 할지라도 여기 명시된 priority보다 낮은 메세지들을 로깅하지 않을 것이다. 이것은 콘솔에 모든 메세지가 나타나는 동안 파일에 로깅되는 경우와 같이 메세지의 숫자를 줄이는데 유용하다.

n         ImmediateFlush=true

ü        기본값은 true. 로그메세지들이 전혀 버퍼되지 않는 것을 의미하며 대부분의 상황에 적당하다.

n         Target=System.err

ü        기본값은 System.out

n         File=mylog.txt

ü        로깅할 파일명. 앞부분에 경로를 나타내기 위해 ${some_property_key} (예를 들어 java.home 또는 user.home 과 같은 시스템 프로퍼티)를 사용할 수 있다. 사실 모든 옵션들의 프로퍼티키들은 이런 종류의 값을 설정 가능하다.

n         Append=false

ü        기본값은 true이며 파일 끝에 추가하는 것을 의미한다. false 는 각각의 프로그램이 시작할때 파일에 덮어씌운다.

n         MaxFileSize=100KB

ü        끝에 KB, MB 또는 GB를 붙인다. 지정한 크기에 도달하면 로그파일을 교체한다(roll).

n         MaxBackupIndex=2

ü        최대 2()의 백업 파일들을 유지시킨다. 오래된 파일들은 삭제한다. 0 은 백업파일을 만들지 않는다.

n         DatePattern='.'yyyy-ww

ü        매주마다 파일을 교체(roll)한다. 교체주기를 월, , , 하루 2, 시간, 분 별로 정할수 있다. 이 값은 교체주기를 설정할 뿐만 아니라 백업파일의 붙는 문자열도 정한다.

ü        콜론(:) 문자를 값의 어디에도 사용하지 말라. 그것 말고는 자바의 SimpleDateFormat 의 어떤 형식 문자열을 사용할 수 있다. 특히 한쌍의 작은따옴표(single quote) 안에 있는 문자를 반드시 제어해주어야 한다.(예의 '.' 와 같이)

ü        '.'yyyy-MM: 매달의 첫날에 로그파일을 교체한다.

ü        '.'yyyy-ww: 매주의 첫날에 로그파일을 교체한다.

ü        '.'yyyy-MM-dd: 매일 자정에 로그파일을 교체한다.

ü        '.'yyyy-MM-dd-a: 매일 자정정오에 로그파일을 교체한다.

ü        '.'yyyy-MM-dd-HH: 시간마다(시간이 시작할때) 로그파일을 교체한다.

ü        '.'yyyy-MM-dd-HH-mm: 분마다(분이 시작할때) 로그파일을 교체한다.

 

layout 옵션

 

PatternLayout

ConversionPattern=%m%n

HTMLLayout

LocatoinInfo=true

Title=My app title

XMLLayout

LocatoinInfo=true

TTCCLayout

(이것 대신 더 유연한 PatternLayout을 사용하라)

DateFormat=ISO8601

TimeZoneID=GMT-8:00

CategoryPrefixing=false

ContextPrinting=false

ThreadPrinting=false

 

n         ConversionPattern

ü        %d{yyyy-MM-dd HH:mm:ss,SSS} : 날짜 출력 {} 내용은 SimpleDateFormat 형식을 따름

ü        %-5p : Priority 출력 (fatal, error, warn, info, debug)

ü        %n : 개행 문자 출력

ü        %t : 자바 스레드명 출력

ü        %F : 파일명출력

ü        %L : 라인넘버 출력

ü        %c{2} : 클래스명 출력.

예를 들어 category 이름이 "a.b.c" 일때 %c{2} "b.c"를 출력하며 {2}는 도트(.)로 구분된 category 이름의 마지막 두개의 컴포넌트를 의미한다. {n} 이 없으면 기본적으로 카테고리의 이름을 모두 출력한다.

ü        %x : 로깅이벤트를 발생시킨 스레드에 관련된 내포검사항목(Nested Diagnostic Context : NDC)을 출력한다.

ü        Java Servlet 과 같이 다수의 클라이언트가 분산된 스레드에 의해 다루어 질 때 유용하다.

ü        %m : 메시지 출력

ü        %r : 어플리케이션이 시작되어 로깅이벤트가 일어날때까지의 경과시간을 밀리세컨드 값으로 출력

ü        %% : 하나의 % 기호를 출력

ü        %l : 소스코드의 위치정보를 출력. %C. %M(%F:%L) 의 축약형

ü        %C : 호출자의 완전한 클래스이름을 출력. %C. %M(%F:%L) 의 축약형

ü        %M : 로깅요청을 일으킨 메소드를 출력

 

ü        필드 안에서 완쪽 정렬을 하기위해 마이너스 기호(-)를 사용

ü        %20c : 최소 20문자 공간에서 category 이름을 (기본적인)오른쪽 정렬

ü        %-20c : 최소 20문자 공간에서 category 이름을 왼쪽 정렬

ü        %.30c : 만약 category 이름이 30문자보다 길면 (앞에서부터)자른다. 최소폭이 없으므로 30문자보다 짧다고 해도 여백공간은 없다.

ü        %20.30c : category 이름이 20문자보다 짧으면 오른쪽 정렬을 하고, 30자보다 길면 시작부터 자른다.

ü        %-20.30c : category 이름이 20자보다 짧으면 왼쪽 정렬을 하고, 30자보다 길면 시작에서부터 자른다.

 

è [경고] 프로그램의 실행속도를 느리게 하는 옵션 : %d, %l, %C, %M, %F, %L

n         LocatoinInfo=true

ü        기본값은 false. 자바파일명과 행번호를 출력한다.

n         Title=My app title

ü        기본값은 Log4j Log Message. HTML <title>태그에 주어진다

n         DateFormat=ISO8601

ü        자바의 SimpleDateFormat 의 생성자이거나 NULL, RELATIVE, ABSOLUTE, DATE, ISO8601 중 하나.

n         TimeZoneID=GMT-8:00

ü        TimeZone.getTimeZone(java.lang.String) 메소드에 의해 나올만한 형식의 문자열

n         CategoryPrefixing=false

ü        기본값은 true. category 이름을 출력한다.

n         ContextPrinting=false

ü        기본값은 true. 현재 스레드에 속하는 내포검사항목 정보를 출력한다.

n         ThreadPrinting=false

ü        기본값은 true. 스레드명을 출력한다.

 

Log4j 참고 사항

성능

 

n         코드상에서 성능이 매우 중요한 곳에서는 로깅메소드의 파라미터를 만드는 시간을 절약하기 위해 다음과 같이 사용한다. (isDebugEnabled(), isInfoEnabled() 사용)

 

if (Logger.isDebugEnabled() {

    Logger.debug("debug code");

}

 

n         SimpleLayout을 사용하였거나 %p, %m, %n의 패턴만 사용하여 설정한 경우 System.out.println(...) 만큼 성능이 빠르다고 테스트됐다.

n         ConversionPattern 에서 프로그램의 실행속도를 느리게 하는 옵션 è %d, %l, %C, %M, %F, %L

 

내포검사항목(NDC) 사용

 

n         가끔 서블릿처럼 하나의 코드가 각각의 클라이언트를 서비스 하기위해 여러개의 스레드로 인스턴스화 되어 많은 클라이언트를 서비스한다. 이때 다른 클라이언트로 부터의 로깅 요청을 차별화하기 위해서 내포검사항목(NDC)를 사용할 수 있다. 할 수 있는 것은 로깅하기 전에 클라이언트의 고유한 정보를 NDC로 넣는다. 고유한 정보는 클라이언트의 IP주소, 호스트이름 또는 요청과 관련된 어떤 것도 될 수 있다. %x layout 패턴에 명시하면 요청한 로그 메세지에 그 문자열(고유한 정보)을 찍는다.

 

[NDC 사용 프로그램 예제 (Log4jTest.java)]

import org.apache.log4j.Logger;

import org.apache.log4j.NDC;

 

public class Log4jTest

{

        protected static final Logger logger = Logger.getLogger(Log4jTest.class);

 

        public static void main(String[] args)

        {

               //BasicConfigurator.configure();

              

               NDC.push("Client #45890");

 

               // ROOT

               Logger logger = Logger.getRootLogger();

               logger.info("프로그램 시작");

 

               switchNDC();

              

               // ROOT

               logger.info("프로그램 끝");  

        }

       

        static void switchNDC() {

               NDC.push("Client #99999");

               logger.info("프로그램 중간");

               NDC.pop();

        }

}

 

[NDC 사용 프로그램 예제 결과]

2006-01-02 18:02:11,984 INFO  root Client #45890 - 프로그램 시작

2006-01-02 18:02:11,984 INFO  Log4jTest Client #45890 Client #99999 - 프로그램 중간

2006-01-02 18:02:11,984 INFO  root Client #45890 - 프로그램 끝

 

기타 참고 사항

 

n         root category는 항상 지정된 priority가 있다.(기본값은 Priority.DEBUG),

n         일반적으로 Log4j 는 어플리케이션이 초기화되는 동안 보통 설정파일을 읽어들여 한번만 설정된다.

n         appender 들은 singleton 이 아니라 추가된다는 것을 주의하라. appender 로부터 물려받는 것을 불가능하게 하기 위해 category cat.setAdditivity(false) 메소드를 사용하라.  그러면 로그 메세지는 해당 category에 특별히 설정된 appender 로만 보내질 것이다.

n         정적 메소드인 BasicConfigurator.configure() 메소드는 System.out.println(...) 구문이 그러하듯 콘솔에 로깅한다. 이 메소드는 루트 category ConsoleAppender 를 붙여 콘솔에 프린트 하는 기능을 가지고 있다. 출력은 %-4r [%t] %-5p %c %x - %m%n 으로 세팅된 PatternLayout 을 사용하여 구성된다. 이 메소드는 log4j.properties 파일을 사용하는 것이 더 간단하고 유연하기 때문에 그다지 필요하지 않다.

n         log4j 를 설정하는 기본 파일은 log4j.properties 이다. 이 파일을 어플리케이션의 클래스패스에 지정된 어느곳이든 위치시킨다.

n         Java 프로퍼티 파일에서 설정 정보를 읽어오려면 정적메소드 중 하나인 PropertyConfigurator.configure(...) 메소드를 사용하라. 이미 설정되어 있는 설정은 지워지지도 재설정되지도 않는다. 이 메소드를 사용하려면 정적메소드인 BasicConfigurator.resetConfiguration() 메소드를 먼저 호출하라. 이 메소드 사용은 코드를 길고 복잡하게 할 수도 있다. 초보자는 각각의 어플리케이션의 루트디렉토리에 log4j.properties 파일 하나만 위치시켜라.

n         참고 사이트 : http://logging.apache.org/log4j/docs/

 

[]