로깅 프레임워크 Logback 적용하기

이경영·2022년 10월 14일
0

스프링부트2

목록 보기
14/19

출처 : https://youtu.be/fkwb8coxBJM

Logback 이란?

  • Logback이란 Log4J를 기반으로 개발된 로깅 라이브러리
  • log4j에 비해 약 10배정도 빠른 퍼포먼스, 메모리 효율성 증대

※ 출시순서 : log4j -> logback -> log4j2

Logback 특징

  • 로그에 특정 레벨을 설정할 수 있음 (Trace -> Debug -> Info ->Warn -> Error)
  • 실운영과 테스트 상황에서 각각 다른 출력 레벨을 설정하여 로그를 확인할 수 있음
  • 출력 방식에 대해 설정할 수 있음
  • 설정 파일을 일정 시간마다 스캔하여 어플리케이션 중단 없이 설정 변경가능
  • 별도의 프로그램 없이 자체적으로 로그 압축을 지원
  • 로그 보관 기간 설정 가능

Logback 구조

Logback 설정

  • 일반적으로 Classpath에 있는 logback 설정 파일을 참조하게 됨
  • Java Legacy, Spring의 경우에는 logback.xml 파일을 참조
  • Spring boot의 경우에는 logback-spring.xml 파일을 참조

appender

  • Log의 형태 및 어디에 출력할지 설정하기 위한 영역
  • 대표적인 Appender형식은 다음과 같음
    • ConsoleAppender : 콘솔에 로그를 출력
    • FileAppender : 파일에 로그를 저장
    • RollingFileAppender : 여러개의 파일을 순회하며 로그를 저장(로그 레벨 중심)
    • SMTPAppender : 로그를 메일로 보냄
    • DBAppender : 데이터베이스에 로그를 저장

Encoder

  • Appender 내에 포함되는 항목이며, pattern을 사용하여 원하는 형식으로 출력

root

  • 설정한 Appender를 참조하여 로그의 레벨을 설정할 수 있음
  • root는 전역설정이며, 지역설정을 하기 위해서는 logger를 사용

로그 레벨

TRACE > DEBUG > INFO > WARN > ERROR

1) ERROR : 로직 수행 중에 오류가 발생한 경우, 시스템적으로 심각한 문제가 발생하여 작동이 불가한 경우
2) WARN : 시스템 에러의 원인이 될 수 있는 경고 레벨, 처리가능한 사항
3) INFO : 상태 변경과 같은 정보성 메시지
4) DEBUG : 어플리케이션의 디버깅을 위한 메시지 레벨
5) TRACE : DEBUG 레벨보다 더 디테일한 메시지를 표현하기 위한 레벨

※예를 들어 로그 레벨을 INFO로 설정할 경우 TRACE, DEBUG 레벨은 출력되지 않음.

-- 실습

<?xml version="1.0" encoding="UTF-8"?>
<configuration scan="true" scanPeriod="30 seconds"> <!-- logback 구현체가 설정을 확인하는 주기 -->
    <property name="moduleId" value="around_hub_spring_boot"/><!-- moduleId는 프로젝트가 설치된 폴더명 또는 구분할 수 있는 식별자이면 됨 -->
    <property name="type" value="around_hub"/><!-- 로그파일명을 구성하는 인자 -->
    <property name="logback" value="logback"/><!-- log를 저장할 최종 디렉토리명 -->
    <property name="logdir" value="D:\Workspace\LogFiles"/>

    <!-- Appenders -->
    <appender name="console" class="ch.qos.logback.core.ConsoleAppender">  <!-- 콘솔에 출력 : class형식 콘솔에 출력되는 형식-->
        <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
            <level>DEBUG</level> <!-- 디버그 이상의 출력값들을 보겠다는 이야기 -->
        </filter>
        <encoder>
            <pattern>[%d{yyyy-MM-dd HH:mm:ss.SSS}] [%-5level] [%thread] %logger{30} %msg%n</pattern>
          <!-- 로그 출력 패턴-->
        </encoder>
    </appender>


<!--    <appender name="DEBUG_LOG" class="ch.qos.logback.core.rolling.RollingFileAppender">-->
<!--        <filter class="ch.qos.logback.classic.filter.ThresholdFilter">-->
<!--            <level>DEBUG</level>-->
<!--        </filter>-->
<!--        <file>${logdir}/${moduleId}/${logback}/debug_${type}.log</file>-->
<!--        <append>true</append>-->
<!--        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">-->
<!--            <fileNamePattern>${logdir}/${moduleId}/${logback}/debug_${type}.%d{yyyy-MM-dd}.gz</fileNamePattern>-->
<!--            <maxHistory>30</maxHistory>-->
<!--        </rollingPolicy>-->
<!--        <encoder>-->
<!--            <pattern>[%d{yyyy-MM-dd HH:mm:ss.SSS}] [%-5level] [%thread] %logger %msg%n</pattern>-->
<!--        </encoder>-->
<!--    </appender>-->

<!--    <appender name="INFO_LOG" class="ch.qos.logback.core.rolling.RollingFileAppender">-->
<!--        <filter class="ch.qos.logback.classic.filter.ThresholdFilter">-->
<!--            <level>INFO</level>-->
<!--        </filter>-->
<!--        <file>${logdir}/${moduleId}/${logback}/info_${type}.log</file>-->
<!--        <append>true</append>-->
<!--        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">-->
<!--            <fileNamePattern>${logdir}/${moduleId}/${logback}/info_${type}.%d{yyyy-MM-dd}.gz</fileNamePattern>-->
<!--            <maxHistory>30</maxHistory>-->
<!--        </rollingPolicy>-->
<!--        <encoder>-->
<!--            <pattern>[%d{yyyy-MM-dd HH:mm:ss.SSS}] [%-5level] [%thread] %logger %msg%n</pattern>-->
<!--        </encoder>-->
<!--    </appender>-->

    <!--
    <appender name="WARN_LOG" class="ch.qos.logback.core.rolling.RollingFileAppender">
      <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
        <level>WARN</level>
      </filter>
      <file>${logdir}/${moduleId}/${logback}/warn_${type}.log</file>
      <append>true</append>
      <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
        <fileNamePattern>${logdir}/${moduleId}/${logback}/warn_${type}.%d{yyyy-MM-dd}.gz</fileNamePattern>
        <maxHistory>30</maxHistory>
      </rollingPolicy>
      <encoder>
        <pattern>[%d{yyyy-MM-dd HH:mm:ss.SSS}] [%-5level] [%thread] %logger %msg%n</pattern>
      </encoder>
    </appender>
    <appender name="ERROR_LOG" class="ch.qos.logback.core.rolling.RollingFileAppender">
      <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
        <level>WARN</level>
      </filter>
      <file>${logdir}/${moduleId}/${logback}/error_${type}.log</file>
      <append>true</append>
      <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
        <fileNamePattern>${logdir}/${moduleId}/${logback}/error_${type}.%d{yyyy-MM-dd}.gz</fileNamePattern>
        <maxHistory>30</maxHistory>
      </rollingPolicy>
      <encoder>
        <pattern>[%d{yyyy-MM-dd HH:mm:ss.SSS}] [%-5level] [%thread] %logger %msg%n</pattern>
      </encoder>
    </appender>
  -->
    <!-- TRACE > DEBUG > INFO > WARN > ERROR > OFF -->
    <!-- Root Logger -->
  	<!-- INFO 레벨에 맞게끔 출력해라 -->
    <root level="INFO">
      	<!-- 윗부분의 appender의 이름과 매칭되어야한다. -->
        <appender-ref ref="console" />
        <!--
    <appender-ref ref="DEBUG_LOG" />
    <appender-ref ref="INFO_LOG" />
    <appender-ref ref="WARN_LOG" />
    <appender-ref ref="ERROR_LOG" />
    -->
    </root>
</configuration>

원래 spring에서 로그백 설정하기 위해서는 디펜던시를 추가해야함
스프링 부트같은 경우 starterweb이라는 dependency에서 의존성을 잡고 있기 때문에 자동으로 로그백 잡혀있음 -> 별도 라이브러리 세팅할 필요 없음

package com.example.testproject.controller;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class HelloController {
    //
    private final Logger LOGGER= LoggerFactory.getLogger(HelloController.class);

    @RequestMapping("/hello")
    public String hello(){
        return "Hello World";
    }

    @PostMapping("log-test")
    public void logTest(){
        LOGGER.trace("trace log");
        LOGGER.debug("debug log");
        LOGGER.info("info log");
        LOGGER.warn("warn log");
        LOGGER.error("error log");
    }
}
  • RUN했을때 콘솔의 모습

  • swaggerUI에 들어가서 execute해주었을때

-로그가 추가로 찍히는것을 볼 수 있다.

[%d{yyyy-MM-dd HH:mm:ss.SSS}][%-5level] [%thread] %logger{30} %msg%n
[INFO ] : 레벨
[%thread] : 쓰레드이름-번호
%logger : 로거의 항목 뒤에 {30}붙여도 됨 (간단하게 만들때)
%msg%n : 로거의 메세지 출력

로그에 info와 warning만 찍히게 된 이유는 logback설정 해줄때
<root level="INFO"> 로 설정해놓았기 때문임


    // http://localhost:8080/api/v1/product-api/product/{productId}
    @GetMapping(value = "/product/{productId}")
    public ProductDto getProduct(@PathVariable String productId) {

        long startTime=System.currentTimeMillis();
        LOGGER.info("[ProductController] perform {} of Around Hub API.", "getProduct");

        ProductDto productDto=productService.getProduct(productId);

        //중괄호를 사용해서 원하는 값들을 넣어준다
        LOGGER.info("[ProductController] Response :: productId = {}, productName = {}, productPrice = {}, productStock = {}, Response Time = {}ms",
                productDto.getProductId(),productDto.getProductName(),productDto.getProductPrice(),productDto.getProductStock(),
                (System.currentTimeMillis()-startTime));
        return productDto;
    }
  • swagger로 이동후 일단 create를 excute시켜보기 (조회하기위해)

  • get 실행시 하단 로그 찍히는걸 볼 수 있음.

[2022-10-19 00:37:32.607] [INFO ] [http-nio-8081-exec-10] c.e.t.c.ProductController [ProductController] perform getProduct of Around Hub API.
Hibernate: select productent0_.product_id as product_1_0_0_, productent0_.product_name as product_2_0_0_, productent0_.product_price as product_3_0_0_, productent0_.product_stock as product_4_0_0_ from product productent0_ where productent0_.product_id=?
[2022-10-19 00:37:32.613] [INFO ] [http-nio-8081-exec-10] c.e.t.c.ProductController [ProductController] Response :: productId = string, productName = string, productPrice = 0, productStock = 0, Response Time = 6ms
profile
꾸준히

0개의 댓글