회고록

logging (Log4j2)

sehunbang 2024. 4. 18. 16:58

AOP 정의 (복습)

Spring AOP(Aspect-Oriented Programming)는 Spring 프레임워크의 핵심 기능 중 하나로, 관점 지향 프로그래밍을 지원.

 

관점 지향 프로그래밍은 횡단 관심사(cross-cutting concerns)를 모듈화하여 코드 중복을 줄이고 유지보수성을 향상시키는 소프트웨어 개발 방법론.

AOP는 프로그래머가 핵심 비즈니스 로직에서 횡단 관심사를 분리하고, 이를 각각의 모듈화 한것이고.

로깅도 여기에 포함이 됩니다.

 

sout vs logging

1. 로그 데이터가 기록되지 않는다.

2. 에러 발생 시 추적할 수 있는 정보의 부재( 스레드, 시간 등)

3. 로그 레벨설정 불가능

4. 성능저하(synchronized 키워드 붙어있음)

https://0soo.tistory.com/241

 

Java 로깅 logger, log4j, logback, slf4j 비교

로그(log)는 소프트웨어의 이벤트를 시스템의 상태 및 동작 정보를 시간 경과에 따라 기록하는 것을 의미합니다. 소프트웨어 개발 과정 혹은 개발 후에 동작상태를 파악하여 문제가 발생했을 때

0soo.tistory.com

 

logback vs log4j2

lo4j의 다음 버전으로 나왔으며 logback처럼 필터링 기능과 자동 리로딩을 지원합니다.

또한 람다표현식과 사용자 정의 로그 레벨을 지원합니다.

logback과의 큰 차이는 Multi Thread 환경에서 비동기 로거의 경우 다른 로킹 프레임워크보다 많은 처리량과 짧은 대기 시간을 제공합니다.

( spring boot는 기본설정으로 logback을 사용하기 때문에 log4j2를 사용하기 위해서는 logback의존성을 제거해 주는 작업이 필요합니다. )

 

https://tech.forums.softwareag.com/t/difference-between-synchronous-logging-and-asynchronous-logging/177759

 

Difference between synchronous logging and asynchronous logging?

Hi Experts, What is the difference between synchronous logging and asynchronous logging? In which case we should use synchronous logging, in which case we use asynchronous logging? Thank you.

tech.forums.softwareag.com

 

 

AsyncAppender를 적용했을 때 문제가 있을지 장점은 무엇인지:

 

 

TRACE < DEBUG < INFO < WARN < ERROR < FATAL

왼쪽으로 갈 수록 상세한 정보를 출력한다.

 

1 .Log4j2 정의

Log4j2는 Apache Software Foundation이 개발한 자바 기반의 로깅 라이브러리입니다. Log4j2는 다양한 로깅 요구사항을 충족시키며, 고성능 및 구성 가능한 로깅 시스템을 제공합니다. 다음은 Log4j2의 정의와 간단한 예시입니다.

Log4j2의 주요 특징:

  • 다양한 로깅 수준(Level)을 지원하여 디버깅, 정보, 경고, 에러, 치명적 에러 등 다양한 로그 레벨을 다룰 수 있습니다.
  • 다양한 로그 메시지 형식을 지원하여 로그 메시지를 원하는 형식으로 출력할 수 있습니다.
  • 로그 메시지의 동적인 생성을 위한 매개변수화된 로깅을 지원합니다.
  • 다양한 출력 대상에 로그를 전달할 수 있도록 지원합니다. 파일, 콘솔, 데이터베이스 등 다양한 대상에 로그를 출력할 수 있습니다.
  • 비동기 로깅을 지원하여 로깅 작업이 애플리케이션의 성능에 미치는 영향을 최소화할 수 있습니다.
  • 구성 파일을 통한 유연한 로깅 설정을 지원합니다.

Log4j2 구성과 예시

출처 : https://loosie.tistory.com/831

 

[Spring] 스프링 부트에서 로그(Log) 사용하기2 - Log4j2 (Sync, Async Appender, Async Logger)

스프링 부트에서 Log4j2 사용하기 Log4j2는 Apache의 log4j의 다음 버전이며 가장 최근에 등장한 프레임워크이다. 이는 Logback와 동일하게 자동 리로드와 필터링 기능을 제공하고 이 외에도 Java8부터 도

loosie.tistory.com

 

log4j2를 사용하기 위해서는 build.gradle 파일에서 해당 라이브러리를 삭제하고 Log4j2 라이브러리 의존성을 추가해줘야 한다.

 

 //log4j2 logging
implementation 'org.springframework.boot:spring-boot-starter-log4j2'

 

configurations {
    all {
        exclude group: 'org.springframework.boot', module: 'spring-boot-starter-logging'
    }
}

 

log xml: 

 

<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="INFO">
  <Properties>
    <Property name="LOG_PATH">logs</Property>
    <Property name="DEFAULT_PATTERN">[%d{yyyy-MM-dd HH:mm:ss.SSS}] %5p ${sys:PID} --- [%15.15t] %-40.40c{1.} : %m%n%xwEx</Property>
    <Property name="COLOR_PATTERN">[%clr{%d{yyyy-MM-dd HH:mm:ss.SSS}}{faint}] %clr{%5p} %clr{${sys:PID}}{magenta} %clr{---}{faint} %clr{[%15.15t]}{faint} %clr{%-40.40c}{cyan} %clr{:}{faint} %m%n%xwEx</Property>
    <Property name="FILE_PATTERN">%d{yyyy-MM-dd}-%i</Property>
    <Property name="LOG_PATTERN">%d{yyyy-MM-dd HH:mm:ss}:%-3relative] %-5level ${PID:-} --- [%15.15thread] %-40.40logger{36} : %msg%n</Property>
  </Properties>

  <!-- CONSOLE에 로그 출력 세팅 -->
  <Appenders>
    <Console name="ConsoleAppender" target="SYSTEM_OUT" follow="true">
      <PatternLayout pattern="${COLOR_PATTERN}"/>
    </Console>

    <RollingFile name ="RollingFileAppender">
      <FileName>${LOG_PATH}/logs.log</FileName>
      <FilePattern>${LOG_PATH}/log.%d{yyyy-MM-dd-hh-mm}.%i.log.gz</FilePattern>
      <PatternLayout>
        <Pattern>${DEFAULT_PATTERN}</Pattern>
      </PatternLayout>
      <Policies>
        <SizeBasedTriggeringPolicy size="500KB"/>
        <!--                <TimeBasedTriggeringPolicy interval = "1" modulate = "true"/>-->
      </Policies>
      <DefaultRolloverStrategy>
        <!-- 삭제에 대한 설정 -->
        <Delete basePath="logs" maxDepth="1">
          <IfAccumulatedFileCount exceeds="10"/>
        </Delete>
      </DefaultRolloverStrategy>
    </RollingFile>

    <RollingFile name ="RollingFileErrorAppender">
      <FileName>${LOG_PATH}/log_error.log</FileName>
      <FilePattern>${LOG_PATH}/log_error.%d{yyyy-MM-dd-hh-mm}.%i.log.gz</FilePattern>
      <PatternLayout>
        <Pattern>${DEFAULT_PATTERN}</Pattern>
      </PatternLayout>
      <Policies>
        <SizeBasedTriggeringPolicy size="500KB"/>
        <!--                <TimeBasedTriggeringPolicy interval = "1" modulate = "true"/>-->
      </Policies>
    </RollingFile>
  </Appenders>


  <Loggers>
    <!-- Root : 일반적인 로그 정책, 반드시 하나 정의해야함 -->
    <Root level="INFO" additivity="false">
      <AppenderRef ref="ConsoleAppender"/>
      <AppenderRef ref="RollingFileAppender"/>
      <AppenderRef ref="RollingFileErrorAppender" level="ERROR" />
    </Root>

    <!-- springframework logger -->
    <Logger name="org.springframework" level="INFO" additivity="false">
      <AppenderRef ref="ConsoleAppender" />
      <AppenderRef ref="RollingFileAppender"/>
    </Logger>

    <!-- jdbc logger -->
    <Logger name="jdbc.sqlonly" level="OFF" additivity="false">
      <AppenderRef ref="ConsoleAppender"/>
      <AppenderRef ref="RollingFileAppender"/>
    </Logger>

    <Logger name="jdbc.sqltiming" level="INFO" additivity="false">
      <AppenderRef ref="ConsoleAppender"/>
      <AppenderRef ref="RollingFileAppender"/>
    </Logger>

    <Logger name="jdbc.resultsettable" level="INFO" additivity="false">
      <AppenderRef ref="ConsoleAppender"/>
      <AppenderRef ref="RollingFileAppender"/>
    </Logger>

    <Logger name="jdbc.audit" level="OFF" additivity="false">
      <AppenderRef ref="ConsoleAppender"/>
      <AppenderRef ref="RollingFileAppender"/>
    </Logger>

    <Logger name="jdbc.resultset" level="OFF" additivity="false">
      <AppenderRef ref="ConsoleAppender"/>
      <AppenderRef ref="RollingFileAppender"/>
    </Logger>

    <Logger name="jdbc.connection" level="OFF" additivity="false">
      <AppenderRef ref="ConsoleAppender"/>
      <AppenderRef ref="RollingFileAppender"/>
    </Logger>
  </Loggers>
</Configuration>

 

 

지난 로그들을 gz (zip) 으로 변경 하는 이유 :

  1. 컴퓨터/서버의 공간 절약 
  2. 1번으로 인한 아주 많은 로그 들을 저장 할수 있다.
  3. 로그 파일을 옴길때(인터넷/네트워크) 더 적은 용량 + 시간 으로 옴길수 있음.

xml 기능들 정리 되어 있는 블로그.

https://velog.io/@bread_dd/Log4j-2-%EC%A0%9C%EB%8C%80%EB%A1%9C-%EC%82%AC%EC%9A%A9%ED%95%98%EA%B8%B0-%EA%B0%9C%EB%85%90

 

Log4j 2 제대로 사용하기 - 개념

log4j2.xml이전 글에서 log4j 2 설정파일을 보여드렸는데요, 각각의 요소가 뭘 의미하는지 알아보도록 할게요Configuration은 로그 설정의 최상위 요소입니다. 일반적으로 Configuration은 Properties, Appenders,

velog.io

 

 

기능 측정 : 

 

1. 일반 테스트 코드 속도 측정 결과. (실제 파일 만드는 시간 까지 포함 입니다.)

25000 개의  로그 를 찍는 함수.

@SpringBootTest
public class LogSpeedTest extends TimeManager{
public void testLogger(){
    for (int i = 0; i < 5000; i++) {
        log.debug("디버그 로그 메시지");
        log.info("정보 로그 메시지");
        log.warn("경고 로그 메시지");
        log.error("에러 로그 메시지");
        log.fatal("치명적 에러 로그 메시지");
    }
}

 

1.1 Log4j2 적용전 :

1.2  Log4j2 적용후.

1.2.1 동기  (sync)

1.2.2  비동기 (Async)

확실히 비동기 처리 를 하니 속도다 빠르다.

 

 

 

2. Jmeter 테스트 결과 

에러 log 를 발생 하게 하는 test 용 api 를 만들었습니다.

 

2.1 로그 2000 쓰레드 2번 작업 의 log 찍는 api 호출 

2.1.1 기존에 logback

 

2.1.2 jog4j2적용후

큰차이는 없어 보입니다만 

 

줄어든 처리 시간 감소

줄어든 표준 편차 

빨리진 처리량 

빨라진 수신/전송 량

 

 

 

 

동기  (sync) vs  비동기 (Async)

그럼 무조권 비동기가 좋은 건가 ? 하면 당연이 그런건 아닙니다.

비동기의 단점 :

(고려해야 하는 사항들이 생각보다 많다)

 

CPU 사용량 증가 : 버퍼를 이용하니 메모리의 사용량이 증가하고 CPU 사용량 또한 증가한다.

 

로그 손실 : 중간에 서버가 shutdown되는 경우에 버퍼에 로그가 남아 있으면 버퍼의 로그를 다 쓰기 전에 종료되어 손실이 발생한다 , queueSize를 너무 작게 하는 경우 WARN, ERROR를 제외하고 로그의 손실을 가져올 수 있다.

 

로그 순서의 불일치: 비동기적 로깅은 로그 작업을 백그라운드에서 처리하므로 호출 순서와 로깅 순서가 일치하지 않을 수 있습니다. 따라서 로그 메시지의 순서가 중요한 경우 문제를 발생시킬 수 있습니다.

 

실행 흐름의 불확실성: 호출자가 로깅 작업의 성공을 즉시 확인할 수 없으므로 로깅 작업이 실패했을 때 즉각적으로 대응하기 어렵습니다.