logback을 이용하여 운영 환경 및 콘솔에서 로그를 찍어봅시다!
공식 팀의 깃허브에서 자세한 코드를 확인하실 수 있습니다.
클라우드를 사용하는 운영 환경에선 application의 상태를 알지 못합니다.
그렇다면 클라이언트가 알 수 없는 에러가 발생한 경우를 대비하여 로그를 찍고 문제를 해결해야합니다.
지속가능한 개발을 하기위해서 로그는 개발자들에게 꼭 필요하다고 할 수 있습니다.
로깅 라이브러리는 크게 log4j, logback, java util logger가 있습니다
로그 라이브러리들의 특징은 다음과 같습니다.
공식팀에서는 여러 로깅 라이브러리중 log4j와 logback중 고민을 하였는데요.
log4j가 어느 환경에서든 실행시간이 가장 비슷하다고 하지만, 우리 운영 환경에서 어떤 로그 프레임워크를 사용하는 것이 메모리, 실행시간 측면에서 좋을지 확인해봐야합니다.
따라서 현재는 의존성 추가가 필요 없이 비교적 간단하게 사용 가능한 logback을 사용하고 있습니다.
추후에 운영 환경에서 기회 비용을 따져 다시 결정할 예정입니다.
Logback은 logback-core, logback-classic, logback-access 이렇게 3가지 모듈로 나뉘어져 있습니다.
Logback은 3개의 주요 클래스(Logger, Appender, Layout)를 기반으로 합니다.
개발자들은 이 3개의 클래스를 이용하여 로그를 남길 수 있습니다.
Appender
(어디에?) , Layout
(어떻게) 가 core에 속하고 classic, access에 모두 쓰인다.Logger
(무엇을?)먼저 main-resource에 logback-spring.xml 파일을 만듭니다.(위치가 꼭 여기여야합니다!)
logback-spring.xml에 logback-classic(logger, root)을 작성하여 어떤 로그를 찍을지 작성하고, appender.xml 파일을 로그 레벨 별로 생성합니다.
그렇다면 공식팀은 로그를 어디에 기록할까요?
로그백의 로그는 console과 file에 기록할 수 있습니다.
어디에 기록할지 설정하는 곳을 appender라고 합니다.
어느 위치에 기록할지에 따라 appender가 존재합니다.
아래는 콘솔 appender의 예시입니다.
<included>
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>"[%d{yyyy-MM-dd HH:mm:ss}:%-4relative] %green([%thread]) %highlight(%-5level) %boldWhite([%C.%M:%yellow(%L)]) - %msg%n"</pattern>
</encoder>
</appender>
<appender name="CONSOLE-DB" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<charset>utf8</charset>
<Pattern>"%green( > %msg%n)"</Pattern>
</encoder>
</appender>
</included>
아래는 file-info레벨 appender의 예시입니다.
<included>
<appender name="FILE-INFO" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>./log/info/info-%d{yyyy-MM-dd}.log</file>
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>INFO</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
<encoder>
<pattern>"[%d{yyyy-MM-dd HH:mm:ss}:%-4relative] %green([%thread]) %highlight(%-5level) %boldWhite([%C.%M:%yellow(%L)]) - %msg%n"</pattern>
</encoder>
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<fileNamePattern>$./log/info/info-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
<maxFileSize>10MB</maxFileSize>
<maxHistory>7</maxHistory>
</rollingPolicy>
</appender>
</included>
name : logback-classic(logger, root)을 작성할 때, 어떤 appender를 사용할지 명시하기 위해서 사용합니다.
class : 해당 appender의 구현 class입니다.
ch.qos.logback.core.ConsoleAppender : 콘솔에 찍을 경우 사용하며 이 때, System.out 또는 System.err를 이용합니다.
ch.qos.logback.core.rolling.RollingFileAppender : 시간이나 용량에 따라 타겟 파일을 바꾸기 위해 이용합니다. 현재는 시간에 따라 다른 파일을 사용하기 위해 사용합니다.
ch.qos.logback.classic.filter.LevelFilter : 로그 레벨로 필터링을 해주기 위해서 사용합니다. 현재는 각 로그레벨 별로 appender를 만들어 사용하고 있습니다.
ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy : 로그 파일의 크기나, 저장 시간을 지정하기 위해서 사용합니다. 현재는 한 파일당 10MB, 7일간 저장하기위해 사용합니다.
그렇다면 공식팀은 어떤 모양으로 로그를 찍고 있을까요?
appender 내에 encoder는 로그를 어떻게 찍을 것인지를 결정합니다.
현재는 db관련, http관련, 그 외로 나눠서 사용합니다.
"%green( > %msg%n)"
예시
db관련해서는 binder, extractor를 보기 위해 사용하고 있고, 많은 양이 예상 되므로 필요한 정보인 msg만 출력합니다.
"%n###### HTTP Request ###### %n%fullRequest%n###### HTTP Response ###### %n%fullResponse"
현재는 http request, response 전체를 로그로 찍고 있는데 이대로 운영해보면서 filter를 이용하여 필요한 정보만 볼 수 있도록 수정할 예정입니다.
"[%d{yyyy-MM-dd HH:mm:ss}:%-4relative] %green([%thread]) %highlight(%-5level) %boldWhite([%C.%M:%yellow(%L)]) - %msg%n"
예시
db, http를 제외한 로그들에 일반적으로 사용되는 포멧입니다.
어떤 정보들을 로그에 포함하는지는 아래와 같습니다.
그렇다면 공식팀은 어떤 로그를 찍을까요?
dev, prod - 파일
Application Exception(info)
,UnHandled Exception(error)
dev에선 debug, prod에선 info로 출력중이나, 운영 환경이 안정화되면 prod를 error로 수정할 예정합니다.local, test - 콘솔
참고참고
[Logging] Logback이란?
logback 공식 사이트
[10분 테코톡] ☂️ 검프의 Logging(로깅) #2