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 단위로 남기려면 내에, 특정 애플리케이션 단위로 남기려면 내에 설정한다.