하지만 Log4J를 알게 되더라도 그때 당시는 선배들의 자세한 가르침이 있었다기 보다는 '이렇게 하면 돼~!'라는 식의 명령아닌 명령식 가르침 덕분에 어떻게 하면 좀더 Log4J를 효율적으로 사용할 수 있는지에 대해 몰랐다. 지금 생각해면 학교 졸업작품 하면서 사용했던 System클래스 사용하듯 남용하며 사용하지 않았나 생각이 든다.(그럴때 가끔 오싹 하기도 한다...^^;). 해서 이렇게 프로젝트가 끝나갈 무렵 시간이 남는 시간에 하나씩 정리도 해갈겸 해서 제일 먼저 선택한것이 인터넷에 자료도 많고 그나마 간단하다고 생각 하기에 Log4J 부터 시작한다.
일단은 처음부터 무리하게 갈 생각은 없다. 우선은 Log4J가 무엇이고 어떤 것이며 특징이 무엇인지 정도만 다룰 예정이다. 기능이나 자세한 세팅방법 및 사용방법은 차차 진행할 예정이다.
Log4J란 무엇일까......
우선 Log4J가 무엇이지 부터 시작 해보자. 그럼 이름이 왜 Log4J인지 부터 알아보면 Log4J를 풀어 놓아보면 Log for Java란 말이 된다. 이 넘을 줄여서 Log4J간 된것이다. 고로 Jakarta-Project에서 순수 JAVA를 위한 프로젝트중 하나인 것이다.
Log4J는 프로그래머 즉 개발자가 로그를 다양하게 할 수 있도록 도와주는데 즉, 간단하게 말해서 프로그램을 개발하는 사람이라면 어떻게든 로그를 남기겨서 자신이 개발한 프로그램이 정상적으로 작동을 하는지 아니면 오류가 나면 어느부분에서 오류가 나는지에 대해서 좀더 쉽고 빠르게 찾기 위해 사용된다. 또한 불법 접근자가 못된짓을 하는지 감시할때도 중요한 역활을 한다. 이렇게 다양한 용도에 사용되는 로그라면 하나의 방식으로 여러가지를 표현하기 보다는 다양한 방법으로 표현할 수 있는게 더 좋지 않을까? 또한 성능(속도)에도 영향을 미치지 않게 하며 좀더 편리하게 사용할 수 있는 방법이 있지 않을까? 해서 Log4J가 이러한 욕구들을 해결해 주기 위해 등장한 것이다.
Log4J는 신뢰성 있는 시스템인가.......
log4j는 신뢰성(작업 혹은 통신이 손실, 중복 없이, 선입선출로 합리적인 시간 안에 반드시 수행되어야 신뢰성을 있다고 한다:역주)을 갖고 있지 않다. log4j는 best-effort(UDP 프로토콜처럼 불완전한 신뢰성을 제공할 때 best-effort라 한다:역주)와 fail-stop(오류 발생시, 불완전한 동작을 하지 않고 바로 멈추는 것을 의미한다:역주)의 성질을 가진 로깅 시스템이다
fail-stop은 log4j가 잠재적으로 프로그램의 오동작을 유발할 수 있는, 예상치 못한 예외를 던지지 않을 거라는 의미이다. 만일 어떤 이유로든, log4j가 예외를 던지면, log4j-user@jakarta.apache.org 메일링 리스트로 알려주기 바란다. 예상치 못한 예외는 즉각적인 조치가 필요한 심각한 버그로 간주된다.
이에 더해서 log4j는 출력 스트림을 열 수 없거나, 쓸 수 없거나, 스트림이 다 찼을 때 출력을 System.out 이나 System.err로 대신 내보내지 않는다. 이것은 로깅 실패 때문에 사용자의 화면이 엉망이 되는 일이 없게 하기 위해서이다. 하지만, log4j가 로깅을 할 수 없을 때, 이를 알리기 위해 하나의 메시지를 System.err로 출력하기는 한다.
Log4J의 특징은?
- log4j는 속도에 최적화되어있다.
- log4j는 이름있는 로그 계층에 기반한다.
- log4j는 fail-stop이지만 신뢰성은 없다.
- log4j는 thread-safe하다(멀티스레드 환경에서 사용해도 안전하다:역주).
- log4j는 융통성이 풍부하다.
- 설정 파일은 property 파일과 XML 형식으로 실행 중 수정 적용 가능하다.
- log4j는 처음부터 자바의 예외를 처리하기 위해 디자인되었다.
- log4j는 출력을 파일, 콘솔, java.io.OutputStream, java.io.Writer, TCP를 사용하는 원격서버, 원격 Unix Syslog 데몬, 원격 JMS 구독자, 윈도우NT EventLog로 보낼 수 있고, 심지어는 e-mail로 보낼 수도 있다.
- log4j는 다음 5단계의 장애레벨을 사용한다. DEBUG, INFO, WARN, ERROR, FATAL.
- 로그 출력의 형식은 Layout 클래스를 확장함으로써 쉽게 바꿀 수 있다.
- 로그가 출력될 대상과 출력 방법은 Appender 인터페이스로 할 수 있다.
- log4j는 로거 하나에 다수의, 출력을 담당하는 appender를 할당할 수 있다.
- log4j는 국제화를 지원한다.
Log4J의 구조는 어떻게 되어 있을까...
log4J는 크게 3가지 요소로 구성되며 그 구조는 다음과 같다.- Logger(Category) : 로깅 메세지를 Appender에 전달한다. log4J의 심장부에 위치 하며, 개발자가 직접 로그출력 여부를 런타임에 조정되도록 해준다. logger는 로그레벨을 가지고 있으며, 로그의 출력 여부는 로그문의 레벨과 로거의 레벨을 가지고 결정된다.
- Appender : 전달된 로깅 메세지를 파일에다 기록할 것인지, 콘솔에 출력할 것인지 아니면 DB에 저장할 것인지 매개체 역활을 담당한다. 즉, 로그의 출력위치를 결정한다. log4J API문서의 XXXAppender로 끝나는 클래스들의 이름을 보면, 출력위치를 어느정도 짐작할 수 있다.
- Layout : Appender가 어디에 출력할 것인지 결정했다면 어떤 형식으로 출력할 것이지
출력 layout을 결졍한다.
log4J의 기능은 뭐가 있을까...
log4J의 기능은 크게 5가지 레벨로 되어 있다. 각각의 레벨은 로그가 사용되어지는 용도나 상황에 연관되어져 있다. 그럼 5개의 레벨이 어떻게 나뉘는지, 또 레벨에 따라 어떻게 쓰여지는지 알아보자.
- FATAL : 가장 크리티컬한 에러가 일어 났을 때 사용.
- ERROR : 일반 에러가 일어 났을 때 사용.
- WARN : 에러는 아니지만 주의할 필요가 있을 때 사용.
- INFO : 일반 정보를 나타낼 때 사용.
- DEBUG : 일반 정보를 상세히 나타낼 때 사용.
만약 로깅 레벨을 WARN 으로 설정하였다면 그 이상 레벨만 로깅하게 된다.즉 WARN, ERROR, FATAL 의 로깅이 됩니다.
오늘은 Log4J의 Properties설정에 대해 정리를 할 생각이다. 물론 내가 아는 범위 이외의 것들은 인터넷에서 검색하여 지원을 받은 부분도 있다. 상당히.....(-_-);;
일단 로그를 출력할 곳을 선택하기 위해서 설정해야할것...log4j.rootLogger=DEBUG, console, save
앞의 DEBUG는 전체 Level설정값이다...뒤에 log4j.appender.console.Threshold를 이용해서 Level을 지정해주지 않으면 여기서 설정된 설정치를 이용하여 log가 생성된다. 참고로 로그 레벨은 ( DEBUG <>순으로 제일 왼쪽이 레벨이 낮다. 만약 여기서 WARN을 설정하면 WARN, INFO까지만 로그가 출력이 된다.
뒤의 consloe, save는 appender의 이름으로 2개의 appender를 사용하겠다는 설정이다.
ConversionPattern은 로그를 어떤 형태로 기록할지에 대한 설정이다. 각 옵션에 대한 설명은 아래와 같다.
- %m : 당신이 지정한 메세지를 출력한다.
- -%p : 로깅 이벤트의 priority를 출력한다.
- -%r : 어플리케이션이 시작되어 로깅이벤트가 일어날때까지의 경과시간을 밀리세컨드 값으로 출력한다.
- -%c : 로깅이벤트의 category를 출력한다. 예를 들어 category 이름이 "a,b,c"일때 -%c{2}는 "b,c"를 출력하며 {2}는 도트(.)로 구분된 category 이름의 마지막 두개의 컴포넌트를 의미한다. {n}이 없으면 기본적으로 카테고리의 이름을 모두 출력한다.
- -%t : 로그 이벤트가 발생한 쓰레드의 이름을 출력한다.
- -%x : 로깅이 발생한 thread 와 관련된 NDC(nested diagnostic context) 를 출력한다. java servlet 과 같이 다수의 클리이언트가 분산된 스레드에 의해 다루어 질 때 유용하다.
- -%n : 플랫폼 종속적인 개행문자가 출력(\r\n 또는 \n)-%% = %표시를 출력한다.
※ 아래의 형식은 프로그램의 실행 속도에 영향을 미치게 된다. 그러므로 중요하지 않은 것이 아니라면 사용을 피하는편이 좋다.
- -%d : 로깅 이벤트가 일어난 날짜를 출력한다.%d{HH:mm:ss} 또는 %d{dd MMMM yyyy HH:mm:ss} 만약 날짜 형식 지정자가 주어져 있지 않다면 ISO8601 형식으로 나타난다. 날짜형식 지정자는 자바의 속도가 느린 SimpleDAteFormat 클래스의 시간형식 문자열과 같은 문법을 수용했다. 더 빠른 성능을 위해 %d{ISO8601}, %d{ABSOLUTE}, %d{RELATIVE}(프로그램 시작 후 경과시간의 밀리세컨드 값을 나타내며 가장 빠르다.) 또는 %d{DATE}를 사용하며 각각은 log4j의 ISO8601DateFormat, AbsoluteTimeDateFormat, RelativeTimeDateFormat, DateTimeDateFormat날짜형식을 사용한다.
- -%C : 로깅 요청을 일으킨 호출자의 클래스명을 출력한다. 예를 들어 org.apache.xyz.SomeClass 처럼 되어 있다면 %C{2}는 xyz.SomeClass 가 출력된다.
- -%M : 로깅이 발생한 method 이름을 출력한다.
- -%F : 로깅이 발생한 프로그램 파일명을 출력한다.
- -%l : 소스코드의 위치 정보를 출력한다.
- -%L : 로깅이 발생한 행번호를 출력한다.
각 클래스나 패키지별로 로그를 따로 설정할 수 있다.
설정방법은 아래와 같다. Class 혹은 Package별로 다른 출력 방식을 적용할 수 있다.
log4j.properties설정
#Root Loggerlog4j.rootLogger=INFO
바로 위처럼 Root Logger에 어떤 Appender도 설정하지 않으면 Root Logger는 Log Message를 출력하지 않는다.
각 Package마다 다른 Appender를 적용시켜서 Package별로 다른 파일에 Log Message를 출력한다.
##log4j.loggerFactory=com.sds.eo.common.PemLoggerFactorylog4j.rootCategory=DEBUG, console, pemlog
log4j.logger.pem.mysingle_log=DEBUG, mysingle
log4j.logger.pem.seven_log=DEBUG, seven
log4j.logger.pem.createItem=DEBUG, createItem
log4j.logger.pem.getItem=DEBUG, getItem
log4j.logger.pem.ews=DEBUG, ewslog4j.appender.console=org.apache.log4j.ConsoleAppender
log4j.appender.console.layout=org.apache.log4j.PatternLayout
log4j.appender.console.layout.ConversionPattern=%d{HH:mm:ss} %5p (%C{2} - %M:%L) - %m%n## pushemail 관련 로그
##/eouser/axis/webapps/axis
log4j.appender.pemlog=org.apache.log4j.DailyRollingFileAppender
log4j.appender.pemlog.File=${eo.logging.path}/logs/pem.log
log4j.appender.pemlog.DatePattern='.'yyyy-MM-dd
log4j.appender.pemlog.layout=org.apache.log4j.PatternLayout
#log4j.appender.A2.layout.ConversionPattern=%d{HH:mm:ss} %5p [%t] (%c:%L) - %m%n
log4j.appender.pemlog.layout.ConversionPattern=%d{HH:mm:ss} %5p (%C{2} - %M:%L) - %m%n
log4j.appender.pemlog.Threshold=DEBUG## single 관련 로그
log4j.appender.mysingle=org.apache.log4j.DailyRollingFileAppender
log4j.appender.mysingle.File=${eo.logging.path}/logs/single.log
log4j.appender.mysingle.DatePattern='.'yyyy-MM-dd
log4j.appender.mysingle.layout=org.apache.log4j.PatternLayout
#log4j.appender.A2.layout.ConversionPattern=%d{HH:mm:ss} %5p [%t] (%c:%L) - %m%n
log4j.appender.mysingle.layout.ConversionPattern=%d{HH:mm:ss} %5p (%C{2} - %M:%L) - %m%n
log4j.appender.mysingle.Threshold=DEBUG## 세븐 인터페이스 관련 로그
log4j.appender.seven=org.apache.log4j.DailyRollingFileAppender
log4j.appender.seven.File=${eo.logging.path}/logs/seven.log
log4j.appender.seven.DatePattern='.'yyyy-MM-dd
log4j.appender.seven.layout=org.apache.log4j.PatternLayout
#log4j.appender.A2.layout.ConversionPattern=%d{HH:mm:ss} %5p [%t] (%c:%L) - %m%n
log4j.appender.seven.layout.ConversionPattern=%d{HH:mm:ss} %5p (%C{2} - %M:%L) - %m%n
log4j.appender.seven.Threshold=DEBUG## address performance 측정 로그
log4j.logger.com.sds.eo.service.mysingle.address=DEBUG, address
log4j.appender.address=org.apache.log4j.DailyRollingFileAppender
log4j.appender.address.File=${eo.logging.path}/logs/address.log
log4j.appender.address.DatePattern='.'yyyy-MM-dd
log4j.appender.address.layout=org.apache.log4j.PatternLayout
#log4j.appender.A4.layout.ConversionPattern=%d{HH:mm:ss} %5p [%t] (%c:%L) - %m%n
log4j.appender.address.layout.ConversionPattern=%d{HH:mm:ss}|%m%n
log4j.appender.address.Threshold=DEBUG## approval performance 측정 로그
log4j.logger.com.sds.eo.service.mysingle.approval=DEBUG, approval
log4j.appender.approval=org.apache.log4j.DailyRollingFileAppender
log4j.appender.approval.File=${eo.logging.path}/logs/approval.log
log4j.appender.approval.DatePattern='.'yyyy-MM-dd
log4j.appender.approval.layout=org.apache.log4j.PatternLayout
#log4j.appender.A4.layout.ConversionPattern=%d{HH:mm:ss} %5p [%t] (%c:%L) - %m%n
log4j.appender.approval.layout.ConversionPattern=%d{HH:mm:ss}|%m%n
log4j.appender.approval.Threshold=DEBUG## createitem 로그
log4j.logger.createItem=DEBUG, createItem
log4j.appender.createItem=org.apache.log4j.DailyRollingFileAppender
log4j.appender.createItem.File=${eo.logging.path}/logs/createItem.log
log4j.appender.createItem.DatePattern='.'yyyy-MM-dd
log4j.appender.createItem.layout=org.apache.log4j.PatternLayout
#log4j.appender.A4.layout.ConversionPattern=%d{HH:mm:ss} %5p [%t] (%c:%L) - %m%n
log4j.appender.createItem.layout.ConversionPattern=%d{HH:mm:ss}|%m%n
log4j.appender.createItem.Threshold=DEBUG## getItem 로그
log4j.logger.getItem=DEBUG, getItem
log4j.appender.getItem=org.apache.log4j.DailyRollingFileAppender
log4j.appender.getItem.File=${eo.logging.path}/logs/item.log
log4j.appender.getItem.DatePattern='.'yyyy-MM-dd
log4j.appender.getItem.layout=org.apache.log4j.PatternLayout
#log4j.appender.A4.layout.ConversionPattern=%d{HH:mm:ss} %5p [%t] (%c:%L) - %m%n
log4j.appender.getItem.layout.ConversionPattern=%d{HH:mm:ss}|%m%n
log4j.appender.getItem.Threshold=DEBUGlog4j.logger.ews=DEBUG, ews
log4j.appender.ews=org.apache.log4j.DailyRollingFileAppender
log4j.appender.ews.File=${eo.logging.path}/logs/ews.log
log4j.appender.ews.DatePattern='.'yyyy-MM-dd
log4j.appender.ews.layout=org.apache.log4j.PatternLayout
#log4j.appender.A4.layout.ConversionPattern=%d{HH:mm:ss} %5p [%t] (%c:%L) - %m%n
log4j.appender.ews.layout.ConversionPattern=%d{HH:mm:ss}|%m%n
log4j.appender.ews.Threshold=DEBUG
#log4j.appender.A2.MaxFileSize=300KB
# Keep one backup file
#log4j.appender.A2.MaxBackupIndex=2log4j.logger.com.ibatis=INFO
log4j.logger.java.sql=INFO
#log4j.logger.java.sql.PreparedStatement=INFO
log4j.logger.org.apache=INFO
log4j.logger.org.apache.struts=INFO
log4j.logger.org.apache.commons.beanutils=INFO
log4j.logger.org.apache.commons.httpclient=INFO
log4j.logger.org.apache.axis=INFO[출처] Log4J를 정리하며 - 제 3화 Properties설정|작성자 붉은눈
'프로그래밍' 카테고리의 다른 글
멀티캐치(multicatch) (0) | 2017.06.22 |
---|---|
try-with-resources 이용 자원 해제 자동 처리 (0) | 2017.06.22 |
[Java / 자바] 소켓 통신 (Socket) (0) | 2017.06.07 |
[Java / 자바]쓰레드 처리 (Thread) (0) | 2017.06.07 |
Java 소켓 프로그래밍 (0) | 2017.06.06 |