org.slf4j:slf4j-simple
에 의존성을 걸면 최소한의 slf4j simple logger가 활성화된다.org.slf4j:slf4j-api
만 의존성 걸면 아무 logger도 작동하지 않는다.// 자동으로 현재 클래스를 찾아낸다. import java.lang.invoke.MethodHandles; private static final Logger logger = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
Java → Templates
에서 slf4j_eclipse_template.7z를 import 해서 slf4j
라고 에디터에서 치면 즉시 Slf4j 의 기본 코드가 작성된다.
설정 → Live Templates 에서 다음 처럼 하나의 항목을 추가해 준다.
slf4j
private final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger($CLASS$.class);
CLASS
className()
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' } }
<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>
* // Optionally remove existing handlers attached to j.u.l root logger SLF4JBridgeHandler.removeHandlersForRootLogger(); // (since SLF4J 1.6.5) // add SLF4JBridgeHandler to j.u.l's root logger, should be done once during // the initialization phase of your application SLF4JBridgeHandler.install();
logging.properties
로 설정 (SLF4JBridgeHandler.install()
이거 안할경우에 만)handlers = org.slf4j.bridge.SLF4JBridgeHandler
LevelChangePropagator
필요(http://logback.qos.ch/manual/configuration.html)<configuration debug="true"> <contextListener class="ch.qos.logback.classic.jul.LevelChangePropagator"> <resetJUL>true</resetJUL> </contextListener> .... </configuration>
org.slf4j.spi.LocationAwareLogger
를 통해서 이 문제를 해소할 수 있다. java - Wrapping the slf4j APIprivate 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 = MarkerFactory.getMarker("markerName");
// 버전에 따라 프라퍼티 명이 simpleLogger가 아닌 simplelogger일 수도 있음. // 버전에 따라 defaultLogLevel -> defaultlog 일 수도 있음. System.setProperty("org.slf4j.simpleLogger.defaultLogLevel", "info"); // 기본 레젤 지정 System.setProperty("org.slf4j.simpleLogger.log.com.microsoft.sqlserver", "trace"); // 특정 logger의 레벨 지정
private static final
필드에 관한 사항 참조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("로그 메시지. 로그 인자 {}", "로그 인자"); } }