Log4j2를 이용한 로깅(logging) 방법 - V
이번 시간에는 로그 파일 용량이 커지게 될 때 파일을 추가로 생성하는 방법에 대해서 살펴보겠습니다.
로그 파일에 로그가 계속 기록되면 당연히 파일 용량이 커지게 됩니다.(1MB > 10MB > 1GB > 1TB ...) 파일 용량이 너무 크게 되면 메모장 등과 같은 에디터 툴에서 open하는데 시간이 많이 소요되거나 아예 open하지 못하는 경우가 발생합니다. 또한 아주 오래된 로그는 굳이 보관하지 않아도 됩니다. 이런 상황들을 고려에서 파일의 용량 또는 날짜를 기준으로 파일을 분리할 수 있습니다.
용량 또는 날짜를 기준으로 파일을 분리하기 위해서 log4j2에서는 'Rolling'이라는 것을 지원하는데요, 기존 로그 설정파일에 <RollingFile>을 적용해 보겠습니다.
1. 설정 파일 복제
기존 어펜더 중에서 'FileForAppByDebug'를 보겠습니다.
<!-- DEBUG -->
<File name="FileForAppByDebug" fileName="${LOG_PATH}/spring-app-debug.log">
<PatternLayout pattern="${LOG_PATTERN}"/>
<Filters>
<LevelRangeFilter minLevel="DEBUG" maxLevel="DEBUG" onMatch="ACCEPT" onMismatch="DENY" />
</Filters>
</File>
'FileForAppByDebug' 어펜더는 심각도가 'DEBUG'인 로그를 'spring-app-debug.log'에 저장합니다. 여기에 Rolling을 적용하기 위해서는 <File> 대신 <RollingFile>을 사용하면됩니다. 본격적으로 코드를 수정하기 전에 'log4j2-dev-file.xml'복사해서 'log4j2-dev-rollingfile.xml'을 만들고 진행하겠습니다.
2. application.properties 수정
application.properties 파일을 open해서 애플리케이션이 'log4j2-dev-rollingfile.xml'를 사용하도록 logging.config를 다음과 같이 변경합니다.
# log4j2
#logging.config=classpath:logger/log4j2-local.xml
#logging.config=classpath:logger/log4j2-dev-file.xml
logging.config=classpath:logger/log4j2-dev-rollingfile.xml
3. <File>를 <RollingFile> 어펜더로 변경하기
'DEBUG'에 대한 로그를 출력하기 위한 'FileForAppByDebug' 어펜더를 <RollingFile>로 변경합니다.
<!-- DEBUG -->
<!--
<File name="FileForAppByDebug" fileName="${LOG_PATH}/spring-app-debug.log">
<PatternLayout pattern="${LOG_PATTERN}"/>
<Filters>
<LevelRangeFilter minLevel="DEBUG" maxLevel="DEBUG" onMatch="ACCEPT" onMismatch="DENY" />
</Filters>
</File>
-->
<RollingFile
name="RollingFileForAppByDebug"
fileName="${LOG_PATH}/debug/spring-app-debug.log"
filePattern="${LOG_PATH}/debug/%d{yyyy-MM-dd}/spring-app-debug-%d{yyyy-MM-dd}-%i.log">
<PatternLayout pattern="${LOG_PATTERN}"/>
<Filters>
<LevelRangeFilter minLevel="DEBUG" maxLevel="DEBUG" onMatch="ACCEPT" onMismatch="DENY" />
</Filters>
<Policies>
<!-- 용량 기반 롤링 -->
<SizeBasedTriggeringPolicy size="128B"/>
<!-- 날짜 기반 롤링 -->
<TimeBasedTriggeringPolicy interval="1" modulate="true"/>
</Policies>
<DefaultRolloverStrategy max="5"/>
</RollingFile>
기존 <File>을 주석 처리하고, 대신 <RollingFile>을 사용합니다. <RollingFile>을 분석해 보겠습니다.
- name: 어펜더 이름
- fileName: 로그 파일 이름
- filePattern: 추가 되는 파일 이름 규칙
<File> 대신 <RollingFile>을 이용하면 특정 규칙(용량 초가, 날짜 지남)에 따라 파일을 추가합니다. 로그는 'fileName'에 기록이 되다가 일정 용량을 초과하면 로그를 'filePattern'으로 이동시킵니다. 그리고 ' fileName'있던 로그는 모두 지워버립니다.
이런 정책에 대한 설정은 <Policies>로 설정합니다. <Policies>를 분석해 보겠습니다.
- <SizeBasedTriggeringPolicy size="128B"/>: 'fileName'의 파일 용량이 128바이트를 초과하면 로그를 'filePattern'로 이동
- <TimeBasedTriggeringPolicy interval="1" modulate="true"/>: 1일 마다 자정에 'filePattern'로 이동(interval이 2면 2일 마다 이동)
마지막으로 <DefaultRolloverStrategy max="5"/>의 의미는 로그 파일 회전 시 유지할 최대 로그 파일 개수를 5개로 제한한다는 것입니다. 'filePattern'에 로그가 옮겨지다가 5개가 넘으면 오래된 파일부터 삭제해서 항상 5개의 파일을 유지하게 됩니다.
DEBUG외에 다른 어펜더로 같은 방법으로 설정을 변경합니다. 다음은 어펜저 전체 코드입니다.
<Appenders>
<!-- 콘솔 출력 -->
<Console name="Console" target="SYSTEM_OUT">
<PatternLayout pattern="${LOG_PATTERN}"/>
</Console>
<!-- 로그 파일 기록 :: Root -->
<File name="FileByInfo" fileName="${LOG_PATH}/spring-info.log">
<PatternLayout pattern="${LOG_PATTERN}"/>
<Filters>
<ThresholdFilter level="INFO" onMatch="ACCEPT" onMismatch="DENY"/>
</Filters>
</File>
<!-- 로그 파일 기록 :: Application -->
<!--
<File name="FileForAppByInfo" fileName="${LOG_PATH}/spring-app-info.log">
<PatternLayout pattern="${LOG_PATTERN}"/>
<Filters>
<ThresholdFilter level="INFO" onMatch="ACCEPT" onMismatch="DENY"/>
</Filters>
</File>
-->
<!-- DEBUG -->
<!--
<File name="FileForAppByDebug" fileName="${LOG_PATH}/spring-app-debug.log">
<PatternLayout pattern="${LOG_PATTERN}"/>
<Filters>
<LevelRangeFilter minLevel="DEBUG" maxLevel="DEBUG" onMatch="ACCEPT" onMismatch="DENY" />
</Filters>
</File>
-->
<RollingFile
name="RollingFileForAppByDebug"
fileName="${LOG_PATH}/debug/spring-app-debug.log"
filePattern="${LOG_PATH}/debug/%d{yyyy-MM-dd}/spring-app-debug-%d{yyyy-MM-dd}-%i.log">
<PatternLayout pattern="${LOG_PATTERN}"/>
<Filters>
<LevelRangeFilter minLevel="DEBUG" maxLevel="DEBUG" onMatch="ACCEPT" onMismatch="DENY" />
</Filters>
<Policies>
<!-- 용량 기반 롤링 -->
<SizeBasedTriggeringPolicy size="128B"/>
<!-- 날짜 기반 롤링 -->
<TimeBasedTriggeringPolicy interval="1" modulate="true"/>
</Policies>
<DefaultRolloverStrategy max="5"/>
</RollingFile>
<!-- INFO -->
<!--
<File name="FileForAppByInfo" fileName="${LOG_PATH}/spring-app-info.log">
<PatternLayout pattern="${LOG_PATTERN}"/>
<Filters>
<LevelRangeFilter minLevel="INFO" maxLevel="INFO" onMatch="ACCEPT" onMismatch="DENY" />
</Filters>
</File>
-->
<RollingFile
name="RollingFileForAppByInfo"
fileName="${LOG_PATH}/info/spring-app-info.log"
filePattern="${LOG_PATH}/info/%d{yyyy-MM-dd}/spring-app-info-%d{yyyy-MM-dd}-%i.log">
<PatternLayout pattern="${LOG_PATTERN}"/>
<Filters>
<LevelRangeFilter minLevel="INFO" maxLevel="INFO" onMatch="ACCEPT" onMismatch="DENY" />
</Filters>
<Policies>
<!-- 용량 기반 롤링 -->
<SizeBasedTriggeringPolicy size="128B"/>
<!-- 날짜 기반 롤링 -->
<TimeBasedTriggeringPolicy interval="1" modulate="true"/>
</Policies>
<DefaultRolloverStrategy max="5"/>
</RollingFile>
<!-- WARN -->
<!--
<File name="FileForAppByWarn" fileName="${LOG_PATH}/spring-app-warn.log">
<PatternLayout pattern="${LOG_PATTERN}"/>
<Filters>
<LevelRangeFilter minLevel="WARN" maxLevel="WARN" onMatch="ACCEPT" onMismatch="DENY" />
</Filters>
</File>
-->
<RollingFile
name="RollingFileForAppByWarn"
fileName="${LOG_PATH}/warn/spring-app-warn.log"
filePattern="${LOG_PATH}/warn/%d{yyyy-MM-dd}/spring-app-warn-%d{yyyy-MM-dd}-%i.log">
<PatternLayout pattern="${LOG_PATTERN}"/>
<Filters>
<LevelRangeFilter minLevel="WARN" maxLevel="WARN" onMatch="ACCEPT" onMismatch="DENY" />
</Filters>
<Policies>
<!-- 용량 기반 롤링 -->
<SizeBasedTriggeringPolicy size="128B"/>
<!-- 날짜 기반 롤링 -->
<TimeBasedTriggeringPolicy interval="1" modulate="true"/>
</Policies>
<DefaultRolloverStrategy max="5"/>
</RollingFile>
<!-- ERROR -->
<!--
<File name="FileForAppByError" fileName="${LOG_PATH}/spring-app-error.log">
<PatternLayout pattern="${LOG_PATTERN}"/>
<Filters>
<LevelRangeFilter minLevel="ERROR" maxLevel="ERROR" onMatch="ACCEPT" onMismatch="DENY" />
</Filters>
</File>
-->
<RollingFile
name="RollingFileForAppByError"
fileName="${LOG_PATH}/error/spring-app-error.log"
filePattern="${LOG_PATH}/error/%d{yyyy-MM-dd}/spring-app-error-%d{yyyy-MM-dd}-%i.log">
<PatternLayout pattern="${LOG_PATTERN}"/>
<Filters>
<LevelRangeFilter minLevel="ERROR" maxLevel="ERROR" onMatch="ACCEPT" onMismatch="DENY" />
</Filters>
<Policies>
<!-- 용량 기반 롤링 -->
<SizeBasedTriggeringPolicy size="128B"/>
<!-- 날짜 기반 롤링 -->
<TimeBasedTriggeringPolicy interval="1" modulate="true"/>
</Policies>
<DefaultRolloverStrategy max="5"/>
</RollingFile>
</Appenders>
4. <Logger> 수정
<Logger>의 <AppenderRef>를 수정합니다.
<Loggers>
<!-- 기본 로거 설정 -->
<Root level="info">
<AppenderRef ref="Console"/>
<AppenderRef ref="FileByInfo"/>
</Root>
<!-- 애플리케이션 패키지 로깅 -->
<Logger name="com.office" level="debug" additivity="false">
<AppenderRef ref="Console"/>
<AppenderRef ref="RollingFileForAppByDebug"/>
<AppenderRef ref="RollingFileForAppByInfo"/>
<AppenderRef ref="RollingFileForAppByWarn"/>
<AppenderRef ref="RollingFileForAppByError"/>
</Logger>
</Loggers>
5. 애플이케이션 실행 및 결과 확인
애플리케이션을 실행하고 logs 디렉터리를 확인합니다.
로그가 심각도에 따라 구분되고, 파일 용량이 128바이트를 초과하면 해당 날짜 디렉터리로 옮겨진 것을 확인할 수 있습니다. 지금은 학습을 위해서 파일 최대 사이즈는 '128B'로 했지만 실제로는 '10MB' 또는 그이상으로 하겠죠~. 그리고 <DefaultRolloverStrategy max="5"/>도 100개 정도로 설정하겠죠~. (10MB * 100개 = 1000MB(약 1GB))
이번 시간에는 파일 용량이 커질 때 효율적으로 파일을 관리하기 위해서 사용하는 <RollingFile>에 대해서 살펴봤습니다.
이로써 log4j2에 대한 학습이 끝났습니다. 이제 여러분 애플리케이션 운영상황을 고려해서 로깅 정책을 세우고 적용해 보시기 바랍니다.
지금까지 소스 첨부합니다.