Enum을 이용한 Logback의 프로그램적 설정 방법과 관리

Logback 사용할 시 기본적으로 설정을 아래와 같이 logback.xml 에서 선언적으로 사용을 하게 된다.

<configuration> 
  <appender name=”FILE” class=”xxx.RollingFileAppender”>
    <rollingPolicy class=”xxx.TimeBasedRollingPolicy”>
      <fileNamePattern>logFile.%d{yyyy-MM-dd}.log</fileNamePattern>
      <maxHistory>30</maxHistory> 
    </rollingPolicy>
    <encoder>
      <pattern>
        %-4relative [%thread] %-5level %logger{35} — %msg%n
      </pattern>
    </encoder>
  </appender>
 
  <root level=”DEBUG”>
    <appender-ref ref=”FILE” />
  </root>
</configuration>

xml를 이용한 선언적 방식이 설정을 분리하고 관리하는데에 장점이 있지만 설정하는 양이 많아질수록 xml을 크기는 점점 증가되어 오히려 관리에 대한 부담과 가독성을 떨어트리는 시점이 올 수 가 있다. 또한, 패스 경로나 파일명만 다르고 나머지는 동일한 설정들이 반복되는 현상도 발견할 수 있을 것이다.

이 때 Logback 설정을 선언적 방식이 아닌 소스 코드내에서의 프로그램적 방식을 이용하여 중복되는 설정을 간소화 할 수 있고, Enum 클래스와 약간의 컨벤션을 이용하여 Logback 설정을 여러 파일에 분산시키지 않고 한 곳에서 관리할 수 도 있다.

import ch.qos.logback.classic.Level;
import ch.qos.logback.classic.Logger;
import ch.qos.logback.classic.LoggerContext;
import ch.qos.logback.classic.encoder.PatternLayoutEncoder;
import ch.qos.logback.core.rolling.RollingFileAppender;
import ch.qos.logback.core.rolling.TimeBasedRollingPolicy;
import com.google.common.base.Joiner;
import org.slf4j.LoggerFactory;

public enum ProgrammticLoggers {

  auth, // 인증 관련 로그
  error // 에러 관련 로그
  ;

  private final Joiner joiner = Joiner.on("/");

  private final LoggerContext loggerContext 
             = (LoggerContext) LoggerFactory.getILoggerFactory();

  private final String PATTERN 
             = "%d{yyyy/MM/dd} %-5p %c{0}\t[ip=%X{IP}] %m%n";
 
  private final String LOG_ROOTPATH = "/logback/logs";

  private ProgrammticLoggers() {

    // 로그 파일 경로 생성
    final String filepath 
               = joiner.join(LOG_ROOTPATH, this.name()) + ".log";

    // Appender 설정
    RollingFileAppender rfAppender = new RollingFileAppender();
    rfAppender.setContext(loggerContext);
    rfAppender.setFile(filepath);

    // Policy 설정
    TimeBasedRollingPolicy rollingPolicy 
                           = new TimeBasedRollingPolicy();
    rollingPolicy.setContext(loggerContext);
    rollingPolicy.setParent(rfAppender);
    rollingPolicy.setFileNamePattern(filepath + ".%d{yyMMdd}.gz");
    rollingPolicy.setMaxHistory(30);
    rollingPolicy.start();

    // Encoder 설정
    PatternLayoutEncoder encoder = new PatternLayoutEncoder();
    encoder.setContext(loggerContext);
    encoder.setPattern(PATTERN);
    encoder.start();

    // Appender에 Policy와 Encoder를 연결
    rfAppender.setEncoder(encoder);
    rfAppender.setRollingPolicy(rollingPolicy);
    rfAppender.start();

    // 해당 enum의 이름으로 Logger를 만들고 Appender를 연결해준다.
    Logger logbackLogger = loggerContext.getLogger(this.name());
    logbackLogger.setLevel(Level.INFO);
    logbackLogger.setAdditive(false);
    logbackLogger.addAppender(rfAppender);
  }
}

위와 같이 Enum 클래스 생성자에 Logback 설정을 하게되면 각 enum 마다 그 enum의 이름으로 Logger가 생성 된다. 그 후 아래와 같이 Logger를 사용하면 된다.

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class SomeClass {

  private final Logger logger 
       = LoggerFactory.getLogger(ProgrammticLoggers.auth.name());

  public void someMethod() {
    ...
    logger.error("Failed to login.");
    ...
  }
}

logger를 사용하는 각 클래스에서 getLogger에 문자열을 매번 생성하지 않고 enum의 이름을 넘겨줌으로서 추 후 변경/관리에 용이하고 새로운 logger 설정을 추가할 때 Enum 클래스에 새로운 enum 한줄만 추가하면 된다. 만약 다른 Appender, Policy를 적용한 logger를 사용하고 싶을 때는 Enum 클래스에 맴버변수를 이용하여 각 enum의 속성을 설정하고 이를 바탕으로 프로그램적 설정방식의 이점을 이용하여 logger생성 로직이 있는 Enum클래스 생성자 안에서 동적으로 구성을 하면 될 것 이다.

Advertisements

답글 남기기

아래 항목을 채우거나 오른쪽 아이콘 중 하나를 클릭하여 로그 인 하세요:

WordPress.com 로고

WordPress.com의 계정을 사용하여 댓글을 남깁니다. 로그아웃 / 변경 )

Twitter 사진

Twitter의 계정을 사용하여 댓글을 남깁니다. 로그아웃 / 변경 )

Facebook 사진

Facebook의 계정을 사용하여 댓글을 남깁니다. 로그아웃 / 변경 )

Google+ photo

Google+의 계정을 사용하여 댓글을 남깁니다. 로그아웃 / 변경 )

%s에 연결하는 중