본문 바로가기

JAVA/Spring Framework

[Spring] Logging

Logging

로그를 통해 개발 또는 운영 시 발생하는 문제점을 추적하거나 운영 상태를 모니터링 할 수 있다.

로깅(Logging)이란 로그를 생성하도록 시스템을 작성하는 활동

로깅은 프로그램 개발 시 ==비 기능적인 요구사항==이지만 개발 중 디버깅, 개발 완료 후 문제점 추적 및 분석을 위해 필수적으로 갖추어야 할 요구 조건이다.

자바에서의 로깅

  • java.util. logging

  • Apache의 JCL

  • Log4J

    ** Log4J 의 성능 및 기능 개선을 위하여 대체 로거들이 생김, 자바 로거의 표준 및 일관된 인터페이스가 필요 **

  • SLF4J ( Simple Logging Façade )

    Logback( SLF4J의 구현체 중 하나)

    1. Log4J 보다 속도와 메모리 사용량이 개선
    2. XML & Groovy 설정 지원 ( 자동 리로딩 기능 )
    3. 다양한 Appender ( console, file, socket, JDBC )
    4. Rolling & Archiving ( 자동 압축 )
    5. HTTP 디버깅 ( logback-access 컴포넌트 )

*logging 확인을 위한 테스트 *

pom.xml

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.douzon</groupId>
    <artifactId>logex</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>war</packaging>

    <properties>
        <org.springframework-version>4.2.1.RELEASE</org.springframework-version>
        <!-- Logback을 설치하기 위한 설정 -->
        <jcloverslf4j.version>1.7.6</jcloverslf4j.version>        
        <logback.version>1.1.1</logback.version>
    </properties>

    <dependencies>
        <!-- spring -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>${org.springframework-version}</version>

            ** <!-- JCL 제외 -->
            <exclusions>
               <exclusion>
                  <groupId>commons-logging</groupId>
                  <artifactId>commons-logging</artifactId>
               </exclusion>
            </exclusions>** 

        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>${org.springframework-version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-web</artifactId>
            <version>${org.springframework-version}</version>
        </dependency>

        <!-- jstl -->
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>jstl</artifactId>
            <version>1.2</version>
        </dependency>



        <!-- Logback --> 
        <dependency>                                    
            <groupId>org.slf4j</groupId>                
            <artifactId>jcl-over-slf4j</artifactId>     
            <version>${jcloverslf4j.version}</version>  
        </dependency>
        <dependency>
            <groupId>ch.qos.logback</groupId>
            <artifactId>logback-classic</artifactId>
            <version>${logback.version}</version>
        </dependency>

    </dependencies>

    <build>
        <sourceDirectory>src</sourceDirectory>
        <plugins>
            <plugin>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.1</version>
                <configuration>
                    <source>1.7</source>
                    <target>1.7</target>
                </configuration>
            </plugin>
            <plugin>
                <artifactId>maven-war-plugin</artifactId>
                <version>2.3</version>
                <configuration>
                    <warSourceDirectory>webapp</warSourceDirectory>
                    <failOnMissingWebXml>false</failOnMissingWebXml>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>

/Java Resources/resource/logback.xml

<?xml version="1.0" encoding="UTF-8"?>
<configuration>

    <appender name="consoleAppender" class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <charset>UTF-8</charset>
            <Pattern>
                %d{HH:mm:ss.SSS} [%thread] %-5level %logger{5} - %msg%n
            </Pattern>
        </encoder>
    </appender>

    <appender name="fileAppender2" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <file>/logex/logex2.log</file>
        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
            <Pattern>
                %d{HH:mm:ss.SSS} [%thread] %-5level %logger{5} - %msg%n
            </Pattern>
        </encoder>
        <!-- 로그 파일이 50KB를 넘으면 FileNamePattern에 따라 파일을 만들고 10개까지만 만들어라. -->
        <rollingPolicy class="ch.qos.logback.core.rolling.FixedWindowRollingPolicy">
            <FileNamePattern>/logex/logex2.%i.log.zip</FileNamePattern>
            <MinIndex>1</MinIndex>
            <MaxIndex>10</MaxIndex>
        </rollingPolicy>
        <triggeringPolicy
            class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">
            <MaxFileSize>50KB</MaxFileSize>
        </triggeringPolicy>
    </appender>

    <appender name="fileAppender3" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <file>/logex/logex3.log</file>
        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
            <Pattern>
                %d{HH:mm:ss.SSS} [%thread] %-5level %logger{5} - %msg%n
            </Pattern>
        </encoder>
        <rollingPolicy class="ch.qos.logback.core.rolling.FixedWindowRollingPolicy">
            <FileNamePattern>/logex/logex3.%i.log.zip</FileNamePattern>
            <MinIndex>1</MinIndex>
            <MaxIndex>10</MaxIndex>
        </rollingPolicy>
        <triggeringPolicy
            class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">
            <MaxFileSize>1MB</MaxFileSize>
        </triggeringPolicy>
    </appender>    


    <!--
        com.cafe24.logex2 아래 패키지 로그들만  \logex\logex2.log 파일에만  출력하는 로거
        level을 debug로 해놓으면 모든 오류가 다 나옴 level 수준에 따라 다르게 로그가 남으므로 주의
    -->
    <logger name="com.cafe24.logex2"  level="debug" additivity="false">
            <appender-ref ref="fileAppender2" />
    </logger>

    <!--
        com.cafe24.logex3 아래 패키지 로그들만  \logex\logex3.log 파일과 콘솔로 출력하는 로거
    -->
    <logger name="com.cafe24.logex3"  level="warn" additivity="false">
            <appender-ref ref="fileAppender3" />
            <appender-ref ref="consoleAppender" />
    </logger>    

    <!-- 루트(글로벌) 로거 -->
    <root level="warn">
        <appender-ref ref="consoleAppender" />
    </root>

</configuration>

테스트를 위한 java source, ExampleController1.java

package com.cafe24.logex1.controller;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

@Controller
public class ExampleController {

    /**
     *  Logger 생성
     */
    private static final Log LOG = LogFactory.getLog( ExampleController.class );

    @RequestMapping( "/ex1" )
    @ResponseBody
    public String ex1() {

        /**
         *  이 예제에서는 logback.xml 에서,
         *  
         *  1. consoleAppender 와 root logger 만 세팅해서 테스트 해 볼 수 있습니다. 
         *  2. root logger의 level="DEBUG" 조정해 봅니다.
         *  
         *  3. 테스트 해보면,
         *     DEBUG  > INFO > WARN > ERROR 순으로 로그가 출력 되는 것을 확인할
         *     수 있습니다.
         *     
         *     가령, WARN 설정하면, warn, error 메서드의 로그 메세지만 출력 됩니다.
         *     직접 테스트 해 보세요.
         *  
         */
        LOG.debug( "#ex1 - debug log" );
        LOG.info( "#ex1 - info log" );
        LOG.warn( "#ex1 - warn log" );
        LOG.error( "#ex1 - error log" );

        return "Logback Logging Example1";
    }
}