ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • Server Log
    STUDY/백엔드 2020. 12. 28. 15:53

    Logging이란?

    - 프로그램 개발 중이나 완료 후에 발생할 수 있는 오류에 대해 디버깅하거나 운영 중인 프로그램 상태를 모니터링하기 위해 필요한 정보(로그)를 기록하는 것이다.

    • 서비스 동작 상태 파악
    • 장애 파악 & 알람

     

    - 종류

    • java.util.logging
      • JDK 1.4부터 포함된 표준 로깅 API
      • 별도 라이브러리 추가 불필요
      • 기능이 많이 부족해 다른 로그 라이브러리를 많이 사용
    • Apache Commons logging
      • 아파치 재단의 Commons 라이브러리 중에 로그 출력을 제공하는 라이브러리
    • Log4j/Log4j2
      • 아파치 제단에서 제공하는 자바 기반 로깅 라이브러리
    • Logback
      • Log4j를 개발한 Ceki Gulcu가 Log4j의 단점 개선 및 기능을 추가하여 개발한 로깅 라이브러리

    Log4j

    - 프로그램을 작성하는 도중에 로그를 남기기 위해 사용되는 자바 기반 로깅 유틸리티이다. 현재는 많이 사용하지 않고, logback이나 log4j2를 사용한다.

     

    - 로그 레벨(TRACE < DEBUG < INFO < WARN < ERROR < FETAL)

    • FETAL : 아주 심각한 에러가 발생한 상태를 나타낸다. 시스템적으로 심각한 문제가 발생해서 어플리케이션 작동이 불가능할 경우가 해당하는데, 일반적으로는 어플리케이션에서는 사용할 일이 없다.
    • ERROR : 어떠한 요청을 처리하는 중 문제가 발생한 상태를 나타낸다.
    • WARN : 프로그램의 실행에는 문제가 없지만, 향후 시스템 에러의 원인이 될 수 있는 경고성 메시지를 나타낸다.
    • INFO : 로그인, 상태변경과 같은 정보성 메시지를 나타낸다.
    • DEBUG : 개발시 디버그 용도로 사용하는 메시지를 나타낸다.
    • TRACE : 디버그 레벨이 너무 광범위한것을 해결하기 위해서 좀 더 상세한 이벤트를 나타낸다.

     

     

    - 구성 요소

    • Logger : 출력할 메세지를 Appender에게 전달한다.
      • 실제 로그 기능을 수행하는 객체로 Name을 가지고 사용된다. 로그 출력 레벨을 설정할 수 있고, 0개 이상의 Appender를 지정할 수 있다. 입력받은 로깅 메시지는 로그 레벨에 따라 Appender로 전달되고, 최상위 Logger인 root Logger를 설정해야 한다.
    • Appender : 전달된 로그를 어디에 출력할지 결정한다.
      • ConsoleAppender : 콘솔에 로그 메시지를 출력한다.
      • FilerAppender : 로그 메시지를 지정된 파일에 기록한다.
      • RollingFileAppender : 파일 크기가 일정 수준 이상이 되면 기존 파일을 백업파일로 두고 처음부터 다시 기록한다.
      • DailyRollingFilerAppender : 일정 기간 단위로 로그 파일을 생성하고 기록한다.

     

    • Layout : 로그를 어떤 형식으로 출력할지 결정한다.
      • %m : 로그 내용 출력
      • %p : debug, info, warn, error 등의 priority 출력
      • %r : 어플리케이션 시작 후 이벤트가 발생하는 시점까지의 경과시간
      • %c : package 출력
      • %C : 클래스명 출력
      • %d : 에빈트 발생 날짜 출력
      • %n : 개행문자(\n) 출력
      • %M : 로깅이 발생한 method 이름 출력
      • %F : 로깅이 발생한 프로그램 파일명 출력
      • %l : 로깅이 발생한 caller 정보 출력
      • %L : 로깅이 발생한 caller 라인수 출력
      • %x : 로깅이 발생한 thread와 관련된 NDC 출력
      • %X : 로깅이 발생한 thread와 관련된 MDC 출력
      • % : % 출력
      • %t : thread 이름 출력

    Logback

    - Java에서 많이 사용되던 로깅 라이브러리인 log4j의 후속 버전으로 현재 많이 사용되고 있다.

    - scan을 true로 하면 설정 변경시 설정을 자동으로 reload한다. scanPeriod로 스캔 검사 간격 주기를 지정할 수 있다.(기본값 밀리초)

    <configuration scan="true" scanPeriod="30 seconds" >
    ...
    </configuration>

     

    - 세가지 모듈로 구성된다.

    • logback-core : logback-clssic과 logback-access 모듈을 위한 기반이다.
    • logback-classic : logback-core를 확장한 것으로 log4j의 매우 발전한 형태로 본다. SLF4J API를 기본적으로 구현하므로 JDK1.4에 도입된 log4j나 java.util.logging(JUL)과 같은 로깅 프레임워크 사이에서 쉽게 전환할 수 있다.
    • logback-access : 서블릿 컨테이너와 통합돼 HTTP-access 로그 기능을 제공한다.

     

    <dependencies>
        <!-- logback-core.jar 추가 -->
        <dependency>
            <groupId>ch.qos.logback</groupId>
            <artifactId>logback-core</artifactId>
            <version>1.2.3</version>
        </dependency>
        <!-- logback-classic.jar 추가 -->
        <dependency>
            <groupId>ch.qos.logback</groupId>
            <artifactId>logback-classic</artifactId>
            <version>1.2.3</version>
        </dependency>
        <!-- slf4j-api.jar 추가-->
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-log4j12</artifactId>
            <version>1.7.28</version>
        </dependency>
    </dependencies>
    • 보통 이렇게 의존성을 추가하지만 spring boot의 경우 기본적으로 포함하고 있기 때문에 추가하지 않아도 된다.

     

    - 설정파일

    • Classpath(JVM이 프로그램을 실행할 때, 클래스 파일을 찾는 데 기준이 되는 파일 경로)에서 logback.groovy > logback-test.xml > logback.xml 순으로 파일을 찾아 적용시키고, 만약 모두 없다면 기본 설정을 출력한다.

     

    - 로그 레벨(TRACE < DEBUG < INFO < WARN < ERROR)

    • TRACE : 추적 레벨은 Debug보다 좀더 상세한 정보를 나타냅니다.
    • DEBUG : 프로그램을 디버깅하기 위한 정보를 표시합니다. (운영서버에서는 표시하지 않도록 설정함)
    • INFO : 상태변경과 같은 정보성 로그를 표시합니다.
    • WARN : 처리 가능한 문제, 향후 시스템 에러의 원인이 될 수 있는 경고성 메시지를 나타냄
    • ERROR : 요청을 처리하는 중 오류가 발생한 경우 표시합니다.

     

    - logback 아키텍처

    • Logger(실제 로그 기능을 수행하는 객체)

     

    // 기본적인 최상위 Logger
    <root level="INFO">
        <appender-ref ref="STDOUT" />
    </root>

     

    public class GrandParentsLogger{
        public void log() {
            logger.trace("trace");
            logger.debug("debug");
            logger.info("info");
            logger.warn("warn");
            logger.error("error");
        }
    }
    ParentsLogger class는 GrandParentsLogger class 상속
    ChildrenLogger class는 ParentsLogger class 상속

                                 ↓

    <logger name="com.logback.logger.grandParentsLogger" level="TRACE"/>
    <logger name="com.logback.logger.grandparentsLogger.parentsLogger" level="INFO" additivity="true"/>
    <logger name="com.logback.logger.grandparentsLogger.parentsLogger.childrenLogger" level="ERROR" additivity = "false"/>

                                 ↓

    GrandParentsLogger.log();
    ParentsLogger.log();
    ChildLogger.log();

                                 ↓

    GrandParentsLogger.log() => trace, debug, info, warn, error 출력
    ParentsLogger.log() => info, warn, error 출력
    ChildLogger.log() => error 출력

     

    Logger Name Level Appender additivity
    grandParentsLogger TRACE Console  
    parentsLogger INFO File true(기본값)
    childrenLogger ERROR RollingFile false

     

    Additivity : 상위 Logger로부터의 상속 여부를 의미한다.
    parentsLogger의 경우 additivity가 true여서, grandParentsLogger의 TRACE 레벨을 상속받지만 현재 로거에 INFO 레벨이 설정되어있기 때문에, 최종적으로 INFO 레벨이 적용되고 grandParentsLogger의 Console과 현재 로거의 File Appender에 로그 메시지를 전달한다.
    그러나 childrenLogger의 경우 false이기때문에, 상위 로거로부터 상속받지 않고 최종적으로 ERROR이상의 로그 메시지가 RollingFileAppender에 전달된다.
    • Appender(로그 출력 위치, 형식설정)
      1. ConsoleAppender :  콘솔에 로그 메시지 출력
      2. FileAppender : 파일에 로그 메시지 기록
      3. RollingFileAppender : 파일 크기가 일정 수준 이상이 되면 기존 파일을 백업파일로 바꾸고 처음부터 기록
    <appender name="ConsoleAppender" class="ch.qos.logback.core.ConsoleAppender">
        <layout class="ch.qos.logback.classic.PatternLayout">
            <Pattern>%d{HH:mm:ss.SSS} [%-5level] [%thread] [%logger{36}] - %m%n</Pattern>
        </layout>
    </appender>

    <appender name="FILE" class="ch.qos.logback.core.FileAppender">
        <file>logs/logger.log</file>
        <encoder>
            <Pattern>%d{HH:mm:ss.SSS} [%-5level] [%thread] [%logger{36}] - %m%n</Pattern>
        </encoder>
    </appender>

    <appender name="RollingFileAppender" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
            <level>INFO</level>
        </filter>
        <file>logs/logger.log</file>
        <encoder>
             <pattern>%d{yyyy-MM-dd HH:mm:ss} [%-5level] [%thread] [%logger{36}] - %m%n</pattern>
        </encoder>
        <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
            <fileNamePattern>logs/logger.%d{yyyy_MM_dd}_%i.log</fileNamePattern>
            <maxFileSize>50MB</maxFileSize>
        </rollingPolicy>
    </appender>

     

    • Layouts(로그 출력 형태 설정)
      • %Logger{length} : Logger name을 축약할 수 있다. {length}는 최대 자리 수, ex)logger{35}
      • %-5level : 로그 레벨, -5는 출력의 고정폭 값(5글자)
      • %msg : - 로그 메시지 (=%message)
      • ${PID:-} : 프로세스 아이디
      • %d : 로그 기록시간
      • %p : 로깅 레벨
      • %F : 로깅이 발생한 프로그램 파일명
      • %M : 로깅일 발생한 메소드의 명
      • %l : 로깅이 발생한 호출지의 정보
      • %L : 로깅이 발생한 호출지의 라인 수
      • %thread : 현재 Thread 명
      • %t : 로깅이 발생한 Thread 명
      • %c : 로깅이 발생한 카테고리
      • %C : 로깅이 발생한 클래스 명
      • %m : 로그 메시지
      • %n : 줄바꿈(new line)
      • %% : %를 출력
      • %r : 애플리케이션 시작 이후부터 로깅이 발생한 시점까지의 시간(ms)

    Log4j2

    - 자바 진영에서 제공하는 로깅 시스템이며 로깅과 관련된 여러 기능을 제공하는 유용한 라이브러리이다.

    - 로그 레벨은 기존 log4j와 동일하다.

    - 구성 요소

    • Logger로깅 작업을 수행하는 주체로, Logger 설정을 제외한 모든 로깅 기능이 이 Logger를 통해 처리된다.
      • <Loggers> 아래에 선언하고, Root Logger는 반드시 선언해야하고, 하나 이상의 Logger를 선언할 수 있다.
    <Loggers>
        <Root level="INFO"> 
            <AppenderRef ref="console"/> 
        </Root>
        <Logger name="logger" level="DEBUG" additivity="false">
            <AppenderRef ref="console"/>
        </Logger>

    </Loggers>

     

    • Appender : 로그를 어디에 출력할지 결정한다. 기존에 class 속성을 통해 Appender 종류를 구분한 것과 달리 태그를 통해 구분한다.
      • ConsoleAppender(<Console>) : 콘솔에 로그 메시지를 출력한다.
      • FilerAppender(<File>) : 로그 메시지를 지정된 파일에 기록한다.
      • RollingFileAppender(<RollingFile>) : 파일의 크기 또는 파일 백업 인덱스 등의 지정을 통해서 특정 크기 이상으로 파일의 크기가 커지면 기존 파일(target)을 백업파일(history)로 바꾸고, 다시 처음부터 로깅을 시작한다.
      • JDBCAppender(<JDBC>) : RDB Table에 출력한다.

     

    • Layout : 로그를 어떤 형식으로 출력할지 결정한다. Class 속성이 아닌 태그로 구분한다.

     

    HTMLLayout PatternLayout RFC5424Layout SerializedLayout SyslogLayout XMLLayout

     

    PatternLayout의 pattern

    c, logger 로깅 이벤트를 발생시키기 위해 선택한 로거의 이름을 출력
    C, class 로깅 이벤트가 발생한 클래스의 풀네임명을 출력
    M, method 로깅 이벤트가 발생한 메서드명을 출력
    F, file 로깅 이벤트가 발생한 클래스의 파일명을 출력
    l, location 로깅 이벤트가 발생한 클래스의 풀네임명.메서드명(파일명:라인번호)를 출력
    d, date 로깅 이벤트의 일자와 시간을 출력,\\SimpleDateFormat클래스에 정의된 패턴으로 출력 포맷 지정가능
    L, line 로깅 이벤트가 발생한 라인 번호를 출력
    m, msg, message 로그문에서 전달된 메시지를 출력
    n 줄바꿈
    p, level 로깅 이벤트의 레벨을 출력
    r, relative 로그 처리시간 (milliseconds)
    t, thread 로깅 이벤트가 발생한 스레드명을 출력
    %% %를 출력하기 위해 사용하는 패턴

    slf4j(Simple Logging Facade for Java)란?

    -Log4j 또는 Logback과 같은 백엔드 Logging Framework의 Facade pattern이다.

    • 다양한 Logging Framework에 대한 추상화로 단독으로는 사용하지 않는다.
    • JVM에 의해 유효성 체크가 되며, 바인딩 된 Logging Framework가 없으면 아무런 동작을 하지 않는다.
    • 인자형 로그 메시지를 지원한다.(ex. logger.info("hello {}", world);)
    • slf4j api를 사용하면 구현체의 종류에 상관없이 일관된 로깅 코드를 작성할 수 있다.
      • slf4j를 사용하지 않는 상황에서 log4j → logback으로 교체해야하는 상황이 발생하면, maven이나 gradle을 수정하고 기존의 import와 구문을 변경해야 한다. 이것은 IDE에서 한번에 replace 해줄 수 있지만, commit을 하는 경우 수백개의 파일이 commit되고 다른 사람들의 코드가 변경되며 오류가 발생할 수 있다. 하지만 slf4j를 사용하면 원하는 라이브러리로 변경해주면 된다.
      • 로그 라이브러리를 교체하더라도, 어플리케이션 코드를 변경하지 않아도 된다.
    • 배포할 때 원하는 Logging Framework를 선택할 수 있다.
      • 개발할 때, slf4j api를 사용해 로깅 코드를 작성한다.
      • 배포할 때, 바인딩된 Logging Framework가 실제 로깅 코드를 수행한다.
    • Logging Framework 간에 쉬운 전환이 가능하다.

    • 세가지 모듈을 제공한다.(API / Binding / Bridging)
      • API : Logging에 대한 추상 레이어를 제공하는 모듈이다.
      • Binding : slf4j Interface를 Logging Framework와 연결하는 어댑터 역할을 하는 라이브러리이다. 오직 하나의 Logging Framework만을 사용하도록 바인딩해야한다. 만약 바인딩된 것이 없다면 기본적으로 no-operation으로 설정된다.(출력되는 것이 없음) 따라서 반드시 사용할 Logging Framework에 대한 binding을 하나 추가해야한다.
      • Bridging : slf4j이외의 다른 Logging API로의 Logger 호출을 slf4j Interface로 연결하여 slf4j API가 대신 처리할 수 있도록 하는 일종의 어댑터 역할을 하는 라이브러리이다.

     

    log4j, log4j2 참고

    logging.apache.org/log4j/2.x/index.html

    to-dy.tistory.com/20

    www.egovframe.go.kr/wiki/doku.php?id=egovframework:rte3:fdl:logging:log4j_2:%EC%84%A4%EC%A0%95_%ED%8C%8C%EC%9D%BC%EC%9D%84_%EC%82%AC%EC%9A%A9%ED%95%98%EB%8A%94_%EB%B0%A9%EB%B2%95

    logback 참고

    logback.qos.ch/index.html

    dololak.tistory.com/632

    sonegy.wordpress.com/category/logback/

    slf4j 참고

    www.slf4j.org/

    kchanguk.tistory.com/45

    codingnotes.tistory.com/72

    'STUDY > 백엔드' 카테고리의 다른 글

    Bean  (0) 2021.01.05
    Mybatis  (0) 2020.12.31
    Apache Spring boot(내부 tomcat) 연동  (0) 2020.12.24
    TC(Test Case) & JUnit  (0) 2020.12.18
    WEB 서버와 WAS  (0) 2020.12.17
Designed by Tistory.