본문 바로가기
가치관 쌓기/개발 돌아보기

[우아한테크코스Pro] 서비스 진단하기 - 1 (Logging) [6/9]

by simplify-len 2021. 7. 16.

[목표]

  1. Spring 의 로깅을 남길 수 있다.
  2. 웹 성능을 테스트 할 수 있다.

스프링 프레임워크에서는 LogBack을 활용해서 로그를 남길 수 있다.

공식 사이트

Spring boot 는 Commons Logging(org.apache.commons.logging) 를 사용하는데, 기본 설정자로서, Log4J2, Java Util Logging, 그리고 오늘 우리가 알아볼 LogBack 을 사용합니다.

Logging 의 Level 은 총 크게 4단계로 나눠집니다.

  • ERROR - 예상하지 못한 심각한 문제가 발생하여 즉시 조사해야 함.
  • WARN - 로직상 유효성 확인, 예상 가능한 문제로 인한 예외처리 등을 남김, 서비스는 운영될 수 있지만, 주의해야 함.
  • INFO - 운영에 참고할만한 사항으로, 중요한 비즈니스 프로세스가 완료됨
  • DEBUG / TRACE - 개발 단계에서만 사용하고 운영 단계에서는 사용하지 않음

기본적으로는 ERROR, WARN, INFO 가 로깅이 되고, DEBUG mode 를 추가할 경우 DEBUG 레벨의 로그가 추가되어집니다.

java -jar myapp.jar --debug

또는 debug=trueapplication.properties 에 추가합니다.

Console Output 그 외에도 File Output 이 있습니다. File Output 은 application.properties 에 logging.file 또는logging.path 를 해야 합니다.

만약 위의 규칙이 아니라, Custom Log 를 만들고 싶다면 어떻게 할까요?

이번 미션 과제의 과제이기도 한, Custom Log 각 Logging System 마다 아래 표와 같은 파일을 만들어 Custom 된 Logging 파일 임을 암시합니다.

Logging System Cusomization
Logback logback-spring.xml logback-spring.groovy, logback.xml or logback.groovy
Log4j2 log4j2-spring.xml or log4j2.xml
JDK(Java Util Logging) logging.properties

여기서 LogBack 은 다음과 같이 사용할 수 있습니다.

  • logback 환경을 설정한 뒤에, 아래와 같은 코드로 logging을 합니다.
  • import org.slf4j.Logger; import org.slf4j.LoggerFactory; import ch.qos.logback.classic.LoggerContext; import ch.qos.logback.core.util.StatusPrinter; public class HelloWorld2 { public static void main(String[] args) { Logger logger = LoggerFactory.getLogger("chapters.introduction.HelloWorld2"); logger.debug("Hello world."); // print internal state LoggerContext lc = (LoggerContext) LoggerFactory.getILoggerFactory(); StatusPrinter.print(lc); } }
  • 만약 아무것도 설정하지 않고 위와 같은 코드를 작성한다면 BasicConfigurator 가 사용될 것입니다.

application.properties 가 아니라 logback-test.xml 와 같이 logback-xxx.xml 파일을 사용해 로그를 설정하는 경우, appender,logger,root 이 세 가지를 기억해야 한다.(XML 안에는 카멜케이스 컨벤션을 따라야 한다.)

image-20210716115329644

어떻게 사용해야 하는지는 다음 코드를 살펴봅시다.

// sample.xml
<configuration>

  <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
    <!-- encoders are assigned the type
         ch.qos.logback.classic.encoder.PatternLayoutEncoder by default -->
    <encoder>
      <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
    </encoder>
  </appender>

  <logger name="chapters.configuration" level="INFO"/>

  <!-- Strictly speaking, the level attribute is not necessary since -->
  <!-- the level of the root level is set to DEBUG by default.       -->
  <root level="DEBUG">          
    <appender-ref ref="STDOUT" />
  </root>  

</configuration>

logger 에는 어떤 클래스에 어떤 레벨의 로그를 남기겠다 라고 남기면,

17:34:07.578 [main] INFO  chapters.configuration.MyApp3 - Entering application.
17:34:07.578 [main] INFO  chapters.configuration.MyApp3 - Exiting application.

처럼 보입니다.

Appenders 는 크게 2가지 속성을 꼭 넣어야 하는데, name 과 Class입니다.

<appender name="file" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <!--로깅이 기록될 위치-->
        <file>${home}file.log</file>
        <!--로깅 파일이 특정 조건을 넘어가면 다른 파일로 만들어 준다.-->
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <fileNamePattern>${home}file-%d{yyyyMMdd}-%i.log</fileNamePattern>
            <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
                <maxFileSize>15MB</maxFileSize>
            </timeBasedFileNamingAndTriggeringPolicy>
        </rollingPolicy>
        <!--   해당 로깅의 패턴을 설정   -->
        <encoder>
            <charset>utf8</charset>
            <Pattern>
                %d{yyyy-MM-dd HH:mm:ss.SSS} %thread %-5level %logger - %m%n
            </Pattern>
        </encoder>
    </appender>

이제 간단히 개념을 살펴봤다는 가정하에 작업하면서 알았던 부분에 대해서 써내려가볼까 합니다.

Spring 에 Log 를 남기는 방법은 크게 2가지가 있습니다.

application.properties 를 사용하는 것과, logback-xxx.xml 을 사용하는 것이다. 이번 미션에서 두개 다 사용해보면서, 최종적으로는 Spring Boot 가 자동으로 설정된 기능을 거의다 가져와서 사용하는 방식을 사용했다. applciation.properties 를 사용하는 방식을 사용했는데, 그 이유는 File 을 Logger 로 사용할 경우에 이슈가 있었기 때문입니다.

xml 내에서 Profile 별로 Log Configuration 을 변경할 수 있는 기능이 있습니다.

이 기능을 사용하면서, Logging을 테스트 하는데, File Logging을 사용하지 않는 Local Profile 에서도 계속해서 불필요하게 빈 파일의 Log File 을 만드는 것을 볼 수 있었습니다.

아래 File 형태로 Logger 할 경우의 XML 입니다.

<configuration debug="false">

    <!--spring boot의 기본 logback base.xml은 그대로 가져간다.-->
    <include resource="org/springframework/boot/logging/logback/base.xml" />
    <include resource="file-appender.xml" />

    <!--    logger name이 file일때 적용할 appender를 등록한다.-->
    <logger name="file" level="INFO" >
        <appender-ref ref="file" />
    </logger>
</configuration>  
    <property name="home" value="log/" />

    <!--  appender이름이 file인 consoleAppender를 선언  -->
    <appender name="file" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <!--로깅이 기록될 위치-->
        <file>${home}file.log</file>
        <!--로깅 파일이 특정 조건을 넘어가면 다른 파일로 만들어 준다.-->
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <fileNamePattern>${home}file-%d{yyyyMMdd}-%i.log</fileNamePattern>
            <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
                <maxFileSize>15MB</maxFileSize>
            </timeBasedFileNamingAndTriggeringPolicy>
        </rollingPolicy>
        <!--   해당 로깅의 패턴을 설정   -->
        <encoder>
            <charset>utf8</charset>
            <Pattern>
                %d{yyyy-MM-dd HH:mm:ss.SSS} %thread %-5level %logger - %m%n
            </Pattern>
        </encoder>
    </appender>
<?xml version="1.0" encoding="UTF-8"?>
<configuration debug="false">
    <include resource="org/springframework/boot/logging/logback/base.xml" />
    <include resource="file-appender.xml" />

    <springProfile name="local, test">
        <root level="DEBUG">
            <appender-ref ref="file-appender"/>
        </root>
    </springProfile>

    <springProfile name="prod">
        <root level="INFO">
            <appender-ref ref="file-appender"/>
        </root>
    </springProfile>
</configuration>

이렇게 하고 Profile을 local 로 하더라도 무조건 빈 파일의 로그가 만들어집니다.

이런 단점 때문에 나는 application.properties 에 설정하는 방법을 선택합니다.

image-20210716121652984

이런 식으로, 각각의 프로필 마다 properties 을 만들어 prod 에서만 File Logging 이 될 수 있도록 설정합니다. 설정하지 않으면 Console 로 logging 됩니다.

//application-prod.properties

...

logging.file.name=/home/ubuntu/log/subway.log

logging.logback.rollingpolicy.max-file-size=15MB
logging.logback.rollingpolicy.max-history=30

[읽어볼만한 자료]

https://meetup.toast.com/posts/149

댓글