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 설정에 따라 출력 대상과 위치가 결정됩니다.
- Logger 선언과 정의
- Root Logger를 포함한 모든 Logger는 상위 요소인 아래에 선언합니다.
- Root Logger는 요소로 일반 Logger는 요소로 정의합니다.
- Logger는 하나 이상 정의할 수 있으며, Root 요소를 반드시 정의해야 합니다.
<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>
- AppenderRef 요소에 지정한 “console” Appender가 없는 경우 정상적인 로깅이 수행될 수 없으니 주의해야 합니다.
- Logger의 호출
- (1),(2)와 같이 Logger Name에 해당하는 Logger 설정 파일이 없는 경우 다음 Logger 계층 규칙에 따라 결정됩니다.
- 결과적으로 (1), (2)에 생성된 Logger 객체는 Root Logger 설정을 따르게 됩니다.
- 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 객체가 어떤 설정을 따르는지 이해하기 위해서는 Logger Hierarchy를 알고 있어야 합니다.
- 내부적으로 설정 파일에 정의된 각 Logger설정에 따라 LoggerConfig 객체가 생성되며 Logger Name에 따라 객체 간 부모-자식 관계가 성립됩니다. (부모 Logger 설정을 자식 Logger가 상속받음)
- Hierarchy 규칙
- 호출한 Logger Name과 동일한 Logger가 있는 경우 해당 Logger 설정을 따름
- 동일한 Logger는 없지만 Parent Logger가 존재하는 경우 Parent Logger 설정을 따름
- Parent Logger도 존재하지 않는 경우 Root Logger 설정을 따름
- 현재 정의된 Logger가 Root, X, X.Y 만 있다고 가정할 경우 동작 원리
Logger NameAssigned LoggerConfigLevelJava 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
FATAL > ERROR > WARN > INFO > DEBUG > TRACE
- FATAL
- 아주 심각한 에러가 발생한 상태를 나타낸다.
- 시스템적으로 심각한 문제가 발생해서 어플리케이션 작동이 불가능한 경우
- 일반적으로는 어플리케이션에서 사용할 경우가 없음
- ERROR
- 요청을 처리하는 도중 문제가 발생한 상태
- WARN
- 처리 가능한 문제이지만 이후 시스템 에러의 원인이 될 수 있는 경고성 메시지를 나타냄
- INFO
- 로그인/ 상태정보와 같은 정보성 메시지를 나타냄
- DEBUG
- 개발시 디버그 용도로 사용한 메시지를 나타냄
- TRACE
- 디버그 레벨이 너무 광범위한 것을 해결하기 위해 좀 더 상세한 상태를 나타냄
- 어플리케이션 수행 중 Log Level 변경 가능
Appender 설정
Appender는 로그가 출력되는 위치를 나타냅니다. xxxAppender로 끝나는 클래스 이름을 확인하면 출력 위치를 확인할 수 있습니다. Log4j2는 Console, File, RollingFile, Socket, DB등 다양한 로그 출력 위치와 방법을 지원합니다.
Appender 종류
Appenders태그명출력 위치
ConsoleAppender | Console | 콘솔 출력 |
FileAppender | File | 파일 출력 |
RollingFileAppender | RollingFile | 조건에 따라 파일 출력 |
JDBCAppender | JDBC | RDB Table에 출력 |
Layout 설정
Layout을 설정하면 발생한 로그 이벤트 포맷을 지정하고 원하는 형식으로 로그 출력이 가능합니다. 출력 형식에 따라 Layout의 종류가 달라지며, 아래와 같은 Layouts을 제공합니다.
종류
- HTMLLayout
- PatternLayout
- RFC5424Layout
- SerializedLayout
- SyslogLayout
- XMLLayout
이 중 제일 많이 사용하는 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 | 로깅 이벤트가 발생한 스레드명을 출력 |
'Spring' 카테고리의 다른 글
Spring - JdbcTemplate (0) | 2022.11.21 |
---|---|
Spring - ConnectionPool (0) | 2022.11.21 |
Spring - ExceptionHandler (0) | 2022.11.21 |
Spring - JUnit+Mock 기반 스프링 단위테스트 (0) | 2022.11.21 |
Spring - ResponseEntity, RequestEntity (0) | 2022.11.21 |
댓글