프로젝트를 진행하다 보면 Exception Handler
에서 예외가 잡혀 stackTrace를 보지 못하고 에러 지점을 찾지 못하는 경우가 있습니다.
그런 경우에 Spring Boot에서 기본으로 제공하는 Logback을 사용하는데요, Lombok 플러그인을 사용하면 그 사용법이 정말 간단합니다.
// lombok과 spring-boot-starter-web을 dependency에 추가해야합니다.
@Slf4j
public class LogbackTest {
public static void main(String[] args) {
log.info("어쩌규");
log.error("저쩌구");
}
}
이렇게 코드로 작성한 로그를 항상 콘솔로 보며 모니터링 할 수 있을까요?
당연히 불가능합니다. 따라서 Spring의 경우 src/main/resources
경로에 logback-spring.xml
파일을 두어 profile, 로그 종류 등에 따라 각기 다른 로깅 조건을 설정할 수 있습니다.
Spring에서 기본 Console 로깅 전략으로 아래와 같은 xml파일을 확인할 수 있는데요.
<!-- {consol-appender.xml} -->
<included>
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>${CONSOLE_LOG_PATTERN}</pattern>
<charset>${CONSOLE_LOG_CHARSET}</charset>
</encoder>
</appender>
</included>
<!-- {file-appender.xml} -->
<included>
<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<encoder>
<pattern>${FILE_LOG_PATTERN}</pattern>
<charset>${FILE_LOG_CHARSET}</charset>
</encoder>
<file>${LOG_FILE}</file>
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<fileNamePattern>${LOGBACK_ROLLINGPOLICY_FILE_NAME_PATTERN:-${LOG_FILE}.%d{yyyy-MM-dd}.%i.gz}</fileNamePattern>
<cleanHistoryOnStart>${LOGBACK_ROLLINGPOLICY_CLEAN_HISTORY_ON_START:-false}</cleanHistoryOnStart>
<maxFileSize>${LOGBACK_ROLLINGPOLICY_MAX_FILE_SIZE:-10MB}</maxFileSize>
<totalSizeCap>${LOGBACK_ROLLINGPOLICY_TOTAL_SIZE_CAP:-0}</totalSizeCap>
<maxHistory>${LOGBACK_ROLLINGPOLICY_MAX_HISTORY:-7}</maxHistory>
</rollingPolicy>
</appender>
</included>
형태를 대략적으로 살펴보면 아래와 같습니다.
- 이름과 클래스를 가진 appender
- pattern과 charset을 지정할 수 있는 encoder
- (RollingFileAppender의 경우) rollingPolicy와 그 전략(파일 이름 패턴, 시작시 클린, 최대 파일 사이즈, 총 사이즈 제한, 최대 저장 기한) 등
이 xml Configuration들이 어딘가에 객체로 할당되어 사용되고 있다는 뜻인데요. 이제부터 이 설정파일이 어디에 저장되고 사용하는지 알아보겠습니다.
Logback-core
위 사진이 바로 Logback-core의 핵심이 되는 존재인 Appender입니다. Appender는 방금 xml 코드에서 봤던, 설정의 root가 되는 존재인데요.
공식 문서에서는 OutputStreamAppender부터 상세히 설명하고 있었습니다.
OutputStreamAppender는 문자열로 쉽게 매핑할 수 없어, 직접 인스턴스화하지 않습니다. 즉 configure 파일에 직접 이 OutputStreamAppender를 설정하여 사용할 수 없습니다. 따라서 ConsolAppender, FileAppender, RollingFileAppender를 root appender 로 사용하게 되겠죠?
ConsoleAppender
ConsoleAppender의 경우 설정해야 할 내용이 크게 없습니다. 가장 핵심이 되는 존재가 encoder 클래스인데요. 그 외에도 여러 몇 가지들이 있습니다.
- target : System.out or System.err / default System.out
- withJansi: 윈도우인데, 콘솔 로그에 색을 주고싶다면 true(class path에 jansi version이 담긴 클래스도 함께 입력해야함), default는 false 하지만 맥과 리눅스는 자동으로 지원해줍니다.
- Encoder: encoder의 default 클래스는 PatternLayoutEncoder입니다. FileAppender와 그 하위 클래스는 꼭 PatternLayoutEncoder를 사용해야 하고 Layout(Pattern, charset)과 logback Context, 로그 파일 상단에 Pattern을 작성하는 옵션을 제공합니다.
Encoder는 챕터가 따로 존재합니다. 간단한 내용을 소개하자면 현재는 PatternLayoutEncoder가 only really usefult encoder라고 합니다. 그 이유는 챕터에 소개가 되어 있으니 읽어보는 것을 추천합니다. 링크
FileAppender와 RollingFileAppender
로그는 파일로 저장해두어야 합니다. 그 파일을 이용하여 서비스를 더욱 개선할 수 있는 자료로 만들 수 있고, 또 적절하게 에러를 고칠 수도 있습니다. FileAppender 클래스는 이런 기능을 제공해줍니다. 하지만 FileAppender에는 용량이 가득찼을 때 대처할 수 있는 방법이 존재하지 않습니다. 또, 오래된 로그 파일을 제거할 수 있는 방법도 없습니다.
그래서 로그 파일을 저장할 때 File을 Rolling하며 로그를 저장할 수 있는 기능을 가진 RollingFileAppender를 주로 사용합니다.
- file: 파일 명 지정, 폴더가 없을 경우 직접 생성해줍니다.
- rollingPolicy: 롤오버가 필요할 때를 지정해주는 정책입니다. 주로 TimeBasedRollingPolicy 나 SizeAndTimeBasedRollingPolicy를 사용합니다.
- triggeringPolicy: 롤오버를 활성화 할때를 지정해주는 정책입니다. 이해한 바로는 RollingPolicy와 유사하여 굳이 동시에 쓸 필요는 없어보입니다.
- Prudent: 서로 다른 호스트의 JVM에서 File에 로그를 저장하려 할 때 이를 안정적으로 처리해줍니다. 다만 성능이 false일 때보다 약 3배 가량 늦습니다. 1초에 100개 이상의 로그가 남을 때 성능에 크리티컬한 이슈가 발생하므로, 해당 상황에는 이 전략을 피해야 합니다. TimeBasedRollingPolicy에서 이 전략을 사용할 수 있고 두가지 주의사항이 있으니 참고하여 사용해야 합니다.
- immediate flush: outputSream에 남은 로그를 바로 flush합니다. 덕분에 로그를 잃을 일이 없어 안정적이지만, 로깅 입력이 급격하게 늘어날 때 이 옵션을 false로 유지해야 합니다. (Disk에 I/O 를 로그가 남을 때 마다 진행하면 성능 저하가 발생하기 때문이지 않을까..)
위와 같은 Appender설정으로 최초에 설명했던 xml 코드를 읽어와 로깅을 효과적으로 할 수 있게 됐습니다.
하지만 이렇게만 설정하면 로그가 남지 않습니다. 바로 <included>
이녀석 때문인데요, 아직 로그 설정에 포함 될 수 있는 존재로만 설정이 된 것입니다.
다음 포스팅에는 Spring profile 별, 에러 레벨 별로 다른 로그 정책을 설정하는 방법에 대해 소개해보겠습니다.
'우아한테크코스 4기 > 레벨3' 카테고리의 다른 글
의존관계 분리 경험 공유(2) (0) | 2022.08.10 |
---|---|
의존관계 분리 경험 공유(1) (0) | 2022.08.10 |
[Logback] Spring Logback configuration 과정 (2) - Spring (0) | 2022.07.17 |
[Linux] Shell Script로 자기소개하기 (0) | 2022.07.11 |