Log4j2는 이전 버전인 Log4j의 업그레이드 버전으로 Logbakc 아키텍처에 내재된 몇 가지 문제를 해결하면서 Logback에서 사용할 수 있는 로깅 프레임워크입니다. Logback처럼 필터링 기능과 자동 리로딩 기능을 지원하며 멀티 스레드 환경에서 비동기 로거는 다른 로깅 프레임워크보다 더 많은 처리를 할 수 있고, 대기 시간도 더 짧다는 장점을 가지고 있습니다.
이번 포스트에서는 Log4j2를 이용한 로깅에 대해 정리해보았습니다.
Log4j2 환경설정
log4j2.xml을 작성하고 WEB-INF/classes 하위에 포함될 수 있도록 위치시켜야 합니다.
Log4j2가 초기화될 때 해당 설정 파일을 읽어들이기 때문입니다.
[xml 파일 정의]
<?xml version="1.0" encoding="UTF-8"?>
<Configuration>
<!-- Appender, Layout 설정 -->
<Appenders>
<Console name="console" target="SYSTEM_OUT">
<PatternLayout/>
</Console>
<File name="file" fileName="./logs/file/sample.log" append="true">
<PatternLayout pattern="%d %5p [%c] %m%n"/>
</File>
</Appenders>
<!-- Logger 설정 -->
<Loggers>
<Logger name="egovLogger" level="DEBUG" additivity="true">
<AppenderRef ref="console"/>
<AppenderRef ref="file"/>
</Logger>
<Root level="warn" additivity="true">
<AppenderRef ref="console"/>
</Root>
</Loggers>
</Configuration>
Logger
Logger는 로깅 작업을 수행하는 Log4j2의 주체입니다. Logger 설정을 제외한 모든 로깅 기능이 이 Logger를 통해 처리됩니다. 따라서 사용자는 어플리케이션 내에서 사용할 Logger를 정의해야 합니다. Log Level과 Appender 설정에 따라 출력 대상과 위치가 결정됩니다.
<Loggers>
<!-- attribute: name (Logger명), level (Log Level), additivity (중복로깅여부, true or false) -->
<!-- element: AppenderRef (Appender명) -->
<Logger name="X.Y" level="INFO" additivity="false">
<AppenderRef ref="console"/>
</Logger>
<Logger name="X" level="DEBUG" additivity="false">
<AppenderRef ref="console"/>
</Logger>
<Root level="warn" additivity="false">
<AppenderRef ref="console"/>
</Root>
</Loggers>
package me.overview.sample;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
public class LoggerTest {
// (1) Logger Name이 "me.overview.sample.LoggerTest"인 Logger 설정을 따르는 Logger 객체 생성
Logger logger1 = LogManager.getLogger();
// (2) 위와 동일
Logger logger2 = LogManager.getLogger(LoggerTest.class);
// (3) Logger Name이 "X"인 Logger 설정을 따르는 Logger 객체 생성
Logger logger3 = LogManager.getLogger("X");
}
Logger 객체가 어떤 설정을 따르는지 이해하기 위해서는 Logger Hierarchy를 알고 있어야 합니다.
내부적으로 설정 파일에 정의된 각 Logger설정에 따라 LoggerConfig 객체가 생성되며 Logger Name에 따라 객체 간 부모-자식 관계가 성립됩니다. (부모 Logger 설정을 자식 Logger가 상속받음)
Hierarchy
규칙
현재 정의된 Logger가 Root, X, X.Y 만 있다고 가정할 경우 동작 원리
Logger Name | Assigned LoggerConfig | Level | Java Code | 설명 |
---|---|---|---|---|
root | root | ERROR | LogManager.getLogger(“root”); | 설정 파일의 Root 설정을 따름 |
X | X | DEBUG | LogManager.getLogger(“X”); | 설정 파일의 X Logger 설정을 따름 |
X.Y | X.Y | INFO | LogManager.getLogger(“X.Y”); | 설정 파일의 X.Y Logger 설정을 따름 |
X.Y.Z | X.Y | INFO | LogManager.getLogger(“X.Y.Z”); | X.Y.Z Logger 설정이 없으므로 부모인 X.Y 설정을 따름 |
X.YZ | X | DEBUG | LogManager.getLogger(“X.YZ”); | X.YZ Logger 설정이 없으므로 부모인 X 설정을 따름 |
Y | root | ERROR | LogManager.getLogger(“Y”); | Y Logger 설정이 없으므로 부모인 Root 설정을 따름 |
Log Level
Appender 설정
Appender는 로그가 출력되는 위치를 나타냅니다. xxxAppender로 끝나는 클래스 이름을 확인하면 출력 위치를 확인할 수 있습니다. Log4j2는 Console, File, RollingFile, Socket, DB등 다양한 로그 출력 위치와 방법을 지원합니다.
Appenders | 태그명 | 출력 위치 |
---|---|---|
ConsoleAppender | Console | 콘솔 출력 |
FileAppender | File | 파일 출력 |
RollingFileAppender | RollingFile | 조건에 따라 파일 출력 |
JDBCAppender | JDBC | RDB Table에 출력 |
Layout 설정
Layout을 설정하면 발생한 로그 이벤트 포맷을 지정하고 원하는 형식으로 로그 출력이 가능합니다. 출력 형식에 따라 Layout의 종류가 달라지며, 아래와 같은 Layouts을 제공합니다.
종류
PatternLayout
이 중 제일 많이 사용하는 PatternLayout에 대해 더 자세히 알아보겠습니다.
PatternLayout의 선언은 Appender 요소의 하위 요소로 정의합니다. <PatternLayout />
을 선언하면 디폴트 pattern이 적용됩니다. pattern 속성을 이용하여 일자, 시간, 클래스, 로거명, 메시지 등 여러 정보를 선택하여 다양한 조합의 로그 메시지를 출력할 수 있습니다.
<Console>
<!-- 디폴트 패턴 적용, "%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n" -->
<PatternLayout />
</Console>
PatternLayout 패턴은 %로 시작하고 %뒤에는 format modifiers와 conversion character로 정의합니다. 이외 다양한 패턴은 다음 표로 정리하겠습니다.
패턴 | 설명 |
---|---|
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 | 로깅 이벤트가 발생한 스레드명을 출력 |
%% |