[펌] Log4J...

프로그래밍/Library 2007. 11. 28. 09:38 Posted by galad

/**
 * Created on 2004. 3. 05.
 *
 *
 * @author 짱가
 *
 * *******************************************************
 *                             코드수정히스토리
 * 날짜                               작업자                      내용
 * 2004. 3. 3.                       짱가
 * *******************************************************
 *
 */
/**
 * System.out.println("[WARN]  : " +  e.toSting()  );
 * 이런식으로 코딩해본적 있을것이다. 혹시라도 로그를 빼달라고 하면 모두들
 * System.out.println("[WARN] : " +  e.toSting()  ); //라고 해본사람들이 꽤될것이다.
 * 컴파일 했다가 말았다가 어느게 시스템 Debug용이고 어느게 뭔지 .....
 * 프로그래밍이 끝나고 운용에 들어가면서 속도 향상을 위해 클라이언트가 FATAL에러만 빼고 모두 빼달라고 했다던지
 * 혹은 운용중에 에러를 잡기위해 어느단계까지는 모두 나오게 해야한다던지 할때 이런기능이 없다면
 * 아마 소스코드는 IF문과 System.out.println() 으로 뒤범벅이 될것이다.
 *
 *
 * 로그레벨이라는 개념을 사용하면 약간 수고를 덜수 있다.
 * DEBUG < INFO < WARN < ERROR < FATAL
 * 보통 로그level에서 DEBUG가 가장작고 FATAL이 가장크다. 그래서 위의 예제 결과는 아래와 같이 나온다.
 * 결과를 봐서 알겠지만 예제에서 WORN을 LogLevel로 삼았기 때문에 위의 그림과 같게 아래의 결과가 나온다.
 * java.lang.Object
 *|
 * +--org.apache.log4j.Category
 *       |
 *       +--org.apache.log4j.Logger
 * 보는 바와 같이 Logger class는 Category의 child class였다.
 *
 *
 *
 *
 * API의 일부....
 *
 * Constructor Summary
 * protected Logger(String name)
 *
 * Method Summary
 *
 * 1) static Logger getLogger(Class clazz) --- Same as calling getLogger(clazz.getName()).
 *
 * 2) static Logger getLogger(String name) --- Retrieve a logger by name.
 *
 * 3) static Logger getLogger(String name, LoggerFactory factory) ---Like getLogger(String)
 *     except that the type of logger instantiated depends on the type
 *     returned by the LoggerFactory.makeNewLoggerInstance(java.lang.String) method of the factory parameter.
 *
 * 4) static Logger getRootLogger() --- Retrieve the root logger. 
 *
 * ----------------------------------------------------------------------------------------------------
 * 1)과 2번은 클라스로 근본적으로 같고 예를들면 Logger.getLogger( xxxx.class.getName( ) )
 * 이런식으로 쓰므로 1번과 2번은 근본적으로 같다고 볼수 있다.
 * 3)은 LoggerFactory에 의해 불리우는것에 따라 logger type이 달라지고....
 * 4)째는 모든 Logger는 부모가 있는데 이 부모logger를 사용가능하지만 별로 권장하지 않는다고 한다.
 * http://www.onjava.com/lpt/a/2525 을 참조하기 바란다.
 * 이글에 보면 Tomcat에서의 사용법까지 나와있으며 어떻게 로그를 남기는것이 효율적인지에 대하여 적고 있다.
 *--------------------------------------------------------------------------------------
 *
 * logger class는 Category 클라스의 setLevel( )을 호출하게 되면 level이 정해진다.
 * http://logging.apache.org/log4j/docs/api/org/apache/log4j/Level.html 에서 보는바와같이 level의 종류는
 * 코드:
 * static Level ALL
 * static Level DEBUG
 * static Level ERROR
 * static Level FATAL
 * static Level INFO
 * static Level OFF
 * static Level WARN 와같다.
 * http://logging.apache.org/log4j/docs/api/org/apache/log4j/Category.html
 * 실제 로그를 뿌리는 메서드들을 발견할수 있을것이다. 
 *

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

 *****************************************************************************
 *
 *  여기서 작성한 클래스는 각 기능 별로 txt로 생성하는 로그
 *                                          html로 생성하는 로그
 *           pattern matching을 사용하는 로그
 *            xml로 생성하는 로그
 *           그리고 configuration file로 xml을 사용하여 log파일로 생성하고
 *           그 log파일이 일정 사이즈가 될때 증가시키는 로그로 나뉘어져 있다
 *  참고로 각 실행시에 main으로 실행한후 메소드 명만 수정하였으므로 실행은 그렇게 하면 실행이 가능하다.
 *
 *****************************************************************************
 *
 */

import java.io.FileOutputStream;

import org.apache.log4j.BasicConfigurator;
import org.apache.log4j.ConsoleAppender;
import org.apache.log4j.FileAppender;
import org.apache.log4j.HTMLLayout;
import org.apache.log4j.Level;
import org.apache.log4j.Logger;
import org.apache.log4j.PatternLayout;
import org.apache.log4j.SimpleLayout;
import org.apache.log4j.WriterAppender;
import org.apache.log4j.xml.DOMConfigurator;
import org.apache.log4j.xml.XMLLayout;

public class Logging4J {

 //  Logger.getInstance()의 실체는 Category.getInstance()이며,
 //  Category가 반환되기때문이다. 그리고 이 Category 클래스나 getInstance()
 //     메소드는 추천 되지 않는 API인것으로 알려져있다.
 //  Logger의 취득은 Logger.getLogger()로 하기 바란다
 static Logger logger = Logger.getLogger(Logging4J.class);

 public void consoleLog() {

  Logger logger = Logger.getLogger("loggerTest");
  BasicConfigurator.configure();
  logger.setLevel(Level.WARN);
  logger.debug("this is debug!!!");
  logger.info("this is info!!!");
  logger.warn("this is warn!!!");
  logger.error("this is error!!!");
  logger.fatal("this is fatal!!!");

 }
 /**
  * 생성 로그  txt
  * DEBUG - debug!!!
  * INFO - info!!!
  * WARN - warn!!!
  * ERROR - error!!!
  * FATAL - fatal!!!     *
  */
 public void txtLog() {

  SimpleLayout layout = new SimpleLayout();

  FileAppender appender = null;
  try {
   appender = new FileAppender(layout, "Logging4J.txt", false);
  } catch (Exception e) {
  }

  //  FileAppender(Layout layout, String filename)  : constructor
  //  FileAppender(Layout layout, String filename, boolean append)

  logger.addAppender(appender);

  logger.setLevel(Level.DEBUG);
  logger.debug("debug!!!");
  logger.info("info!!!");
  logger.warn("warn!!!");
  logger.error("error!!!");
  logger.fatal("fatal!!!");
 }
 // html은 너무 길다.. ^^;;
 public void htmlLog() {

  HTMLLayout layout = new HTMLLayout();

  WriterAppender appender = null;
  try {
   FileOutputStream output = new FileOutputStream("Logging4J.html");
   appender = new WriterAppender(layout, output);
  } catch (Exception e) {
  }

  //  FileAppender(Layout layout, String filename)  : constructor
  //  FileAppender(Layout layout, String filename, boolean append)
  //  Logger.getInstance()의 실체는 Category.getInstance()이며,
  //  Category가 반환되기때문이다. 그리고 이 Category 클래스나 getInstance() 메소드는
  //     추천 되지 않는 API인것으로 알려져있다.
  //  Logger의 취득은 Logger.getLogger()로 하기 바란다

  logger.addAppender(appender);

  logger.setLevel(Level.DEBUG);
  logger.debug("HERE is some Debug!!!");
  logger.info("HERE is some info!!!");
  logger.warn("HERE is some WARN!!!");
  logger.error("HERE is some ERROR!!!");
  logger.fatal("HERE is some FATAL!!!");
 }
 /**
  * Classname: Logging4J
  * Date in ISO8601 format: 2004-03-04 11:08:43,950
  * 이벤트 위치: Logging4J.main(Logging4J.java:194)
  * 메시지 : Here is some DEBUG
  * 
  * Classname: Logging4J
  * Date in ISO8601 format: 2004-03-04 11:08:43,950
  * 이벤트 위치: Logging4J.main(Logging4J.java:195)
  * 메시지 : Here is some INFO
  * 
  * Classname: Logging4J
  * Date in ISO8601 format: 2004-03-04 11:08:43,950
  * 이벤트 위치: Logging4J.main(Logging4J.java:196)
  * 메시지 : Here is some WARN
  * 
  * Classname: Logging4J
  * Date in ISO8601 format: 2004-03-04 11:08:43,950
  * 이벤트 위치: Logging4J.main(Logging4J.java:197)
  * 메시지 : Here is some ERROR
  * 
  * Classname: Logging4J
  * Date in ISO8601 format: 2004-03-04 11:08:43,950
  * 이벤트 위치: Logging4J.main(Logging4J.java:198)
  * 메시지 : Here is some FATAL
  *
  *
  */
 public void patternLog() {
  // Note, %n is newline
  String pattern = "Classname: %C %n";
  pattern += "Date in ISO8601 format: %d{ISO8601} %n";
  pattern += "이벤트 위치: %l %n";
  pattern += "메시지 : %m %n %n";

  PatternLayout layout = new PatternLayout(pattern);
  ConsoleAppender appender = new ConsoleAppender(layout);

  logger.addAppender(appender);
  logger.setLevel((Level) Level.DEBUG);

  logger.debug("Here is some DEBUG");
  logger.info("Here is some INFO");
  logger.warn("Here is some WARN");
  logger.error("Here is some ERROR");
  logger.fatal("Here is some FATAL");
 }
 // xml로 기록
 public void xmlLog() {
  XMLLayout layout = new XMLLayout();

  //option setting
  layout.setLocationInfo(true);

  FileAppender appender = null;
  try {
   appender = new FileAppender(layout, "Logging4J.xml", false);
  } catch (Exception e) {
  }

  logger.addAppender(appender);
  logger.setLevel((Level) Level.DEBUG);

  logger.debug("Here is some DEBUG");
  logger.info("Here is some INFO");
  logger.warn("Here is some WARN");
  logger.error("Here is some ERROR");
  logger.fatal("Here is some FATAL");
 }

 //--------참고.    http://www.vipan.com/htdocs/log4jhelp.html  --------//
 // for using xml conf

 // properties를 이용하는 것은 다루지 않았다.

 /**
  * conf file
  * <?xml version="1.0" encoding="UTF-8" ?>
  * <!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
  *
  * <log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">
  *
  *    <appender name="cad" class="org.apache.log4j.FileAppender">
  *       <param name="File"   value="Logging4J.xml" />
  *       <param name="Append" value="false" />
  *       <layout class="org.apache.log4j.xml.XMLLayout"/>
  *    </appender>
  *
  *    <root>
  *       <priority value ="debug" />
  *       <appender-ref ref="cad"/>
  *    </root>
  *
  * </log4j:configuration>
  *
  */
 public void confLog() {
  //dom conf start
  String conf = "log4jconf.xml";
  DOMConfigurator.configure(conf);
  //dom conf end

  logger.debug("Here is some DEBUG");
  logger.info("Here is some INFO");
  logger.warn("Here is some WARN");
  logger.error("Here is some ERROR");
  logger.fatal("Here is some FATAL");
 }
 //LollingFileAppender
 //log4j가 쌓는 로그의 순서
 //최근것은 항상 Logging4J.log 에 쌓이고 이것이 예에서 1000바이트가 차들어가면
 //Logging4J.log를 복사하여
 //Logging4J.log.1을 만들고 Logging4J.log에는 최근게 계속 쌓인다.
 /**
  * <?xml version="1.0" encoding="UTF-8" ?>
  * <!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
  *
  * <log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">
  *
  *    <appender name="cad" class="org.apache.log4j.RollingFileAppender">
  *       <!--<param name="File"   value="Logging4J.xml" />-->
  *       <param name="File"   value="Logging4J.log" />
  *       <param name="Append" value="true" />
  *       <param name="MaxFileSize" value="1000"/>
  *       <param name="MaxBackupIndex" value="3"/>
  *
  *
  *       <!--<layout class="org.apache.log4j.xml.XMLLayout">
  *       </layout>-->
  *
  *       <layout class="org.apache.log4j.PatternLayout">
  *          <param name="ConversionPattern"
  *                 value="%d %-5p [%t] %C{2} (%F:%L) - %m%n"/>
  *       </layout>
  *
  *    </appender>
  *
  *    <root>
  *       <priority value ="debug" />
  *       <appender-ref ref="cad"/>
  *    </root>
  *
  * </log4j:configuration>
  */
 public void lollingLog() {
  //dom conf start
  String conf = "log4jconfLolling.xml";
  DOMConfigurator.configure(conf);
  //dom conf end

  logger.debug("Here is some DEBUG");
  logger.info("Here is some INFO");
  logger.warn("Here is some WARN");
  logger.error("Here is some ERROR");
  logger.fatal("Here is some FATAL");
 }

 // pattern layout
 // --참고 -- http://logging.apache.org/log4j/docs/api/org/apache/log4j/PatternLayout.html
 /**
  * 출력패턴
  *
  * * ------+-------------------------------------------------------------------------------
 * %c    | 로그 이벤트의 카테고리명을 출력한다. 
 * ------|-------------------------------------------------------------------------------
 * %C    | 로깅 요구를 실시하는 클래스명을 출력한다. 
 * ------|-------------------------------------------------------------------------------
 * %d    | 로그 이벤트의 일시를 출력한다.
 *       | %d{HH:mm:ss} 나 %d{dd MMM yyyy HH}로서보다 유연하게 일시 정보를 출력할 수가 있다. 
 * ------|-------------------------------------------------------------------------------
 * %F(*) | 로그 요구가 발생한 파일명을 출력한다. 
 * ------|-------------------------------------------------------------------------------
 * %l(*) | 로그가 생성되었을 때에 불려 간 위치(소스명, 행)를 출력한다. 
 * ------|-------------------------------------------------------------------------------
 * %L(*) | 로깅 요구를 행한 행 번호를 출력한다. 
 * ------|-------------------------------------------------------------------------------
 * %m    | 로깅이벤트로 설정된 메세지를 출력한다. 
 * ------|-------------------------------------------------------------------------------
 * %M(*) | 로그 요구가 행해진 메소드명을 출력한다. 
 * ------|-------------------------------------------------------------------------------
 * %n    | 플랫폼 의존의 개행 문자를 출력한다. 
 * ------|-------------------------------------------------------------------------------
 * %p    | 로그의 우선도를 출력합니다. 
 * ------|-------------------------------------------------------------------------------
 * %r    | 어플리케이션이 개시하고 나서, 로그가 출력될 때까지의 시간을 밀리 세컨드 단위로 출력한다. 
 * ------|-------------------------------------------------------------------------------
 * %t    | 로그를 생성한 thread의 이름을 출력한다. 
 * ------|-------------------------------------------------------------------------------
 * %x    | 로그가 생성된 thread의 NDC(네스트화 진단 문맥)를 출력한다. 
 * ------|-------------------------------------------------------------------------------
 * %%    | %를 출력한다. 
 * ------+-------------------------------------------------------------------------------
 *
 *(*)이것들을 출력할 때의 퍼포먼스는 좋지 않기 때문에, 어플리케이션의 실행 속도가 문제가 되지 않는 경우에게만
 *사용하는 것이 추천 되고 있다
 *
 *
 ** 여러가지 출력포멧 : 위의 xml에 아래의 포멧들을 적용해서 이것저것 찍어보도록 하자코드:
 * ----------+-------------------------------------------------------------------------
 * %10m      | 출력 캐릭터 라인이 10 문자 이하의 경우,
 *           | 캐릭터 라인의 좌측으로 공백이 삽입된다. 
 * ----------+-------------------------------------------------------------------------
 * %-10m     | 출력 캐릭터 라인이 10 문자 이하의 경우,
 *           | 캐릭터 라인의 우측으로 공백이 삽입된다. 
 * ----------+-------------------------------------------------------------------------
 * %.10m     | 출력 캐릭터 라인이 10 문자를 넘는 경우,
 *           | 캐릭터 라인의 오른쪽으로부터 세어 11 문자눈 이후의 문자(선두의 문자)가 잘라내진다. 
 * ----------+-------------------------------------------------------------------------
 * %10.20m   | 출력 캐릭터 라인이 10 문자 이하의 경우,
 *           | 캐릭터 라인의 좌측으로 공백이 삽입된다.
 *           | 출력 캐릭터 라인이 20 문자를 넘는 경우,
 *           | 캐릭터 라인의 오른쪽으로부터 세어
 *           | 21 문자 이후의 문자(선두의 문자)가 잘라내진다. 
 * ----------+-------------------------------------------------------------------------
 * %-10.20m  | 출력 캐릭터 라인이 10 문자 이하의 경우,
 *           | 캐릭터 라인의 우측으로 공백이 삽입된다.
 *           | 출력 캐릭터 라인이 20 문자를 넘는 경우,
 *           | 캐릭터 라인의 오른쪽으로부터 세어 21 문자이후의 문자(선두의 문자)가 잘라내진다. 
 * ----------+-------------------------------------------------------------------------
 *
 *
 *  패턴 layout을 쓰는 예제 xml conf 파일코드:
 * <?xml version="1.0" encoding="UTF-8" ?>
 * <!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
 *
 * <log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">
 *
 *    <appender name="cad" class="org.apache.log4j.RollingFileAppender">
 *       <!--<param name="File"   value="Logging4J.xml" />-->
 *       <param name="File"   value="Logging4J.log" />
 *       <param name="Append" value="true" />       
 *       <param name="MaxFileSize" value="1000"/>
 *       <param name="MaxBackupIndex" value="3"/>
 *      
 *      
 *       <!--<layout class="org.apache.log4j.xml.XMLLayout">
 *       </layout>-->
 *      
 *       <layout class="org.apache.log4j.PatternLayout">
 *          <param name="ConversionPattern"
 *                 value="%d %-5p [%t] %C{2} (%F:%L) - %m%n"/>
 *       </layout>           
 *       
 *    </appender>
 *
 *    <root>
 *       <priority value ="debug" />
 *       <appender-ref ref="cad"/>
 *    </root>
 *
 * </log4j:configuration> 
  */
 
 public static  void main(String[] args) {
   //dom conf start
   String conf = "log4jPattern.xml";
   DOMConfigurator.configure(conf);
   //dom conf end

   logger.debug("Here is some DEBUG");
   logger.info("Here is some INFO");
   logger.warn("Here is some WARN");
   logger.error("Here is some ERROR");
   logger.fatal("Here is some FATAL");
  }
/**
 *  결과
 * 2004-03-04 11:27:57,038 DEBUG [main] Logging4J (Logging4J.java:440) - Here is some DEBUG
 * 2004-03-04 11:27:57,038 INFO  [main] Logging4J (Logging4J.java:441) - Here is some INFO
 * 2004-03-04 11:27:57,038 WARN  [main] Logging4J (Logging4J.java:442) - Here is some WARN
 * 2004-03-04 11:27:57,038 ERROR [main] Logging4J (Logging4J.java:443) - Here is some ERROR
 * 2004-03-04 11:27:57,038 FATAL [main] Logging4J (Logging4J.java:444) - Here is some FATAL
 */
 
}

Log4j를 사용하여 Tomcat 5.x로깅 설정하기

알림 : 여기의 방법은 Tomcat에 log4j로깅을 셋팅하기 위한것이다. 당신의 애플리케이션은 해당 웹 애플리케이션만의 log4j.properties를 WEB-INF/classes디렉토리로 배치될수 있다.

$CATALINA_HOME/common/classes에 log4j.properties파일을 생성한다.

log4j.rootLogger=ERROR, R
log4j.appender.R=org.apache.log4j.DailyRollingFileAppender
log4j.appender.R.File=${catalina.home}/logs/tomcat.log
log4j.appender.R.DatePattern='.'yyyy-MM-dd
log4j.appender.R.layout=org.apache.log4j.PatternLayout
log4j.appender.R.layout.ConversionPattern={%p} %c{2} %x %m%n

commons-logging.jar 와 log4j-1.2.9.jar을 $CATALINA_HOME/common/lib로 복사할 필요가 있다. 주의, 몇몇 참조문서에서는 $CATALINA_HOME/server/lib로 이 파일을 복사해야 한다고 말하고 있으나 나의 경우 common/lib로 복사하는 것이 잘 작동했다.

그리고 나서, 당신의 애플리케이션 log4j.properties($APPFUSE_HOME/web/WEB-INF/classes)에 다음의 내용을 추가한다.

# Suppress the tomcat logging whilst DEBUG is switched on
log4j.logger.org.apache.catalina.core=ERROR
log4j.logger.org.apache.catalina.session=ERROR
log4j.logger.org.apache.jasper.compiler=ERROR

개발하는 동안, 당신은 root logger를 DEBUG로 셋팅한다. 그리고 나서 Tomcat로깅이 DEBUG로 셋팅이 되면, 당신은 Jasper컴파일러로부터 수천라인의 컴파일 추적메시지를 보게될것이다.

물론, 특정 애플리케이션을 구별하여, 당신의 애플리케이션 log4j.properties ROOT로그 레벨을 WARN이나 ERROR로 유지하고 특정 애플리케이션을 위해 디버깅을 활성화한다.(이를테면, org.appfuse=DEBUG)

노트: 만약 당신이 stdout으로 Tomcat로깅을 수행하길 원한다면, 당신의 $CATALINA_HOME/common/classes/log4j.properties파일은 다음과 같을것이다.

log4j.rootLogger=ERROR, stdout, TOMCAT

log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d{dd-MM-yy HH:mm:ss:SSS} - {%p} %c{2} Thread [%t]; %x %m%n

log4j.appender.TOMCAT=org.apache.log4j.DailyRollingFileAppender
log4j.appender.TOMCAT.File=${catalina.home}/logs/tomcat.log
log4j.appender.TOMCAT.DatePattern='.'yyyy-MM-dd
log4j.appender.TOMCAT.layout=org.apache.log4j.PatternLayout
log4j.appender.TOMCAT.layout.ConversionPattern=%d{dd-MM-yy HH:mm:ss:SSS} - {%p} %c{2} Thread [%t]; %x %m%n

'프로그래밍 > Library' 카테고리의 다른 글

[펌] WEBLOGIC + LOG4J  (0) 2007.11.28
[펌] Log4J...  (0) 2007.11.28
[펌] log4j 설정법  (0) 2007.11.28
[펌] Log4J Configuration  (0) 2007.11.28
[펌] Log4J 사용하기  (0) 2007.11.28

[펌] log4j 설정법

프로그래밍/Library 2007. 11. 28. 09:37 Posted by galad
[펌]log4j 설정법
참고파일



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

본문서는 자유롭게 배포/복사 할수 있지만

이문서의 저자에 대한 언급을 삭제하시면 안됩니다

저자 : GoodBug (unicorn@jakartaproject.com)

최초 : http://www.jakartaproject.com 

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


LOG4J

I. 들어가면서.. 그리고 log4j


log4j는 자바 어플리케이션에서 빠르고 효과적으로 로깅 할 수 있도록 도와주는 오픈 소스 프로젝트입니다.


로깅(logging)은 코드의 가독성을 떨어뜨리는 단점이 있지만 애플리케이션에 문제가 있을 때 개발자가 자세한 상황을 파악할 수 있도록 해 주며 테스팅시 빠질 수 없는 요소입니다.


아마도 여러분들은 여러 어플리케이션이 추가되면서 각 개발자들만의 독특한 로깅방식이 서로 썩이고 얽혀서 화면에 나타나는것을 많이 봤을겁니다 -_-;
즉 로깅방법을 통일할 필요가 있는것이죠. 모든 개발자가 특정 포맷에 맞추어서 로깅 한다면 한결 로깅하기도 편하겠지요


오픈 소스 프로젝트인 Log4j는 개발자들이 매우 손쉽고 다양한 형태로 로깅을 할 수 있도록 도와줍니다. 성능또한 우수해 더이상 System.out.println을 사용할 필요가 없습니다.



II. 다운로드


다운로드 http://logging.apache.org/log4j/docs/download.html

매뉴얼 http://logging.apache.org/log4j/docs/documentation.html

API spec http://logging.apache.org/log4j/docs/api/index.html



III. LOG4J 구조


일단 log4j를 잘 모르지만 그 구조만 살짝 살펴보고 넘어갑시다

log4j는 크게 3가지 요소로 구성되며 그 구조는 다음과 같습니다

① Logger(Category) : 로깅 메세지를 Appender에 전달합니다.

② Appender : 전달된 로깅 메세지를 파일에다 기록할 것인지, 콘솔에 출력할 것인지

                   아니면 DB에 저장할 것인지 매개체 역활을 합니다.

③ Layout : Appender가 어디에 출력할 것인지 결정했다면 어떤 형식으로 출력할 것이지

                출력 layout을 결졍합니다.

쉽죠?



IV. LOG4J 로깅 레벨


log4j는 다양한 로깅레벨을 지원합니다.


① FATAL : 가장 크리티컬한 에러가 일어 났을 때 사용합니다.

② ERROR : 일반 에러가 일어 났을 때 사용합니다.

③ WARN : 에러는 아니지만 주의할 필요가 있을 때 사용합니다.

④ INFO : 일반 정보를 나타낼 때 사용합니다.

⑤ DEBUG : 일반 정보를 상세히 나타낼 때 사용합니다.


만약 로깅 레벨을 WARN 으로 설정하였다면 그 이상 레벨만 로깅하게 됩니다.

즉 WARN, ERROR, FATAL 의 로깅이 됩니다.



V. 샘플코드 1


jsp에서 사용하는 예제가 없어 만들어 봤습니다.


test.jsp


<%@ page contentType="text/html;charset=MS949"
 import="org.apache.log4j.Logger" %>

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

<%
logger.fatal("fatal!!");

logger.fatal("fatal2!!", new NullPointerException("널입니다요"));

logger.error("error!", new NumberFormatException());

logger.error("error!2");

logger.warn("warn");

logger.info("info");

logger.debug("debug");
%>


결과 콘솔화면








static Logger logger = Logger.getLogger("test.jsp");

static 메소드 getLogger를 통해 logger 인스턴스를 가져옵니다.
getLogger에는 파라미터로 스트링 혹은 클래스를 사용하는데 jsp에서는 클래스를 파라미터로 주기에는 좀 애매합니다. 그냥 스트링으로 주도록 하지요


logger.fatal("fatal!!");
logger.fatal("fatal2!!", new NullPointerException("널입니다요"));
  
logger에 fatal 레벨의 메세지를 전달합니다. 다음 두가지 메소드를 지원하는군요

fatal(Object message)

fatal(Object message, Throwable t)

각 레벨마다 위처럼 두가지 메소드를 지원합니다.


지원 메쏘드
logger.fatal(Object message) logger.fatal(Object message, Throwable t)
logger.error(Object message) logger.error(Object message, Throwable t)
logger.warn(Object message) logger.warn(Object message, Throwable t)
logger.info(Object message) logger.info(Object message, Throwable t)
logger.debug(Object message) logger.debug(Object message, Throwable t)


VI. 샘플코드 2


서블릿의 경우 다음과 같이 코딩하면 되겠군요

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);
          }
     }
}



VII. LOG4J 설정


log4j 설정은 프로그램 내에서 할 수 있지만 설정파일을 사용함으로서 좀더 유연하게 log4j환경을 만들 수 있습니다.


프로그램에서 설정

<%@ 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.MaxFileSize=500KB

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


#최상위 카테고리에 INFO로 레벨 설정 및 appender로 stdout, rolling을 정의

log4j.rootLogger=INFO, stdout, rolling

#stdout 어펜더는 콘솔에 뿌리겠다는 정의

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

#stdout 어펜더는 patternlayout을 사용하겠다는 정의

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

#페턴은 다음과 같이 포맷팅 하겠다는 것을 정의

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


#역시나 rolling 어펜더는 파일로 처리한다라고 정의

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

#로그 파일 이름은 output.log

log4j.appender.rolling.File=output.log

#true면 톰캣을 내렸다 올려도 파일이 리셋되지 않습니다.

log4j.appender.rolling.Append=true

#파일 최대 사이즈는 500KB로 설정

log4j.appender.rolling.MaxFileSize=500KB

#파일 포맷은 output.log.2005-03-10 으로 관리하겠다고 정의

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

#역시나 rolling 어펜더는 패턴 레이아웃을 사용하겠다고 정의

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

#rolling 어펜더는 패턴 레이아웃 포맷

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



VIII. 설정 포맷


로그파일명 포맷 (DatePattern)
로그파일명 포맷입니다. 날짜, 시간 및 분단위로까지 로그 파일을 분리할 수 있습니다.

형식 설명
'.'yyyy-MM 매달 첫번째날에 로그파일을 변경합니다
'.'yyyy-ww 매주의 시작시 로그파일을 변경합니다.
'.'yyyy-MM-dd 매일 자정에 로그파일을 변경합니다.
'.'yyyy-MM-dd-a 자정과 정오에 로그파일을 변경합니다.
'.'yyyy-MM-dd-HH 매 시간의 시작마다 로그파일을 변경합니다.
'.'yyyy-MM-dd-HH-mm 매분마다 로그파일을 변경합니다.



PatternLayout 포맷
로그자체를 어떤 포맷으로 남길지 결정합니다.
layout에는 HTMLLayout, PatternLayout, SimpleLayout, XMLLayout등이 있으며 PatternLayout이 일반적으로 가장 많이 쓰입니다.


형식 설명
%p debug, info, warn, error, fatal 등의 priority 가 출력된다.
%m 로그내용이 출력됩니다
%d 로깅 이벤트가 발생한 시간을 기록합니다.
포맷은 %d{HH:mm:ss, SSS}, %d{yyyy MMM dd HH:mm:ss, SSS}같은 형태로 사용하며 SimpleDateFormat에 따른 포맷팅을 하면 된다
%t 로그이벤트가 발생된 쓰레드의 이름을 출력합니다.
%% % 표시를 출력하기 위해 사용한다.
%n 플랫폼 종속적인 개행문자가 출력된다. \r\n 또는 \n 일것이다.
%c 카테고리를 표시합니다
예) 카테고리가 a.b.c 처럼 되어있다면 %c{2}는 b.c가 출력됩니다.
%C 클래스명을 포시합니다.
예) 클래스구조가 org.apache.xyz.SomeClass 처럼 되어있다면 %C{2}는 xyz.SomeClass 가 출력됩니다
%F 로깅이 발생한 프로그램 파일명을 나타냅니다.
%l 로깅이 발생한 caller의 정보를 나타냅니다
%L 로깅이 발생한 caller의 라인수를 나타냅니다
%M 로깅이 발생한 method 이름을 나타냅니다.
%r 어플리케이션 시작 이후 부터 로깅이 발생한 시점의 시간(milliseconds)
%x 로깅이 발생한 thread와 관련된 NDC(nested diagnostic context)를 출력합니다.
%X 로깅이 발생한 thread와 관련된 MDC(mapped diagnostic context)를 출력합니다.

예시) (같은 색끼리 보시면 됩니다)

위의 test.jsp를 다음 포맷으로 출력해본다면

[%c] [%C] [%d] [%F] [%l] [%L] [%m] [%M] [%n] [%p] [%r] [%t] [%x] [%X]는 다음과 같다

[test.jsp] [org.apache.jsp.test_jsp] [2005-03-10 12:37:23,561] [test_jsp.java] [org.apache.jsp.test_jsp._jspService(test_jsp.java:64)] [64] [fatal!!] [_jspService] [개행] [FATAL] [765567] [http-8080-Processor25] [] []

'프로그래밍 > Library' 카테고리의 다른 글

[펌] Log4J...  (0) 2007.11.28
[펌] Log4j를 사용하여 Tomcat 5.x로깅 설정하기  (0) 2007.11.28
[펌] Log4J Configuration  (0) 2007.11.28
[펌] Log4J 사용하기  (0) 2007.11.28
[펌] Tomcat의 Logger(로거)가 이상해요..  (0) 2007.11.28

[펌] Log4J Configuration

프로그래밍/Library 2007. 11. 28. 09:37 Posted by galad
#####################################
#  Log4J Configuration                       #
#####################################

작성자 : 장형화(hhjang97@venus.uos.ac.kr)
작성일 : 2005. 08. 11
수정일 :

원본 :
설명 :


################################# ################################# #################################

LOG4J !!

디버그나 에러 확인을 위해 항상 사용하는 API입니다.

다양한 Level로 나눠서 설정 가능하며, System.out.println을 난발(?) 하지 않도록 도와주고 있죠 ^^;



설정 부분에서 필요한 부분을 그때그때 웹사이트 돌아다니며 찾았는데,

여기에 포스트 해놓고 필요할때 찾아 쓰려고요 ^^;



!-----------------------------------------------------------------------------!
! category(logger) 설정                                                                                    !
!-----------------------------------------------------------------------------!
log4j.debug=true
#log4j.disable=INFO
log4j.rootLogger=DEBUG, CONSOL, SYSTEM





!-----------------------------------------------------------------------------!
! appender(log destinations/targets) 와 옵션들을 설정                                         !
!-----------------------------------------------------------------------------!

! FILE에 로그 쓰기, 지정한 크기를 넘어서면 파일을 교체
log4j.appender.CONSOL=org.apache.log4j.ConsoleAppender


! 로그메세지들이 전혀 버퍼되지 않는 것을 의미하며 대부분의 상황에 적당하다.
log4j.appender.CONSOL.ImmediateFlush=true


! 이 appender 는 여기 명시된 priority 와 같거나 높은 메세지만 로깅한다
log4j.appender.CONSOL.Threshold=DEBUG


! Layout 형식 : TTCCLayout, HTMLLayout,  XMLLayout, PatternLayout, SimpleLayout
! PatternLayout, SimpleLayout - 자바의 Throwable 에러들과 예외를 무시한다
log4j.appender.CONSOL.layout=org.apache.log4j.PatternLayout


! %l - 소스코드의 위치정보를 출력한다. %C. %M(%F:%L) 의 축약형이다
log4j.appender.CONSOL.layout.ConversionPattern=%-5p %l %x =>%m%n







log4j.appender.SYSTEM=org.apache.log4j.DailyRollingFileAppender
log4j.appender.SYSTEM.File=C:/logs/system.html


! 매일 자정에 로그파일을 교체하며 기존파일은 xx.log_2004.07.12
log4j.appender.SYSTEM.DatePattern='.'yyyy-MM-dd
log4j.appender.SYSTEM.Threshold=DEBUG


! 자바의 Throwable 에러들과 예외를 포함하기 위해 HTMLLayout을 사용한다.
log4j.appender.SYSTEM.layout=org.apache.log4j.HTMLLayout


! [%d{yyyy-MM-dd}형식은 프로그램의 실행속도를 느리게 함으로 SimpleDateFormat 형식지정한다.
log4j.appender.SYSTEM.layout.DateFormat=ISO8601
! [YYYY-MM-DD HH:MM:SS, mm] 형식을 뜻한다.
log4j.appender.SYSTEM.layout.TimeZoneID=GMT-8:00


! %l - 소스코드의 위치정보를 출력한다. %C. %M(%F:%L) 의 축약형이다
log4j.appender.SYSTEM.layout.ConversionPattern=[%d] %-5p %l - %m%n







! 각 업무 상위패키지를 지정하여 logging 셋팅한다.


log4j.logger.rkhwang.biz.protoss=DEBUG, PROTOSS
log4j.logger.rkhwang.biz.teran=DEBUG, TERAN
log4j.logger.rkhwang.biz.zerg=DEBUG, ZERG





log4j.appender.PROTOSS=org.apache.log4j.DailyRollingFileAppender
log4j.appender.PROTOSS.File=C:/logs/protoss.log
log4j.appender.PROTOSS.DatePattern='.'yyyy-MM-dd
log4j.appender.PROTOSS.Threshold=DEBUG
log4j.appender.PROTOSS.layout=org.apache.log4j.PatternLayout
log4j.appender.PROTOSS.layout.DateFormat=ISO8601
log4j.appender.PROTOSS.layout.TimeZoneID=GMT-8:00
log4j.appender.PROTOSS.layout.ConversionPattern=[%d] %-5p %l - %m%n





log4j.appender.TERAN=org.apache.log4j.DailyRollingFileAppender
log4j.appender.TERAN.File=C:/logs/teran.log
log4j.appender.TERAN.DatePattern='.'yyyy-MM-dd
log4j.appender.TERAN.Threshold=DEBUG
log4j.appender.TERAN.layout=org.apache.log4j.PatternLayout
log4j.appender.TERAN.layout.DateFormat=ISO8601
log4j.appender.TERAN.layout.TimeZoneID=GMT-8:00
log4j.appender.TERAN.layout.ConversionPattern=[%d] %-5p %l - %m%n



log4j.appender.ZERG=org.apache.log4j.DailyRollingFileAppender
log4j.appender.ZERG.File=C:/logs/zerg.log
log4j.appender.ZERG.DatePattern='.'yyyy-MM-dd
log4j.appender.ZERG.Threshold=DEBUG
log4j.appender.ZERG.layout=org.apache.log4j.PatternLayout
log4j.appender.ZERG.layout.DateFormat=ISO8601
log4j.appender.ZERG.layout.TimeZoneID=GMT-8:00
log4j.appender.ZERG.layout.ConversionPattern=[%d] %-5p %l - %m%n


#################################
#  참고 log4j.properties 파일
#################################

log4j.rootCategory=, dest2, C

log4j.appender.C=org.apache.log4j.DailyRollingFileAppender
log4j.appender.C.File= error.log
log4j.appender.C.layout=org.apache.log4j.PatternLayout
#log4j.appender.C.layout.ConversionPattern=[%d{yyyy-MM-dd hh:mm:ss}] %-5p [%-10t] %c{2} - %m%n
log4j.appender.C.layout.ConversionPattern=[%d{yyyy-MM-dd hh:mm:ss}] - %m%n
log4j.appender.C.Append=true
log4j.appender.C.DatePattern='.'yyyyMMdd
log4j.appender.C.Threshold=ERROR
log4j.appender.C.ImmediateFlush=true


log4j.appender.dest2=org.apache.log4j.DailyRollingFileAppender
log4j.appender.dest2.File=debug.log
log4j.appender.dest2.layout=org.apache.log4j.PatternLayout
#log4j.appender.dest2.layout.ConversionPattern=[%d{yyyy-MM-dd HH:mm:ss}] %-5p [%-10t] %c{2} - %m%n
log4j.appender.dest2.layout.ConversionPattern=[%d{yyyy-MM-dd HH:mm:ss}] - %m%n
log4j.appender.dest2.Append=true
log4j.appender.dest2.DatePattern='.'yyyyMMdd
log4j.appender.dest2.Threshold=DEBUG
log4j.appender.dest2.ImmediateFlush=true



#---------------------------------------------------------------------
# %n - newline                                                               
# %m - your log message                                               
# %p - message priority (FATAL, ERROR, WARN, INFO, DEBUG or custom)          
# %r - millisecs since program started running                               
# %% - percent sign in output                                                
#                                                                            
#-----------------------SOME MORE CLUTTER IN YOUR LOG-------------------------
# %c - name of your category (logger), %c{2} will outputs last two components
# %t - name of current thread                                                
# %x - Nested Diagnostic Context (NDC) (you supply it)        
#                                                                            
#-------------------------SLOW PERFORMANCE FORMATS----------------------------
# %d - date and time, also %d{ISO8601}, %d{DATE}, %d{ABSOLUTE},              
#        %d{HH:mm:ss,SSS}, %d{dd MMM yyyy HH:mm:ss,SSS} and so on       
# %l - Shortcut for %F%L%C%M                                                 
# %F - Java source file name                                                 
# %L - Java source line number                                             
# %C - Java class name, %C{1} will output the last one component             
# %M - Java method name    
#-----------------------------------------------------------------------




#################################
#
#################################

[펌] 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을 기준으로 한거 같으니 잘 구별해서 사용하길 바란다).
 
Tomcat의 Logger(로거)가 이상해요..
Tomcat의 로거가 다음과 같은 오류를 내며 작동하지 않는다면...

log4j:WARN No appenders could be found for logger (org.apache.commons.digester.Digester).
log4j:WARN Please initialize the log4j system properly.


혹은 내가 작성한 Log4j 를 사용하는 웹 어플리케이션의 로거가 내가 설정하지 않는 프라퍼티를 읽으려 들거나 한다면, 그것의 거의 log4j-*.jar가 의도하지 않게 클래스패스로 잡혀 있기 때문이다.

웹 어플리케이션의 log4j-*.jar 는 "WEB-INF/lib" 디렉토리 아래에만 둔다. 결코 "$CATALINA_HOME/common/lib" 등에 두지 말아야 한다.

또한 log4j-*.jar를 클래스 패스로 지정하지도 말고, $JAVA_HOME/jre/lib/ext 디렉토리에 둬서도 안된다.

이거 때문에 며칠 삽질... --;

절대 명심해야 할 사항중에 하나는 스스로 절대적인 확신이 없으면 $JAVA_HOME/jre/lib/ext 디렉토리에는 절대로 다른 *.jar 파일을 넣어 두면 안된다!!! 항상 수동으로 클래스패스를 설정하도록 하고, TOMCAT의 경우 WEB-INF/lib를 자기 스스로 클래스패스를 잡아주니, 그곳을 이용하도록 한다.
 
http://kwon37xi.egloos.com/2176400

Eclipse WTP에서 Apache Cactus사용하기

Cactus는 Web Application 에 올라가 있는 servlet, jsp, filter등을 테스트 할수 있도록 하는 JUnit 기반위의 Framework이다. (HttpUnit 과의 관계가 어떻게 되는지 모르겠네요..)

Cactus를 이용하여 서블릿에 대한 request를 설정하고 response를 확인할 수 있다.


  • New -> Java -> JUnit -> Servlet Test Case 를 클릭하여 Servlet Test Case를 만들면 자동으로 Cactus 설정이 프로젝트에 추가된다.
  • classpath 경로 안에 cactus.properties 파일을 만들고 아래와 같이 연동할 web application 의 url을 잡아준다.

  • 아래를 참고해서 Servlet Test Case를 만든다. beginXXX 에서 request를 보내기 전 작업을 할 수 있고, endXXX에서 response 에 대한 데이터를 확인할 수 있다.

public class ServletTest extends ServletTestCase {

    public void testProdSpecSel() throws IOException {

        ProdSpecSel servlet = new ProdSpecSel();

        servlet.service(request, response);

    }

    public void beginProdSpecSel(WebRequest request) throws Exception{

        String data = "product_spec";

        InputStream input = new ByteArrayInputStream(data.getBytes());

        request.setUserData(input);

    }

    public void endProdSpecSel(WebResponse response) throws Exception{

        System.out.println(response.getText());

    }

}

  • Web Application 을 띄운후 JUnit으로 실행하면 Test가 수행된다.

http://skccdev.pbwiki.com/Cactus