Spring Boot Logback(๋กœ๊ทธ๋ฐฑ) ์„ค์ •, ์ด ๊ธ€ ํ•˜๋‚˜๋กœ ๋๋‚ด์„ธ์š”!!

spring boot๋Š” ๊ธฐ๋ณธ์ ์œผ๋กœ logback์„ ๊ธฐ๋ณธ ๋กœ๊น… ์‹œ์Šคํ…œ์œผ๋กœ ์ฑ„ํƒํ•˜์—ฌ ์‚ฌ์šฉํ•œ๋‹ค.
logback์€ log4j ํ”„๋กœ์ ํŠธ์˜ ํ›„์† ๋ฒ„์ „์œผ๋กœ log4j 1.x๊ฐ€ ์ค‘๋‹จ๋œ ์ดํ›„ ๋ฒ„์ „์„ ์ด์–ด๋ฐ›์•„ ๋ฐœ์ „์‹œ์ผœ ์™”๋‹ค.
logback-spring.xml ์ž‘์„ฑ์œผ๋กœ spring boot logback์— ๋Œ€ํ•œ ํ™•์žฅ ์„ค์ •์„ ์ œ๊ณตํ•˜์—ฌ ๋กœ๊ทธ๋ฅผ ์ปค์Šคํ…€ํ•˜๊ฒŒ ๊ธฐ๋กํ•  ์ˆ˜ ์žˆ๋‹ค.
์ด๋ฒˆ ํฌ์ŠคํŒ…์—์„œ๋Š” spring boot logback์— ๋Œ€ํ•œ ๋ช‡ ๊ฐ€์ง€ ์ค‘์š”ํ•œ ๋‚ด์šฉ์— ๋Œ€ํ•œ ์„ค๋ช…๊ณผ ์ด๋ฅผ ํ™œ์šฉํ•˜์—ฌ logback ํ™•์žฅ์„ค์ •(logback-spring.xml) ํ•˜๋Š” ๋ฐฉ๋ฒ•์— ๋Œ€ํ•ด์„œ ์ •๋ฆฌํ•ด ๋ณด๊ณ ์ž ํ•œ๋‹ค.

sprng boot logback dependency

org.springframework.boot:spring-boot-starter-logging ์ข…์†์„ฑ์— logback์— ๋Œ€ํ•œ ์ข…์†์„ฑ์ด ํฌํ•จ๋˜์–ด ์žˆ๋‹ค.
org.springframework.boot:spring-boot-starter-logging ์ข…์†์„ฑ์€ org.springframework.boot:spring-boot-starter ์ข…์†์„ฑ์— ํฌํ•จ๋˜์–ด ์žˆ๋‹ค.

Logback Architecture

logback ์•„ํ‚คํ…์ฒ˜๋Š” Logger, Appender, Layout ์„ธ ๊ฐ€์ง€ ํด๋ž˜์Šค๋กœ ๊ตฌ์„ฑ๋œ๋‹ค.
Logger๋Š” ๋กœ๊ทธ ๋ฉ”์‹œ์ง€์˜ ์ฝ˜ํ…์ŠคํŠธ์ด๋‹ค. ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์ด ๋กœ๊ทธ ๋ฉ”์‹œ์ง€๋ฅผ ์ƒ์„ฑํ•˜๊ธฐ ์œ„ํ•ด์„œ ์ƒํ˜ธ ์ž‘์šฉํ•˜๋Š” ํด๋ž˜์Šค๋ฅผ ์˜๋ฏธํ•œ๋‹ค.
Appender๋Š” ๋กœ๊ทธ ๋ฉ”์‹œ์ง€๋ฅผ ์ตœ์ข… ๋Œ€์ƒ์— ๋ฐฐ์น˜ํ•œ๋‹ค. Logger๋Š” ๋‘˜ ์ด์ƒ์˜ Appender๋ฅผ ๊ฐ€์งˆ ์ˆ˜ ์žˆ๋‹ค.
Layout์€ ์ถœ๋ ฅํ•  ๋ฉ”์‹œ์ง€๋ฅผ ์ค€๋น„ํ•˜๋Š” ์—ญํ• ์„ ํ•œ๋‹ค. logback์€ ๋ฉ”์‹œ์ง€ ์„œ์‹ ์ง€์ •์„ ์œ„ํ•œ ์‚ฌ์šฉ์ž ์ง€์ • ํด๋ž˜์Šค ์ƒ์„ฑ์„ ์ง€์›ํ•˜๊ณ  ๊ธฐ์กด ํด๋ž˜์Šค์— ๋Œ€ํ•œ ๊ตฌ์„ฑ ์˜ต์…˜๋„ ์ง€์›ํ•œ๋‹ค.

Logback ๋กœ๊ทธ ๋ ˆ๋ฒจ

logback์—์„œ ์ง€์›ํ•˜๋Š” ๋ ˆ๋ฒจ์€ ์•„๋ž˜์™€ ๊ฐ™๋‹ค.

  • TRACE
  • DEBUG
  • INFO
  • WARN
  • ERROR

๋กœ๊ทธ ๋ ˆ๋ฒจ์€ ch.qos.logback.classic.Level ํด๋ž˜์Šค์— ์ •์˜๋˜์–ด ์žˆ๋‹ค.

Logback ๋กœ๊ทธ ๋ ˆ๋ฒจ ์ƒ์†

Logger์— ๋กœ๊ทธ ๋ ˆ๋ฒจ์ด ํ• ๋‹น๋˜์ง€ ์•Š์€ ๊ฒฝ์šฐ ๋กœ๊ทธ ๋ ˆ๋ฒจ์ด ํ• ๋‹น๋œ ๊ฐ€์žฅ ๊ฐ€๊นŒ์šด ์กฐ์ƒ Logger๋กœ๋ถ€ํ„ฐ ๋ ˆ๋ฒจ์„ ์ƒ์†๋ฐ›๋Š”๋‹ค.
๋ชจ๋“  Logger๊ฐ€ ๋ ˆ๋ฒจ์„ ์ƒ์†๋ฐ›์„ ์ˆ˜ ์žˆ๋„๋ก ํ•˜๊ธฐ ์œ„ํ•ด์„œ root Logger์—๋Š” ํ•ญ์ƒ ํ• ๋‹น๋œ ๋ ˆ๋ฒจ์ด ์žˆ๊ณ  ๋””ํดํŠธ ๋ ˆ๋ฒจ์€ DEBUG๋‹ค.
๋ช‡ ๊ฐ€์ง€ ์˜ˆ์‹œ๋ฅผ ๋“ค์–ด ๋‚ด์šฉ์„ ์‚ดํŽด๋ณด์ž.

์•„๋ž˜ ์˜ˆ์‹œ๋Š”
logback document ๋ฅผ์ฐธ๊ณ ํ•˜์˜€๋‹ค.

์˜ˆ์‹œ 1)

Logger name์ง€์ •๋œ ๋ ˆ๋ฒจ์ ์šฉ๋˜๋Š” ๋ ˆ๋ฒจ
rootDEBUGDEBUG
X์—†์ŒDEBUG
X.Y์—†์ŒDEBUG
X.Y.Z์—†์ŒDEBUG

X, X.Y, X.Y.Z Logger์—๋Š” ๋กœ๊ทธ ๋ ˆ๋ฒจ์ด ํ• ๋‹น๋˜์ง€ ์•Š์•˜๊ธฐ ๋•Œ๋ฌธ์— root Logger์˜ ๋กœ๊ทธ ๋ ˆ๋ฒจ์„ ์ƒ์†๋ฐ›๋Š”๋‹ค.

์˜ˆ์‹œ 2)

Logger name์ง€์ •๋œ ๋ ˆ๋ฒจ์ ์šฉ๋˜๋Š” ๋ ˆ๋ฒจ
rootERRORERROR
XINFOINFO
X.YDEBUGDEBUG
X.Y.ZWARNWARN

๋ชจ๋“  Logger์— ๋กœ๊ทธ ๋ ˆ๋ฒจ์ด ์ง€์ •๋˜์–ด ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ์ƒ์†์€ ์ผ์–ด๋‚˜์ง€ ์•Š๋Š”๋‹ค. ๊ฐ Logger์— ์ง€์ •๋œ ๋กœ๊ทธ ๋ ˆ๋ฒจ์ด ์ ์šฉ๋œ๋‹ค.

์˜ˆ์‹œ 3)

Logger name์ง€์ •๋œ ๋ ˆ๋ฒจ์ ์šฉ๋˜๋Š” ๋ ˆ๋ฒจ
rootDEBUGDEBUG
XINFOINFO
X.Y์—†์ŒINFO
X.Y.ZERRORERROR

X.Y Logger์—๋Š” ๋กœ๊ทธ ๋ ˆ๋ฒจ์ด ์ง€์ •๋˜์ง€ ์•Š์•˜๊ธฐ ๋•Œ๋ฌธ์— ๊ฐ€์žฅ ๊ฐ€๊นŒ์šด ์กฐ์ƒ์ธ X Logger๋กœ๋ถ€ํ„ฐ ๋กœ๊ทธ ๋ ˆ๋ฒจ์„ ์ƒ์†๋ฐ›๋Š”๋‹ค.

์˜ˆ์‹œ 4)

Logger name์ง€์ •๋œ ๋ ˆ๋ฒจ์ ์šฉ๋˜๋Š” ๋ ˆ๋ฒจ
rootDEBUGDEBUG
XINFOINFO
X.Y์—†์ŒINFO
X.Y.Z์—†์ŒINFO

X.Y, X.Y.Z Logger์—๋Š” ๋กœ๊ทธ ๋ ˆ๋ฒจ์ด ์ง€์ •๋˜์ง€ ์•Š์•˜๊ธฐ ๋•Œ๋ฌธ์— ๊ฐ€์žฅ ๊ฐ€๊นŒ์šด ์กฐ์ƒ์ธ X Logger๋กœ๋ถ€ํ„ฐ ๋กœ๊ทธ ๋ ˆ๋ฒจ์„ ์ƒ์†๋ฐ›๋Š”๋‹ค.

๋กœ๊ทธ ๋ ˆ๋ฒจ ์œ ํšจ ๋ฒ”์œ„

์ ์šฉ๋œ ๋กœ๊ทธ ๋ ˆ๋ฒจ q๋ฅผ ๊ฐ€์ง„ Logger์—๊ฒŒ ๋ฐœํ–‰๋œ ๋ ˆ๋ฒจ p์˜ ๋กœ๊ทธ ์š”์ฒญ์„ p >= q์ผ ๋•Œ ํ™œ์„ฑํ™” ๋œ๋‹ค.
logback์— ์ ์šฉ๋œ ๋กœ๊ทธ ๋ ˆ๋ฒจ์˜ ์ •๋ ฌ์€ ์•„๋ž˜์™€ ๊ฐ™๋‹ค.

TRACE < DEBUG < INFO < WARN < ERROR
Plaintext

spring boot ๋กœ๊ทธ๋ฐฑ (logback) ์„ค์ • ๋ฐฉ๋ฒ• - ๋กœ๊ทธ ๋ ˆ๋ฒจ - undefined - ๋กœ๊ทธ ๋ ˆ๋ฒจ ์œ ํšจ ๋ฒ”์œ„
์ถœ์ฒ˜ https://logback.qos.ch/manual/architecture.html

์„ธ๋กœ ์—ด์€ ๋กœ๊ทธ ์š”์ฒญ ๋ ˆ๋ฒจ์ด๊ณ  ๊ฐ€๋กœ ์—ด์€ Logger์— ์ง€์ •๋œ ๋กœ๊ทธ ๋ ˆ๋ฒจ์ด๋‹ค.
Logger์— ์ ์šฉ๋œ ๋ ˆ๋ฒจ์ด TRACE์ธ ๊ฒฝ์šฐ์—๋Š” ๋ชจ๋“  ์š”์ฒญ ๋ ˆ๋ฒจ์— ๋Œ€ํ•ด์„œ ๋กœ๊ทธ๊ฐ€ ๊ธฐ๋ก๋œ๋‹ค.
Logger์— ์ ์šฉ๋œ ๋ ˆ๋ฒจ์ด ERROR์ธ ๊ฒฝ์šฐ์—๋Š” ERRO ์š”์ฒญ ๋ ˆ๋ฒจ์ธ ๊ฒฝ์šฐ์—๋งŒ ๋กœ๊ทธ๊ฐ€ ๊ธฐ๋ก๋œ๋‹ค.

Logback Configuration

Status Data

์ƒํƒœ ๋ฐ์ดํ„ฐ ์ถœ๋ ฅ์„ ํ™œ์„ฑํ™”ํ•˜๋ฉด ์ผ๋ฐ˜์ ์œผ๋กœ logback ๊ด€๋ จ ๋ฌธ์ œ๋ฅผ ์ง„๋‹จํ•˜๋Š”๋ฐ ๋„์›€์ด ๋œ๋‹ค.
๋””์Šคํฌ๊ฐ€ ์ฐจ๊ฑฐ๋‚˜ ๊ถŒํ•œ ์˜ค๋ฅ˜๋กœ ์ธํ•ด ๋กœ๊ทธ ํŒŒ์ผ์„ ์•„์นด์ด๋ธŒ ํ•  ์ˆ˜ ์—†๋Š” ๊ฒฝ์šฐ์™€ ๊ฐ™์ด ๊ตฌ์„ฑ ํ›„์—๋„ ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ๋Š” ๋ฌธ์ œ๋ฅผ ์ง„๋‹จํ•  ์ˆ˜ ์žˆ๋‹ค. ์ด๋ฅผ ์œ„ํ•ด์„œ๋Š” ์•„๋ž˜์™€ ๊ฐ™์ด StatusListener๋ฅผ ๋“ฑ๋กํ•˜์—ฌ logback์— ๋Œ€ํ•œ ์ƒํƒœ ๋กœ๊ทธ๋„ ์ถœ๋ ฅํ•  ์ˆ˜ ์žˆ๋‹ค.

<configuration>
   <!-- Recommendation: place status listeners towards the the top of the configuration file -->
   <statusListener class="ch.qos.logback.core.status.OnConsoleStatusListener" />

   <!-- ... the rest of the configuration file -->

</configuration>
XML

Listener๋Š” <configuration>์˜ ์ƒ๋‹จ์— ๋ฐฐ์น˜ํ•˜์—ฌ ๋“ฑ๋กํ•˜๋Š” ๊ฒƒ์„ ๊ถŒ์žฅํ•œ๋‹ค. ์ถ”๊ฐ€๋กœ OnErrorConsoleStatusListener๋‚˜ OnFileStatusListener๋ฅผ ๋“ฑ๋กํ•  ์ˆ˜ ์žˆ๋‹ค.
debug=true๋ฅผ ์ง€์ •ํ•˜์—ฌ ์œ„ ์„ค์ •์„ ๊ฐ„๋‹จํ•˜๊ฒŒ ์ง€์ •ํ•  ์ˆ˜๋„ ์žˆ๋‹ค.

<configuration debug="true">
...
</configuration>
XML

debug=”true”๋ฅผ ์„ค์ •ํ•œ ๊ฒƒ์€ OnConsoleStatusListener๋ฅผ ์„ค์น˜ํ•œ ๊ฒƒ๊ณผ ๋™์ผํ•˜๋‹ค.
OnConsoleStatusListener๋ฅผ ์„ค์ • ํ›„ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ์‹คํ–‰ํ•˜๋ฉด ์•„๋ž˜์™€ ๊ฐ™์ด logback์— ๋Œ€ํ•œ ์ƒํƒœ ๋กœ๊ทธ๊ฐ€ ์ถœ๋ ฅ๋œ๋‹ค.

15:49:52,466 |-INFO in ch.qos.logback.classic.LoggerContext[default] - This is logback-classic version 1.4.11
15:49:52,467 |-INFO in ch.qos.logback.classic.util.ContextInitializer@4648ce9 - Here is a list of configurators discovered as a service, by rank:
15:49:52,467 |-INFO in ch.qos.logback.classic.util.ContextInitializer@4648ce9 -   org.springframework.boot.logging.logback.RootLogLevelConfigurator
15:49:52,467 |-INFO in ch.qos.logback.classic.util.ContextInitializer@4648ce9 - They will be invoked in order until ExecutionStatus.DO_NOT_INVOKE_NEXT_IF_ANY is returned.
15:49:52,467 |-INFO in ch.qos.logback.classic.util.ContextInitializer@4648ce9 - Constructed configurator of type class org.springframework.boot.logging.logback.RootLogLevelConfigurator
15:49:52,470 |-INFO in ch.qos.logback.classic.util.ContextInitializer@4648ce9 - org.springframework.boot.logging.logback.RootLogLevelConfigurator.configure() call lasted 1 milliseconds. ExecutionStatus=INVOKE_NEXT_IF_ANY
15:49:52,470 |-INFO in ch.qos.logback.classic.util.ContextInitializer@4648ce9 - Trying to configure with ch.qos.logback.classic.joran.SerializedModelConfigurator
...
15:49:52,652 |-INFO in ch.qos.logback.classic.jul.LevelChangePropagator@4ebea12c - Propagating WARN level on Logger[org.apache.coyote.http11.Http11NioProtocol] onto the JUL framework
15:49:52,652 |-INFO in ch.qos.logback.classic.model.processor.LoggerModelHandler - Setting level of logger [org.apache.sshd.common.util.SecurityUtils] to WARN
15:49:52,652 |-INFO in ch.qos.logback.classic.jul.LevelChangePropagator@4ebea12c - Propagating WARN level on Logger[org.apache.sshd.common.util.SecurityUtils] onto the JUL framework
15:49:52,652 |-INFO in ch.qos.logback.classic.model.processor.LoggerModelHandler - Setting level of logger [org.apache.tomcat.util.net.NioSelectorPool] to WARN
15:49:52,652 |-INFO in ch.qos.logback.classic.jul.LevelChangePropagator@4ebea12c - Propagating WARN level on Logger[org.apache.tomcat.util.net.NioSelectorPool] onto the JUL framework
15:49:52,652 |-INFO in ch.qos.logback.classic.model.processor.LoggerModelHandler - Setting level of logger [org.eclipse.jetty.util.component.AbstractLifeCycle] to ERROR
15:49:52,652 |-INFO in ch.qos.logback.classic.jul.LevelChangePropagator@4ebea12c - Propagating ERROR level on Logger[org.eclipse.jetty.util.component.AbstractLifeCycle] onto the JUL framework
15:49:52,652 |-INFO in ch.qos.logback.classic.model.processor.LoggerModelHandler - Setting level of logger [org.hibernate.validator.internal.util.Version] to WARN
15:49:52,652 |-INFO in ch.qos.logback.classic.jul.LevelChangePropagator@4ebea12c - Propagating WARN level on Logger[org.hibernate.validator.internal.util.Version] onto the JUL framework
15:49:52,653 |-INFO in ch.qos.logback.classic.model.processor.LoggerModelHandler - Setting level of logger [org.springframework.boot.actuate.endpoint.jmx] to WARN
15:49:52,653 |-INFO in ch.qos.logback.classic.jul.LevelChangePropagator@4ebea12c - Propagating WARN level on Logger[org.springframework.boot.actuate.endpoint.jmx] onto the JUL framework
15:49:52,653 |-INFO in ch.qos.logback.core.model.processor.AppenderModelHandler - Processing appender named [CONSOLE]
15:49:52,653 |-INFO in ch.qos.logback.core.model.processor.AppenderModelHandler - About to instantiate appender of type [ch.qos.logback.core.ConsoleAppender]
15:49:52,654 |-INFO in ch.qos.logback.core.model.processor.ImplicitModelHandler - Assuming default type [ch.qos.logback.classic.encoder.PatternLayoutEncoder] for [encoder] property
15:49:52,659 |-INFO in ch.qos.logback.classic.model.processor.RootLoggerModelHandler - Setting level of ROOT logger to INFO
15:49:52,659 |-INFO in ch.qos.logback.classic.jul.LevelChangePropagator@4ebea12c - Propagating INFO level on Logger[ROOT] onto the JUL framework
15:49:52,659 |-INFO in ch.qos.logback.core.model.processor.AppenderRefModelHandler - Attaching appender named [CONSOLE] to Logger[ROOT]
15:49:52,659 |-INFO in ch.qos.logback.core.model.processor.DefaultProcessor@2baa8d82 - End of configuration.
15:49:52,659 |-INFO in org.springframework.boot.logging.logback.SpringBootJoranConfigurator@791cbf87 - Registering current configuration as safe fallback point
Plaintext

configuration file ์ž๋™ ์žฌ๋กœ๋”ฉ

<configuration scan="true" scanPeriod="30 seconds" >
  ...
</configuration>
XML

๊ตฌ์„ฑ ํŒŒ์ผ์˜ ๋ณ€๊ฒฝ ์‚ฌํ•ญ์„ ๊ฒ€์ƒ‰ํ•˜๊ณ  ๊ตฌ์„ฑ ํŒŒ์ผ์ด ๋ณ€๊ฒฝ๋˜๋ฉด ์ž๋™์œผ๋กœ ๊ตฌ์„ฑ ์ •๋ณด๋ฅผ ์žฌ๋กœ๋”ฉ ํ•  ์ˆ˜ ์žˆ๋‹ค.
๊ธฐ๋ณธ์ ์œผ๋กœ scan=”true”์ธ ๊ฒฝ์šฐ ๊ฒ€์‚ฌ ์ฃผ๊ธฐ๋Š” 1๋ถ„์ด์ง€๋งŒ scanPeriod ์†์„ฑ์„ ์ง€์ •ํ•˜์—ฌ ๊ฒ€์‚ฌ ์ฃผ๊ธฐ๋ฅผ ์„ค์ •ํ•  ์ˆ˜ ์žˆ๋‹ค.
์‹œ๊ฐ„ ๋‹จ์œ„๋ฅผ ์ง€์ •ํ•˜์ง€ ์•Š์œผ๋ฉด ๋””ํดํŠธ๋กœ ๋ฐ€๋ฆฌ์ดˆ๋กœ ๊ฐ„์ฃผ๋œ๋‹ค.
์ง€์ •ํ•  ์ˆ˜ ์žˆ๋Š” ์‹œ๊ฐ„ ๋‹จ์œ„๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค.

  • milliseconds (ex. 30 milliseconds)
  • seconds (ex. 30 seconds)
  • minutes (ex. 30 minutes)
  • hours (ex. 1 hours)

configuration ํŒŒ์ผ ๊ตฌ์กฐ

configuration ํŒŒ์ผ์˜ ๊ฐ€์žฅ ๊ธฐ๋ณธ์ ์ธ ๊ตฌ์กฐ๋Š” 0๊ฐœ ์ด์ƒ์˜ <appender> ์š”์†Œ์™€ ๊ทธ ๋’ค์— 0๊ฐœ ์ด์ƒ์˜ <logger> ์š”์†Œ, ๊ทธ๋ฆฌ๊ณ  ์ตœ๋Œ€ ํ•˜๋‚˜์˜ <root> ์š”์†Œ๋ฅผ ํฌํ•จํ•˜๋Š” <configuration> ํƒœ๊ทธ ๊ตฌ์กฐ๋‹ค.

spring boot ๋กœ๊ทธ๋ฐฑ (logback) ์„ค์ • ๋ฐฉ๋ฒ• - Logback Configuration - undefined - configuration ํŒŒ์ผ ๊ตฌ์กฐ
configuration ํŒŒ์ผ ๊ตฌ์„ฑ
spring boot ๋กœ๊ทธ๋ฐฑ (logback) ์„ค์ • ๋ฐฉ๋ฒ• - Logback Configuration - undefined - configuration ํŒŒ์ผ ๊ตฌ์กฐ
appender ๊ตฌ์„ฑ

๊ธฐ๋ณธ์ ์ธ configuration ํŒŒ์ผ์˜ ๊ตฌ์กฐ ์˜ˆ์ด๋‹ค.

<configuration>

  <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
    <!-- encoders are assigned the type
         ch.qos.logback.classic.encoder.PatternLayoutEncoder by default -->
    <encoder>
      <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} -%kvp- %msg%n</pattern>
    </encoder>
  </appender>

  <logger name="chapters.configuration" level="INFO"/>

  <!-- Strictly speaking, the level attribute is not necessary since -->
  <!-- the level of the root level is set to DEBUG by default.       -->
  <root level="DEBUG">
    <appender-ref ref="STDOUT" />
  </root>

</configuration>
XML

<configuration> ์š”์†Œ ์•ˆ์— ํ•˜๋‚˜์˜ <appender> ์š”์†Œ์™€ <logger> ์š”์†Œ ๊ทธ๋ฆฌ๊ณ  <root> ์š”์†Œ๊ฐ€ ํฌํ•จ๋˜์–ด ์žˆ๋‹ค.
<appender> ์š”์†Œ ์•ˆ์— ์ •์˜๋œ <encoder> ์š”์†Œ๋Š” ์ธ์Šคํ„ด์Šคํ™”ํ•  encoder ํด๋ž˜์Šค์˜ ์ •๊ทœํ™”๋œ full ์ด๋ฆ„์„ ์ง€์ •ํ•˜๋Š” class ์†์„ฑ์„ ์ง€์ •ํ•˜๋Š”๋ฐ encoder ํด๋ž˜์Šค๊ฐ€ PattenrLayoutEncoder์ธ ๊ฒฝ์šฐ class ์†์„ฑ์„ ์ƒ๋žตํ•  ์ˆ˜ ์žˆ๋‹ค.

context name ์„ค์ •

  • ๋ชจ๋“  Logger๋Š” Logger Context์— ์—ฐ๊ฒฐ๋˜๋Š”๋ฐ ๊ธฐ๋ณธ์ ์œผ๋กœ Logger Context๋Š” “default”๋กœ ์‚ฌ์šฉ๋œ๋‹ค.
  • <contextName> ํƒœ๊ทธ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ Logger Context ์ด๋ฆ„์„ ๋ณ€๊ฒฝํ•  ์ˆ˜ ์žˆ๋‹ค.
  • Logger Context์˜ ์ด๋ฆ„์€ ํ•œ๋ฒˆ ์„ค์ •ํ•˜๋ฉด ๋ณ€๊ฒฝํ•  ์ˆ˜ ์—†๋‹ค.
  • Context ์ด๋ฆ„์„ ์„ค์ •ํ•˜๋Š” ๊ฒƒ์€ ๋™์ผํ•œ ๋Œ€์ƒ์— ๋กœ๊น…ํ•˜๋Š” ์—ฌ๋Ÿฌ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ๊ตฌ๋ถ„ํ•˜๊ธฐ ์œ„ํ•œ ๊ฐ„๋‹จํ•œ ๋ฐฉ๋ฒ•์ด๋‹ค.
<configuration>
  <contextName>myAppContext</contextName>
  ...
</configuration>
XML

๋ณ€์ˆ˜ ์„ค์ •

  • ๋ณ€์ˆ˜๋Š” ๊ตฌ์„ฑ ํŒŒ์ผ ๋‚ด์—์„œ ํ•œ ๋ฒˆ์— ํ•˜๋‚˜์”ฉ ์ •์˜ํ•˜๊ฑฐ๋‚˜ ์™ธ๋ถ€ ์†์„ฑ ํŒŒ์ผ ๋˜๋Š” ์™ธ๋ถ€ ๋ฆฌ์†Œ์Šค์—์„œ ์ผ๊ด„ ๋กœ๋“œ ํ•  ์ˆ˜ ์žˆ๋‹ค.
  • ๋ณ€์ˆ˜๋ฅผ ์ •์˜ํ•˜๋Š” XML ์š”์†Œ๋Š” <property>์ด์ง€๋งŒ logback 1.0.7 ์ด์ƒ์—์„œ๋Š” <variable> ์š”์†Œ์™€ ํ˜ผ์šฉํ•ด์„œ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

๊ตฌ์„ฑ ํŒŒ์ผ ๋‚ด์—์„œ ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•œ ๋‹จ์ผ ๋ณ€์ˆ˜ ์ƒ์„ฑ ์˜ˆ์ด๋‹ค.

<configuration>
  <variable name="USER_HOME" value="/home/sebastien" />
  <appender name="FILE" class="ch.qos.logback.core.FileAppender">
    <file>${USER_HOME}/myApp.log</file>
    ...
</configuration>
XML

๋‹ค์Œ์€ ์™ธ๋ถ€ System property ์†์„ฑ์„ ๋ณ€์ˆ˜๋กœ ์‚ฌ์šฉํ•˜๋Š” ์˜ˆ์ด๋‹ค.

java -DUSER_HOME="/home/sebastien" app
Bash
<configuration>
  <appender name="FILE" class="ch.qos.logback.core.FileAppender">
    <file>${USER_HOME}/myApp.log</file>
    ...
</configuration>
XML

๋‹ค์Œ์€ ๋ณ€์ˆ˜๋ฅผ ์ •์˜ํ•œ ์„ค์ • ํŒŒ์ผ์„ ๋กœ๋“œํ•˜์—ฌ ์‚ฌ์šฉํ•˜๋Š” ์˜ˆ์ด๋‹ค.

src/main/resources/logback.properties ํŒŒ์ผ ์„ค์ •

USER_HOME=/home/sebastien
Plaintext
<configuration>
  <variable file="src/main/resources/logback.properties" />
  <appender name="FILE" class="ch.qos.logback.core.FileAppender">
     <file>${USER_HOME}/myApp.log</file>
     ...
</configuration>
XML

๋‹ค์Œ์€ class path์—์„œ ๋ฆฌ์†Œ์Šค ํŒŒ์ผ์„ ๋กœ๋“œ ํ•˜์—ฌ ์‚ฌ์šฉํ•˜๋Š” ์˜ˆ์ด๋‹ค.

<configuration>
  <variable resource="logback.properties" />
  <appender name="FILE" class="ch.qos.logback.core.FileAppender">
     <file>${USER_HOME}/myApp.log</file>
     ...
</configuration>
XML

variable scope ์†์„ฑ์ด ์žˆ๋Š”๋ฐ 3๊ฐ€์ง€ ์ •์˜๊ฐ€ ์žˆ๋‹ค.

  • local : ๊ตฌ์„ฑ ํŒŒ์ผ์—์„œ ์ •์˜๋œ ์‹œ์ ๋ถ€ํ„ฐ ํ•ด๋‹น ๊ตฌ์„ฑ ํŒŒ์ผ์˜ ํ•ด์„/์‹คํ–‰์ด ๋๋‚  ๋•Œ๊นŒ์ง€ ์กด์žฌํ•œ๋‹ค.
  • context : context์— ํ•ด๋‹น ๋ณ€์ˆ˜๊ฐ€ ์‚ฝ์ž…๋˜๋ฉฐ context๊ฐ€ ์‚ญ์ œ๋  ๋•Œ๊นŒ์ง€ ์œ ์ง€๋œ๋‹ค. ์›๊ฒฉ ํ˜ธ์ŠคํŠธ๋กœ ์ „์†ก๋˜๋Š” ์ด๋ฒคํŠธ๋ฅผ ํฌํ•จํ•˜์—ฌ ๋ชจ๋“  ๋กœ๊น… ์ด๋ฒคํŠธ์—์„œ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.
  • system : JVM์˜ system property์— ์‚ฝ์ž…๋˜๋ฉฐ JVM์ด ์ง€์†๋˜๋Š” ๋™์•ˆ ์œ ์ง€๋œ๋‹ค.

<springProperty> ์š”์†Œ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ scope์„ ์ง€์ •ํ•˜์—ฌ ์‚ฌ์šฉํ•˜๋Š” ๊ฒฝ์šฐ์—๋„ ๋™์ผํ•˜๊ฒŒ ์ ์šฉ๋˜๋Š” ๋“ฏํ•˜๋‹ค.

# application.yml
spring:
  application:
    name: logging-test
YAML
<configuration>
    <springProperty scope="local" name="PKG_NAME" source="spring.application.name" />
    <appender name="APPLICATION" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <file>${LOG_PATH}/${PKG_NAME}.log</file>
        ...
</configuration>
XML

PKG_NAME ๋ณ€์ˆ˜๋Š” local scope๋กœ์จ spring.application.name ์†์„ฑ ๊ฐ’์„ ์‚ฌ์šฉํ•œ๋‹ค.
configuration ํŒŒ์ผ์˜ ๊ตฌ๋ฌธ ๋ถ„์„์ด ์™„๋ฃŒ๋  ๋•Œ๊นŒ์ง€ ์œ ์ง€๋œ๋‹ค.

๋ณ€์ˆ˜์˜ default ๊ฐ’

์™ธ๋ถ€ ์„ค์ • ํŒŒ์ผ์—์„œ ๋ณ€์ˆ˜ ๊ฐ’์„ ์ฃผ์ž…๋ฐ›๊ฑฐ๋‚˜ ํ•˜๋Š” ๊ฒฝ์šฐ ํ•ด๋‹น ์„ค์ •์ด ์ฃผ์ž…๋˜์ง€ ์•Š์€ ๊ฒฝ์šฐ ๋ณ€์ˆ˜์˜ default ๊ฐ’ ํ‘œํ˜„์€ ์•„๋ž˜์™€ ๊ฐ™๋‹ค.

${๋ณ€์ˆ˜๋ช…:-defaultValue}
Plaintext
<configuration>
    <variable resource="logback.properties"/>
    <appender name="APPLICATION" class="ch.qos.logback.core.rolling.RollingFileAppender">
        ...
        <!-- rolling ์ •์ฑ… -->
        <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
            ...
            <maxFileSize>${logging.application.file.max-size:-10MB}</maxFileSize>
            <maxHistory>${logging.application.file.max-history:-7}</maxHistory>
        </rollingPolicy>
    </appender>
</configuration>
XML

class path์— ์žˆ๋Š” logback.properties ํŒŒ์ผ์— logging.application.file.max-size ์„ค์ •์ด ์—†๋Š” ๊ฒฝ์šฐ 10MB ๊ฐ’์œผ๋กœ ๋™์ž‘ํ•œ๋‹ค.
logging.application.file.max-history ์„ค์ •์ด ์—†๋Š” ๊ฒฝ์šฐ 7 ๊ฐ’์œผ๋กœ ๋™์ž‘ํ•œ๋‹ค.

Appender

Appender๋Š” ์‰ฝ๊ฒŒ ๋งํ•ด ๋กœ๊ทธ์˜ ์ถœ๋ ฅ ๋Œ€์ƒ์„ ์˜๋ฏธํ•œ๋‹ค.
์ง€์›๋˜๋Š” Appender ์œ ํ˜•์€ ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค.

  • console
  • file
  • remote server socket
  • DB
  • JMS
  • UNIX syslog demon
  • SMTP

Logger๋Š” ๋‘ ๊ฐœ ์ด์ƒ์˜ Appender ์œ ํ˜•์„ ์ ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

additivity

Appender๋Š” Logger ๊ณ„์ธต ๊ตฌ์กฐ์—์„œ ์ถ”๊ฐ€์ ์œผ๋กœ ์ƒ์†๋œ๋‹ค.
์˜ˆ๋ฅผ ๋“ค์–ด Console Appender๊ฐ€ root Logger์— ์ถ”๊ฐ€๋˜๋ฉด ํ™œ์„ฑํ™”๋œ ๋ชจ๋“  ๋กœ๊น… ์š”์ฒญ์ด ์ตœ์†Œํ•œ ์ฝ˜์†”์— ์ ์šฉ๋œ๋‹ค.
L์ด๋ผ๋Š” Logger์— File Appender๊ฐ€ ์ถ”๊ฐ€๋˜๋ฉด L ๋ฐ L์˜ ์ž์‹ Logger์— ๋Œ€ํ•ด์„œ ํ™œ์„ฑํ™”๋œ ๋กœ๊น… ์š”์ฒญ์ด ํŒŒ์ผ๊ณผ ์ฝ˜์†”์— ๋ชจ๋‘ ์ถœ๋ ฅ๋œ๋‹ค.
Logger์˜ additivity ์†์„ฑ์„ false๋กœ ์ง€์ •ํ•˜๋ฉด ์ด๋Ÿฌํ•œ ์ƒ์†์ด ์ด๋ฃจ์–ด์ง€์ง€ ์•Š๋„๋ก ํ•  ์ˆ˜ ์žˆ๋‹ค. (additivity๋Š” default true)

์•„๋ž˜ ํ‘œ๋Š” additivity ์†์„ฑ์— ๋Œ€ํ•œ ์˜ˆ์‹œ ํ‘œ์ด๋‹ค.

spring boot ๋กœ๊ทธ๋ฐฑ (logback) ์„ค์ • ๋ฐฉ๋ฒ• - Appender - undefined - additivity
์ถœ์ฒ˜: https://logback.qos.ch/manual/architecture.html

root Logger๋Š” additivity flag๋ฅผ ์„ค์ •ํ•  ์ˆ˜ ์—†๋‹ค.
์œ„ ํ‘œ์—์„œ x, x.y, x.y.z๋Š” ์ƒ์œ„ Logger๋กœ๋ถ€ํ„ฐ appender๋ฅผ ์ƒ์†๋ฐ›์•„ ์ ์šฉ๋จ์„ ์•Œ ์ˆ˜ ์žˆ๋‹ค. (root์˜ A1์ด ํฌํ•จ)
security.access Logger๋Š” additivity๊ฐ€ true ์ง€๋งŒ ์ƒ์œ„ security Logger์˜ additivity๊ฐ€ false ์ด๋ฏ€๋กœ root Logger์˜ appender๋ฅผ ์ƒ์†๋ฐ›์ง€ ์•Š๋Š”๋‹ค.

logback์—์„œ ๊ธฐ๋ณธ์ ์œผ๋กœ ์ง€์›ํ•˜๋Š” appender๋Š” ์•„๋ž˜์™€ ๊ฐ™๋‹ค.

๊ฐ ํ•ญ๋ชฉ์˜ appender์— ๋Œ€ํ•œ ๋ฌธ์„œ ๋งํฌ ์—ฐ๊ฒฐํ•ด ๋‘์—ˆ๋‹ค.

access ๋กœ๊ทธ๋ฅผ ์œ„ํ•œ logback-access ๋ชจ๋“ˆ์—๋„ logback-classic์—์„œ ์ œ๊ณตํ•˜๋Š” appender์™€ ๋™์ผํ•œ appender๋ฅผ ์ œ๊ณตํ•œ๋‹ค.
๊ฐ€์žฅ ์ผ๋ฐ˜์ ์œผ๋กœ ๋งŽ์ด ์‚ฌ์šฉ๋˜๋Š” RollingFileAppender์— ๋Œ€ํ•ด์„œ ์•Œ์•„๋ณด์ž.
๋‚˜๋จธ์ง€ Appender์— ๋Œ€ํ•ด์„œ๋Š” ๊ฐ ๋งํฌ์˜ ๋ฌธ์„œ๋ฅผ ์ฐธ๊ณ ํ•˜๋ฉด ๋„์›€์ด ๋œ๋‹ค.

RollingFileAppender

RollingFIleAppender๋Š” ๋กœ๊ทธ ํŒŒ์ผ์„ ๋กค์˜ค๋ฒ„ ํ•˜๋Š” ๊ธฐ๋Šฅ์œผ๋กœ FileAppender๋ฅผ ํ™•์žฅํ•œ๋‹ค.
RollingFileAppender์™€ ์ƒํ˜ธ์ž‘์šฉํ•˜๋Š” ๋‘ ๊ฐ€์ง€ ํ•˜์œ„ ์ปดํฌ๋„ŒํŠธ๊ฐ€ ์žˆ๋Š”๋ฐ ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค.

  • RollingPolicy : ๋กค์˜ค๋ฒ„์— ํ•„์š”ํ•œ ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•œ๋‹ค. (๋ฌด์—‡์„)
  • TriggeringPolicy : ๋กค์˜ค๋ฒ„๊ฐ€ ๋ฐœ์ƒํ• ์ง€ ์—ฌ๋ถ€์™€ ์ •ํ™•ํ•œ ์‹œ๊ธฐ๋ฅผ ๊ฒฐ์ •ํ•œ๋‹ค. (์–ธ์ œ)

RollingFileAppender๋ฅผ ์‚ฌ์šฉํ•˜๋ ค๋ฉด RollingPolicy์™€ TriggeringPolicy ๋ชจ๋‘ ์„ค์ •๋˜์–ด์•ผ ํ•˜๋Š”๋ฐ RollingPolicy๊ฐ€ TriggeringPolicy ์ธํ„ฐํŽ˜์ด์Šค๋„ ๊ตฌํ˜„ํ•˜๋Š” ๊ฒฝ์šฐ RollingPolicy๋งŒ ๋ช…์‹œ์ ์œผ๋กœ ์ง€์ •ํ•˜๋ฉด ๋œ๋‹ค.
๋Œ€ํ‘œ์ ์œผ๋กœ ์‚ฌ์šฉ๋˜๋Š” RollingPolicy๋Š” SizeAndTimeBaseRollingPolicy์ธ๋ฐ ์ด๊ฒƒ์€ TriggeringPolicy๋„ ํ•จ๊ป˜ ๊ตฌํ˜„ํ•˜๊ณ  ์žˆ๋‹ค.

properties

RollingFileAppender์˜ ์†์„ฑ์€ ์•„๋ž˜์™€ ๊ฐ™๋‹ค.

Property NameTypeDescription
fileStringnull์ธ ๊ฒฝ์šฐ ๋กœ๊ทธ๋Š” RollingPolicy์— ์ง€์ •๋œ ๋Œ€์ƒ์—๋งŒ ๊ธฐ๋ก๋œ๋‹ค.
appendbooleantrue์ธ ๊ฒฝ์šฐ ๊ธฐ์กด ํŒŒ์ผ ๋์— ๋กœ๊ทธ๊ฐ€ ์ถ”๊ฐ€๋œ๋‹ค. false์ธ ๊ฒฝ์šฐ ๊ธฐ์กด ํŒŒ์ผ์€
truncate ๋œ๋‹ค.
encoderEncoder๋กœ๊ทธ ์ด๋ฒคํŠธ ๊ธฐ๋ก๋˜๋Š” ๋ฐฉ์‹์„ ๊ฒฐ์ •ํ•œ๋‹ค. Encoder ํŽ˜์ด์ง€๋ฅผ ์ฐธ๊ณ .
rollingPolicyRollingPolicy๋กค์˜ค๋ฒ„๊ฐ€ ๋ฐœ์ƒํ•  ๋•Œ RollingFileAppender์˜ ๋™์ž‘์„ ์„ค์ •ํ•˜๋Š” ์ปดํฌ๋„ŒํŠธ์ด๋‹ค.
triggeringPolicyTriggeringPolicy๋กค์˜ค๋ฒ„๊ฐ€ ๋ฐœ์ƒํ•  ์กฐ๊ฑด์„ ์„ค์ •ํ•˜๋Š” ์ปดํฌ๋„ŒํŠธ์ด๋‹ค.
prudentbooleanprudent ๋ชจ๋“œ๋Š” ๋™์ผํ•œ ํŒŒ์ผ์— ์“ฐ๋Š” ๋ชจ๋“  JVM๊ฐ„์˜ I/O ์ž‘์—…์„ ํšจ๊ณผ์ ์œผ๋กœ ์ง๋ ฌํ™” ํ•œ๋‹ค. exclusive file lock์— ํฌ๊ฒŒ ์˜์กดํ•˜๊ฒŒ ๋˜์–ด prudent ๋ชจ๋“œ๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ์•Š์„๋•Œ์™€ ๋น„๊ตํ•˜์—ฌ ๋กœ๊ทธ ์ด๋ฒคํŠธ ์“ฐ๊ธฐ ๋น„์šฉ์„ ์•ฝ 3๋ฐฐ ์ •๋„ ์ฆ๊ฐ€์‹œํ‚ค๋Š” ๊ฒƒ์œผ๋กœ ๋‚˜ํƒ€๋‚ฌ๋‹ค.
prudent ๋ชจ๋“œ์—์„œ๋Š” FixedWindowRollingPolicy๊ฐ€ ์ง€์›๋˜์ง€ ์•Š๋Š”๋‹ค. TimeBaseRollingPolicy์™€ ํ•จ๊ป˜ prudent ๋ชจ๋“œ์—์„œ๋Š” ๋‘๊ฐ€์ง€ ์ œ์•ฝ์ด ์žˆ๋‹ค.
1. prudent ๋ชจ๋“œ์—์„œ๋Š” ํŒŒ์ผ ์••์ถ•์ด ์ง€์›๋˜์ง€ ์•Š๋Š”๋‹ค.
2. FileAppender์˜ file ์†์„ฑ์€ ์„ค์ •ํ•  ์ˆ˜ ์—†์œผ๋ฉฐ ๋น„์›Œ๋‘ฌ์•ผ ํ•œ๋‹ค.
๋Œ€๋ถ€๋ถ„์˜ ์šด์˜์ฒด์ œ ์—์„œ๋Š” ๋‹ค๋ฅธ ํ”„๋กœ์„ธ์Šค์—์„œ ํŒŒ์ผ์ด ์—ด๋ ค ์žˆ๋Š” ๋™์•ˆ์—๋Š” ํŒŒ์ผ ์ด๋ฆ„์„ ๋ณ€๊ฒฝํ•  ์ˆ˜ ์—†๋‹ค. ๋””ํดํŠธ๋Š” false ๋กœ ๋™์ž‘ํ•œ๋‹ค.

RollingPolicy

  • TimeBasedRollingPolicy
    • ์ผ๋ณ„ ๋˜๋Š” ์›”๋ณ„๋“ฑ ์‹œ๊ฐ„์„ ๊ธฐ์ค€์œผ๋กœ ๋กค์˜ค๋ฒ„ ์ •์ฑ…์„ ์ •์˜ํ•œ๋‹ค.
    • RollingPolicy์™€ TriggeringPolicy ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๋ชจ๋‘ ๊ตฌํ˜„ํ•œ๋‹ค.
    • fileNamePattern ์†์„ฑ์€ ํ•„์ˆ˜ ์†์„ฑ์ด๋ฉฐ ์ด ์†์„ฑ์œผ๋กœ ๋กค์˜ค๋ฒ„ ๋˜๋Š” ๋กœ๊ทธ ํŒŒ์ผ์˜ ์ด๋ฆ„์„ ์ •์˜ํ•œ๋‹ค.
      • ํŒŒ์ผ ์ด๋ฆ„๊ณผ ์ ์ ˆํ•˜๊ฒŒ ๋ฐฐ์น˜๋œ %d ๋ณ€ํ™˜ ์ง€์ •์ž๋กœ ๊ตฌ์„ฑ๋˜์–ด์•ผ ํ•œ๋‹ค.
      • %d ๋ณ€ํ™˜ ์ง€์ •์ž์—๋Š” java.text.SimpleDateFormat ํด๋ž˜์Šค์— ์ง€์ •๋œ ๋‚ ์งœ ๋ฐ ์‹œ๊ฐ„ ํŒจํ„ด์ด ํฌํ•จ๋  ์ˆ˜ ์žˆ๋‹ค.
      • ๋‚ ์งœ ๋ฐ ์‹œ๊ฐ„ ํŒจํ„ด์„ ์ƒ๋žตํ•˜๋ฉด ๊ธฐ๋ณธ ํŒจํ„ด์ธ yyyy-MM-dd๊ฐ€ ์‚ฌ์šฉ๋œ๋‹ค.
      • ๋กค์˜ค๋ฒ„ ๊ธฐ๊ฐ„์€ fileNamePattern์˜ ๊ฐ’์—์„œ ์ถ”๋ก ๋œ๋‹ค.
public class TimeBasedRollingPolicy<E> extends RollingPolicyBase implements TriggeringPolicy<E>
Java

example

<configuration>
  <appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
    <file>logFile.log</file>
    <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
      <!-- daily rollover -->
      <fileNamePattern>logFile.%d{yyyy-MM-dd}.log</fileNamePattern>
      <!-- keep 30 days' worth of history capped at 3GB total size -->
      <maxHistory>30</maxHistory>
      <totalSizeCap>3GB</totalSizeCap>
    </rollingPolicy>
    <encoder>
      <pattern>%-4relative [%thread] %-5level %logger{35} -%kvp- %msg%n</pattern>
    </encoder>
  </appender>

  <root level="DEBUG">
    <appender-ref ref="FILE" />
  </root>
</configuration>
XML

TimeBasedRollingPolicy์— ๋Œ€ํ•œ ์ƒ์„ธํ•œ ์ŠคํŽ™์€ ํ•ด๋‹น ๋งํฌ๋ฅผ ์ฐธ๊ณ ํ•˜๊ธฐ ๋ฐ”๋ž€๋‹ค.

  • SizeAndTimeBasedRollingPolicy
    • ํŒŒ์ผ์„ ๊ธฐ๋ณธ์ ์œผ๋กœ ๋‚ ์งœ๋ณ„๋กœ ์•„์นด์ด๋ธŒ ํ•˜๋ฉด์„œ ๋™์‹œ์— ๊ฐ ๋กœ๊ทธ ํŒŒ์ผ์˜ ํฌ๊ธฐ๋ฅผ ์ œํ•œํ•˜๊ณ  ์‹ถ์€ ๊ฒฝ์šฐ ์‚ฌ์šฉํ•œ๋‹ค.
    • totalSizeCap ์†์„ฑ์„ ์‚ฌ์šฉํ•˜์—ฌ ์ด๋ฏธ ์•„์นด์ด๋ธŒ ๋œ ๋กœ๊ทธ ํŒŒ์ผ์˜ ํ•ฉ์‚ฐ ํฌ๊ธฐ๋ฅผ ์ œํ•œํ•  ์ˆ˜ ์žˆ๋‹ค.
    • fileNamePattern์—์„œ %i์™€ %d ํ† ํฐ์€ ํ•„์ˆ˜๋กœ ์‚ฌ์šฉํ•ด์•ผ ํ•œ๋‹ค.
    • maxHistory ์†์„ฑ์„ ์‚ฌ์šฉํ•˜์—ฌ ํŒŒ์ผ ๋ณด๊ด€ ๊ธฐ๊ฐ„์„ ์ง€์ •ํ•˜์—ฌ ์˜ค๋ž˜๋œ ํŒŒ์ผ์˜ ์‚ญ์ œ๋ฅผ ์ง€์›ํ•œ๋‹ค.
    • RollingPolicy์™€ TriggeringPolicy ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๋ชจ๋‘ ๊ตฌํ˜„ํ•œ๋‹ค.

exampel

<configuration>
  <appender name="ROLLING" class="ch.qos.logback.core.rolling.RollingFileAppender">
    <file>mylog.txt</file>
    <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
      <!-- rollover daily -->
      <fileNamePattern>mylog-%d{yyyy-MM-dd}.%i.txt</fileNamePattern>
       <!-- each file should be at most 100MB, keep 60 days worth of history, but at most 20GB -->
       <maxFileSize>100MB</maxFileSize>
       <maxHistory>60</maxHistory>
       <totalSizeCap>20GB</totalSizeCap>
    </rollingPolicy>
    <encoder>
      <pattern>%msg%n</pattern>
    </encoder>
  </appender>

  <root level="DEBUG">
    <appender-ref ref="ROLLING" />
  </root>
</configuration>
XML
  • FixedWindowRollingPolicy
    • FixedWindowRollingPolicy๋Š” ๋” ์ด์ƒ ์‚ฌ์šฉ๋˜์ง€ ์•Š๋Š” ์ •์ฑ…์œผ๋กœ ๊ฐ„์ฃผํ•˜๋ฉฐ ์‚ฌ์šฉ์„ ๊ถŒ์žฅํ•˜์ง€ ์•Š๋Š”๋‹ค.

TriggeringPolicy

TriggeringPolicy๋Š” ๋กค์˜ค๋ฒ„ ์‹œ์ ์„ RollingFileAppender์— ์ง€์‹œํ•˜๋Š” ์—ญํ• ์„ ๋‹ด๋‹นํ•œ๋‹ค.
TriggeringPolicy ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๊ตฌํ˜„ํ•˜๋Š” ๊ตฌํ˜„์ฒด๋Š” ์•„๋ž˜์™€ ๊ฐ™๋‹ค.

spring boot ๋กœ๊ทธ๋ฐฑ (logback) ์„ค์ • ๋ฐฉ๋ฒ• - Appender - RollingFileAppender - TriggeringPolicy
TriggeringPolicy ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๊ตฌํ˜„ํ•˜๋Š” ๊ตฌํ˜„์ฒด

RollingFileAppender์—์„œ SizeAndTimeBasedRollingPolicy ํ˜น์€ TimeBasedRollingPolicy๊ฐ€ ์ฃผ๋กœ ์‚ฌ์šฉ๋˜๋ฏ€๋กœ TriggeringPolicy๋ฅผ ๋”ฐ๋กœ ์ง€์ •ํ•ด์„œ ์‚ฌ์šฉํ•˜๋Š” ์ผ์€ ๊ฑฐ์˜ ์—†์„ ๋“ฏํ•˜๋‹ค.

example

<configuration>
  <appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
    <file>test.log</file>
    <rollingPolicy class="ch.qos.logback.core.rolling.FixedWindowRollingPolicy">
      <fileNamePattern>test.%i.log.zip</fileNamePattern>
      <minIndex>1</minIndex>
      <maxIndex>3</maxIndex>
    </rollingPolicy>
    <triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">
      <maxFileSize>5MB</maxFileSize>
    </triggeringPolicy>
    <encoder>
      <pattern>%-4relative [%thread] %-5level %logger{35} -%kvp -%msg%n</pattern>
    </encoder>
  </appender>

  <root level="DEBUG">
    <appender-ref ref="FILE" />
  </root>
</configuration>
XML

Layout

  • Layout์€ ๋กœ๊ทธ ์ด๋ฒคํŠธ๋ฅผ String์œผ๋กœ ๋ณ€ํ™˜ํ•˜๋Š” logback ์ปดํฌ๋„ŒํŠธ๋‹ค.
  • Layout์„ Appender์™€ ์—ฐ๊ฒฐํ•˜์—ฌ ์ถœ๋ ฅ ํ˜•์‹์„ ์ง€์ •ํ•  ์ˆ˜ ์žˆ๋‹ค.
  • Layout์€ ์‚ฌ์šฉ์ž๊ฐ€ ์›ํ•˜๋Š” ๋Œ€๋กœ ๋กœ๊น… ์š”์ฒญ์˜ ํ˜•์‹์„ ์ง€์ •ํ•˜๋Š” ์—ญํ• ์„ ํ•œ๋‹ค.
  • ํ‘œ์ค€ logback ๋ฐฐํฌ์˜ ์ผ๋ถ€์ธ PatternLayout์„ ์‚ฌ์šฉํ•˜์—ฌ C ์–ธ์–ด์˜ printf์™€ ์œ ์‚ฌํ•œ ํŒจํ„ด์œผ๋กœ ์ถœ๋ ฅ ํ˜•์‹์„ ์ง€์ •ํ•  ์ˆ˜ ์žˆ๋‹ค.

PatternLayout

  • PatternLay์˜ ๋ณ€ํ™˜ ํŒจํ„ด์€ C ํ”„๋กœ๊ทธ๋ž˜๋ฐ ์–ธ์–ด์˜ printf() ํ•จ์ˆ˜์˜ ๋ณ€ํ™˜ ํŒจํ„ด๊ณผ ๋ฐ€์ ‘ํ•œ ๊ด€๋ จ์ด ์žˆ๋‹ค.
  • ๋ณ€ํ™˜ ํŒจํ„ด์€ ๋ฆฌํ„ฐ๋Ÿด ํ…์ŠคํŠธ์™€ ๋ณ€ํ™˜ ์ง€์ •์ž๋ผ๊ณ  ํ•˜๋Š” ํ˜•์‹ ์ œ์–ด ํ‘œํ˜„์‹์œผ๋กœ ๊ตฌ์„ฑ๋œ๋‹ค.
  • ๊ฐ ๋ณ€ํ™˜ ์ง€์ •์ž๋Š” ‘%’๋กœ ์‹œ์ž‘ํ•˜๊ณ  ์ค‘๊ด„ํ˜ธ ์‚ฌ์ด์— ์„ ํƒ์  ํ˜•์‹ ์ˆ˜์ •์ž, ๋ณ€ํ™˜ ๋‹จ์–ด ๋ฐ ์„ ํƒ์  ๋งค๊ฐœ๋ณ€์ˆ˜๊ฐ€ ์ด์–ด์ง„๋‹ค.
  • ๋ณ€ํ™˜ ๋‹จ์–ด๋Š” Logger ์ด๋ฆ„, ๋กœ๊ทธ ๋ ˆ๋ฒจ, ๋‚ ์งœ ๋˜๋Š” ์Šค๋ ˆ๋“œ ์ด๋ฆ„๋“ฑ ๋ณ€ํ™˜ํ•  ๋ฐ์ดํ„ฐ ํ•„๋“œ๋ฅผ ์ œ์–ดํ•œ๋‹ค.
  • ํ˜•์‹ ์ˆ˜์ •์ž๋Š” ํ•„๋“œ ๋„ˆ๋น„, ํŒจ๋”ฉ, ์™ผ์ชฝ ๋˜๋Š” ์˜ค๋ฅธ์ชฝ ๋งž์ถค์„ ์ œ์–ดํ•œ๋‹ค.
  • FileAppender์™€ ๊ทธ ์„œ๋ธŒ ํด๋ž˜์Šค(e.g. RollingFileAppender)๋“ค์€ Encoder๋ฅผ ํ•„์š”๋กœ ํ•œ๋‹ค.
  • FileAppender ํ˜น์€ ๊ทธ ์„œ๋ธŒ ํด๋ž˜์Šค์™€ ํ•จ๊ป˜ ์‚ฌ์šฉํ•  ๋•Œ PatternLayout์€ Encoder ์•ˆ์— ๋ž˜ํ•‘ ๋˜์–ด์•ผ ํ•œ๋‹ค.
  • PatternLayoutEncoder๋Š” PatternLayout ์ธ์Šคํ„ด์Šค๋ฅผ ์ธ์ฝ”๋”๋กœ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ๋„๋ก ๋ž˜ํ•‘ ํ•œ ํด๋ž˜์Šค์ด๋‹ค.

๋ณ€ํ™˜ ๋‹จ์–ดํ‘œ

๋Œ€ํ‘œ์ ์ธ ๋ณ€ํ™˜ ๋‹จ์–ด์™€ ํ•ด๋‹น ์˜ต์…˜์— ๋Œ€ํ•œ ํ‘œ์ด๋‹ค. ๋™์ผ ์…€์— ์—ฌ๋Ÿฌ ๊ฐœ์˜ ๋ณ€ํ™˜ ๋‹จ์–ด๊ฐ€ ์žˆ๋Š” ๊ฒฝ์šฐ ๋ณ„์นญ์œผ๋กœ ๊ฐ„์ฃผํ•œ๋‹ค.

์ž์„ธํ•œ ์‚ฌํ•ญ์€ PatternLayout ๋งํฌ๋ฅผ ์ฐธ๊ณ ํ•˜๋ฉด ๋„์›€์ด ๋œ๋‹ค.

๋ณ€ํ™˜ ๋‹จ์–ดํšจ๊ณผ
%c{length}
%lo{length}
%logger{length}
Logger์˜ ์ด๋ฆ„์„ ์ถœ๋ ฅํ•œ๋‹ค.
%logger : mainPackage.sub.sample.Bar
%logger{10} : m.s.s.Bar
%contextName
%cn
Logger๊ฐ€ ์—ฐ๊ฒฐ๋œ Logger context์˜ ์ด๋ฆ„์„ ์ถœ๋ ฅํ•œ๋‹ค.
%d{pattern}
%date{pattern}
%d{pattern, timezone}
%date{pattern, timezone}
%d{pattern, timezone, locale}
%date{pattern, timezone, locale}
๋กœ๊น… ์ด๋ฒคํŠธ์˜ ๋‚ ์งœ๋ฅผ ์ถœ๋ ฅํ•œ๋‹ค.
๋‚ ์งœ ๋ณ€ํ™˜ ๋‹จ์–ด๋Š” ํŒจํ„ด ๋ฌธ์ž์—ด์„ ๋งค๊ฐœ๋ณ€์ˆ˜๋กœ ํ—ˆ์šฉํ•œ๋‹ค.
ํŒจํ„ด ๊ตฌ๋ฌธ์€ java.text.SimpeDateFormat(logback 1.2.X) java.time.format.DateTimeFormatter (logback 1.3.X) ์—์„œ ํ—ˆ์šฉํ•˜๋Š” ํ˜•์‹๊ณผ ํ˜ธํ™˜๋œ๋‹ค.
ํŒจํ„ด ๋งค๊ฐœ๋ณ€์ˆ˜๊ฐ€ ์—†๋Š” ๊ฒฝ์šฐ ๊ธฐ๋ณธ์ ์œผ๋กœ ISO8601 ๋‚ ์งœ ํ˜•์‹์„ ์‚ฌ์šฉํ•œ๋‹ค.
%d : 2006-10-20 14:06:49,812
%date : 2006-10-20 14:06:49,812
%date{HH:mm:ss.SSS} : 14:06:49.812
‘,’ ๋ฌธ์ž๋Š” ๋งค๊ฐœ ๋ณ€์ˆ˜ ๊ตฌ๋ถ„ ๊ธฐํ˜ธ๋กœ ์‚ฌ์šฉ๋˜๋ฏ€๋กœ ํŒจํ„ด ๊ตฌ๋ฌธ์— ‘,’ ๋ฌธ์ž๊ฐ€ ํฌํ•จ๋˜๋ฉด
์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ๋‹ค.
๋‚ ์งœ ํŒจํ„ด์— ‘,’ ๋ฌธ์ž๋ฅผ ํฌํ•จํ•˜๋ ค๋ฉด ํŒจํ„ด์„ ์ž‘์€๋”ฐ์˜ดํ‘œ ํ˜น์€ ํฐ๋”ฐ์˜ดํ‘œ๋กœ ๋ฌถ์–ด์•ผ ํ•œ๋‹ค.
%date{“HH:mm:ss,SSS”} ํ˜น์€ %date{‘HH:mm:ss,SSS’}
%L
%line
๋กœ๊น… ์š”์ฒญ์ด ๋ฐœ์ƒํ•œ ๋ผ์ธ ๋ฒˆํ˜ธ๋ฅผ ์ถœ๋ ฅํ•œ๋‹ค.
๋ผ์ธ ๋ฒˆํ˜ธ ์ •๋ณด๋ฅผ ์ƒ์„ฑํ•˜๋Š” ์†๋„๊ฐ€ ๋น ๋ฅด์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์— ๊ฐ€๊ธ‰์  ์‚ฌ์šฉํ•˜์ง€ ์•Š์„ ๊ฒƒ์„ ๊ถŒ๊ณ 
%m
%msg
%message
์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์—์„œ ์ œ๊ณตํ•œ ๋กœ๊ทธ ๋ฉ”์‹œ์ง€๋ฅผ ์ถœ๋ ฅํ•œ๋‹ค.
์• ํ”Œ๋ž˜์ผ€์ด์…˜์—์„œ ์ž‘์„ฑํ•œ log.info(“log message”); ๋‚ด์šฉ ์ด๋ผ๊ณ  ๋ณด๋ฉด ๋œ๋‹ค.
%n์ค„๋ฐ”๊ฟˆ ๋ฌธ์ž๋ฅผ ์ถœ๋ ฅํ•œ๋‹ค.
%p
%le
%level
๋กœ๊ทธ ๋ ˆ๋ฒจ์„ ์ถœ๋ ฅํ•œ๋‹ค.
%t
%thread
๋กœ๊น… ์ด๋ฒคํŠธ๊ฐ€ ๋ฐœ์ƒํ•œ ์Šค๋ ˆ๋“œ ์ด๋ฆ„์„ ์ถœ๋ ฅํ•œ๋‹ค.
%X{key:-defaultValue} %mdc{key:-defaultValue}๋กœ๊น… ์ด๋ฒคํŠธ๋ฅผ ์ƒ์„ฑํ•œ ์Šค๋ ˆ๋“œ์™€ ์—ฐ๊ด€๋œ MDC๋ฅผ ์ถœ๋ ฅํ•œ๋‹ค.
%mdc{userid} : userid ํ‚ค์— ํ•ด๋‹นํ•˜๋Š” MDC ๊ฐ’์ด ์ถœ๋ ฅ๋œ๋‹ค.
๊ฐ’์ด null ์ด๋ฉด ‘:-‘ ์—ฐ์‚ฐ์ž ๋’ค์— ์ง€์ •๋œ default ๊ฐ’์ด ์ถœ๋ ฅ๋œ๋‹ค.
ํ‚ค๋ฅผ ์ง€์ •ํ•˜์ง€ ์•Š์œผ๋ฉด MDC์˜ ์ „์ฒด ๋‚ด์šฉ์ด “key1=val1, key2=val2” ํ˜•์‹์œผ๋กœ ์ถœ๋ ฅ๋œ๋‹ค.
  • % ๊ธฐํ˜ธ๋Š” ํŠน๋ณ„ํ•œ ์˜๋ฏธ๋ฅผ ๊ฐ€์ง€๋ฏ€๋กœ ๋ฆฌํ„ฐ๋Ÿด๋กœ ํฌํ•จํ•˜๋ ค๋ฉด ๋ฐฑ์Šฌ๋ž˜์‹œ(”)๋กœ escape ์ฒ˜๋ฆฌ๋ฅผ ํ•ด์•ผ ํ•œ๋‹ค.
  • ๋กœ๊ทธ ๋ ˆ๋ฒจ์— ๋Œ€ํ•ด์„œ TRACE, DEBUG, INFO, WARN, ERROR๋ฅผ ์ถœ๋ ฅํ•˜๋Š” ๋Œ€์‹  T, D, I, W, E ๋งŒ ์ถœ๋ ฅํ•˜๋ ค๋ฉด %.-1level ์„ ์ง€์ •
  • Grouping with parentheses ๋งํฌ ์ฐธ๊ณ 
  • Coloring ๋งํฌ ์ฐธ๊ณ 

HTMLLayout

  • HTMLLayout์€ HTML ํ˜•์‹์œผ๋กœ ๋กœ๊ทธ๋ฅผ ์ƒ์„ฑํ•œ๋‹ค.
  • HTML ํ…Œ์ด๋ธ”์˜ ๊ฐ ํ–‰์— ๋กœ๊น… ์ด๋ฒคํŠธ๋ฅผ ์ถœ๋ ฅํ•œ๋‹ค.
  • ํ…Œ์ด๋ธ” ์—ด์˜ ์ฝ˜ํ…์ธ ๋Š” ๋ณ€ํ™˜ ํŒจํ„ด์„ ์‚ฌ์šฉํ•˜์—ฌ ์ง€์ •๋œ๋‹ค.
  • HTMLLayout๊ณผ ํ•จ๊ป˜ PatternLayout์„ ์‚ฌ์šฉํ•  ๋Œ€ ๋ณ€ํ™˜ ์ง€์ •์ž๋ฅผ ๊ณต๋ฐฑ ๋ฌธ์ž๋‚˜ ๋” ์ผ๋ฐ˜์ ์œผ๋กœ ๋ฆฌํ„ฐ๋Ÿด ํ…์ŠคํŠธ๋กœ ๊ตฌ๋ถ„ํ•ด์„œ๋Š” ์•ˆ๋œ๋‹ค.
    • ํŒจํ„ด์—์„œ ๋ฐœ๊ฒฌ๋˜๋Š” ๊ฐ ์ง€์ •์ž๋Š” ๋ณ„๋„์˜ ์—ด์„ ์ƒ์„ฑํ•œ๋‹ค.
    • ํŒจํ„ด์— ์žˆ๋Š” ๊ฐ ๋ฆฌํ„ฐ๋Ÿด ํ…์ŠคํŠธ ๋ธ”๋ก์— ๋Œ€ํ•ด ๋ณ„๋„์˜ ์—ด์ด ์ƒ์„ฑ๋˜๋ฏ€๋กœ ํ™”๋ฉด์—์„œ์˜ ๊ณต๊ฐ„์„ ๋‚ญ๋น„ํ•  ์ˆ˜ ์žˆ๋‹ค.

example

<configuration debug="true">
  <appender name="FILE" class="ch.qos.logback.core.FileAppender">
    <encoder class="ch.qos.logback.core.encoder.LayoutWrappingEncoder">
      <layout class="ch.qos.logback.classic.html.HTMLLayout">
        <pattern>%relative%thread%mdc%level%logger%msg</pattern>
      </layout>
    </encoder>
    <file>test.html</file>
  </appender>

  <root level="DEBUG">
    <appender-ref ref="FILE" />
  </root>
</configuration>
XML

test.html ํŒŒ์ผ์ด ์ƒ์„ฑ๋˜๋ฉฐ ํŒŒ์ผ์˜ ๋‚ด์šฉ์€ ๋‹ค์Œ๊ณผ ๊ฐ™์€ ํ˜•์‹์ด ๋  ๊ฒƒ์ด๋‹ค.

spring boot ๋กœ๊ทธ๋ฐฑ (logback) ์„ค์ • ๋ฐฉ๋ฒ• - Layout - RollingFileAppender - HTMLLayout
์ถœ์ฒ˜: https://logback.qos.ch/manual/layouts.html#ClassicHTMLLayout

์ง€๊ธˆ๊นŒ์ง€ ๋‚ด์šฉ ์™ธ์—๋„ ๊ด€๋ จ๋œ ๋‚ด์šฉ์ด ์ƒ๋‹นํžˆ ๋งŽ์€๋ฐ ํ•ด๋‹น ๋‚ด์šฉ์€ logback ์‚ฌ์ดํŠธ document ๋ฅผ ์ฐธ๊ณ ํ•˜๋ฉด ๋„์›€์ด ๋œ๋‹ค.

logback-spring.xml ์ƒ˜ํ”Œ

์ง€๊ธˆ๊นŒ์ง€์˜ ๋‚ด์šฉ์„ ๊ธฐ๋ฐ˜์œผ๋กœ logback-spring.xml ์ƒ˜ํ”Œ์„ ์ž‘์„ฑํ•˜์˜€๋‹ค.
์ƒ˜ํ”Œ logback configuration์€ ๊ธฐ๋Šฅ์ƒ 4๊ฐ€์ง€ ์š”์†Œ๋กœ ๋ถ„๋ฆฌํ•˜์—ฌ ๊ฐ ์š”์†Œ๋ณ„๋กœ ๋กœ๊ทธ ํŒŒ์ผ์„ ๋ถ„๋ฆฌํ•˜์—ฌ ๊ธฐ๋กํ•˜๋„๋ก ํ•˜์˜€๋‹ค.
๋ณ„๋„์˜ logging properties(logback.properties) ํŒŒ์ผ์„ ๋‘์–ด variable์„ ํ•˜๋‚˜์˜ ํŒŒ์ผ๋กœ ๊ด€๋ฆฌํ•˜๋„๋ก ํ•˜์˜€๋‹ค.

  • SMTP ํ”„๋กœํ† ์ฝœ ๊ธฐ๋ฐ˜์œผ๋กœ ์ด๋ฉ”์ผ์„ ์ˆ˜์‹ ํ•˜๋Š” MTA ๋ชจ๋“ˆ (appender ์ด๋ฆ„ : MTA)
  • Spring Boot ๊ธฐ๋ณธ ์ œ๊ณต ๋ชจ๋“ˆ (appender ์ด๋ฆ„ : APPLICATION)
  • JPA ๋ชจ๋“ˆ (appender ์ด๋ฆ„ : QUERY)
  • ์ด๋ฉ”์ผ ์ „์†ก ๋ชจ๋“ˆ (appender ์ด๋ฆ„ : DELIVERY)

logback.properties

ํŒŒ์ผ ์œ„์น˜๋Š” resources/logback.properties์ด๋‹ค.

logging.mta.filename=mta.log
logging.mta.file.max-history=7
logging.mta.file.max-size=10MB
logging.mta.file.logpattern=%-5level %d{yy-MM-dd HH:mm:ss.SSS} %msg%n

logging.application.filename=application.log
logging.application.file.max-history=7
logging.application.file.max-size=10MB
logging.application.file.logpattern=%-5level %d{yyyy/MM/dd HH:mm:ss}[%thread] [%logger{0}:%line] - %msg%n

logging.query.filename=qry.log
logging.query.file.max-size=10MB
logging.query.file.max-history=7
logging.query.file.logpattern=%-5level [%d{yy-MM-dd HH:mm:ss}] %msg%n

logging.delivery.filename=delivery.log
logging.delivery.file.max-size=10MB
logging.delivery.file.max-history=7
logging.delivery.file.logpattern=%-5level [%d{yy-MM-dd HH:mm:ss}] %msg%n
Plaintext

์„ค์ • ํ•ญ๋ชฉ์—์„œ ์ง์ž‘ํ•  ์ˆ˜ ์žˆ๊ฒ ์ง€๋งŒ RollingFileAppender์™€ SizeAndTimeBasedRollingPolicy๋ฅผ ์ ์šฉํ•˜์˜€๋‹ค.
๋กค์˜ค๋ฒ„ ์กฐ๊ฑด์€ ์ผ๋ณ„๋กœ 10MB ๋‹จ์œ„๋กœ ๋กœ๊ทธ ํŒŒ์ผ์ด ์ƒ์„ฑ๋œ๋‹ค. ๋กœ๊ทธ ๋ณด๊ด€๊ธฐ๊ฐ„์€ 7์ผ์ด๋‹ค.

logback-spring.xml

ํŒŒ์ผ ์œ„์น˜๋Š” resources/logback-spring.xml์ด๋‹ค.

<?xml version="1.0" encoding="UTF-8"?>

<!-- 60 ์ดˆ๋งˆ๋‹ค ์„ค์ •ํŒŒ์ผ์˜ ๋ณ€๊ฒฝ์„ ํ™•์ธ ํ›„ ๊ฐฑ์‹  -->
<configuration scan="true" scanPeriod="60 seconds">
    <!--
    LOG_DIR์„ ์ง์ ‘ ๋ณ€์ˆ˜๋กœ ์„ ์–ธํ•˜๋Š” ๊ฒƒ ๋Œ€์‹ ์—
    application.yml ์—์„œ logging.file.path: log ๋กœ ์„ค์ •ํ•˜์—ฌ ๋ฐ”๋กœ ${LOG_PATH}๋กœ ์‚ฌ์šฉํ•ด๋„ ๋œ๋‹ค.
    -->
    <property name="LOG_DIR" value="./log"/>
    <!-- class path์˜ logback.properties ํŒŒ์ผ์„ ๋กœ๋”ฉํ•˜์—ฌ variables๋กœ ์‚ฌ์šฉํ•œ๋‹ค -->
    <property resource="logback.properties"/>

    <!-- file appender -->
    <appender name="MTA" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <file>${LOG_DIR}/${logging.mta.filename}</file>

        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
            <pattern>${logging.mta.file.logpattern}</pattern>
        </encoder>

        <!-- rolling ์ •์ฑ… -->
        <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
            <fileNamePattern>${LOG_DIR}/${logging.mta.filename}.%d{yyyy-MM-dd}.%i.log}</fileNamePattern>
            <maxFileSize>${logging.mta.file.max-size:-10MB}</maxFileSize>
            <maxHistory>${logging.mta.file.max-history:-7}</maxHistory>
        </rollingPolicy>
    </appender>

    <!-- ์—๋Ÿฌ์˜ ๊ฒฝ์šฐ ํŒŒ์ผ ๋กœ๊ทธ ์ฒ˜๋ฆฌ -->
    <appender name="APPLICATION" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <file>${LOG_DIR}/${logging.application.filename}</file>
        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
            <pattern>${logging.application.file.logpattern}</pattern>
        </encoder>

        <!-- rolling ์ •์ฑ… -->
        <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
            <fileNamePattern>${LOG_DIR}/${logging.application.filename}.%d{yyyy-MM-dd}.%i.log}</fileNamePattern>
            <maxFileSize>${logging.application.file.max-size:-10MB}</maxFileSize>
            <maxHistory>${logging.application.file.max-history:-7}</maxHistory>
        </rollingPolicy>
    </appender>

    <appender name="QUERY" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <file>${LOG_DIR}/${logging.query.filename}</file>

        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
            <pattern>${logging.query.file.logpattern}</pattern>
        </encoder>

        <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
            <fileNamePattern>${LOG_DIR}/${logging.query.filename}.%d{yyyy-MM-dd}.%i.log}</fileNamePattern>
            <maxFileSize>${logging.query.file.max-size:-10MB}</maxFileSize>
            <maxHistory>${logging.query.file.max-history:-7}</maxHistory>
        </rollingPolicy>
    </appender>

    <appender name="DELIVERY" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <file>${LOG_DIR}/${logging.delivery.filename}</file>

        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
            <pattern>${logging.delivery.file.logpattern}</pattern>
        </encoder>

        <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
            <fileNamePattern>${LOG_DIR}/${logging.delivery.filename}.%d{yyyy-MM-dd}.%i.log}</fileNamePattern>
            <maxFileSize>${logging.delivery.file.max-size:-10MB}</maxFileSize>
            <maxHistory>${logging.delivery.file.max-history:-7}</maxHistory>
        </rollingPolicy>
    </appender>

    <!-- ๋กœ๊ฑฐ ์„ค์ • -->
    <logger name="delivery" level="DEBUG" additivity="false">
        <appender-ref ref="DELIVERY"/>
    </logger>

    <logger name="com.mail.smtp" level="TRACE" additivity="false">
        <appender-ref ref="MTA"/>
    </logger>

    <!-- about hibernate query log -->

    <!-- ์ฟผ๋ฆฌ ๊ฒฐ๊ณผ : level ์„ TRACE ๋กœ ๋ณ€๊ฒฝํ•˜๋ฉด ๊ฒฐ๊ณผ ๋กœ๊ทธ๊ฐ€ ์ƒ์„ฑ๋œ๋‹ค. -->
    <logger name="org.hibernate.type.descriptor.sql.BasicExtractor" level="DEBUG" additivity="false">
        <appender-ref ref="QUERY"/>
    </logger>

    <!-- ์ฟผ๋ฆฌ ํŒŒ๋ผ๋ฏธํ„ฐ -->
    <logger name="org.hibernate.type.descriptor.sql.BasicBinder" level="TRACE" additivity="false">
        <appender-ref ref="QUERY"/>
    </logger>

    <!-- ์ฟผ๋ฆฌ๋ฌธ -->
    <logger name="org.hibernate.SQL" level="DEBUG" additivity="false">
        <appender-ref ref="QUERY"/>
    </logger>

    <!-- root ๋ ˆ๋ฒจ ์„ค์ • -->
    <root level="DEBUG">
        <appender-ref ref="APPLICATION"/>
    </root>
</configuration>
XML
  • ConsoleAppender๋Š” ์‚ฌ์šฉํ•˜์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์— console๋กœ๊ทธ๋Š” ์ƒ์„ฑ๋˜์ง€ ์•Š๋Š”๋‹ค.
  • ๊ฐ Logger์˜ additivity ์†์„ฑ์„ false๋กœ ์ง€์ •ํ•˜์—ฌ root Logger์˜ appender๋ฅผ ์ƒ์†๋ฐ›์ง€ ์•Š๋Š”๋‹ค.
    • ์ง€์ •๋œ Logger๋Š” ๊ฐ์ž ๋ณ„๋„ ํŒŒ์ผ์—๋งŒ ๊ธฐ๋ก์ด ๋œ๋‹ค.
  • QUERY appender๋Š” JPA ์ฟผ๋ฆฌ ๋ฐ binding ์ •๋ณด ๋กœ๊ทธ๋ฅผ ๊ธฐ๋กํ•œ๋‹ค.

logback ๊ด€๋ จ ๋ฌธ์„œ์˜ ๋‚ด์šฉ์ด ์ƒ๋‹นํžˆ ๋ฐฉ๋Œ€ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ๋ชจ๋“  ๋‚ด์šฉ์„ ์ด ๊ธ€์— ๋‹ด์ง€๋Š” ๋ชปํ•ด์„œ ์•„์‰ฝ์ง€๋งŒ logback ๋ฌธ์„œ๋ฅผ ์‚ดํŽด๋ณด๋ฉด ๋งŽ์€ ๋„์›€์ด ๋  ๊ฒƒ์ด๋‹ค.


ํ•จ๊ป˜ ๋ณด๋ฉด ์ข‹์€ ๊ธ€

spring boot logging ์ œ๋Œ€๋กœ ์•Œ๊ธฐ

์ฐธ๊ณ ๋งํฌ

https://logback.qos.ch/manual/configuration.html
https://logback.qos.ch/manual/appenders.html
https://logback.qos.ch/manual/encoders.html
https://logback.qos.ch/manual/layouts.html#customConversionSpecifier