logback 홈페이지의 매뉴얼을 읽으며 내용들을 정리한 글입니다.
RollingFileAppender
RollingFileAppender는 FileAppender를 상속하여 로그 파일을 rollover 합니다. 여기서 rollover는 타깃 파일을 바꾸는 것으로 이해할 수 있습니다. 예를 들어, RollingFileAppender가 타깃 파일로 log.txt에 로그 메시지를 append 하다가 어느 지정한 조건에 다다르면, 타깃 파일을 다른 파일로 바꿀 수 있습니다.
RollingFileAppender와 함께 동작하는 두 가지 component가 존재합니다. 첫 번째는 RollingPolicy로 rollover에 필요한 action을 정의합니다. 두 번째는 TriggeringPolicy로 어느 시점에 rollover가 발생할지 정의합니다. 간단히 RollingPolicy는 what, TriggeringPolicy는 when을 담당하고 있다 보시면 될 것 같습니다.
RollingFileAppender를 사용하기 위해서는 RollingPolicy와 TriggeringPolicy가 모두 필수적으로 필요합니다. 하지만, RollingPolicy는 TriggeringPolicy 인터페이스의 구현체로, 하나의 RollingPolicy만 지정하여도 사용 가능합니다.
RollingFileAppender는 아래의 properties를 갖습니다.
Property | Type | Description |
file | String | 타깃 파일의 이름 |
append | boolean (default: true) | append 정책. true: 이어 쓰기, false: 덮어 쓰기 |
encoder | Encoder | 로그 이벤트가 OutputStreamAppender에 기록되는 방식 |
rollingPolicy | RollingPolicy | rollover 발생 시 RollingFileAppender의 행동 |
triggeringPolicy | TriggeringPolicy | rollover 활성화 시점 |
predent | boolean | FileAppender와 동일. FixedWindowRollingPolicy는 prudent mode를 지원하지 않는다. RollingFileAppender는 TimeBasedRollingPolicy일 경우 두가지 제한조건에 대해 prudent mode를 제공한다. 1. 파일 압축 불가능 2. file 프로퍼티는 설정되지 않아야 한다 |
Rolling Policies
RollingPolicy는 파일 move와 renaming을 포함한 rollover 절차를 담당합니다.
RollingPolicy의 인터페이스는 다음과 같습니다.
package ch.qos.logback.core.rolling;
import ch.qos.logback.core.FileAppender;
import ch.qos.logback.core.spi.LifeCycle;
public interface RollingPolicy extends LifeCycle {
public void rollover() throws RolloverFailure;
public String getActiveFileName();
public CompressionMode getCompressionMode();
public void setParent(FileAppender appender);
}
- rollover 메서드는 현재의 로그 파일을 아카이빙 하는 과정을 포함하여 rollover 작업을 수행합니다.
- getActiveFileName 메서드는 현재의 로깅이 이루어지는 타깃 파일 이름을 가져옵니다.
- getCompressionMode 메서드를 통해 RollingPolicy의 압축 모드를 확인할 수 있습니다.
- setParent 메서드를 통해 부모(FileAppender)에 대한 참조가 가능합니다.
TimeBasedRollingPolicy
TimeBasedRollingPolicy는 가장 잘 알려진 RollingPolicy 종류 중 하나입니다. 시간에 기반하여 rollover 정책을 정의할 수 있으며, 주로 일 또는 월 단위로 rollover 합니다. TimeBasedRollingPolicy는 rollover 뿐만 아닌 Trigger에 대한 책임도 지기 때문에 RollingPolicy와 TriggeringPolicy 인터페이스를 모두 implements 합니다.
TimeBasedPolicy는 필수적으로 fileNamePattern 속성을 가집니다. 아래는 TimeBasedPolicy가 가지는 properties입니다.
Propoerty | Type | Description |
fileNamePattern | String (default %d: yyyy-MM-dd) |
아카이브 될 로그 파일의 패턴을 정의합니다. %d 문자를 이용해 파일의 적절한 부분을 dateTime 패턴으로 치환하도록 합니다. FileAppender의 file 프로퍼티를 통해 활성 로그 파일의 위치와 보관 될 로그 파일의 위치를 분리할 수 있습니다. file 프로퍼티로 등록된 곳이 활성 로그 파일의 위치가 됩니다. %d{} 내부의 dateTime 패턴 안에 '/' 또는 '\' 기호는 디렉터리 분리자로 인식합니다. 이를 통해 시간으로 원하는 디렉터리 구조를 구성할 수 있습니다. ex) /var/log/%d{yyyy/MM}/myapplication.%d{yyyy-MM-dd}.log |
maxHistory | int | 아카이브에 저장 유지할 로그 파일의 개수을 지정합니다. 예를들어 rollover를 1개월 마다 하며 값을 6으로 지정했다면, 6개월의 히스토리가 남게됩니다. 다음 월의 파일이 아카이브 될 경우 오래된 파일이 삭제됩니다. |
totalSizeCap | int | 로그 파일 아카이브 저장소의 최대크기를 지정합니다. totalSizeCap을 초과한다면 가장 오래된 파일이 삭제됩니다. maxHistory와 함께 쓰일 경우 1순위로 maxHistory에 대하여 처리된 후 totalSizeCap 이 적용됩니다. |
cleanHistoryOnStart | boolean (default: false) | Application이 시작될 때 아카이브된 로그 파일을 모두 지웁니다. false로 지정되면 삭제하지 않고 시작됩니다. |
fileNamePattern에 명시된 dateTime 패턴의 최소 단위에 따라 rollover 단위가 달라집니다. 아래의 예시를 통해 rollover가 trigger 되는 시점을 확인하시기 바랍니다.
- /foo.%d - default %d는 yyyy-MM-dd입니다. 매일 자정에 새로운 로그 파일로 rollover 합니다.
- /foo/%d{yyyy/MM}/bar.txt - 매월 새로운 디렉터리를 만들며 하위에 bar.txt 파일로 rollover 합니다.
- /foo/bar.%d{yyyy-MM-dd_HH-mm} - 매 분 새로운 로그 파일로 rollover 합니다.
- /foo/bar.%d.gz - 매일 새로운 로그 파일로 rollover 하고, 이전 로그파일은 GZIP으로 압축합니다.
<configuration>
<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>logFile.log</file>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!-- daily rollover -->
<fileNamePattern>logFile.%d{yyyy-MM-dd}.log</fileNamePattern>
<!-- keep 30 days' worth of history capped at 3GB total size -->
<maxHistory>30</maxHistory>
<totalSizeCap>3GB</totalSizeCap>
</rollingPolicy>
<encoder>
<pattern>%-4relative [%thread] %-5level %logger{35} - %msg%n</pattern>
</encoder>
</appender>
<root level="DEBUG">
<appender-ref ref="FILE" />
</root>
</configuration>
위의 configuration을 살펴봅시다. TimeBasedRollingPolicy를 적용하였으며 file 태그와 fileNamePattern 태그를 함께 사용하고 있습니다. Application이 동작중일 땐 활성화된 logFile.log 로그 파일에 로그를 쌓지만, 매일 자정이 지나면 logFile.2020-10-03.log 와 같은 이름으로 아카이브 됩니다. 아카이브 되는 파일의 개수는 30개이며, 아카이브 된 파일의 크기는 총 3GB을 넘을 수 없습니다. 이 조건을 만족하지 못할 경우 아카이브된 로그 파일 중 가장 오래된 파일을 삭제합니다.
SizeAndTimeBasedRollingPolicy
SizeAndTimeBasedRollingPolicy는 파일의 크기까지 고려한 TimeBasedPolicy를 상속한 RollingPolicy입니다. 위의TimeBasedPolicy 속성 중 totalSizeCap을 이용하면 전체 아카이브 된 로그 파일의 크기를 제한할 수 있습니다. 하지만 이 Policy는 각각의 로그 파일에 대한 크기를 제한합니다.
<configuration>
<appender name="ROLLING" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>mylog.txt</file>
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<!-- rollover daily -->
<fileNamePattern>mylog-%d{yyyy-MM-dd}.%i.txt</fileNamePattern>
<!-- each file should be at most 100MB, keep 60 days worth of history, but at most 20GB -->
<maxFileSize>100MB</maxFileSize>
<maxHistory>60</maxHistory>
<totalSizeCap>20GB</totalSizeCap>
</rollingPolicy>
<encoder>
<pattern>%msg%n</pattern>
</encoder>
</appender>
<root level="DEBUG">
<appender-ref ref="ROLLING" />
</root>
</configuration>
SizeAndTimeBasedRollingPolicy를 이용한 configuration을 함께 살펴봅시다. TimeBasedRollingPolicy와 다른점은 fileNamePattern에서 %i와 %d가 필수적인 토큰이라는 것입니다. 또한 maxFileSize라는 태그가 추가되었습니다. maxFileSize 태그는 각각의 로그파일이 가질 수 있는 최대 크기를 제한합니다. 활성화된 로그 파일의 크기가 maxFileSize에 다다르면 해당 로그파일을 아카이브 하며, 이때 %i 토큰이 index로 작용하여 다음 로그 파일의 이름을 결정합니다. 나머지 속성들은 TimeBasedRollingPolicy와 동일합니다.
FixedWindowRollingPolicy
FixedWindowRollingPolicy는 Fixed Window 알고리즘에 따라 로그 파일의 이름을 지정합니다. fileNamePattern은 파일의 이름 패턴을 지정하며 반드시 %i 토큰이 필요합니다.
Property | Type | Description |
minIndex | int | window index의 최소값 |
maxIndex | int | window index의 최대값 |
fileNamePattern | String | FixedWindowRollingPolicy를 통해 지어지게된 로그 파일 이름입니다. 반드시 window index를 위해 %i 토큰을 반드시 포함하고 있어야 합니다. 예를들어 minIndex=1, maxIndex=3일 경우, MyLogFile%i.log의 파일은 MyLogFile1.log MyLogFile2.log, MyLogFile3.log로 지어지게됩니다. 아카이브할 로그 파일을 압축 하고싶다면 .zip이나 .gz을 끝에 붙여 처리할 수 있습니다. |
아래의 샘플 configuration 파일을 보며 로그파일이 어떻게 만들어지는지 살펴봅시다.
<configuration>
<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>test.log</file>
<rollingPolicy class="ch.qos.logback.core.rolling.FixedWindowRollingPolicy">
<fileNamePattern>tests.%i.log.zip</fileNamePattern>
<minIndex>1</minIndex>
<maxIndex>3</maxIndex>
</rollingPolicy>
<triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">
<maxFileSize>5MB</maxFileSize>
</triggeringPolicy>
<encoder>
<pattern>%-4relative [%thread] %-5level %logger{35} - %msg%n</pattern>
</encoder>
</appender>
<root level="DEBUG">
<appender-ref ref="FILE" />
</root>
- rollover가 한번도 일어나지 않았을 때 file 태그의 이름으로 활성화된 로그 파일(test.log)만이 존재합니다.
- rollover가 1번 일어나면, 아카이브된 로그 파일의 이름은 minIndex=1로부터 시작되어 test.1.log.zip으로 만들어집니다. 여전히 활성 로그 파일의 이름은 test.log입니다.
- rollover가 2번 일어나면, 이전의 test.1.log.zip 파일의 이름이 test.2.log.zip으로 수정됩니다. 그리고 새로 아카이브 될 로그파일의 이름이 test.1.log.zip으로 지어집니다.
- rollover가 4번 일어나면, 기존에 아카이브 된 로그 파일 test.1.log.zip, test.2.log.zip, test.3.log.zip 중 maxIndex에 해당하는 test.3.log.zip 파일이 삭제됩니다. 그리고 각 파일들이 다음 index 파일명으로 renaming 됩니다. 새로 아카이브 될 로그파일의 이름은 항상 test.1.log.zip으로 지어집니다.
Triggering Policies
TriggeringPolicy는 언제 rollover가 발생할지 정의합니다. TriggeringPolicy의 인터페이스는 아래와 같습니다.
package ch.qos.logback.core.rolling;
import java.io.File;
import ch.qos.logback.core.spi.LifeCycle;
public interface TriggeringPolicy<E> extends LifeCycle {
public boolean isTriggeringEvent(final File activeFile, final <E> event);
}
- isTriggeringEvent 메서드는 activeFile과 현재의 로깅 이벤트를 파라미터로 전달받습니다. 메서드 내부에서는 rollover가 일어날 조건을 판단 하여 rollover 발생 혹은 현재 로그 파일 유지 여부를 반환합니다.
SizeBasedTriggeringPolicy
SizeBasedTriggeringPolicy는 현재의 활동 로그 파일의 크기를 판단의 요소로 사용합니다. 활성 로그파일이 명시한 파일 크기보다 그다면 RollingFileAppender가 현재 활동 로그 파일을 rollover 하도록 신호를 보냅니다. SizeBasedTriggeringPolicy는 단 하나의 프로퍼티로 maxFileSize 만을 가지며 설정하지 않았을 때의 기본 크기는 10MB입니다. maxFileSize는 숫자와 함께 파일 크기(KB, MB, GB)의 단위와 함께 사용되어 표기 가능합니다 (5000KB, 5MB, 2GB).
<configuration>
<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>test.log</file>
<rollingPolicy class="ch.qos.logback.core.rolling.FixedWindowRollingPolicy">
<fileNamePattern>test.%i.log.zip</fileNamePattern>
<minIndex>1</minIndex>
<maxIndex>3</maxIndex>
</rollingPolicy>
<triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">
<maxFileSize>5MB</maxFileSize>
</triggeringPolicy>
<encoder>
<pattern>%-4relative [%thread] %-5level %logger{35} - %msg%n</pattern>
</encoder>
</appender>
<root level="DEBUG">
<appender-ref ref="FILE" />
</root>
</configuration>
위의 설정 파일은 SizeBasedTriggeringPolicy를 사용하였으며 활성 로그 파일의 크기가 5MB 이상 파일이 되었을 때 rollover를 trigger 합니다.