1. 개요
Tomcat 로그 관리 기법인 Java Logging 과 JULI 에 대하여 알아보고, 인스턴스 레벨에서 기본 생성되는 ${INST_HOME}/logs 하위의 로그 파일들에 대하여 설명한다.
2. logging.properties
Java 1.4 부터 java.util.logging이라는 java Logging Framework이 제공되었다. 여러 장점이 있는 반면에 JVM 레벨의 설정만 가능하다는 단점이 있다. 즉, 웹 애플리케이션 단위로는 로그를 남길 수 없다는 것이다.
Tomcat 은 이러한 Java Logging 의 단점을 해결하기 위하여 Java Logging 을 확장한 JULI 라는 이름의 로그 관리를 사용하고 있다. 때때로 JULI 는 Java Logging 의 Tomcat 버전으로 표현되기도 하며, Java Logging 의 설정 방법과 기본적으로 동일하다. JULI 는 ${INSTANCE_DIR}/bin/tomcat-juli.jar 파일로 존재하고 있다.
JULI 는 Java Logging 설정 뿐 아니라 classloader 당 설정이 가능하다. 따라서 다음과 같이 logging.properties를 위치시킬 수 있다.
1-1. ${INSTANCE_DIR}/conf/logging.properties
Java Logging 에 대한 설정 파일이다. 이 파일 경로는 Tomcat 에 의하여 java.util.logging.config.file 이라는 JVM 시스템 속성으로 정의되어 있다. 만일 이 속성이 없다면 default 로 ${JAVA_HOME}/lib/logging.properties 를 사용하게 된다.
1-2. WEB-INF/classes/logging.properties
각 애플리케이션의 설정 파일이다.
(단, access 로그는 JULI 가 아닌 AccessLogValve 가 담당하며, access 로그에 대해서는 별도로 기술한다)
이 밖에 Java Logging 대비하여 JULI 에서 추가 구현된 기능은 다음과 같다.
1-3. Hander
이름에 prefix를 넣을 수 있어서 하나의 class에 여러 hander 적용이 가능하다. Prefix는 숫자로 시작하여 . (dot)으로 끝나야 한다. 아래와 같다.
2localhost.org.apache.juli.FileHandler.level = FINE 2localhost.org.apache.juli.FileHandler.directory = ${catalina.base}/logs 2localhost.org.apache.juli.FileHandler.prefix = localhost.
1-4. 변수화
${systemPropertyName} 과 같이 시스템 속성을 변수화하여 사용할 수 있다. 아래 ${catalina.base} 와 같다.
3manager.org.apache.juli.FileHandler.directory = ${catalina.base}/logs
1-5. 기타
- Java 6 이상에서는 logger 가 loggerName.handers 속성을 이용하여 hander 목록을 정의할 수 있다.
- Tomcat 7과 Tomcat 8은 기본 설정에 차이가 있다.
- 기본적으로 logger 가 parent 의 handler 를 delegation 하지 않지만, boolean 값을 갖는 loggerName.useParentHanders 속성을 이용하여 변경할 수도 있다.
- Root logger 는 .handers 속성을 이용하여 hander 의 set 을 정의할 수 있다. 아래와 같다.
.handlers = 1catalina.org.apache.juli.FileHandler, java.util.logging.ConsoleHandler
JULI 에 추가된 클래스 중 주목할 만한 것은 org.apache.juli.FileHandler 이다. 이는 기본적으로 제공하지 않는 버퍼링 기능을 지원한다. 버퍼링을 설정하면 bufferSize 속성을 사용할 수 있는데, 0 으로 설정할 경우 시스템 기본 버퍼링(일반적으로 8k)이 되고, 0 보다 작게 설정하면 로그를 기록할 때마다 writer 를 강제로 flush 한다. 0 보다 크게 설정하는 경우 시스템 기본 버퍼링과 함께 설정된 값으로 BufferedOutputStream 된다.
2. 로그 파일 종류
2-1. catalina.out
Tomcat 기동 시 ${INSTANCE_DIR}/bin/catalina.sh 에 의해 생성되는 로그 파일이다.
… if [ -z "$CATALINA_OUT" ] ; then CATALINA_OUT="$CATALINA_BASE"/logs/catalina.out fi … >> "$CATALINA_OUT" 2>&1 "&"
위와 같이 ${CATALINA_OUT} 은 ${CATALINA_BASE}/logs (본 문서의 ${INSTANCE_DIR}/logs) 하위에 catalina.out 파일이며, java 기동 시 standard output 과 standard error 를 모두 ${CATALINA_OUT} 으로 보내게 한다.
catalina.out 은 기본적으로 Tomcat 이 기동되어 있는 동안에는 단 하나의 파일에 계속 내용이 추가된다. 따라서 catalina.out 의 크기가 계속 늘어나 유용하고 중요한 로그가 골치 덩어리로 전락하는 상황이 발생할 수 있다. 이 경우 CATALINA_OUT 을 /dev/null 로 설정하는 등 catalina.sh 파일을 수정하여 대응하도록 한다.
… if [ -z "$CATALINA_OUT" ] ; then CATALINA_OUT="/dev/nnull" fi …
2-2. catalina.YYYY-MM-DD.log
${INSTANCE_DIR}/conf/logging.properties 에 의하여 생성되고 제어된다.
catalina.YYYY-MM-DD.log 파일은 catalina.out 파일과 유사한 것 처럼 보이나 Tomcat 에서 생성하는 로그 이외에 standard output, standard error 의 로깅은 제외된다. 즉, 소스에서 System.out.println 이나 System.err.println 으로 남기는 로그가 있다면 그 내용은 오직 catalina.out 에서만 찾아볼 수 있다.
2-3. 기타 로그
- manager.YYYY-MM-DD.out
- host-manager.YYYY-MM-DD.out
- localhost_access_log.YYYY-MM-DD
manager 혹은 host-manager 사용시 로그와 Tomcat access 로그이다.
2-4. 로그 관리 전략
catalina.out 과 catalina.YYYY-MM-DD.log 파일을 중복으로 유지하는 것은 특히나 운영 환경에서는 파일 시스템 낭비 뿐 아니라 성능 저하 요인으로 볼 수 있다. 따라서 다음과 같은 로그 관리 전략을 제안한다.
첫 번째는 용도 별로 로그를 분리/관리하고 standard out, standard error 는 보지 않아도 되는 경우이다.
- catalina.out 파일은 생성하지 않는다. (catalina.sh 에서 /dev/null 처리한다)
- catalina.YYYY-MM-DD.log 파일로부터 daily rotate 되는 시스템 로그를 모니터링한다.
- 응용에서는 framework 의 로그를 활용하거나 log4j 를 사용하여 별도의 로그를 남긴다.
두 번째는 모든 로그를 하나의 파일(catalina.out) 에서 보고 싶은 경우이다.
- 현재 방식으로는 catalina.out 파일이 비대해 질 수 있으므로 서버의 logrotate 기능을 사용하거나 별도의 로그 분리 스크립트를 적용하여 daily 혹은 일정주기마다 강제 분리되도록 한다.
- catalina.YYYY-MM-DD.log 파일은 생성하지 않는다. (logging.properties 에서 설정)
이외에 manager, host-manager 등에서 생성되는 로그도 manager나 host-manager 를 사용하지 않거나 굳이 로그가 필요 없다면 logging.properties 에서 제거한다.
3. Access 로그
사용자 request 기록을 위한 access 로그는 ${INSTANCE_DIR}/conf/server.xml 파일내에서 org.apache.catalina.valves.AccessLogValve를 활성화 함으로서 생성 가능하다.
Tomcat 배포 버전에 따라 이 AccessLogValve가 비활성화되어 있기도 하고, 활성화되어 있기도 하다.
3-1. Tomcat 6.0.37
<!-- Access log processes all example. Documentation at: /docs/config/valve.html --> <!-- <Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs" prefix="localhost_access_log." suffix=".txt" pattern="common" resolveHosts="false"/> -->
위와 같이 기본적으로 비활성화되어 있다.
3-2. Tomcat 7.0.42
<!-- Access log processes all example. Documentation at: /docs/config/valve.html Note: The pattern used is equivalent to using pattern="common" --> <Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs" prefix="localhost_access_log." suffix=".txt" pattern="%h %l %u %t "%r" %s %b" />
인스턴스 내 모든 요청에 대해 access 로그를 남기려면 내에 AccessLogValve 를 설정하고, 특정 virtual host 단위로 남기려면 내에, 특정 애플리케이션 단위로 남기려면 내에 설정한다.