Logback

김상훈·2024년 6월 16일

Spring Boot

목록 보기
1/2

Spring에서 기본 로깅 구조

스프링에서는 따로 설정하지 않는한 기본적으로 Apache의 JCL(Jakarta Common Logging)을 사용함

  • Spring Framework에서는 JCL의 구현체인 log를 사용하는데 대표적인 JCL 구현체로는 log4j가 있음
  • JCL 구현체 라이브러리를 스프링 어플리케이션의 의존성으로 추가할 경우 위처럼 Log4j 위치에 해당 구현체가 추가되어 로깅 프레임워크가 동작하는 방식임

Logback

  • logback은 slf4j 인터페이스의 구현체
  • JCL의 구현체가 아니기 때문에 logback을 사용하려면 다음과 같은 방법이 있음
    • Spring의 jar 파일을 열어 로깅 수행 소스를 전부 수정
    • 브릿지 라이브러리를 통해 JCL과 연동

jcl-over-slf4j와 같은 어댑터 역할을 수행하는 라이브러리를 이용해야 logback을 이용 가능

Logback이란

  • log4j 1.x 버전에서 제공하는 기능을 보완하고 성능적으로도 향상시킨 로깅 시스템
  • Logback은 3가지 모듈을 통해 다양한 기능을 제공함
    • logback-core: Appender와 Layout 인터페이스가 존재하는 모듈
    • logback-classiclogback-core와 SLF4J API 라이브러리를 포함하고 있음(Logger 클래스가 포함된 모듈)
    • logback-access: Servlet Container와 통합되어 HTTP 액세스에 대한 로깅 기능을 제공(Container 레벨에서 사용)

사용 방법

Logback을 이용하고 싶은 경우, 아래의 의존성을 추가(Spring 로깅 구조 참고)

//@Slf4j에 필요
compileOnly 'org.projectlombok:lombok'
annotationProcessor 'org.projectlombok:lombok'

//logback이랑 logstash 연동
implementation 'net.logstash.logback:logstash-logback-encoder:7.4'

//logback이랑 kafka 연동
implementation group: 'com.github.danielwegener', name: 'logback-kafka-appender', version: '0.2.0-RC2'

Logback 기본 구성

Logback 구성 요소 역할

  • appender: logging 이벤트 처리 역할을 담당함
    • Appender 인터페이스를 구현해 이벤트를 처리(Logger는 logging 이벤트를 처리)
  • logger: 이벤트의 대상, 어떤 내용을 log로 남길 것인지 정의하며 log level을 선택적으로 설정할 수 있음
  • root: 최상단의 logger를 root라 칭함
    • configuration 태그는 내부에 최대 1개의 root 태그를 갖고 0개 이상의 appender와 logger를 갖음

Appender란

Logger로 정의한 내용들을 어떻게 처리할 것인지 처리 역할을 위임받은 클래스

Appender는 태그를 통하여 구성되며 name와 class 속성을 필수적으로 가져야만 함

Appender 클래스 다이어그램

Appender 종류

1. ConsoleAppender

  • Logging 이벤트를 System.err 또는 System.out에 추가
  • 사용자가 지정한 인코더를 사용해 이벤트 형식을 지정

예시

<!--System.out에 찍히는 로그 설정-->
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"></appender>

2. FileAppender

OutputStreamAppender의 서브클래스로서 파일에 로그 이벤트를 추가

  • 대상 파일은 파일 옵션을 통해 지정되며 속성에 따라 파일이 추가되거나 분할됨

예시

<!--FILE에 찍히는 로그 설정-->
<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">

3. RollingFileAppender

  • RollingFileAppender는 FileAppender를 상속하며 파일을 롤오버하는 기능으로 확장
  • 롤오버의 예시로는 날짜별 로그파일 작성, 시간별 로그파일 작성 등 일정 기간, 혹은 조건 등에 따라 로그 파일을 분리하는 것

예시

<appenders>
	<rollingFile name="LogToFile" fileName="logs/application.log"filePattern="logs/application.log.%d{yyyy-MM-dd-hh-mm}">
		<patternLayout pattern="${sys:FILE_LOG_PATTERN}" />
		<!-- 정책을 통해 로그파일 롤오버 -> 1분마다 로그파일이 생성-->
			<policies>
				<timeBasedTriggeringPolicy interval="1" modulate="true" />
			</policies>
			<!-- 기본 롤오버 전략 => 생성된 로그 파일이 3개가 초과될 때 1개 삭제-->
			<defaultRolloverStrategy>
				<delete basePath="logs" maxDepth="1">
					<ifAccumulatedFileCount exceeds="3"/>
				</delete></defaultRolloverStrategy>
		</rollingFile>
</appenders>

4. SMTP Appender

  • SMTP Appender는 하나 이상의 고정 버퍼에 로깅 이벤트를 누적하고 사용자 지정 이벤트가 발생한 이후 해당 버퍼의 내용을 이메일로 발송
  • 기본적으로 이메일 전송은 ERROR 레벨의 로깅 이벤트에 의해 트리거되며, 비동기식으로 수행됨

예시

<appender name="EMAIL" class="ch.qos.logback.classic.net.SMTPAppender">
	<smtpHost>rlatkd.smtp.com</smtpHost>
	<to>rlatkdgns042@khu.ac.kr</to>
	<from>rlatkdgns042@khu.ac.kr</from>
	<subject>TESTING: %logger{20} - %m</subject>
	<layout class="ch.qos.logback.classic.PatternLayout">
		<pattern>%date %-5level %logger{35} - %message%n</pattern>
	</layout>
</appender>
<root level="DEBUG">
	<!--에러 발생시 이메일 발송 트리거 -->
	<appender-ref ref="EMAIL" /
</root>

5. Custom Appender

  • CustomAppender는 사용자가 직접 구현하는 appender 클래스를 의미함
  • AppenderBase<ILoggingEvent>를 상속해 클래스를 작성함
  • logback.xml에서 해당 appender를 호출 시 start() 메소드는 자동으로 실행
  • 해당 logger가 동작할 경우 append(ILoggingEvent iLoggingEvent)메소드가 동작을 수행

예시

package com.rlatkd.monitoring.utils

public class LoggingAppender extends AppenderBase<ILoggingEvent> {

    private static final SimpleDateFormat datetimeFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

    @Override
    protected void append(ILoggingEvent iLoggingEvent) {
        System.out.println(iLoggingEvent.getFormattedMessage());
    }

    @Override
    public void start() {
        super.start();
    }

}
<!-- GellogerMapper.create 호출시 trace level로  EvidenceLoggingAppender가 이벤트 실행 -->
<appender name="customlog" class="com.EvidenceLoggingAppender"></appender><logger name="test.gelog.GellogerMapper.create" level="trace"><appender-ref ref="customlog"/></logger>

Encoder

  • Encoder는 들어오는 log 이벤트를 OutputStream에서 바이트 배열로 변환시키는 작업을 수행함
  • logback 0.9.19버전 이후 출시된 Encoder는 Layout과 함께 log 출력값을 정의함

LayoutWrappingEncoder

  • LayoutWrappingEncoder는 Encoder와 Layout 간의 격차를 해소해주기 위해 Layout을 wrapping함
package ch.qos.logback.core.encoder;

public class LayoutWrappingEncoder<E> extends EncoderBase<E> {

  protected Layout<E> layout;
  private Charset charset;

   public byte[] encode(E event) {
     String txt = layout.doLayout(event);
     return convertToBytes(txt);
  }

  private byte[] convertToBytes(String s) {
    if (charset == null) {
      return s.getBytes();
    } else {
      return s.getBytes(charset);
    }
  }
}

Encoder는 Layout이 로그 이벤트를 정의해놓은 형식으로 변환한 문자열에 대해 바이트로 변환해 반환하는 역할을 수행

PatternLayoutEncoder

  • 가장 일반적으로 사용되는 레이아웃
  • FileAppender 또는 FileAppender의 서브클래스는 PatternLayout으로 구성될 때마다 무조건 PatternLayoutEncoder를 사용해야 함
  • logback은 로그 파일의 상단에 로그 출력 패턴을 정의할 수 있음
  • 기본적으로 패턴은 비활성되어 있어 outputPatternAsHeader을 활성화 시켜야 이용이 가능함

예시

<appender name="FILE" class="ch.qos.logback.core.FileAppender">
	<file>rlatkd.log</file>
	<encoder>
		<pattern>%d %-5level [%thread] %logger{0}: %msg%n</pattern>
		<outputPatternAsHeader>true</outputPatternAsHeader>
	</encoder>
</appender>

Layout

  • 들어오는 이벤트를 문자열로 변환하는 역할을 하는 logback 구성 요소
  • appender와 encoder, layout의 조합으로 들어오는 로그를 원하는 형식대로 구성할 수 있음

예시

package chapters.layouts;

import ch.qos.logback.classic.spi.ILoggingEvent;
import ch.qos.logback.core.LayoutBase;

public class MySampleLayout extends LayoutBase<ILoggingEvent> {

public String doLayout(ILoggingEvent event) {
    StringBuffer sbuf = new StringBuffer(128);
    sbuf.append(event.getTimeStamp() - event.getLoggingContextVO.getBirthTime());
    sbuf.append(" ");
    sbuf.append(event.getLevel());
    sbuf.append(" [");
    sbuf.append(event.getThreadName());
    sbuf.append("] ");
    sbuf.append(event.getLoggerName();
    sbuf.append(" - ");
    sbuf.append(event.getFormattedMessage());
    sbuf.append(CoreConstants.LINE_SEP);
    return sbuf.toString();
  }
}
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
	<encoder class="ch.qos.logback.core.encoder.LayoutWrappingEncoder">
	<!--log 이벤트가 다음 문자열로 들어옴-->
    <layout class="chapters.layouts.MySampleLayout" />
  </encoder>
</appender>
<root level="DEBUG">
	<appender-ref ref="STDOUT" />
</root>

Filter

  • 필터를 통해 Appender는 특정 이벤트에 대해 조건을 가지고 필터링을 수행할 수 있음

필터 종류

  • ACCEPT: 허용, 남아있는 필터를 무시한체 바로 이벤트를 처리
  • NEUTRAL: 중립, 다음 필터를 확인함
  • DENY: 거부, 즉시 이벤트를 버림

예시

public class SampleFilter extends Filter<ILoggingEvent> {

  @Override
  public FilterReply decide(ILoggingEvent event) {
  
  //"sample"이라는 문자열을 포함할 경우 ACCEPT, 아닐 경우 다음 필터 확인
    if (event.getMessage().contains("sample")) {
      return FilterReply.ACCEPT;
    } else {
      return FilterReply.NEUTRAL;
    }
  }
}
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
	<filter class="chapters.filters.SampleFilter" />
	<encoder>
		<pattern>
      %-4relative [%thread] %-5level %logger - %msg%n
    </pattern>
  </encoder>
</appender>

Logger란

  • Logger는 log를 남길 대상들을 의미함
  • Root는 최상단 logger로서 아무 설정도 안할 경우 root의 log level에 따라 로그 이벤트를 남길지 안남길지 설정이 가능해짐

예시

<!--기본 로그 레벨은 INFO-->
<!--내 프로젝트 패키지 로그 레벨은 DEBUG-->
<logger name="com.rlatkd.monitoring" level="DEBUG" />
<root level="INFO">
	<appender-ref ref="CONSOLE" />
	<appender-ref ref="FILE" />
	<appender-ref ref="KAFKA" />
	<!--<appender-ref ref="STASH" />-->
</root>

log level

  • log level은 크게 6가지로 나뉨

log level 종류

로그Level
FATAL애플리케이션이 이벤트를 발생했거나 중요한 비즈니스 기능 중 하나가 더 이상 작동하지 않는 상태일 경우를 알려주는 로그 Level
ERROR애플리케이션이 하나 이상의 기능이 제대로 작동하지 않는 문제에 부딪힐 때 사용해야 하는 로그 Level
WARN애플리케이션이 문제 또는 프로세스에 방해가 될 수 있는 상황에 예기치 않은 일이 발생했음을 나타내는 로그 Level
INFO애플리케이션이 특정 상태에 들어갔는지 등을 나타내는 표준 로그 Level, 일반적으로 정보제공을 위해 사용
DEBUG문제를 해결하는데 필요할 수 있는 정보 제공, 모든 것이 올바르게 정상적으로 동작하는지 확인하기 위해 테스트 환경에서 실행할 경우 사용
TRACE애플리케이션의 모든 상황을 완벽하게 파악하는 상황에서 사용, debug의 윗 수준으로 log정보가 매우 상세하게 나타냄

Reference

https://ckddn9496.tistory.com/79

https://www.baeldung.com/logback

https://www.baeldung.com/log4j2-custom-appender

https://logback.qos.ch/manual/appenders.html

https://tecoble.techcourse.co.kr/post/2021-08-07-logback-tutorial/

0개의 댓글