목차

Slf4j

의존성

로거 객체 생성

// 자동으로 현재 클래스를 찾아낸다.
import java.lang.invoke.MethodHandles;
 
private static final Logger logger = 
  LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());

Eclipse Slf4j Template

Java → Templates에서 slf4j_eclipse_template.7z를 import 해서 slf4j라고 에디터에서 치면 즉시 Slf4j 의 기본 코드가 작성된다.

IntelliJ IDEA Slf4j Live Template

설정 → Live Templates 에서 다음 처럼 하나의 항목을 추가해 준다.

Legacy Logging Framework 제거하고 LogBack 사용

Gradle 설정

ext {
    slf4jVersion = '1.7.5'
    logbackVersion = '1.0.13'
}
 
List loggers = [
    "org.slf4j:slf4j-api:${slf4jVersion}",
    "org.slf4j:jcl-over-slf4j:${slf4jVersion}",
    "org.slf4j:log4j-over-slf4j:${slf4jVersion}",
    "org.slf4j:jul-to-slf4j:${slf4jVersion}",
    "ch.qos.logback:logback-core:${logbackVersion}",
    "ch.qos.logback:logback-classic:${logbackVersion}"
]
// .. 의존성에 loggers 추가
dependencies {
    compile loggers
}
 
// commons-logging, log4j, jul 의존성 제거
configurations {
    all.collect { configuration ->
        configuration.exclude group: 'commons-logging', module: 'commons-logging'
        configuration.exclude group: 'log4j', module: 'log4j'
        configuration.exclude group: 'org.apache.logging.log4j'
        configuration.exclude group: 'org.slf4j', module: 'slf4j-log4j12'
        configuration.exclude group: 'org.slf4j', module: 'slf4j-jcl'
        configuration.exclude group: 'org.slf4j', module: 'slf4j-jdk14'
    }
}

Spring에서 JCL빼고 Slf4j 사용하기

<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-context</artifactId>
    <version>${spring.version}</version>
    <exclusions>
        <exclusion>
            <groupId>commons-logging</groupId>
            <artifactId>commons-logging</artifactId>
        </exclusion>
    </exclusions>
    <type>jar</type>
</dependency>
 
<dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>jcl-over-slf4j</artifactId>
    <version>${slf4j.version}</version>
    <scope>runtime</scope>
</dependency>
 
<dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>slf4j-api</artifactId>
    <version>${slf4j.version}</version>
    <type>jar</type>
</dependency>

java.util.logging

SLF4JBridgeHandler 설정

Logback 설정

Logger Wrapping

private static final String FQCN = Logger.class.getName();
 
 
public static void debug(String clazz, String message) {
    org.slf4j.Logger logger = LoggerFactory.getLogger(clazz);
    if (logger instanceof LocationAwareLogger) {
        ((LocationAwareLogger) logger).log(null, FQCN, LocationAwareLogger.DEBUG_INT, message, null, null);
    } else {
        logger.debug(message);
    }
}

Marker

Marker marker = MarkerFactory.getMarker("markerName");

SimpleLogger

// 버전에 따라 프라퍼티 명이 simpleLogger가 아닌 simplelogger일 수도 있음.
// 버전에 따라 defaultLogLevel -> defaultlog 일 수도 있음.
System.setProperty("org.slf4j.simpleLogger.defaultLogLevel", "info"); // 기본 레젤 지정
System.setProperty("org.slf4j.simpleLogger.log.com.microsoft.sqlserver", "trace"); // 특정 logger의 레벨 지정

Test Slf4j - Reflection 사용

TestTargetClass testTarget = new TestTarget();
 
private Field logField;
private Logger originalLogger;
private Logger mockedLogger;
 
@BeforeEach
void setUp() throws NoSuchFieldException, IllegalAccessException {
    mockedLogger = mock(Logger.class);
 
    Field logField = TestTargetClass.class.getDeclaredField("log");
    logField.setAccessible(true);
 
    Field modifiersField = Field.class.getDeclaredField("modifiers");
    modifiersField.setAccessible(true);
    modifiersField.setInt(logField, logField.getModifiers() & ~Modifier.FINAL);
 
    originalLogger = (Logger) logField.get(null);
    logField.set(null, mockedLogger);
}
 
@AfterEach
void tearDown() throws IllegalAccessException {
    logField.set(null, originalLogger);
}
 
 
@Test
void testMethod() {
    testTarget.callMethod()
 
    verify(mockedLogger).info("로그 메시지. 로그 인자 {}", "로그인자");
 
}
 
// Lombok @Slf4j 로 private static final Logger log 필드 주입
@Slf4j
public static class TestTargetClass {
    public void callMethod() {
        log.info("로그 메시지. 로그 인자 {}", "로그 인자");
    }
}

Test Slf4j

참조