Spring Boot๋ฅผ ์ด์ฉํด ๊ฐ๋ฐํ๋ฉด @Slf4j ์ด๋ ธํ ์ด์ ์ ์ด์ฉํด ๋ก๊ทธ์ ๋จ๊ธฐ๊ณ Console์ ์ฐํ๋ ๋ก๊ทธ๋ฅผ ์ฐธ๊ณ ํ ์ ์๋ค. ๊ฐ๋ฐํ๊ฒฝ์์๋ ์ถฉ๋ถํ ์ ์์ง๋ง ์ด์ํ๊ฒฝ์์๋ Console์ ์ถ๋ ฅํด๋ณด๋ ๊ฒ์ ๊ทธ์น์ง ์๊ณ ํ์ผ๋ก ๋จ๊ธธ ํ์๊ฐ ์๋ค.
๋ก๊น ์ด ํ์ํ ์ด์ ์ ๋ํด์๋ ์๋ ํฌ์คํ ์ด ์ ์ ๋ฆฌ๊ฐ ๋์ด์์ผ๋ ์ฐธ๊ณ ํ๊ธธ ๋ฐ๋๋ค.
๋ก๊น ์ System.out.println() ๋ก ํ๋ฉด ์๋๋ ์ด์
ํ์ต ๋ฐฐ๊ฒฝ ์ฐํ ์ฝ ๋ ๋ฒจ3 ํํ๋ก์ ํธ 3์ฐจ ๋ฐ๋ชจ๋ฐ์ด ์๊ตฌ์ฌํญ ์ค ํ๋๋ ‘๋๋ฒ๊น ํ ์ ์๋ ๋ก๊ทธ ํ์ผ ์ถ๋ ฅ’ ์ด๋ค. ์ด์ ๊น์ง๋ ๋ก๊น ์ ๋ํด ์ ํ ์ ๊ฒฝ์ฐ์ง ์๊ณ ์์๋๋ฐ, ์ฌ์ฌ ๋ก๊น ์๋ ์ ๊ฒฝ์จ
hudi.blog
Slf4j vs Log4j
๋จผ์ ๊ฐ๊ฐ์ ์ฐจ์ด์ ๋ํด ์ดํด๋ณด๊ธฐ ์ํด์๋ `Slf4j`์ `๋๋จธ์ง`๋ฅผ ๋ถ๋ฆฌํด์ ๋ณผ ํ์๊ฐ ์๋ค. Slf4j๋ Sl4fj๋ Simple Logging Facade for Java์ ์ฝ์๋ก ๋ก๊น ์ ์ํ Java API์ด๋ค. ๋น์ฐํ๊ฒ๋ ๋ณ๋์ ๊ตฌํ์ฒด๊ฐ ํ์ํ๊ณ Log4j์ Logback์ด ๊ตฌํ์ฒด์ ์ญํ ์ ํ๋ค. Spring Boot๋ฅผ ์ฌ์ฉํ๋ฉด spring-boot-starter-logging ๋ด์ Slf4j์ Logback์ด ๊ธฐ๋ณธ์ผ๋ก ํฌํจ๋๋ค.
๋ผ์ด๋ธ๋ฌ๋ฆฌ ์ ํ ์ ๊ณ ๋ ค์ฌํญ
๋ก๊น ์ ๋จ๊ธฐ๋ ๊ฒ์ ํ์์ ์ด๋ฏ๋ก ์ด๋ค ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ฌ์ฉํ๋๋๊ฐ ๊ต์ฅํ ์ค์ํ๋ค. ๋ผ์ด๋ธ๋ฌ๋ฆฌ ์ ํ ๊ธฐ์ค์ `์ฑ๋ฅ`๊ณผ `๊ธฐ๋ฅ`์ ๊ด์ ์์ ๊ณ ๋ คํด๋ณผ ์ ์์ ๊ฒ์ธ๋ฐ, ์ฑ๋ฅ ๊ด์ ์ ์ค์ฌ์ผ๋ก ์์๋ณด์.
์ผ์ ์๊ฐ๋์ ์ถ๋ ฅ๋๋ ๋ฉ์ธ์ง์ ์ด๋์ธ `Throughput`๊ณผ ๋ฉ์ธ์ง๋ฅผ ํ๋ฒ ์ถ๋ ฅํ๋ ๋ฐ์ ๊ฑธ๋ฆฌ๋ ์๊ฐ์ธ `Response Time`๋ฅผ ๊ณ ๋ คํด์ผ ํ๋ค. ์ด์์ ์ธ ์ํฉ์ ๋์ Throughput, ๋ฎ์ Response Time์ ์ค๋ ์ ์งํ๋ ๊ฒ์ด๋ค. ์ด๋ ๊ทธ๋ฆฌ ๊ฐ๋จํ ๋ฌธ์ ๋ ์๋๋ค.
๋น๋๊ธฐ ๋ก๊น ์์ Throughput๊ณผ Response Time์ ๊ฒฐ์ ์ง๋ ๊ฐ์ฅ ์ค์ํ ์์๋ ๋๊ธฐ ์์ ์ ์ ์ฅํ๋ Queue๋ผ๊ณ ํ ์ ์๋ค. Queue์ ํฌ๊ธฐ๊ฐ ํด์๋ก ๋ฒํผ๋ง์ ํตํด ๋ง์ ๋ก๊น ์ด๋ฒคํธ๋ฅผ ํ๋ฒ์ ์ฒ๋ฆฌํ ์ ์๊ณ ๋์ Throughput์ ์ ์งํ ์ ์๋ค. ํ์ง๋ง Queue์ ํฌ๊ธฐ๊ฐ ๋๋ฌด ํฌ๋ฉด ๋ฒํผ๋ง๋ ์ค๋ ๊ฑธ๋ฆด ๊ฒ์ด๊ณ Response Time๋ ํจ๊ป ๋์์ง ๊ฒ์ด๋ค. ๋ฟ๋ง ์๋๋ผ ๋ง์ ๋ฉ๋ชจ๋ฆฌ๋ฅผ ์ฌ์ฉํด์ผ ํ๋ค๋ ๋ฌธ์ ๋ ์๋ค.
์ฌ๊ธฐ์ ๋ํ ์ผ๋ฐ์ ์ผ๋ก ๋ก๊น ์์ ์ ์ฌ๋ฌ ์ค๋ ๋ ๊ฐ์ ๊ฒฝํฉ์ด ์์ฃผ ๋ฐ์ํ๋ค๊ณ ํ๋ค. Race Condition์ ์ด๋ป๊ฒ ์ฒ๋ฆฌํ ๊ฒ์ธ๊ฐ๋ ์ค์ํ ๋ถ๋ถ์ด๋ค.
Log4j2๋ฅผ ์ฌ์ฉํ๋ ์ด์
- Logger: ๋ก๊ทธ ์ด๋ฒคํธ ์์ฑ๊ธฐ
- Appender: ๋ก๊ทธ ์ถ๋ ฅ๊ธฐ
์๋ Log4j, Log4j2, Logback์ Thread ์์ ๋ํ ๋ก๊น ์ฒ๋ฆฌ๋์ ๋น๊ตํ ๊ทธ๋ํ์ด๋ค. ArrayBlockingQueue๋ฅผ ์ฌ์ฉํ๋ Async Appender๋ฅผ ์ฌ์ฉํ ์ฑ๋ฅ์ ํฌ๊ฒ ์ฐจ์ด๊ฐ ์์ง๋ง, Log4j2์์ ์ง์๋๋ Lock-free ๊ตฌ์กฐ๋ฅผ ์ฌ์ฉํ๋ฉด Thread ์์ ๋น๋กํด Peak Throughput์ด ์ฆ๊ฐํ๋ ๊ฒ์ ๋ณผ ์ ์๋ค.
Lock-free ๊ตฌ์กฐ๋
CAS(Compare And Swap)๊ณผ ๊ฐ์ ์์์ ์ฐ์ฐ์ ์ฌ์ฉํด ๋ณ๋์ ๋ฎคํ ์ค, ์ธ๋งํฌ์ด์ ๊ฐ์ Lock ๋ฉ์ปค๋์ฆ ์์ด๋ ๋ค์ค ์ค๋ ๋ ํ๊ฒฝ์์ ์์ ํ ์๋ฃ๊ตฌ์กฐ๋ฅผ ์๋ฏธํ๋ค. Lock์ด ์๊ธฐ ๋๋ฌธ์ ๋น ๋ฅด๋ฉฐ ๊ต์ฐฉ์ํ๋ฅผ ํผํ ์ ์๋ค.
์ ๊ทธ๋ํ๋ ์ด๋น 64,000๊ฐ์ ๋ฉ์์ง๋ฅผ 4๊ฐ์ ์ค๋ ๋๊ฐ ๋์์ ๋ก๊น ํ๋ ์ํฉ์ ๋ํ ๊ทธ๋ํ์ด๋ค. ์ด๋ฌํ ์ํฉ์์ ๊ฐ์ฅ ํฐ ์๋ต์๊ฐ ์ง์ฐ์ ์์ธ์ Minor GC์ธ๋ฐ, Log4j2์์ ์ง์๋๋ Garbage-free Logger๋ฅผ ์ฌ์ฉํ๋ฉด ์๋ต์๊ฐ ์ง์ฐ์ด ๊ฑฐ์ ๋ฐ์ํ์ง ์๋ ๊ฒ์ ๋ณผ ์ ์๋ค.
Log4j2 ์ฌ์ฉ ์ ๊ณ ๋ ค์ฌํญ
๋ฌผ๋ก ์ด๋ค Appender๋ฅผ ์ฐ๋๋, ์ด๋ค Logger๋ฅผ ์ฐ๋๋์ ๋ฐ๋ผ ์ฑ๋ฅ์ ์ธ ์ฐจ์ด๊ฐ ํฌ๊ฒ ๋์ง ์๊ฑฐ๋ ์คํ๋ ค ๋ ๋๋ฆฐ ๊ฒฝ์ฐ๋ ์กด์ฌํ๋ค. ํนํ Async Logger๋ฅผ ์ฌ์ฉํ๋ฉด ๋ก๊น ์ค๋ ๋์ ์์ ์ค๋ ๋์ ๋ถ๋ฆฌ๋์ด ์๊ธฐ ๋๋ฌธ์ ๋ก๊น ์์ ์ค์ ๋ฐ์ํ ์์ธ๋ ์์ค๋ ์ ์๋ค.
๋ฐ๋ผ์ Log4j2๊ฐ ๋ฌด์กฐ๊ฑด ์ข๋ค๋ ๋ฏฟ์์ ๊ฐ๊ธฐ ๋ณด๋ค ์ฌ๋ฐ๋ฅธ ์ค์ ๋ฐฉ๋ฒ์ ์ ์๊ณ ์ฌ์ฉํ๋ ๊ฒ์ด ๊ฐ์ฅ ์ค์ํ๋ค.
Log4j2 + Yaml ์ด์ฉํด ๋ก๊ทธ ํ์ผ ๋จ๊ธฐ๊ธฐ
1. ์์กด์ฑ ์ค์
`build.gradle`
configurations {
compileOnly {
extendsFrom annotationProcessor
}
configureEach {
exclude group: 'org.springframework.boot', module: 'spring-boot-starter-logging'
}
}
dependencies {
// Logging
implementation 'org.springframework.boot:spring-boot-starter-log4j2'
implementation 'com.fasterxml.jackson.dataformat:jackson-dataformat-yaml'
implementation 'com.lmax:disruptor:3.4.4'
}
๋จผ์ log4j ์์กด์ฑ์ ์ถ๊ฐํ๊ณ ๊ธฐ์กด์ spring boot ๋ก๊น ๋ชจ๋์ ๋ฐฐ์ ํด์ค์ผ ํ๋ค. yaml์ ์ฌ์ฉํ๊ธฐ ์ํด์๋ dataformat ์์กด์ฑ์ด ์ถ๊ฐ๋ก ํ์ํ๊ณ , AsyncLogger๋ฅผ ์ฌ์ฉํ๊ธฐ ์ํด์๋ disruptor ์์กด์ฑ์ด ์ถ๊ฐ๋ก ํ์ํ๋ค.
๋ฒ์ ํธํ์ฑ ์ด์
์ฌ๊ธฐ์ ์ ์ํ ์ ์ disruptor์ log4j์ ๋ฒ์ ํธํ์ฑ์ด๋ค. ํ์ฌ(2024.02.08) ๊ธฐ์ค์ผ๋ก `log4j-core 3.0.0-beta`๊ณผ `disruptor 4.0.0`์ด ์ต์ ๋ฒ์ ์ด, `spring-boot-starter-log4j2`๋ ๋ค์ ๋ฒ์ ์ log4j๋ฅผ ์ถ๊ฐํ๋ค.
๋ง์ฝ `log4j-core:2.x`๊ณผ `disruptor 4.0.0`์ ์กฐํฉํด ์ฌ์ฉํ ๊ฒฝ์ฐ ๋ค์๊ณผ ๊ฐ์ ์์ธ๊ฐ ๋ฐ์ํ ์ ์๋ค. `log4j-core:2.x`๋ฒ์ ์ ๊ฒฝ์ฐ, `disruptor-3.x` ๋ฒ์ ๊ณผ ํธํ์ด ๋๋ ๊ฒ์ผ๋ก ๋ณด์ด๋ฏ๋ก ์ด ์ ์ ์ํด์ ์ค์ ํ๊ธฐ ๋ฐ๋๋ค.
Support for com.lmax:disruptor:4 · Issue #1829 · apache/logging-log4j2
Description When I run with async logger and com.lmax:disruptor:4, I get the following error: Exception in thread "main" java.lang.NoClassDefFoundError: com/lmax/disruptor/SequenceReportingEventHan...
github.com
(๋ ์์ธํ ๋ด์ฉ์ log4j2 ๊นํ๋ธ ํ์ด์ง์ ๋ฑ๋ก๋ ์ด์ ์ฐธ๊ณ )
2. ๋ก๊น ์ค์
`application.yml`
logging:
config: classpath:log4j2/log4j2.yml
log4j2- Properties
Configutation:
name: Anchor
Properties:
Property:
- name: "log-path"
value: "./logs"
- name: "charset-UTF-8"
value: "UTF-8"
- name: "console-layout-pattern"
value: "%style{%d}{White} %highlight{%-5level} [%style{%t}{bright,blue}-%c{1}] %style{%C}{bright,yellow}: %msg%n%throwable"
- name: "file-layout-pattern"
value: "%d %-5level [%t :: %c] %C: %msg%n%throwable"
Properties๋ ํ์ผ ๋ด์์ ์ฌ์ฉ๋๋ ํ๊ฒฝ ๋ณ์๋ก ์ฌ์ฌ์ฉ๋๋ ๊ฐ๋ค์ ๋ํด ๋ฏธ๋ฆฌ ์ ์ํด๋์ ๊ฒ์ด๋ค. ๋ ์ฌ๊ฒจ๋ณผ ๊ฒ์ layout-patter์ผ๋ก ๊ฐ ๋ฌธ์๊ฐ ์๋ฏธํ๋ ๋ฐ๋ ๋ค์๊ณผ ๊ฐ๋ค.
- %d: ๋ก๊ทธ ๋ฐ์ ์๊ฐ
- %c: ๋ก๊ทธ ๋ฐ์ ๋ก๊ฑฐ๋ช
- %C: ๋ก๊ทธ ๋ฐ์ ํด๋์ค๋ช
- %t: ๋ก๊ทธ ๋ฐ์ ์ค๋ ๋๋ช
- %msg: ๋ก๊ทธ ๋ฉ์ธ์ง
- %throwable: ์์ธ ๋ก๊ทธ ๋ด์ฉ
- %style{pattern}{ANSI style}: ANSI๋ฅผ ์ด์ฉํ ์คํ์ผ๋ง
log4j2- Appenders
Appenders:
Console:
- name: console-appender
target: SYSTEM_OUT
PatternLayout:
pattern: ${console-layout-pattern}
RollingFile:
name: rolling-file-appender
fileName: ${log-path}/rolling-file.log
filePattern: "${log-path}/archive/rollingFile.log.%d{yyyy-MM-dd_hh:mm}_%i.gz"
immediateFlush: "false"
PatternLayout:
charset: ${charset-UTF-8}
pattern: ${file-layout-pattern}
Policies:
SizeBasedTriggeringPolicy:
size: "1MB"
TimeBasedTriggeringPolicy:
interval: "1"
DefaultRollOverStrategy:
max: "10"
fileIndex: "max"
์ถ๋ ฅํ ๋์์ ์ง์ ํ๋ Appenders๋ฅผ ์ค์ ํ ๊ฒ์ด๋ค. ๋จผ์ Console์ ์์ฑํ ๋ ์ด์์ ํจํด์ผ๋ก System.out ๋ฐฉ์์ ํตํด ์ถ๋ ฅํ๋ ๊ฒ์ ์๋ฏธํ๋ค. (Target ์ต์ ์ ์๋ ์ฌ์ง์ ์ฐธ๊ณ .)
๋ค์์ผ๋ก RollingFile์ fileName์ผ๋ก ํ์ผ์ ๋ง๋ค์ด ์ ์ฅํ๊ณ , ํด๋น ํ์ผ์ด 200KB๋ฅผ ๋๊ธฐ๊ฑฐ๋ 1์ผ์ ๋๊ธฐ๋ฉด filePattern์ผ๋ก ํ์ผ์ ์์ถ ์ ์ฅํ๊ฒ ๋ค๋ ๊ฒ์ ์๋ฏธํ๋ค. ๊ทธ๋ฆฌ๊ณ ์์ถ ํ์ผ์ ์ต๋ 30๊ฐ๊น์ง ์ ์ง๋๋ค๊ฐ 30๊ฐ๊ฐ ๋์ด๊ฐ๋ฉด ์ญ์ ๋๋ค.
log4j2- Loggers
Loggers:
Root:
level: INFO
AppenderRef:
- ref: console-appender
Logger:
- name: com.anchor
additivity: "false"
level: DEBUG
AppenderRef:
- ref: console-appender
AsyncLogger:
- name: p6spy
level: INFO
AppenderRef:
- ref: rolling-file-appender
- name: com
level: INFO
AppenderRef:
- ref: rolling-file-appender
- name: org
level: INFO
AppenderRef:
- ref: rolling-file-appender
Root๋ ๋ชจ๋ ๋ก๊ทธ์ ๋ํ ๊ธฐ๋ณธ ์ค์ ์ด๋ค. console-appender๋ฅผ ์ด์ฉํด INFO ๋ ๋ฒจ ๋ก๊ทธ๋ง ์ถ๋ ฅํ๋ ๊ฒ์ ๊ธฐ๋ณธ์ผ๋ก ์ง์ ํ๋ค. Logger๋ Root์ ๋ณ๊ฐ๋ก ๋์ํ๋ ์ค์ ์ด๋ค. com.anchor ํจํค์ง์์ ๋ฐ์์ํค๋ ๋ก๊ทธ๋ ์์ธ์ ์ผ๋ก DEBUG ๋ ๋ฒจ ๋ก๊ทธ๋ฅผ ์ถ๋ ฅํ๋๋ก Logger๋ฅผ ํ๋ ๋ ํ ๋นํ๋ค.
AsyncLogger๋ ๋ก๊น ์ ๋น๋๊ธฐ ๋ฐฉ์์ผ๋ก ์ฒ๋ฆฌํ๋ ์ค์ ์ด๋ค. `p6spy`, `com.*`, `org.*`ํจํค์ง์์ ๋ฐ์์ํค๋ ๋ก๊ทธ๋ rolling-file-appender๋ฅผ ์ด์ฉํด INFO ๋ ๋ฒจ ๋ก๊ทธ๋ฅผ ๋ฐฉ์์ผ๋ก ์ถ๋ ฅํ๋๋ก ์ง์ ํ๋ค.
์ฐธ๊ณ ์ฌํญ
โ `name` ํ๋๋ `%c (๋ก๊ทธ ๋ฐ์ ๋ก๊ฑฐ๋ช )`์ ๋งคํ๋๋ค. โก ์ฒ์์๋ ๋ก๊ฑฐ๋ช ์ Console์ ์ถ๋ ฅํด๋ณด๊ณ ์ค์ ํ๋๊ฒ ์ข๋ค.
โ DEBUG ๋ ๋ฒจ์ ๋ก๊ทธ๋ ์๊ฐ๋ณด๋ค ๋ง์ ์ฉ๋์ ์ฐจ์งํ๋ค. โก ์ ๋ง ์ค์ํ ์ ๋ณด๊ฐ ์๋๋ผ๋ฉด ๋ถํ์ํ ์์์ ๋ญ๋นํ ์ ์๋ค.
3. ํ ์คํธ ๊ฒฐ๊ณผ
Log4j – Log4j 2 Asynchronous Loggers for Low-Latency Logging - Apache Log4j 2
Asynchronous Loggers for Low-Latency Logging Asynchronous logging can improve your application's performance by executing the I/O operations in a separate thread. Log4j 2 makes a number of improvements in this area. Asynchronous Loggers are a new addition
logging.apache.org
Log4j – Performance
Performance Apart from functional requirements, an important reason for selecting a logging library is often how well it fulfills non-functional requirements like reliability and performance. This page compares the performance of a number of logging framew
logging.apache.org
Difference between AsyncLogger and AsyncAppender in Log4j2
I have understanding that AsyncAppender do the appending job in a separate thread. They use ArrayBlockingQueue for this purpose. AND AsyncLogger uses LMAX disruptor library to move logging event fr...
stackoverflow.com
[springboot] Spring Boot project ์์ํ๊ธฐ, log4j2 + yml
์ด๋ฒ ํฌ์คํ ์์๋ Spring Boot Project ์ log4j2 ๋ฅผ ์ค์ ํด๋ณด๊ฒ ์ต๋๋ค. ํ๋ก์ ํธ๋ฅผ ์์ฑํ๋ ๋ฐฉ๋ฒ์ ์ด์ ํฌ์คํธ๋ฅผ ์ฐธ๊ณ ํด์ฃผ์๊ธธ ๋ฐ๋๋๋ค. ๊ตฌํ ํ๊ฒฝ ์ข ๋ฅ ๋ฒ์ OS M1 Mac(Monterey 12.4) IDE Intellij(2022.1.2) J
olkkani.github.io
[Java] Spring Boot Log4j2 ์ดํดํ๊ธฐ -2 : ๋น๋๊ธฐ ๋ก๊น (Asynchronous Loggers)
ํด๋น ๊ธ์์๋ Spring Boot ํ๊ฒฝ์์ Log4j2๋ฅผ ์ด์ฉํ์ฌ ๋น๋๊ธฐ ๋ก๊น ์ ๋ํด ์ดํดํ๊ณ ์ฌ์ฉํ๋ ๋ฐฉ๋ฒ์ ๋ํด ์์๋ด ๋๋ค. ๐ก [์ฐธ๊ณ ] Log4j2์ ๋ํด ์์ธํ๊ฒ ๊ถ๊ธํ์๊ฑฐ๋ ๋๊ธฐ์ ๋ก๊น ์ ์ํ์๋ฉด ์
adjh54.tistory.com
'๐ง๐ปโ๐ป ๊ฐ๋ฐ > Java & Spring' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
๋ก์ปฌ์์ DB ์ด์คํ ๊ตฌ์ถํ๊ธฐ (with Docker, MySQL) (0) | 2024.02.15 |
---|---|
Scouter ๋ชจ๋ํฐ๋ง ํด ์ฌ์ฉํด๋ณด๊ธฐ (0) | 2024.02.14 |
Spring AOP - Master & Slave DB ์ฟผ๋ฆฌ ๋ถ์ฐํ๊ธฐ (0) | 2024.02.05 |
DB ์ด์คํ ๊ตฌ์ถํ๊ธฐ (with RDS) (0) | 2024.02.05 |
CI/CD ํ๊ฒฝ ๊ตฌ์ถํ๊ธฐ 2ํธ (with Github Actions) (0) | 2024.02.01 |