log4j

kmb·2023년 2월 13일
0

스프링

목록 보기
6/9
post-thumbnail

로그를 찍기위해 System.out.println( ) 를 이용한 시스템 로그를 많이 사용한다.
이는 다음과 같은 단점을 갖는다.

  1. 휘발성이다.

System.out.println( )은 문제가 발생한 날짜, 시간, 수준, 발생 위치 등의 최소한의 정보가 기록되지 않은채로 파일로 저장되지 않고 휘발된다.
문제를 진단하고 고치기위해 로그를 확인해야하는데 저장되지 않고 휘발된다면 로그의 역할을 할 수 없다.

  1. 로그 출력 레벨을 사용할 수 없다.

운영서버에서 동작하는 코드는 에러 및 장애가 발생할 때 문제를 진단할 수 있는 정보만을 남겨야 하는데 System.out.println( ) 의 경우 로그 출력 레벨인 TRACE , DEBUG, INFO, WARN, ERROR, FATAL 기능을 사용할 수 없다.

  1. 성능저하의 원인이 될 수 있다.

WAS인 톰캣은 멀티쓰레드로 동작하는데 특정 요청이 오면 쓰레드 풀에서 쓰레드를 하나 가져와서 요청을 처리한다. 이때 여러개의 System.out.println( ) 여러개의 쓰레드에서 사용하면 오버헤드가 발생하여 처리속도가 저하된다.

따라서 로그 출력 레벨을 결정 할 수 있는 라이브러리인 slf4j 혹은 LogBack을 사용하면 위 단점을 보완할 수 있다.


  • slf4j 라이브러리 설정 및 예시
- 이클립스내의 pom.xml에서 slf4j 설정을 위한 태그설정

<!-- log4j 라이브러리 -->
<dependency>
	<groupId>org.slf4j</groupId>
	<artifactId>slf4j-api</artifactId>
	<version>${org.slf4j-version}</version>
</dependency>
<dependency>
	<groupId>org.slf4j</groupId>
	<artifactId>jcl-over-slf4j</artifactId>
	<version>${org.slf4j-version}</version>
	<scope>runtime</scope>
</dependency>
<dependency>
	<groupId>org.slf4j</groupId>
	<artifactId>slf4j-log4j12</artifactId>
	<version>${org.slf4j-version}</version>
	<scope>runtime</scope>
</dependency>

<!-- log4j 로그문 출력 라이브러리 -->
<dependency>
	<groupId>log4j</groupId>
	<artifactId>log4j</artifactId>
	<version>1.2.15</version>
	<exclusions>
		<exclusion>
			<groupId>javax.mail</groupId>
			<artifactId>mail</artifactId>
		</exclusion>
		<exclusion>
			<groupId>javax.jms</groupId>
			<artifactId>jms</artifactId>
		</exclusion>
		<exclusion>
			<groupId>com.sun.jdmk</groupId>
			<artifactId>jmxtools</artifactId>
		</exclusion>
		<exclusion>
			<groupId>com.sun.jmx</groupId>
			<artifactId>jmxri</artifactId>
		</exclusion>
	</exclusions>
<scope>runtime</scope>
</dependency>

 

  • src/main/resources 폴더내의 log4j.xml 설정
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE log4j:configuration PUBLIC "-//APACHE//DTD LOG4J 1.2//EN" "log4j.dtd">
<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">

	<appender name="console" class="org.apache.log4j.ConsoleAppender">
		<param name="Target" value="System.out" />
		<layout class="org.apache.log4j.PatternLayout">
			<param name="ConversionPattern" value="%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - %m%n" />
		</layout>
	</appender>
	
	<!-- Application Loggers -->
	<logger name="com.mycom.app">
		<level value="info" />
	</logger>
	
	<!-- 3rdparty Loggers -->
	<logger name="org.springframework.core">
		<level value="info" />
	</logger>
	
	<logger name="org.springframework.beans">
		<level value="info" />
	</logger>
	
	<logger name="org.springframework.context">
		<level value="info" />
	</logger>

	<logger name="org.springframework.web">
		<level value="info" />
	</logger>

	<!-- Root Logger -->
	<root>
		<priority value="warn" />
		<appender-ref ref="console" />
	</root>
	
</log4j:configuration>

log4j.xml 내부의
appender 요소는 로그의 출력위치를 설정.
layout 요소는 로그정보의 출력패턴을 설정.
PatternLayout 클래스는 로그정보를 사용자가 설정한 패턴에 따라 기록.

 

사용되는 속성은 다음과 같다.

속성설명
%d로깅 이벤트가 발생한 시간. 여기서는 임의로 yyyy-MM-dd HH:mm:ss 형식으로 설정했다.
%c카테고리
%C클래스명
%L로깅이 발생항 코드 라인수
%m로그내용
%n줄바꿈, 개행

Application Loggers의 logger태그내의 name속성값은 실제로 로그기능을 수행하는 객체를 지정.
(위에서는 내 프로젝트 top-level 패키지인 com.mycom.app 으로 설정)

level 요소의 value="info"는 로그출력레벨을 info로 지정하겠다는 의미.

Root Logger인 최상위로거는 appender-ref 요소의 ref속성값으로 console을 지정하는데
이는 appender요소의 name속성값이 console인 설정을 사용하겠다는 의미.


Logger 클래스는 log4j를 지원하는 핵심 클래스로서 아래와 같은 로그 출력 레벨이 있다.

레벨설명
FATAL (6레벨)조기 종료를 유발하는 심각한 오류가 발생하는 상태를 뜻한다
ERROR기타 런타임오류 or 예기치 않는 상태
WARN경고성메세지. 사용되지 않는 api사용. 바람직하지 않거나 예기치 않는 런타임 상황
INFO로그인, 상태변경같은 정보 제공용 메세지
DEBUG디버그 용도
TRACE (1레벨)가장 하위 로깅 레벨. 모든 로그에 대한 상세한 정보

 

  • 예시 ( logTest.jsp 파일이 없는 상태에서 uri 호출하여 HTTP 404에러 발생 )
@Controller
public class TestController {
	
	private static final Logger logger = LoggerFactory.getLogger(TestController.class);

	@RequestMapping("/logTest")
	public String logTest() {
		
		logger.trace("trace 메세지");
		logger.debug("debug 메세지");
		logger.info("info 메세지");
		logger.warn("warn 메세지");
		logger.error("error 메세지");
		  
		return "test/logTest"; 
	}
}   

결과

2023-02-13 19:12:19 INFO  TestController:35 - info 메세지
2023-02-13 19:12:19 WARN  TestController:36 - warn 메세지
2023-02-13 19:12:19 ERROR TestController:37 - error 메세지

 


  • 출처
  1. https://hudi.blog/do-not-use-system-out-println-for-logging/
  2. https://kingofbackend.tistory.com/67
profile
꾸준하게

0개의 댓글