로컬에 톰캣으로 개발 환경을 셋팅하고 스프링과 log4j를 사용하기 위해 기본적인 설정을 한 후

로깅을 해보았습니다.

log4j.xml은 /WEB-INF/classes에 있었고 기본적인 클래스패쓰에 들어가 있어서인지

web.xml에 별다른 설정을 해주지 않아도 log4j를 사용해 logging이 가능했습니다.

그런데 문제는 같은 로그가 두번씩 찍힌다는 것이었습니다..

log4j.xml의 설정은 아래와 같았습니다.


 <logger name="com.tistiory.devyongsik.indexing">
  <level value="debug" />
  <appender-ref ref="CONSOLE" />
 </logger>
 <root>
  <level value="warn"/>
  <appender-ref ref="CONSOLE"/>
 </root>

문제는.. com.tistiory.devyongsik.indexing 이 패키지안에서 로깅을 하는 것들이
2번씩 중복되어서 나타나는 것이었습니다.

root 로거에 대한 설정을 지우면 한번만 찍히지만
그렇게 되면 tomcat이 구동될때, log4j의 설정을 찾지 못 한다고 나옵니다.

log4j:WARN No appenders could be found for logger (org.apache.catalina.startup.TldConfig).
log4j:WARN Please initialize the log4j system properly.

톰캣이 구동될때는 common-logging.jar와 tomcat/conf/logging.properties를 이용해서 로깅이 되고
그 후에 spring이나 이쪽에서 해당 webapplication에 설정되어 있는 log4j.xml을 이용해서 로깅하려고 할 때
org.apache.catalina.startup.TldConfig 이 패키지에 대해서 로거가 설정되어있는 부분이 없어서 저런 warning 메시지가 나오는 것 같습니다.

(Root 로거 설정이 있을 때 WARN 메시지가 나오지 않는 이유는 당연히 Root 로거가 최상위 로거이기 때문입니다.)

실제로 처음 톰캣이 구동될때의 로깅 메시지는


2008. 12. 17 오후 4:31:30 org.apache.coyote.http11.Http11BaseProtocol init
정보: Initializing Coyote HTTP/1.1 on http-8889
2008. 12. 17 오후 4:31:30 org.apache.catalina.startup.Catalina load
정보: Initialization processed in 468 ms

이렇게 tomcat/conf/loggin.properties 에 설정되어있는 레이아웃이고
제가 WEB-INF/classes/log4j.xml에

 <logger name="org.apache.catalina.startup">
  <level value = "debug" />
  <appender-ref ref="CONSOLE" />
 </logger>
이렇게 로거에 대한 설정을 추가하였을때는 위에서 나오던 warning 메시지는 나오지 않고

12.17 04:31:30 오후 DEBUG - TldConfig.tldScanResourcePaths(576) ||  Accumulating TLD resource paths
12.17 04:31:30 오후 DEBUG - TldConfig.tldScanResourcePaths(583) ||   Scanning <taglib> elements in web.xml
12.17 04:31:30 오후 DEBUG - TldConfig.tldScanResourcePathsWebInf(629) ||   Scanning TLDs in /WEB-INF subdirectory
12.17 04:31:30 오후 DEBUG - TldConfig.tldScanResourcePathsWebInf(629) ||   Scanning TLDs in /WEB-INF/jsp subdirectory
12.17 04:31:30 오후 DEBUG - TldConfig.tldScanResourcePathsWebInf(629) ||   Scanning TLDs in /WEB-INF/jsp/analyzerTest.jsp subdirectory
12.17 04:31:30 오후 DEBUG - TldConfig.tldScanResourcePathsWebInf(629) ||   Scanning TLDs in /WEB-INF/jsp/searchResult.jsp subdirectory

이렇게 로깅이 됩니다. 그리고 이때의 로깅 레이아웃 패턴은 tomcat/conf/logging.properties에 설정되어 있는 패턴이 아니라, 제가 WEB-INF/classes/log4j.xml에 설정해 놓은 레이아웃 패턴으로 나오게 됩니다. 그리고 다시

2008. 12. 17 오후 4:31:32 org.apache.coyote.http11.Http11BaseProtocol start
정보: Starting Coyote HTTP/1.1 on http-8889
2008. 12. 17 오후 4:31:32 org.apache.catalina.startup.Catalina start
정보: Server startup in 2391 ms
2008. 12. 17 오후 4:32:12 org.apache.catalina.core.StandardContext reload
정보: Reloading this Context has started

이런식으로 tomcat/conf/logging.properties에 설정되어있는 패턴으로 로깅이 되게 됩니다.

하나의 webapplication을 구동 할 때 퍼올려지는 순서에 상관이 있는건지도 모르겠습니다.

자세한 내용을 아신다면 코멘트를 부탁드리겠습니다.^^

아무튼 전부다 구동이 되고 이후 로깅을 할 때 위 패키지에서 (com.tistiory.devyongsik.indexing)에서 로깅을 할 때 로깅이 두번씩 된다는 것이 문제였습니다.

root 설정을 지우면 위에서 방금 말씀드린대로 톰캣 구동시 warning 메시지를 보게 되구요..
무슨 방법이 없을까 하고 찾아보다가 .. 이런 내용을 발견했습니다.

"logger는 기본적으로 정의한 패키지의 상위로부터 모든 appender를 상속받는다."

그렇다면 root 로거에서 설정한 appender를

 <logger name="com.tistiory.devyongsik.indexing">
  <level value="debug" />
  <appender-ref ref="CONSOLE" />
 </logger>
이 로거에서도 상속받게 되고 그래서 두번 찍히는 것이 아닌가 하는 생각이 들었습니다.
(물론 설정 때문에 두번찍힌다는 것은 알고 있었습니다. root 로거에 대한 설정을 지우면 한번만 찍히니까요 ^^)

상속받은걸로도 찍고, 자기걸로도 찍고... 말이죠

이것은 하나의 로거에서 여러 다른 appender로 동시에 로그를 출력 할 수 있는 장점이 있습니다. 아마 그래서 그런
구조를 선택한게 아닌가 싶기도 하구요.. 하지만 그렇다고 해서 같은 로그가 두번씩 찍히는 것은 좀 아니잖아요?
ㅎㅎ

이것을 해결하기 위해 로거를 설정 할 때의 옵션이 있습니다.

바로 additivity라는 것입니다. 이것을 logger의 attribute로 지정해주면 됩니다.


 <logger name="com.tistiory.devyongsik.indexing" additivity="false">
  <level value="debug" />
  <appender-ref ref="CONSOLE" />
 </logger>

이렇게되면 이 로거는 상위로부터 내려오는 appender를 상속을 하지 않게 됩니다.

(내부적으로 상속자체를 안 받는건지 받은 걸 안 쓰는건지는 잘 모르겠습니다 -_-)

그리고 또 하나의 방법이 있습니다.

root 로거가 console로 찍히고 위 com.tistory.devyongsik.indexing 로거도 console로 찍혀야 하는데 appender가 상위로부터 상속받아지는 것이라면 굳이 같은 appender를 통해서 로깅이 되는 것들은 appender를 지정하지 않아도 될 것입니다.

즉, 아래와 같이 설정을 해줘도 됩니다.

 <logger name="com.tistiory.devyongsik.indexing" >
  <level value="debug" />
 </logger>

이렇게 설정하면 상속받은 appender 만으로 로깅을 하게 됩니다.

만약 ,

 <logger name="com.tistiory.devyongsik.indexing" >
  <level value="debug" />
  <appender-ref ref="다른APPENDER" />
 </logger>

라고 설정하면, 이 로거는 root로부터 받은 CONSOLE Appender와
자기가 가지고 있는 다른APPENDER를 통해 동시에 로깅을 하게 됩니다.

저작자 표시
신고
Posted by 용식
일반적으로 log4j를 쓰기 위해 WEB-INF/lib에 log4j.jar와 WEB-INF/classes에
log4j.xml을 넣어둔다.

그렇게 되면 톰캣이 구동된 이후 해당 application에서는 위 log4j.xml 의 설정에 따라서
log4j를 사용해 로깅이 가능

final private static org.apahce.Log4j.Logger logger = org.apahce.Log4j.Logger.getLogger(KoreanStemFilter.class);


이것을 대신해서 아파치의 commons 를 사용 할 수도 있다.
final private static org.apache.commons.logging.Log logger = LogFactory.getLog(KoreanStemFilter.class);

아파치의 Commons Logging (JCL)은 commons-logging.properties 파일에 사용하게 될 구현체를
설정하지 않으면, 사용 가능한 로그를 자동으로 찾아 (분기..) 사용하게 된다. (Log4j나, JDK나..)


이것은 Log4j.xml이 없을 경우에는 Tomcat/conf에 있는
logging.properties 이 설정을 따라서 로깅이 된다.


웹 어플리케이션이 아니더라고
java.util의 로깅을 사용 할 수 있는데

이때는 jdk/lib에 있는 logging.properties에 있는 설정을 따르게 되고
이때는 debug대신에 fine을 사용하게 된다.

만일, 위 상황에서
commons-logging.jar를 클래스패스 root에 넣어두게 되면
logger.fine 대신 logger.debug를 사용하면 된다.

마찬가지로 java.util.Logging이나 org.apache.commons.logging.Log가
바라보는 설정은 jdk/lib가 되며

다만 fine이나 debug냐가 달라지는 것..


만일 Log4j.jar를 tomcat/lib에 넣어두면
톰캣이 구동되면서 jvm의 로깅이 아닌 Logj4를 사용해 최초 구동 로그가 올라가게 되고
이렇게 되면 당연히 톰캣이 바라보고 있는 곳에 Logj4.xml이 존재해야 한다.

하지만 이렇게 되면 Log4j.xml이 글로벌하게 잡히기 때문에
위 방식 보다는 각각의 context별로 log4j 설정을 잡아서 사용하는게 낫다.

도움 : 김풍주대리님
신고
Posted by 용식
TAG log4j
출처 얼리뉴스 | 얼리맨
원본 http://blog.naver.com/napple/38214697
TestServlet.java



import javax.servlet.*;
import javax.servlet.http.*;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

public class TestServlet extends HttpServlet {


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



public void init(ServletConfig config) throws ServletException {
super.init(config);
}



public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

try {
...

logger.info("Hellow World~");

...

} catch (Exception e) {
logger.error("Error at TestServlet", e);
}
}
}

////////////////////////////////////


① 프로그램에서 설정
<%@ page contentType="text/html;charset=MS949"
import="org.apache.log4j.*,java.io.* "
%>

<%!
static Logger logger = Logger.getLogger("log4j.jsp");
%>

<%
String layout = "%d %-5p [%t] %-17c{2} (%13F:%L) %3x - %m%n";
String logfilename = "DailyLog.log";
String datePattern = ".yyyy-MM-dd ";

PatternLayout patternlayout = new PatternLayout(layout);
DailyRollingFileAppender appender = new DailyRollingFileAppender(patternlayout, logfilename, datePattern);
logger.addAppender(appender);
logger.setLevel(Level.INFO);
logger.fatal("fatal!!");
%>




② property 파일에 설정
log4j.properties를 만들어 /WEB-INF/classes 밑에 놓으세요





log4j.rootLogger=INFO, stdout, rolling

log4j.appender.stdout=org.apache.log4j.ConsoleAppender

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

log4j.appender.stdout.layout.ConversionPattern=%d %-5p [%t] %-17c{2} (%13F:%L) %3x - %m%n

log4j.appender.rolling=org.apache.log4j.DailyRollingFileAppender

log4j.appender.rolling.File=output.log

log4j.appender.rolling.Append=true

log4j.appender.rolling.DatePattern='.'yyyy-MM-dd

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

log4j.appender.rolling.layout.ConversionPattern=%d %-5p [%t] %-17c{2} (%13F:%L) %3x - %m%n

/////////////////////////////////

[Struts] 무지막지한 Digester의 로그 메시지 막기..

스트럿츠에 Log4J로 로깅을 하고, Log 레벨을 DEBUG로 지정하면 해당 웹 컨텍스트를 포함하고 있는 톰캣 혹은 WAS를 실행할 때마다 엄청난 Digester(스트럿츠가 사용하는 XML 설정 파일 파싱 라이브러리)의 로그에 질려버리게 된다.

그럴때는 스트럿츠 웹 컨텍스트의 log4.properties에 다음을 살짝 추가해준다.


# Remove org.apache.* logs
log4j.logger.org.apache=WARN


물론 로그 레벨은 원하는 대로 바꿔도 된다.

위와 같이 할 경우 저 로그 레벨은 모든 org.apache 패키지 이하의 클래스들의 로깅에 다 적용된다.
특정 아파치 프로젝트의 로깅만 막고 싶다면 그 프로젝트의 패키지명을 지정하면 된다.
예를들면 스트럿츠의 로깅을 막고 싶으면 "log4j.logger.org.apache.struts=WARN" 하는 식으로 바꾼다.


/////////////////////////////////////

// 로거 임포트하기
import org.apache.log4j.Logger;

public class ClassName {
/** Log4J 로거 얻기 */
private Logger log = Logger.getLogger(ClassName.class);
//혹은 private Logger log = Logger.getLogger(this.class);
public void method() {

if (log.isDebugEnabled()) {
log.debug("디버깅용 메시지");
}
log.info("정보를 남기기위한 메시지");

try {
//어쩌구 저쩌구 실행...
} catch (Exception ex) {
//로그에 예외 메시지도 함께 남기기
log.error("예외가 발생했어요~~", ex);
}
}
}

//////////////////////////////////

log4j.rootLogger = DEBUG, stdout, dailyfile

log4j.appender.stdout = org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout = org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%5p (%F[%M]:%L) [%d] - %m%n

log4j.appender.dailyfile.Threshold = DEBUG
log4j.appender.dailyfile = org.apache.log4j.DailyRollingFileAppender
log4j.appender.dailyfile.File = logfile.log
log4j.appender.dailyfile.layout = org.apache.log4j.PatternLayout
log4j.appender.dailyfile.layout.ConversionPattern=%5p (%F[%M]:%L) [%d] - %m%n
신고
Posted by 용식
TAG log4j
출처 dingku.com | 딩구닷컴
원본 http://blog.naver.com/mrdingku/20038704662

준미니(mjm4sky) 님의 블로그에서 퍼온글

=================================================================================

일반적으로 log4j.properties 파일은 /WEB-INF/classes/ 하위에 있어야 좝戮犬歌?자동으로 load 하지만

eclipse나 IDE 툴에서 build clean을 하게 되면 log4j.properties 파일까지 모두 지워지게 된다.

물론 /src 하위에 파일을 놓아두어도 되지만 파일이 두개가 생기게 되므로 혼란을 가져올 수도 있다.

따라서 log4j.properties 파일 정보를 web.xml에 설정하도록 한다.


#web.xml



  log4jConfigLocation
  >/WEB-INF/log4j.properties
 

신고
Posted by 용식
TAG log4j
 

역자: noct ( http://www.noct.pe.kr/ )
원본 : http://www.vipan.com/htdocs/log4jhelp.html


 System.out.println 을 사용하지 말고 Log4j 를 사용하라.



                      Log4j를 사용하기 위한 빠른 시작


- log4j 소프트웨어(약 2.3MB)를 다운로드해서 log4j.jar (약 156KB)를 추출하라.
logging 메소드가 필요한 클래스들을 찾을 수 있도록 log4j.jar 파일을 어플리케이션의 클래스패스에 포함시켜라.
(필자는 log4j.jar 파일을 자바 설치 디렉토리 밑의 lib/ext 디렉토리에 카피했다. 왜냐하면 자바는 자동적으로
그 디렉토리에서 얻어오고 클래스패스에 추가하기 때문이다.)

- 다음의 예제코드를 TestLogging.java 로 저장해여 클래스패스로 지정된 디렉토리에 위치시키라.

import org.apache.log4j.*;

// log4j 사용방법
public class TestLogging {

    // loggin 카테고리를 초기화한다.  여기서 THE ROOT CATEGORY 를 얻는다
    //static Category cat = Category.getRoot();
    // 또는 사용자 정의 category를 얻는다
    static Category cat = Category.getInstance(TestLogging.class.getName());

    // 여기서부터 로깅한다!  해당메소드들: cat.debug(로그메세지문자열),
    // cat.info(...), cat.warn(...), cat.error(...), cat.fatal(...)

    public static void main(String args[]) {
        // 몇가지 로깅 메소드들.
        cat.debug("Start of main()");
        cat.info("Just testing a log message with priority set to INFO");
        cat.warn("Just testing a log message with priority set to WARN");
        cat.error("Just testing a log message with priority set to ERROR");
        cat.fatal("Just testing a log message with priority set to FATAL");

        // 대체할 수 있지만 불편한 형식
        cat.log(Priority.DEBUG, "Calling init()");
       
        new TestLogging().init();
    }

    public void init() {
        java.util.Properties prop = System.getProperties();
        java.util.Enumeration enum = prop.propertyNames();

        cat.info("***System Environment As Seen By Java***");
        cat.debug("***Format: PROPERTY = VALUE***");

        while (enum.hasMoreElements()) {
            String key = (String) enum.nextElement();
            cat.info(key + " = " + System.getProperty(key));
        }
    }

}

Log4j 는 기본적으로 다섯개의 우선권(이하 Priority) 등급으로 메세지를 로깅할 수 있다.

1. 완성된 어플리케이션에서는 출력되지 않아야 할 디버깅 메세지들을 쓰기위해 debug 를 사용하라.
2. 어플리케이션의 verbose 모드에서 출력될만한 메세지들을 로깅하기 위해 info 를 사용하라.
3. 어플리케이션이 이상없이 계속 실행될 수 있는 정도의 경고메세지를 로깅하기 위해 warn 을 사용하라.
4. 어플리케이션이 그럭저럭 돌아갈만한 정도의 에러베세지를 로깅하기 위해 error 를 사용하라.
   예를들어 관리자에 의해 주어진 설정인자가 올바르지 않아 하드코딩된 기본값을 사용해야 할 경우.
5. 로깅후에 애플리케이션이 비정상적으로 종료될 치명적인 메세지를 로깅하기 위해 fatal 을 사용하라.


- 다음의 몇줄을 log4j.properties 라는 이름의 파일로 저장하고 TestLogging.class 파일과 같은 디렉토리에 저장하라.
(TestLogging.java 파일을 컴파일 한 후에)
Log4j는 기본적으로 getRoot()가 호출되거나 getInstatnce("category_name") 이 코드상에서 호출되었을 때
어플리케이션의 클래스패스에서 이 파일을 찻을 것이다.


log4j.rootCategory=DEBUG, dest1
log4j.appender.dest1=org.apache.log4j.ConsoleAppender
log4j.appender.dest1.layout=org.apache.log4j.PatternLayout


PatternLayout 은 기본적으로 사용자가 작성하는 메세지와 개행을 의미하는 %m %n 의 형태이다.
이것은 Log4j의 메소드들의 여러 장점중에 쓰기에 더 짧다는 것을 제외하고는
Java의 System.out.println(...) 메소드와 정확히 동일하게 출력된다.

- TestLoggin.java 파일을 컴파일 하고 실행했을 때 다음과 유사한 출력을 얻게 될 것이다.

Start of main()
Just testing a log message with priority set to INFO
Just testing a log message with priority set to WARN
Just testing a log message with priority set to ERROR
Just testing a log message with priority set to FATAL
Calling init()
***System Environment As Seen By Java***
***Format: PROPERTY = VALUE***
java.runtime.name = Java(TM) 2 Runtime Environment, Standard Edition
sun.boot.library.path = c:\jdk1.3\jre\bin
java.vm.version = 1.3.0_02
java.vm.vendor = Sun Microsystems Inc.
... and so on


- 만약 메세지 다음에 priority 를 출력하고 싶다면(당신이 지정한 메세지에)
  다음 라인을 log4j.properties 파일에 추가하고 저장하면 된다.

log4j.appender.dest1.layout.ConversionPattern=%-5p: %m%n


기본값인 %m %n 을 오버라이드 한다. %p 는 메세지의 priority를, %m은 메세지 자체를,
%n 은 개행문자를 출력할 것이다.
당신은 어떤 자바코드를 바꿀필요도 없고, TestLogging.java 파일을 재컴파일 할 필요도 없이
단지 properties 파일만 바꾸면 된다.

DEBUG: Start of main()
INFO : Just testing a log message with priority set to INFO
WARN : Just testing a log message with priority set to WARN
ERROR: Just testing a log message with priority set to ERROR
FATAL: Just testing a log message with priority set to FATAL
DEBUG: Calling init()
INFO : ***System Environment As Seen By Java***
DEBUG: ***Format: PROPERTY = VALUE***
INFO : java.runtime.name = Java(TM) 2 Runtime Environment, Standard Edition
INFO : sun.boot.library.path = c:\jdk1.3\jre\bin
INFO : java.vm.version = 1.3.0_02
INFO : java.vm.vendor = Sun Microsystems Inc.
... and so on


만약 DEBUG 나 INFO 메세지에 질려서 이것들이 출력되지 않기를 원하고, 다른 메세지들을 여전히 출력되길 원한다면
(예를 들어, 어플리케이션이 생산이 시작될 준비가 되었을 때) log4j.rootCategory=DEBUF, dest1 행을
log4j.rootCategory=WARN, dest1 으로 수정하면 된다.

위의 행은 WARN 보다 priority가 낮은 등급(DEBUG와 INFO 같은)의 메세지들을 제외하는 것이다.
수정하면 다음과 같이 출력될 것이다.

WARN : Just testing a log message with priority set to WARN
ERROR: Just testing a log message with priority set to ERROR
FATAL: Just testing a log message with priority set to FATAL


                               Log4j의 상세


- Log4j에는 세개의 주요한 컴포넌트가 있다. 이것들은 Categories, appenders 그리고 layouts 이다.
- Category를 초기화 시키고 그 후에 여러 로깅메소드를 호출하여 로그파일로 메세지를 보낸다.
- 하나의 Category는 하나 혹은 그 이상의 대상(목적지)에 로그하도록 설정된다.
   Log4j 에서는 이 대상을 "appenders" 라고 부른다. 왜냐하면 이 클래스들은 기본적으로 메세지 문자열을 로그의 끝에
   더하기(append) 때문일 것이다.
   Log4j 는 한번의 로깅을 호출함으로 로그메세지를 콘솔, 텍스트파일, html 파일, xml 파일, 소켓이나
   심지어는 Windows NT Event Log 등 모든 것으로 보낼 수 있다.
   거기다 로그메세지를 이메일로 전송할 수도 있다.(예를 들어 치명적인 에러가 날 경우 사용하기 적당하다)

- 몇몇 appender 클래스들을 나열하자면 ConsoleAppender, FileAppender, SMTPAppender, SocketAppender,
   NTEventLogAppender, SyslogAppender, JMSAppender, AsyncAppender and NullAppender 가 있다.

- appender 는 실제로 로그에 쓰기 전에 메세지 형식을 만드는 layout 을 사용한다.
   예를들어 HTMLLayout 은 모든 메세지를 보기좋은 HTML 테이블 형식으로 만들것이다.

-  Log4j는 날짜, 시간, 메세지 priority(DEBUG, WARN, FATAL 등), Java 클래스명,
   소스코드의 행번호, 메소드명, Java 스레드의 이름 등등을 당신이 보내는 로그메세지에 더할 수 있다.
   로그하는 것은 appender 에 설정된 layout 에 명시된대로이다.


- Category 는 사용자가 지정하며 대소문자를 구별하는 도트로 구분된 문자열이다. 완전한 이름의 자바 클래스를 얻고
  그것을 Category 이름으로 지정하기 위해 보통 클래스명.class.getName() 을 사용한다.
  (게다가 runtime 시에 category 명을 로깅하는 것이 class 명을 로깅하는 것보다 훨씬 더 빠르다.
  만약 빠르면서도 클래스명을 로깅하고 싶다면, class명을 category의 이름으로 지정하고, 카테고리 이름을 로깅하라!)

- category명의 각각의 단어는 그 다음 이어지는 단어의 ancestor(조상)라 하고, 바로 다음 단어의 parent(부모)이다.
  Log4j 는 특정 category 에서 오버라이드 될때까지 ancestor(조상)으로부터 priority와 appender 를
  상속하는 개념이 있기 때문에, 이는 매우 중요하다.

- XML 문서의 root 와 같이 log4j 에는 언제나 이름이 없는 root category 가 존재한다.
  category 를 초기화하기 위해 Category 클래스의 static 메소드를 사용한다.

Category cat = Category.getRoot();
Category cat2 = Category.getInstance("your.category.name");


\\특정 category 이름을 위해 Category.getInstance(...) 메소드는 항상 정확히 동일한 Category 객체를 리턴한다.
따라서 Category 를 초기화해서 차례로 돌릴 필요가 없다. 대신
필요한 어느곳이든 Category.getInstance("wanted.category.name"); 을 써주면 된다.

- "com.comp"라는 패키지의 "TestApp" 라는 이름의 클래스로 Category를 인스턴스화 하는 전형적인 방법은

static Category cat = Category.getInstance(TestApp.class.getName());


TestApp 는 클래스이름 자체이지 인스턴스가 아니라는 것을 명심하라. 또한 TestApp.class 구문은 TestApp 클래스의
새로운 인스턴스를 생성하지 않는다.

- Priority 클래스의 다섯개 priority(우선권) 상수는 우선권이 감소하는 차례로 FATAL, ERROR, WRAN, INFO, DEBUG 이다.
원한다면 (Priority 클래스를) 상속받음으로써 그 이상의 priority를 만들 수 있다.

- category 들에게 priority 를 지정할 수 있지만 꼭 그럴 필요는 없다.
  만약 priority 를 지정하지 않으면 log4j 는 상속관계의 계층구조를 따라서 가장 먼저 할당된 것을 찾아 사용한다.
  root category는 항상 지정된 priority가 있다.(기본값은 Priority.DEBUG),
  따라서 모든 category 들은 항상 priority를 갖도록 보장되어 있다.

- Category 클래스의 logging 메소드의 사용

// 일반적인 로깅 메소드 (불편함)
public void log(Priority p, Object message);

// 편리하게 사용할 수 있는 일반적인 로깅 메소드
public void debug(Object message);
public void info(Object message);
public void warn(Object message);
public void error(Object message);
public void fatal(Object message);


- log4j는 category의 log(...) 메소드가 지정한 priority가 category가 할당되거나 상속받은 priority와
  같거나 더 높을 때에만 로깅한다.

Category cat = Category.getRoot();
cat.setPriority(Priority.ERROR);
// Later...
//cat.info("Started processing..."); //Will not log
cat.error("User input is erroneous!"); //Will log
cat.fatal("Cannot process user input.  Program terminated!"); //Will log


                             Log4j 설정


- 로깅이 가능해지기 전에, 첫째로 log4j 를 설정해야한다. Log4j 를 설정한다는 것은 category(loggers) 들에
  appender (목적지/대상/핸들러)들을 더하고 각각의 appender 에게 layout(전체구성)을 지정하는 것이다.

- category 들은 어떤 순서로든 생성되고 설정될 수 있다. 특히 category 는 그것의 decendants(자손들)을 찾아
  연결할 수 있고, 심지어 그것들보다 나중에 인스턴스화 될 수 있다.

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

- 또한 category 객체의 addAppender() 메소드를 사용함으로써 특정 appender 에 로그하도록 프로그래밍적으로
  category를 설정할 수 있다. 원하는 만큼 더할 수 있다(원하지 않는다면 하지 않아도 상관없다)
  이 메소드는 보통 추천하지 않는다 왜냐 하면 소스파일을 수정하여 다시 컴파일 해야 하기 때문이다.
  java 프로퍼티 파일이나 XML 파일 같은 외부 설정파일을 이용하는 것이 더 좋은 방법이다.

- appender 들은 singleton 이 아니라 추가된다는 것을 주의하라.
  category 는 기본적으로 그것의 조상에서 부터의 모든 appender 들을 물려받는다.
  만약 appender 를 category에 더하고 그것의 기반이 되는 동일한 스트림에 쓴다면(콘솔, 같은 파일 등)
  같은 로그메세지가 두번 이상 로그될 것이다.
  게다가 만약 계층구조의 두개의 category 들이 같은 appender 이름을 사용한다면,
  Log4j 는 그 appender 들에 두번 쓸 것이다.
  appender 로부터 물려받는 것을 불가능하게 하기 위해 category의 cat.setAdditivity(false) 메소드를 사용하라.
  그러면 로그 메세지는 해당 category에 특별히 설정된 appender 로만 보내질 것이다.

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

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

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

- log4j 예제 설정 파일
# root category의 priority 를 to DEBUG 로 설정하고 appender 를 A1 으로 지정한다.
log4j.rootCategory=DEBUG, A1

# A1 을 ConsoleAppender 로 지정(시스템 콘솔에 출력하는).
log4j.appender.A1=org.apache.log4j.ConsoleAppender

# A1 을 PatternLayout 을 사용하도록.
log4j.appender.A1.layout=org.apache.log4j.PatternLayout
log4j.appender.A1.layout.ConversionPattern=%-4r [%t] %-5p %c %x - %m%n

이 예제 파일은 BasicConfigurator.configure() 메소드를 사용한것과 완전히 같이 log4j를 설정한다. 그러나 이방법으로 하면
나중에 설정을 수정할 때에, 예를들어 DEBUG 를 FATAL로 프로퍼티 파일을 고치고 어떤 자바파일도 재컴파일 할 필요가 없다.

- 더 복잡한 log4j 설정파일

#### 두개의 appender를 사용하며, 하나는 콘솔에 로깅하고 다른 하나는 파일에 로깅한다.
log4j.rootCategory=debug, stdout, R

# priority가 WARN 보다 같거나 더 높은 메세지만 출력한다.
log4j.category.your.category.name=WARN
# Specifically inherit the priority level
#log4j.category.your.category.name=INHERITED

#### 첫번째 appender는 콘솔에 쓴다.
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout

# 호출하는 파일명과 라인넘버를 출력하는 Pattern
log4j.appender.stdout.layout.ConversionPattern=%5p [%t] (%F:%L) - %m%n

#### 두번째 appender 는 파일에 쓴다.
log4j.appender.R=org.apache.log4j.RollingFileAppender
log4j.appender.R.File=example.log

# 최대로그파일 크기를 조절
log4j.appender.R.MaxFileSize=100KB
# 집적하는 로그파일의 수 (여기서는 하나의 백업파일)
log4j.appender.R.MaxBackupIndex=1

log4j.appender.R.layout=org.apache.log4j.PatternLayout
log4j.appender.R.layout.ConversionPattern=%p %t %c - %m%n


이제 출력은 example.log 라는 파일에 덧붙여질 것이고, 이 파일은 크기가 100KB 가 될때 롤오버 될것이다.
롤오버가 일어날 때 구버전의 example.log 파일은 자동으로 example.log.1 파일로 바뀐다.
DailyRollingFileAppender 를 사용하여 파일을 매분, 매시간, 매일, 매주, 매달 또는 하루 2회씩 롤오버되게 할 수 있다.


- 서버 같이 오랫동안 실행되는 프로그램에서는 Java 프로퍼티 파일을 이용하여 환경설정을 하기 위해
  configureAndWatch(String configFilename, long delay_in_milliseconds)를 사용한다.
  Log4j 는 몇 밀리세컨드 마다 프로퍼티 파일이 변하는지를 계속 모니터링 하다가
  프로퍼티 파일이 변하면 설정을 업데이트할것이다.

- 프로그램 출시단계가 되면 빠른 성능을 위해 계층구조의 모든 category에서 특정 priority 이하의 모든 메세지를
  로깅하지 않도록 할 수 있다. 예를 들어, 아무것도 로깅하지 않으려면, log.diable=FATAL 을
  설정파일(property파일)에 명시해주면 된다.

단 log.disableOverride 프로퍼티가 false 로 세팅되어 있지 않다면 예외가 일어난다.
따라서 시스템 관리자는 log.disable을 오버라이드 할 수 있도록 환경설정 파일에
log.disableOverride=true 를 (일시적으로)명시하고 모든 메세지를 로그해서 생기는 문제를 조사해봐야 한다.



                               유용한 Layout 들


- 몇가지 layout 클래스들을 들자면 TTCCLayout, HTMLLayout, PatternLayout, SimpleLayout 그리고 XMLLayout이 있다.
- SimpleLayout 과 PatternLayout 클래스들은 자바의 Throwable 에러들과 예외를 무시한다.
  HTMLLayout과 XMLLAyout 은 그것들을 다룬다.
- SimpleLayout 은 로그 구문의 property 에 이어 "-" 이나오고 로그메세지가 나오는 구성이다. 예를 들어
 
  DEBUG - Hello world

- PatternLayout 은 C언어의 printf 함수와 유사한 변환 패턴에 따라 출력을 형식을 지정할 수 있게 한다.
  PatternLayout 의 변환 형식을 %r [%t] %-5p %c - %m%n 로 하면 다음과 같이 출력된다.

176 [main] INFO  org.foo.Bar - Located nearest gas station

- 가장 첫 필드는 프로그램이 시작된 후로부터 경과된 시간의 밀리세컨드 값이다.
- 두번째 필드는 로그 요청을 만든 스레드이다.
- 세번째 필드는 로그 구문의 priority 이다.
- 네번째 필드는 로그요청에 관련된 category의 이름이다.
- "-" 뒤의 문자열은 로깅메세지이다.

- 변환 형식에 어떤 문자도 삽입될 수 있다.
- 변환 문자들은 다음과 같다.
- %m : 당신이 지정한 메세지를 출력
- %p : 로깅 이벤트의 priority 를 출력
- %r : 어플리케이션이 시작되어 로깅이벤트가 일어날때까지의 경과시간을 밀리세컨드 값으로 출력
- %c : 로깅이벤트의 category를 출력한다. 예를 들어 category 이름이 "a.b.c" 일때 %c{2} 는 "b.c"를 출력하며 {2}는
        도트(.)로 구분된 category 이름의 마지막 두개의 컴포넌트를 의미한다.
        {n} 이 없으면 기본적으로 카테고리의 이름을 모두 출력한다.
- %t : 로깅 이벤트를 생성한 스레드 이름을 출력
- %x : 로깅이벤트를 발생시킨 스레드에 관련된 내포검사항목(Nested Diagnostic Context : NDC)을 출력한다.
        Java Servlet 과 같이 다수의 클라이언트가 분산된 스레드에 의해 다루어 질 때 유용하다.
- %n : 플랫폼 독립적인 개행문자를 출력한다. "\n" 또는 "\n\r" 등이 지정될 수 있다.
- %% : 하나의 % 기호를 출력한다.
- 경고 : 아래의 형식은 프로그램의 실행속도를 느리게 한다. 실행속도가 중요하지 않은 것이 아니라면 사용을 피하도록 한다.
- %d : 로깅이벤트가 일어난 날자(date)을 출력한다.
        date 변환 지정자는 날짜형식 지정자 뒤에 이어 나오는 brace({..}) 사이에 둘러쌓여 나온다.
        예: %d{HH:mm:ss,SSS} 또는 %d{dd MMM yyyy HH:mm:ss,SSS}
        만약 날자 형식 지정자가 주어져있지 않다면 ISO8601 형식으로 나타난다. 날짜형식 지정자는 자바의 속도가 느린
        SimpleDateFormat 클래스의 시간형식 문자열과 같은 문법을 수용했다.
        더 빠른 성능을 위해 %d{ISO8601}, %d{ABSOLUTE}, %{RELATIVE}(프로그램 시작 후 경과시간의 밀리세컨드값을 나타내며
        가장 빠르다) 또는 %d{DATE} 를 사용하며 각각은
        log4j의 ISO8601DateFormat, AbsoluteTimeDateFormat, RelativeTimeDateFormat, DateTimeDateFormat 날자형식을 사용한다.

- %l : 소스코드의 위치정보를 출력한다. %C. %M(%F:%L) 의 축약형이다.
- %C : 로깅요청을 일으킨 호출자의 완전한 클래스이름을 출력한다.
        예를들어 "org.apache.xyz.SomeClass"라는 클래스 이름이 있을때, %C{1} 은 "SomeClass"를 출력한다.
        {1} 는 "완전한 클래스이름의 마지막 하나의 구성요소를 출력하라" 는 뜻이다. 만약 {n} 이 없다면
        기본적으로 완전한 클래스 이름을 출력한다.
- %M : 로깅요청을 일으킨 메소드를 출력한다.
- %F : 로깅요청을 일으킨 파일 이름을 출력한다.
- %L : 로깅요청을 일으킨 곳의 행번호를 출력한다.


- 선택적으로 퍼센트 기호와 변환 문자 사이에 형식수정자(format modifier)를 사용하여 최소 필드넓이를 바꾸고,
  최대 필드 넓이와 필드 안에서의 문자의 정렬을 바꿀 수 있다.

- 필드 안에서 완쪽 정렬을 하기위해 마이너스 기호(-)를 사용한다. 기본적으로는 오른쪽 정렬이다(왼쪽에 여백을 둠)
- 최소 필드 넓이를 명시하기 위해 양의 정수를 사용한다. 만약 데이타 항목이 더 적은 문자를 가지고 있으면 최소넓이에
   도달할 때까지 오른쪽 똑은 왼쪽에 공백이 생긴다. 만약 데이터 항목의 길이가 최소 필드폭 보다 크면
   필드넓이가 데이터에 맞게 확장된다.

- 마침표 뒤에 나오는 양의 정수는 최대 필드폭을 지정한다. 만약 데이터항목이 최대필드폭보다 길면 나머지 문자들은
   데이터항목의 끝이 아니라 시작에서부터 지워진다.예를 들어 최대필드폭이 8이고 데이터 항목의 길이가 10개문자라면,
   데이터 항목 처음 두개의 문자는 지워진다. 이런 동작은 끝에서부터 잘라내는 C언어의 printf 함수와 차이가 난다.

- 예 :
- %20c : 최소 20문자 공간에서 category 이름을 (기본적인)오른쪽 정렬
- %-20c : 최소 20문자 공간에서 category 이름을 왼쪽 정렬
- %.30c : 만약 category 이름이 30문자보다 길면 (앞에서부터)자른다.
           최소폭이 없으므로 30문자보다 짧다고 해도 여백공간은 없다.
- %20.30c : category 이름이 20문자보다 짧으면 오른쪽 정렬을 하고, 30자보다 길면 시작부터 자른다.
- %-20.30c : category 이름이 20자보다 짧으면 왼쪽 정렬을 하고, 30자보다 길면 시작에서부터 자른다.
- %r [%t] %-5p %c %x - %m\n : 이 형식이 본래 TTCCLayout 이다.
- %-6r [%15.15t] %-5p %30.30c %x - %m\n : TTCCLayout과 다음의 형식을 제외하고 유사하다.
   상대시간이 6자가 안될때에 오른쪽에 여백을 두고, 스레드명이 15자가 안될때에
   오른쪽에 여백을 두고, 더 길때에는 자르며, category명이 30자가 안될때는 오른쪽에 여백을 두고 더 길때는 자른다.

- 고급 : 단지 log로 문자열만을 넘길 필요는 없다. 객체도 로그메세지에 넘길 수 있다.
         ObjectRenderer 를 implement 하면 객체를 문자열로 표시하여 appender 에 로깅한다.


                 Log4j 에서 Appender와 Layout 옵션의 Property keys

log4j 의 전체 옵션들

- log4j.configuration=app_config.properties : Category.getRoot() 나 Category.getInstance(...) 메소드를 처음으로 호출하여
  Log4j 의 초기화 과정을 마친다.("log4j.debug=true" 로 지정하여 초기화가 일어나는 것을 볼 수 있다)
  초기화되는 동안 Log4j 는 어플리케이션의 클래스패스에서 "log4j.properties" 파일이나
  property key를 통해 지정한 파일을 찾는다. 그러나 이것(설정파일을 지정하기 위해 설정한 property key)을 시스템 property로
  설정할 필요가 있다. 예를 들어 다음과 같이 프로그램을 구동한다.
    java -Dlog4j.configuration=app_config.properties ...

  왜냐하면 만약 설정파일에 세팅했다면 너무 늦기 때문이다.
  Log4j 는 기본 설정파일인 log4j.properties 파일을 읽기 위해 이미 시작했을 것이다.

- log4j.debug=true : 기본값은 false. log4j 를 설정하는 상세 정보를 출력한다.
- log4j.disable=INFO : 모든 category에서 여기 지정한 priority 보다 같거나 낮은 priority 메세지는 로깅하지 않는다.
  log4j.disableOverride 프로퍼티가 기본값인 false 일때에만 동작한다.
- log4j.additivity.your.category.name=false : 기본값은 true. appender를 ancestor(조상)으로부터 쌓이게 할지(true)
  그렇게 하지 않을지(false)를 지정한다.
- 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는 이미 그 파일을 읽기위해 시작되었을 것이다.
- log4j.disableOverride=false: 기본값은 false. 가끔 true로 설정하여 log.disable 프로퍼티를 무시할 수 있다.


ConsoleAppender 옵션들
- Threadhold=WARN: 이 appender는 category의 priority가 더 낮게 지정되어 있다고 할지라도 여기 명시된 priority보다
  낮은메세지들을 로깅하지 않을 것이다. 이것은 콘솔에 모든 메세지가 나타나는 동안 파일에 로깅되는 경우와 같이
  메세지의 숫자를 줄이는데 유용하다.
- ImmediateFlush=true: 기본값은 true. 로그메세지들이 전혀 버퍼되지 않는 것을 의미하며 대부분의 상황에 적당하다.
- Target=System.err: 기본값은 System.out


FileAppender 옵션들
- Threadhold=WARN: 이 appender는 category의 priority가 더 낮게 지정되어 있다고 할지라도 여기 명시된 priority보다
  낮은메세지들을 로깅하지 않을 것이다. 이것은 콘솔에 모든 메세지가 나타나는 동안 파일에 로깅되는 경우와 같이
  메세지의 숫자를 줄이는데 유용하다.
- ImmediateFlush=true: 기본값은 true. 로그메세지들이 전혀 버퍼되지 않는 것을 의미하며 대부분의 상황에 적당하다.
- File=mylog.txt : 로깅할 파일명. 앞부분에 경로를 나타내기 위해 ${some_property_key}
  (예를 들어 java.home 또는 user.home 과 같은 시스템 프로퍼티)를 사용할 수 있다. 사실 모든 옵션들의 프로퍼티키들은
  이런 종류의 값을 설정 가능하다.
- Append=false : 기본값은 true이며 파일 끝에 추가하는 것을 의미한다.
  false 는 각각의 프로그램이 시작할때 파일에 덮어씌운다.


RollingFileAppender 옵션들
- Threadhold=WARN: 이 appender는 category의 priority가 더 낮게 지정되어 있다고 할지라도 여기 명시된 priority보다
  낮은메세지들을 로깅하지 않을 것이다. 이것은 콘솔에 모든 메세지가 나타나는 동안 파일에 로깅되는 경우와 같이
  메세지의 숫자를 줄이는데 유용하다.
- ImmediateFlush=true: 기본값은 true. 로그메세지들이 전혀 버퍼되지 않는 것을 의미하며 대부분의 상황에 적당하다.
- File=mylog.txt : 로깅할 파일명. 앞부분에 경로를 나타내기 위해 ${some_property_key}
  (예를 들어 java.home 또는 user.home 과 같은 시스템 프로퍼티)를 사용할 수 있다. 사실 모든 옵션들의 프로퍼티키들은
  이런 종류의 값을 설정 가능하다.
- Append=false : 기본값은 true이며 파일 끝에 추가하는 것을 의미한다.
  false 는 각각의 프로그램이 시작할때 파일에 덮어씌운다.
- MaxFileSize=100KB : 끝에 KB, MB 또는 GB를 붙인다. 지정한 크기에 도달하면 로그파일을 교체한다(roll).
- MaxBackupIndex=2 : 최대 2개(예)의 백업 파일들을 유지시킨다. 오래된 파일들은 삭제한다. 0 은 백업파일을 만들지 않는다.


DailyRollingFileAppender 옵션들
- Threadhold=WARN: 이 appender는 category의 priority가 더 낮게 지정되어 있다고 할지라도 여기 명시된 priority보다
  낮은메세지들을 로깅하지 않을 것이다. 이것은 콘솔에 모든 메세지가 나타나는 동안 파일에 로깅되는 경우와 같이
  메세지의 숫자를 줄이는데 유용하다.
- ImmediateFlush=true: 기본값은 true. 로그메세지들이 전혀 버퍼되지 않는 것을 의미하며 대부분의 상황에 적당하다.
- File=mylog.txt : 로깅할 파일명. 앞부분에 경로를 나타내기 위해 ${some_property_key}
  (예를 들어 java.home 또는 user.home 과 같은 시스템 프로퍼티)를 사용할 수 있다. 사실 모든 옵션들의 프로퍼티키들은
  이런 종류의 값을 설정 가능하다.
- Append=false : 기본값은 true이며 파일 끝에 추가하는 것을 의미한다.
  false 는 각각의 프로그램이 시작할때 파일에 덮어씌운다.
- 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: 분마다(분이 시작할때) 로그파일을 교체한다.


PatternLayout 옵션들
- ConversionPattern=%m%n : 각각의 로그메세지의 형식을 나타내는 방법(포함하는 정보)


HTMLLayout 옵션들
- LocatoinInfo=true: 기본값은 false. 자바파일명과 행번호를 출력한다.
- Title=My app title : 기본값은 Log4j Log Message. HTML의


출처 : Tong - war333님의 war333님의 기본통 입니다.통

신고
Posted by 용식
TAG log4j

log4j 쓰는 방법..


어제 하루종일 헤맸다..;;


일단 log4j를 쓰기 위해서는


설정 파일이 필요하다.


log4j.properties 나 log4j.xml을 사용하는데


우리는 xml을 쓰지만..그래도 설정 파일 예를 올려보면


##########log4j.properties################

log4j.rootLogger=INFO, stdout1, stdout2


log4j.logger.jsp1=INFO, stdout1
log4j.additivity.jsp1=false


log4j.logger.jsp2=INFO, stdout2
log4j.additivity.jsp2=false


log4j.appender.stdout1=org.apache.log4j.ConsoleAppender
log4j.appender.stdout1.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout1.layout.ConversionPattern=jsp1 appender log %d %-5p [%t] %-17c{2} (%13F:%L) %3x - %m%n


log4j.appender.stdout2=org.apache.log4j.ConsoleAppender
log4j.appender.stdout2.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout2.layout.ConversionPattern=jsp2 appender log %d %-5p [%t] %-17c{2} (%13F:%L) %3x - %m%n

######## log4j.xml ##########

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">

<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">

    <appender name="CONSOLE_APPENDER" class="org.apache.log4j.ConsoleAppender">
        <layout class="org.apache.log4j.SimpleLayout"/>
    </appender>

    <appender name="FILE_APPENDER" class="org.apache.log4j.FileAppender">
        <param name="File" value="file-Log.txt"/>
        <param name="Append" value="false"/>
        <layout class="org.apache.log4j.PatternLayout">
            <param name="ConversionPattern" value="%d [%t] %p - %m%n"/>
        </layout>
    </appender>

    <appender name="ROLL_APPENDER" class="org.apache.log4j.RollingFileAppender">
        <param name="Threshold" value="ALL"/>
        <param name="File" value="/app/logs/testinsu2/application_log.xml"/>
        <param name="Append" value="true"/>
        <param name="ImmediateFlush" value="true"/>
        <param name="BufferedIO" value="false"/>
        <param name="BufferSize" value="8192"/>
        <param name="MaxBackupIndex" value="9"/>
        <param name="MaxFileSize" value="5MB"/>
        <layout class="org.apache.log4j.xml.XMLLayout">
            <param name="locationInfo" value="false"/>
        </layout>
    </appender>


    <appender name="DAILY_APPENDER" class="org.apache.log4j.DailyRollingFileAppender">
        <param name="datePattern" value="yyyy-MM-dd"/>
        <param name="file" value="/app/logs/testinsu2/daily/daily.log"/>
        <param name="append" value="true"/>
        <layout class="org.apache.log4j.PatternLayout">
            <param name="ConversionPattern" value="%n %d{yyyy/MM/dd HH:mm:ss} %-5p %x %M(%F:%L) - %m  %n"/>
        </layout>
    </appender>

    <appender name="SQL_APPENDER" class="org.apache.log4j.DailyRollingFileAppender">
        <param name="datePattern" value="yyyy-MM-dd"/>
        <param name="file" value="/app/logs/testinsu2/sql/sql.log"/>
        <param name="append" value="true"/>
        <layout class="org.apache.log4j.PatternLayout">
            <param name="ConversionPattern" value="%n %d{yyyy/MM/dd HH:mm:ss} %-5p %x %M(%F:%L) - %m  %n"/>
        </layout>

    </appender>


    <category name="sql.log">
        <priority value="debug"/>
        <appender-ref ref="SQL_APPENDER"/>
    </category>

    <category name="time.log">
        <priority value="debug"/>
        <appender-ref ref="DAILY_APPENDER2"/>
    </category>

    <category name="delos.log">
        <priority value="debug"/>
        <!--<priority value="debug"/>-->
        <appender-ref ref="CONSOLE_APPENDER"/>
    </category>
    <!--
        <root>
            <priority value="fatal"/>
            <appender-ref ref="DAILY_APPENDER"/>
        </root>
    -->
</log4j:configuration>



xml에서는 category 태그는 로거 객체를 얻어올때 String을 넘겨서 매핑시켜서 로그를

남길 수 있지만 이는 좀 비효율적으로 보이므로


<logger name="kr.co.mywork.mon">

    <level value = "DEBUG" />

</logger name>


이렇게 설정하여 패키지 단위로 로그 레벨을 설정하도록 하자.



사용 하는 방법은


위 xml 이나 프로퍼티 파일을 톰캣의 클래스패스에 넣으면 되는데

ant등을 사용하여 디플로이를 할 경우에는 src에 넣어두고 타겟을 classes로 설정하여

디플로이 할 때마다 자동으로 배포되도록 하자.


원래는 classes밑에 들어가면 맞다.


그리고


<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@page import="org.apache.log4j.*" %>

<%!
static Logger logger = Logger.getLogger("delos.log");
%>

<%


logger.info("info");
logger.debug("debug");
logger.warn("warn");
logger.error("error");
logger.fatal("fatal error");

out.println("a");
%>


이렇게 String을 넘겨줘서 매핑하던가..


public class Test
{
public static String LOG4J_CONFIG_FILE_PATH = "D:\\JAVA\\workspace\\estore\\dev\\prddataAdminWeb\\WebContent\\WEB-INF\\classes\\log4j.xml";

private static Logger logger = Logger.getLogger("delos.log");


public static void main(String[] args) throws Exception
{
 PropertyConfigurator.configure(Test.LOG4J_CONFIG_FILE_PATH);

//기본설정으로 구성할 때
//BasicConfigurator.configure();

logger.info("info");
logger.debug("debug");
logger.warn("warn");
logger.error("error");
logger.fatal("fatal error");

Exception e = new Exception("Test Exception");
logger.error(e.getMessage(), e);
}
}


이렇게 객체를 줘서 패키지 단위로 설정하던가..


<%!
static Logger logger = Logger.getLogger("index.jsp");
%>

<%

String layout = "%d %-5p [%t] %-17c{2} (%13F:%L) %3x - %m%n";
String logfilename = "DailyLog.log";
String datePattern = ".yyyy-MM-dd ";

PatternLayout patternlayout = new PatternLayout(layout);
DailyRollingFileAppender appender = new DailyRollingFileAppender(patternlayout, logfilename, datePattern);
logger.addAppender(appender);
logger.setLevel(Level.INFO);
logger.fatal("fatal!!");

%>


이렇게 바로 프로그램 안에서 바로 설정해 버릴 수도 있다.


신고
Posted by 용식
TAG log4j