Spring - Log4j2

유재학·2022년 11월 16일
0

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의 호출

    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");   
    
    }
    • (1),(2)와 같이 Logger Name에 해당하는 Logger 설정 파일이 없는 경우 다음 Logger 계층 규칙에 따라 결정됩니다.
    • 결과적으로 (1), (2)에 생성된 Logger 객체는 Root Logger 설정을 따르게 됩니다.
  • Logger 계층도

    • Logger 객체가 어떤 설정을 따르는지 이해하기 위해서는 Logger Hierarchy를 알고 있어야 합니다.

    • 내부적으로 설정 파일에 정의된 각 Logger설정에 따라 LoggerConfig 객체가 생성되며 Logger Name에 따라 객체 간 부모-자식 관계가 성립됩니다. (부모 Logger 설정을 자식 Logger가 상속받음)

    • Hierarchy 규칙

      1. 호출한 Logger Name과 동일한 Logger가 있는 경우 해당 Logger 설정을 따름
      2. 동일한 Logger는 없지만 Parent Logger가 존재하는 경우 Parent Logger 설정을 따름
      3. Parent Logger도 존재하지 않는 경우 Root Logger 설정을 따름
    • 현재 정의된 Logger가 Root, X, X.Y 만 있다고 가정할 경우 동작 원리

Logger NameAssigned LoggerConfigLevelJava Code설명
rootrootERRORLogManager.getLogger(“root”);설정 파일의 Root 설정을 따름
XXDEBUGLogManager.getLogger(“X”);설정 파일의 X Logger 설정을 따름
X.YX.YINFOLogManager.getLogger(“X.Y”);설정 파일의 X.Y Logger 설정을 따름
X.Y.ZX.YINFOLogManager.getLogger(“X.Y.Z”);X.Y.Z Logger 설정이 없으므로 부모인 X.Y 설정을 따름
X.YZXDEBUGLogManager.getLogger(“X.YZ”);X.YZ Logger 설정이 없으므로 부모인 X 설정을 따름
YrootERRORLogManager.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태그명출력 위치
ConsoleAppenderConsole콘솔 출력
FileAppenderFile파일 출력
RollingFileAppenderRollingFile조건에 따라 파일 출력
JDBCAppenderJDBCRDB 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로깅 이벤트가 발생한 스레드명을 출력
%%
profile
github : https://github.com/kiaeh2323 , email : kiaeh9269@gmail.com

0개의 댓글