JAVA/JAVA | Spring 학습기록

[Spring] log4j2를 활용한 로깅 전략을 다룬 yml 파일을 생성하자

kth990303 2022. 8. 21. 20:10
반응형

배포 환경에서, 그리고 개발하면서 api를 맞춰보면서 특정 문제가 발생했을 때 그에 대한 기록을 남겨두면 이후에 그 기록을 바탕으로 대처를 할 수 있다. Spring에서는 다양한 logging configurations들을 제공한다. log4j, logback, log4j2들이 대표적이다.

 

이번 포스팅에선 log4j2를 선택한 이유와, 개발 및 배포환경에서 각각 다른 log4j2 yml을 어떻게 만들었는지 작성해보도록 하겠다.


logback vs log4j2

log4j는 2015년에 서비스가 종료됐고, 오래된 로그 프레임워크이기 때문에 제외하도록 하겠다.

 

 

logback

  • log4j 개발팀이 제작하여 기본적으로 log4j와 비슷하지만 성능이 향상됨.
  • spring-boot-starter-web의 기본 로깅 프레임워크

 

log4j2

  • logback, log4j의 단점을 개선한 로깅 프레임워크
  • logback보다 탁월한 성능 및 다양한 appender 제공

 

이러한 이유로 log4j2가 성능이 가장 좋다는 점, logback의 단점을 개선한 로깅 프레임워크라는 점을 고려하여 log4j2를 활용하기로 했다. 혹시 log4j2를 사용하지 않고 logback을 사용한 이유가 존재한다면 댓글 부탁!


환경세팅

build.gradle

configurations { /*logback 의존성 제거*/
    all {
        exclude group: 'org.springframework.boot', module: 'spring-boot-starter-logging'
    }
}

dependencies { /*log4j2 의존성 추가*/
    implementation 'org.springframework.boot:spring-boot-starter-log4j2'
    implementation 'com.fasterxml.jackson.dataformat:jackson-dataformat-yaml'
}

spring-boot-starter-web에서 기본으로 제공하는 logback 로깅 프레임워크 의존성을 제거하지 않으면 에러가 발생한다.


application.yml

logging:
  config: classpath:log4j2.yml

만약 로컬환경과 개발환경, 배포환경이 나누어져있다면 logging의 config를 그에 맞게 수정해주면 된다.

 

우리의 경우는 아래와 같이 하였다.

# application.yml
logging:
  config: classpath:log4j2.yml
  
# application-develop.yml
logging:
  config: classpath:log4j2-develop.yml

# application-deploy.yml
logging:
  config: classpath:log4j2-deploy.yml

로깅 전략

로깅 전략에 따라서 log4j2 yml 파일의 내용이 달라진다.

우리는 로컬에서는 file(단일 파일, 재실행 시 사라짐), rollingfile(아카이브화 하여 보관)로 남길 필요가 없다고 판단하여 Appender를 Console로 설정했다.

개발 환경에서는 배포하기 전 API를 맞춰봐야 하기 때문에 File로 남겨두는 것이 좋다고 판단해 File_Appender로 설정했다.

배포 환경에서는 로그 파일을 보관하는 것이 좋다고 판단해 RollingFile_Appender로 설정했다.

 

로컬과 개발 환경에서는 DEBUG, 배포 환경에서는 INFO로 로그 레벨을 설정했다. 

그러나, 로컬과 개발에서 Spring Application을 구동 시 스프링 관련 불필요한 정보들이 너무 많이 출력돼 Root log level은 INFO로, Controller 패키지 이하에서는 DEBUG로 설정하는 방식으로 변경했다.

 

log4j2.yml (로컬 환경)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
Configutation:
  name: Default
  status: info
 
  Properties:
    Property:
      name: log-path
      value: "logs"
 
  Appenders:
    Console:
      name: Console_Appender
      target: SYSTEM_OUT
      PatternLayout:
        pattern: "%style{%d{yyyy-MM-dd HH:mm:ss.SSS}}{cyan} %highlight{[%-5p]}{FATAL=bg_red,
            ERROR=red, INFO=green, DEBUG=blue, TRACE=bg_yellow} [%C] %style{[%t]}{yellow}- %m%n"
 
  Loggers:
    Root:
      level: info
      AppenderRef:
        - ref: Console_Appender
    Logger:
      - name: com.woowacourse.naepyeon
        additivity: false
        level: debug
        AppenderRef:
          - ref: Console_Appender
cs

 

log4j2-develop.yml (개발 환경)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
Configutation:
  name: Default
  status: info
 
  Properties:
    Property:
      name: log-path
      value: "logs"
 
  Appenders:
    File:
      name: File_Appender
      fileName: ${log-path}/logfile.log
      append: false
      PatternLayout:
        pattern: "%style{%d{yyyy-MM-dd HH:mm:ss.SSS}}{cyan} %highlight{[%-5p]}{FATAL=bg_red,
            ERROR=red, INFO=green, DEBUG=blue, TRACE=bg_yellow} [%C] %style{[%t]}{yellow}- %m%n"
 
  Loggers:
    Root:
      level: info
      AppenderRef:
        - ref: File_Appender
    Logger:
      - name: com.woowacourse.naepyeon
        additivity: false
        level: debug
        AppenderRef:
          - ref: File_Appender
cs

 

log4j2-deploy.yml (배포 환경)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
Configutation:
  name: Default
  status: info
 
  Properties:
    Property:
      name: log-path
      value: "logs"
 
  Appenders:
    RollingFile:
      - name: RollingFile_Appender
        fileName: ${log-path}/rollingfile.log
        filePattern: "${log-path}/archive/rollingfile.log_%d{yyyy-MM-dd}-%i.gz"
        PatternLayout:
          pattern: "%style{%d{yyyy-MM-dd HH:mm:ss.SSS}}{cyan} %highlight{[%-5p]}{FATAL=bg_red,
            ERROR=red, INFO=green, DEBUG=blue, TRACE=bg_yellow} [%C] %style{[%t]}{yellow}- %m%n"
        Policies:
          TimeBasedTriggeringPolicy:
            Interval: 1
            modulate: true
          SizeBasedTriggeringPolicy:
            size: "10 MB"
        DefaultRollOverStrategy:
          max: 10
          Delete:
            basePath: "${log-path}/archive"
            maxDepth: "1"
            IfLastModified:
              age: "P14D"
            IfAccumulatedFileCount:
              exceeds: 140
  Loggers:
    Root:
      level: info
      AppenderRef:
        - ref: RollingFile_Appender
    Logger:
      - name: com.woowacourse.naepyeon
        additivity: false
        level: info
        AppenderRef:
          - ref: RollingFile_Appender
cs

 

하나하나 찬찬히 살펴보자.


Configuration

Configutation:
  name: Default
  status: info

로그 설정의 최상위 요소이다. 해당 파일의 루트 로깅 전략의 name과 status를 적어주면 된다.

status는 log level을 적어주면 된다. error, warn, info, debug, trace 중에서 선택하자.

로그 레벨에 대해 좀 더 알아보자. 로그 레벨은 아래 순서를 따른다.

 

TRACE > DEBUG > INFO > WARN > ERROR

 

보통은 개발 환경에서는 debug 또는 info, 배포 환경에서는 info를 많이 하는 것으로 보인다.

 

무조건 많은 정보를 띄운다고 좋은 것이 아니다. 그만큼 용량을 많이 차지하고 불필요한 로그가 기록돼 가독성이 떨어지게 되기 때문이다.

 

한 번 비교해보자.

아래는 테스트용으로 소나큐브 인프라 세팅 관련 로그를 각각 DEBUG, INFO, WARN으로 설정하여 비교해본 사진이다.

DEBUG, INFO, WARN

WARN은 30줄임에 비해, INFO는 무려 40,000줄, DEBUG는 45,000줄이다!

이렇게 용량차이가 어마어마하게 난다는 것에 주의해야 한다.

 

Properties

Properties:
    Property:
      name: log-path
      value: "logs"

해당 Logger의 property를 명시하는 곳이다. key-value값으로 명시해주면 된다.

 

 

Appenders

Appenders:
Console:
  name: Console_Appender
  target: SYSTEM_OUT
  PatternLayout:
    pattern: "%style{%d{yyyy-MM-dd HH:mm:ss.SSS}}{cyan} %highlight{[%-5p]}{FATAL=bg_red,
        ERROR=red, INFO=green, DEBUG=blue, TRACE=bg_yellow} [%C] %style{[%t]}{yellow}- %m%n"

로깅 전략을 명시해주는 부분이다.

  • target: 표준 입출력임을 명시
  • pattern: 로그 스타일 지정. 가독성이 높아짐. ERROR는 빨간색, INFO는 초록색 등으로 칠해줌

 

로그 레벨 별로 다른 색이 칠해짐을 확인 가능

 

RollingFile_Appender로 할 경우 파일을 저장할 기간, 용량 관리 등을 설정해주어야 하므로 꽤 복잡해진다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
Appenders:
    RollingFile:
      - name: RollingFile_Appender
        fileName: ${log-path}/rollingfile.log
        filePattern: "${log-path}/archive/rollingfile.log_%d{yyyy-MM-dd}-%i.gz"
        PatternLayout:
          pattern: "%style{%d{yyyy-MM-dd HH:mm:ss.SSS}}{cyan} %highlight{[%-5p]}{FATAL=bg_red,
            ERROR=red, INFO=green, DEBUG=blue, TRACE=bg_yellow} [%C] %style{[%t]}{yellow}- %m%n"
        Policies:
          TimeBasedTriggeringPolicy:
            Interval: 1
            modulate: true
          SizeBasedTriggeringPolicy:
            size: "10 MB"
        DefaultRollOverStrategy:
          max: 10
          Delete:
            basePath: "${log-path}/archive"
            maxDepth: "1"
            IfLastModified:
              age: "P14D"
            IfAccumulatedFileCount:
              exceeds: 140
cs

 

  • File
    • name : RollingFileAppender 이름
    • fileName : 저장할 파일 경로, 이름에 날짜 형식을 지정하여 저장 가능 (Properties에 지정한 logs 디렉토리의 archive 디렉토리 아래에 rollingfile.log_%d{yyyy-MM-dd}.gz 파일명으로 로그 저장)
    • PatternLayout : 로그 출력 양식 지정

 

  • Policy : File RollingUp의 기준을 지정
    • OnStartupTriggeringPolicy : jvm start시 trigger
    • TimeBasedTriggeringPolicy + Interval : time에 따른 trigger(파일 이름 패턴의 최소단위 날짜로 계산, 위 예시는 하루에 한 번 RollingUp). 위 예시는 하루 단위로 압축 보관하도록 함.
    • SizeBasedTriggeringPolicy + size : file size에 따른 trigger.
    • CronTriggeringPolicy : Cron Expression(시간에 관한 표현)에 따른 trigger

 

  • DefaultRollOverStrategy : Rolling File을 Over(삭제)하는 기준을 지정
    • max: 동시간대에 최대 10개까지 RollingFiles가 생성될 수 있도록 지정
    • basePath: 아카이브화할 로그 파일 위치 지정. (Properties에 지정한 logs 디렉토리의 archive 디렉토리 아래에 rollingfile.log_%d{yyyy-MM-dd}.gz 파일명으로 로그 저장)
    • IfLastModified - age: "P14D": 수정된지 14일이 지난 파일은 삭제
    • IfAccumulatedFileCount : RollingUp된 압축파일을 저장하는 디렉토리에 존재할 수 있는 파일 개수. 파일 개수를 넘으면 오래된 파일부터 삭제(총 140개 초과시 오래된 파일부터 삭제)

 

 

자세한 내용은 공식 문서를 참고하자.

https://logging.apache.org/log4j/2.x/manual/appenders.html#RollingFileAppender

 

Log4j – Log4j 2 Appenders

facility String The facility is used to try to classify the message. The facility option must be set to one of "KERN", "USER", "MAIL", "DAEMON", "AUTH", "SYSLOG", "LPR", "NEWS", "UUCP", "CRON", "AUTHPRIV", "FTP", "NTP", "AUDIT", "ALERT", "CLOCK", "LOCAL0",

logging.apache.org

 

위와 같이 아카이브화 된 로그파일들이 남는 것을 확인할 수 있다.

 

Loggers

Loggers:
Root:
  level: info
  AppenderRef:
    - ref: Console_Appender
Logger:
  - name: com.woowacourse.naepyeon
    additivity: false
    level: debug
    AppenderRef:
      - ref: Console_Appender

로깅을 직접하는 요소, 로거는 패키지 별도로 설정이 가능하다. Root 패키지의 로거는 필수적으로 세팅해주어야 하며, 추가적인 로거를 설정하려면 Logger로 설정해주어야 한다.

  • level : 해당 패키지에 찍을 최하 로그 레벨을 지정
  • additivity : false로 지정시 로그가 중복으로 찍히는 것을 방지 (기본값: true)
  • AppenderRef : ref속성으로 적용할 Appender를 지정

여력이 된다면 위 로깅전략을 활용한 로그 인터셉터 구현 관련 포스팅도 작성해보도록 하겠다.

 

참고

 

feat: 로깅 전략을 수립하고 프로젝트에 반영한다. by yxxnghwan · Pull Request #353 · woowacourse-teams/2022-na

출력할 것 Http 요청 정보 (info) METHOD URI AUTHORIZATION HEADER REQUEST BODY 핸들링 한 예외 (info) 핸들링 안된 예외 (error) 예외 Stack Trace (debug) 로그 레벨 local, test: 개발자가 직접 코드를 작성하는 com.woowacours

github.com

 

반응형