로그(log) 관리

JSP, Servlet 공부를 하면서 참고한 서적입니다.

프로젝트로 배우는 자바 웹 프로그래밍

로그 관리

로그(Log)는 프로그램을 개발하거나 운영할 때 발생하는 문제점을 추적하거나
운영 상태를 모니터링하기 위한 텍스트 형식의 데이터 입니다.

우리가 Debugging할 때 사용했던 System.out.println() 메서드는 메서드 호출 결과를
알아 내기 위한 메시지 출력이며 가장 기초적인 로깅이 형태입니다.

로깅(Logging) : 콘솔, 웹, 파일에 기록을 남긴다는 의미

로깅을 하면 문제 발생 시 원인 파악이 쉽고, 프로그램 개발 과정에서의 간단한 구현 검증, 프로그램 진행 과정에 대한 모니터링 등
여러 이점들이 많이 있습니다. 예를 들어 쇼핑몰 쇼핑 기록 등이 로그화되어 관리되어 지는 것입니다.

  • 로그 유형
  1. 어플리케이션 로그 : 어플리케이션 내부 동작 과정에서 발생한 내용에 대한 로깅
  2. 시스템 로그 : 사용자나 데이터와 관련된 내용에 대한 로깅
  • 로그 처리 메소드 및 로그 레벨
Level 처리 메소드
TRACE 가장 상세한 형태의 정보를 말합니다. 로그 파일로만 출력합니다.
DEBUG 시스템 흐름과 관련된 상세 정보를 말합니다. 로그 파일로만 출력 합니다.
INFO 런타임 시 관심 있는 이벤트를 말합니다. 상태 콘솔에 즉시 출력 합니다.
WARN 오류는 아니지만 주의를 요구하는 경우를 말합니다. 더 이상 쓸모없는 API 사용등이 포함됩니다. 상태 콘솔에 즉시 출력합니다.
ERROR 일반적인 오류를 말합니다. 상태 콘솔에 즉시 출력합니다.
FATAL 가장 심각한 오류를 말합니다. 상태 콘솔에 즉시 출력합니다.

Log4J, SLF4J

Log4J는 가장 대표적인 로깅 프레임워크 입니다. 그리고 SLF4J(Simple Logging Framework)는
가장 최근에 나온 로깅 프레임워크 이며 기존 로깅 API들의 문제점을 보완 했습니다.

설치

Log4j : logging.apache.org/log4j

SLF4J : www.slf4j.org

  • 필요 라이브러리
  1. SLF4J : slf4j-api-1.7.5.jar
  2. sl4j-simple-1.7.5.jar OR slf4j-log4j12-1.7.5.jar
  3. Log4J : log4j-1.2.17.jar

라이브러리들을 WebContent/Web-INF/lib 밑에 복사하여 붙여넣기 해야 합니다.

  • Log4j 설정하기(log4j.xml)
  <?xml version="1.0" encoding="UTF-8"?>
  <!DOCTYPE log4j:configuration PUBLIC "-//APACHE//DTD LOG4J 1.2//EN" "http://logging.apache.org/log4j/1.2/apidocs/org/apache/log4j/xml/doc-files/log4j.dtd">
  <log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">
  	<appender name="stdout" class="org.apache.log4j.ConsoleAppender">
      <!-- PatternLayout 설정 -->
  		<layout class="org.apache.log4j.PatternLayout">
  			<param name="ConversionPattern"
  				value="[%d{HH:mm:ss}] [%c{1}.%M()] [%p] %m %n" />
  		</layout>
  	</appender>

  	<appender name="dailyout" class="org.apache.log4j.DailyRollingFileAppender">
  		<param name="file" value="c:/tmp/dailyout.log"/>
  		<param name="Append" value="true" />
  		<param name="DatePattern" value="'.'yyMMdd" />
  		<layout class="org.apache.log4j.PatternLayout">
  			<param name="ConversionPattern" value="%t> [%d{yyyy-MM-dd HH:mm:ss}] [%c{1} [%L] [%p] %m %n" />
  		</layout>
  	</appender>

  	<root>
  		<level value="DEBUG" /> <!-- LOG LEVEL 설정 -->
  		<appender-ref ref="stdout" />
  		<appender-ref ref="dailyout" />
  	</root>
  </log4j:configuration>

위 log4j.xml파일을 src밑에 생성해야 아래 예제를 실행 시킬 수 있습니다.
LOG LEVEL을 DEBUG로 설정하면 trace를 제외한 DEBUG까지 출력됩니다. info로 바꾸면
DEBUG를 제외한 info까지 출력됩니다.

  • 패키지 불러오기 및 객체 만들기 예제
  import org.slf4j.Logger; // Logger 클래스 불러오기
  import org.slf4j.LoggerFactory; // LoggerFactory 클래스 불러오기

  public class LogTest {
  // Logger 객체 만들기 : 클래스(즉, 자바파일)마다 한개 씩 존재
	private static final Logger LOG = LoggerFactory.getLogger(LogTest.class);

	// main 메서드에서 간단한 로그 메시지 처리 확인
	public static void main(String[] args) {
		String msg = "HELLO LOG";
    String msg = "HELLO LOG";
		LOG.info("test log");
		LOG.warn("TEST LOG : {}", msg);
		LOG.debug("debug level test");
		LOG.trace("trace level test");
	 }
  }

SLF4J에서는 { } 중괄호를 사용하여 매개변수 형식처럼 중괄호 안에 msg가 출력되게 할 수 있습니다.

Eclipse LOG 설정

LOG를 사용하기 위해서 Sysout + Ctrl + Space와 같은 방식으로 LOG + Ctrl + Space
자동생성 기능을 만들 수 있습니다.

  • Eclipse - Winodw - Preference - Java - Editor - Templates 클릭

log1

여기서 New를 클릭하고 다음 코드를 추가합시다.

log2

  ${:import(org.slf4j.Logger,org.slf4j.LoggerFactory)}private static final Logger LOG = LoggerFactory.getLogger(${enclosing_type}.class);

소스코드 : Stack Overflow

이제 클래스를 생성하고 LOG를 입력한 뒤에 Ctrl + Space 클릭하고 LOG Template를 클릭합니다.

log3

Log4j 설정

  • log4j.xml 주요 요소
종류 특징
root logger를 정의. (기본 로그 설정)
관리할 로거를 정의 패키지별 로그 레벨에 따른 로거 이름 설정
root에서 설정한 appender 이름에 대한 실제적인 appender 레이아웃 등을 지정

root와 logger는 다음과 같은 속성을 가지고 있습니다.
level : FATAL, ERROR, WARN, INFO, DEBUG, appender-ref : 해당 appender의 세부 설정을 할 때 사용할 이름

  • appender 주요 클래스 종류
종류 특징
ConsoleAppender 콘솔에 로그 메시지를 출력
FileAppender 파일에 로그 메시지를 기록
RollingFileAppender 파일에 로그 메시지를 기록하고, 파일 크기가 일정 수준 이상이 되면 다른 이름으로 저장하고 기록
DailyRollingFileAppender 파일에 로그 메시지를 기록하고, 하루 단위로 로그 파일을 변경해서 저장
SMTPAppender 로그 메시지를 이메일로 전송
NTEventLogAppender NT 시스템 이벤트 로그로 메시지를 전송.
  • layout 클래스 종류
종류 특징
DateLayout 로그 메시지를 날짜 중심으로 간단하게 기록
HTMLLayout 로그 메시지를 HTML 형식으로 기록
PatternLayout 로그 메시지를 사용자 지정 패턴에 따라 기록
SimpleLayout 레벨-메시지 형식의 가장 간단한 로그를 기록
XMLLayout 로그 메시지를 XML 형식으로 기록
  • PatternLayout
종류 특징
%c 카테고리를 출력
%p 로깅 레벨을 출력
%m 로그 내용을 출력
%d 로깅 이벤트가 발생한 시간. yyyy-MM-dd, HH:mm:ss과 같은 시간 형식을 사용
%t 로그 이벤트가 발생된 스레드의 이름을 출력
%% % 기호를 출력
%n 개행 문자(NEW LINE), 다음 행으로 줄바꿈
%C 클래스 이름을 출력
%F 로깅이 발생한 파일 이름을 출력
%l 로깅이 발생한 호출자 정보를 출력
%L 로깅이 발생한 행의 수를 출력
%M 로깅이 발생한 메소드 이름을 출력
%r 애플리케이션 시작 이후부터 로깅이 발생한 시점의 시간 출력
%x 로깅이 발생한 스레드와 관련된 NDC 출력
%X 로깅이 발생한 스레드와 관련된 MDC 출력
  <appender name="stdout" class="org.apache.log4j.ConsoleAppender">
  <layout class="org.apache.log4j.PatternLayout">
    <param name="ConversionPattern"
      value="[%d{HH:mm:ss}] [%c{1}.%M()] [%p] %m %n" />
  </layout>
  </appender>

로그 레벨 기준 정하기

로그 레벨 기준을 정하는 방법은 사람마다 조금씩 다릅니다.

다음은 kldp.org에 올라와있는 어떤 사람의 기준 방법입니다.

  1. FATAL : 시스템이 더 이상 유지될 수 없을 때.
  2. ERROR : 유지될 수 없을 정도는 아니지만, 분명한 문제가 발생했을 때.
  3. WARN : 자체적으로 해결할 수 있으나 그래도 잘못된 경우 - EX) 형식이 잘못된 입력값(날짜를 입력할 때 yyyy-MM-dd인데 2010-1-21로 입력)
  4. INFO : 특정한 이벤트 포인트. 긴 시간이 걸리는 작업(DB 동기화 등)이 시작되거나 종료될 때.
  5. DEBUG : 메서드의 시작과 끝.
  6. TRACE : 메서드의 시작과 끝 이외에 본문 중에서 디버깅에 필요한 정보를 출력할 때.

다음은 Stack Overflow
올라와있는 다른 사람들이 사용하는 기준을 보겠습니다. 원문은 위 링크를 통해 확인하시면 됩니다. 아래는 번역을 하여 적은 것입니다.

  1. FATAL : 데이터 손실 (또는 추가 데이터 손실)을 방지하기 위해 서비스 또는 응용 프로그램의 종료를 강제하는 오류입니다. 나는 가장 혹독한 오류 및 데이터 손상이나 손실이 보장되는 상황에서만 이러한 내용을 보유합니다.
  2. ERROR : 작업에 치명적인 오류는 있지만 서비스 또는 응용 프로그램 은 오류가 아닙니다 (필요한 파일을 열 수 없거나 데이터 누락 등). 이러한 오류는 사용자 (관리자 또는 직접 사용자)의 개입을 강요합니다. 이들은 일반적으로 잘못된 연결 문자열, 누락 된 서비스 등에 대해 (내 응용 프로그램에서) 예약되어 있습니다.
  3. WARN : 잠재적으로 애플리케이션 기이함을 유발할 수 있지만 자동으로 복구 할 수있는 모든 것. (예 : 1차 서버에서 백업 서버로 전환, 조작 재시도, 2차 데이터 누락 등)
  4. INFO : 일반적으로 로그에 유용한 정보 (서비스 시작/중지,구성 가정 등). 정보 항상 이용 가능하지만 보통 정상적인 상황에서는 신경 쓰지 않고 싶습니다. 이것은 내 구성 설정 수준입니다.
  5. DEBUG : 개발자 (IT, 시스템 관리자 등) 이상의 사람들에게 진단 적으로 도움이되는 정보.
  6. TRACE : 코드를 “추적”하고 함수의 특정 부분 을 구체적 으로 찾으려고 할 때만 .

아래도 Stack Overflow에 나와있는 방식입니다.
아래의 방식이 가장 상세하게 설명이 잘 되어있습니다. 이것을 보고 참고하여 코딩을 하면 될 것 같습니다.

FATAL : 즉시 조사해야하는 전반적인 애플리케이션 또는 시스템 오류. 예, SysAdmin을 깨우십시오. 우리는 SysAdmins 경보를 선호하고 잘 휴식하기 때문에이 심각성은 매우 드물게 사용되어야합니다. 매일 일어나는 일이 BFD가 아니라면 의미가 없어집니다. 일반적으로 치명적인 오류는 프로세스 수명에 한 번만 발생하므로 로그 파일이 프로세스에 연결되어 있으면 일반적으로 로그의 마지막 메시지입니다.

ERROR : 조사해야 할 문제입니다. SysAdmin은 자동으로 알림을 받아야하지만 침대 밖으로 끌 필요가 없습니다. 로그를 필터링하여 오류 및 그 이상을 살펴봄으로써 오류 빈도에 대한 개요를 얻고 추가 ​​오류가 연속적으로 발생했을 수있는 오류를 신속하게 식별 할 수 있습니다. 애플리케이션 사용률 대비 오류율을 추적하면 전반적인 품질을 평가하는 데 사용할 수있는 MTBF와 같은 유용한 품질 메트릭을 얻을 수 있습니다. 예를 들어이 측정 항목은 릴리스 전에 다른 베타 테스트주기가 필요한지 여부를 결정하는 데 도움이 될 수 있습니다.

WARN : 문제가 있거나 그렇지 않을 수 있습니다. 예를 들어 네트워크 또는 데이터베이스 연결이 잠시 중단되는 것과 같이 예상되는 일시적인 환경 조건은 경고가 아닌 오류로 기록되어야합니다. 경고 및 오류 만 표시하도록 필터링 된 로그를 보면 후속 오류의 근본 원인에 대한 초기 힌트를 신속하게 파악할 수 있습니다. 경고는 의미가 없어지지 않도록주의해서 사용해야합니다. 예를 들어, 네트워크 액세스 손실은 서버 응용 프로그램의 경고 또는 오류 일 뿐이지 만 가끔 연결이 끊긴 랩톱 사용자를 위해 설계된 데스크톱 응용 프로그램의 정보 일뿐입니다.

INFO : 성공적인 초기화, 서비스 시작 및 중지 또는 중요한 트랜잭션의 성공적인 완료와 같은 정상적인 조건에서 기록되어야하는 중요한 정보입니다. Info 이상을 표시하는 로그를 보면서 발생하는 모든 경고 또는 오류를 이해할 수있는 최상위 컨텍스트를 제공하는 프로세스의 주요 상태 변경 사항에 대한 간략한 개요를 제공해야합니다. Info 메시지가 너무 많지 않아야합니다. 일반적으로 Trace에 비해 <5 % Info 메시지가 있습니다.

DEBUG : 우리는 Debug <Trace를 고려합니다. 차이점은 디버그 메시지가 릴리스 빌드에서 컴파일된다는 것입니다. 즉, 우리는 디버그 메시지의 사용을 권장하지 않습니다. 디버그 메시지를 허용하면 점점 더 많은 디버그 메시지가 추가되거나 제거되지 않습니다. 시간이 지나면 로그 파일을 거의 쓸모 없게 만듭니다. 소음에서 신호를 필터링하기가 너무 어렵 기 때문입니다. 그것은 devs가 죽음을 나선을 계속하는 로그를 사용하지 못하게합니다. 반대로, 추적 메시지를 지속적으로 제거하면 개발자는이를 사용하여 덕이있는 나선형을 만들 수 있습니다. 또한 릴리스 빌드에 포함되지 않은 디버그 코드에 필요한 부작용으로 인해 버그가 발생할 가능성을 없애줍니다. 그래, 나는 좋은 코드에서 발생해서는 안된다는 것을 알고있다.

TRACE : 추적은 가장 일반적으로 사용되는 심각도이며 오류 및 경고를 유발하는 단계를 이해하는 데 필요한 정보를 제공해야합니다. Trace 메시지의 정확한 밀도를 유지하는 것은 소프트웨어를 훨씬 더 유지 관리 할 수 ​​있지만 프로그램이 발전함에 따라 개별 Trace 문이 값이 변할 수 있으므로 약간의 노력이 필요합니다. 이를 달성하는 가장 좋은 방법은 dev 팀이 로그를 정기적으로 검토하는 습관을 가지고 고객이보고 한 문제를 해결하는 표준 부분으로 삼는 것입니다. 팀이 더 이상 유용한 컨텍스트를 제공하지 않는 추적 메시지를 제거하고 후속 메시지의 컨텍스트를 이해하는 데 필요한 곳에 메시지를 추가하도록 팀에 권장하십시오. 예를 들어, 디스플레이 또는 탭 변경과 같은 사용자 입력을 로깅하는 것이 종종 도움이됩니다.