Log4j 사용법 로깅-Log4J
Log4j 사용법 <?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />
Log4j 상세 설명 및 예제 프로그램
작성자: <?xml:namespace prefix = st1 ns = "urn:schemas-microsoft-com:office:smarttags" />
작성일: 2006년 1월 3일
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 ## 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 |
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 ## 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 (2) log4j.search1.log (3) log4j.search2.log |
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- 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-
ü 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 사용 프로그램 예제 – 결과]
|
기타 참고 사항
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/
[끝]