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 | ์ง์ ๋ ๋ ๋ฒจ | ์ ์ฉ๋๋ ๋ ๋ฒจ |
|---|---|---|
| root | DEBUG | DEBUG |
| X | ์์ | DEBUG |
| X.Y | ์์ | DEBUG |
| X.Y.Z | ์์ | DEBUG |
X, X.Y, X.Y.Z Logger์๋ ๋ก๊ทธ ๋ ๋ฒจ์ด ํ ๋น๋์ง ์์๊ธฐ ๋๋ฌธ์ root Logger์ ๋ก๊ทธ ๋ ๋ฒจ์ ์์๋ฐ๋๋ค.
์์ 2)
| Logger name | ์ง์ ๋ ๋ ๋ฒจ | ์ ์ฉ๋๋ ๋ ๋ฒจ |
|---|---|---|
| root | ERROR | ERROR |
| X | INFO | INFO |
| X.Y | DEBUG | DEBUG |
| X.Y.Z | WARN | WARN |
๋ชจ๋ Logger์ ๋ก๊ทธ ๋ ๋ฒจ์ด ์ง์ ๋์ด ์๊ธฐ ๋๋ฌธ์ ์์์ ์ผ์ด๋์ง ์๋๋ค. ๊ฐ Logger์ ์ง์ ๋ ๋ก๊ทธ ๋ ๋ฒจ์ด ์ ์ฉ๋๋ค.
์์ 3)
| Logger name | ์ง์ ๋ ๋ ๋ฒจ | ์ ์ฉ๋๋ ๋ ๋ฒจ |
|---|---|---|
| root | DEBUG | DEBUG |
| X | INFO | INFO |
| X.Y | ์์ | INFO |
| X.Y.Z | ERROR | ERROR |
X.Y Logger์๋ ๋ก๊ทธ ๋ ๋ฒจ์ด ์ง์ ๋์ง ์์๊ธฐ ๋๋ฌธ์ ๊ฐ์ฅ ๊ฐ๊น์ด ์กฐ์์ธ X Logger๋ก๋ถํฐ ๋ก๊ทธ ๋ ๋ฒจ์ ์์๋ฐ๋๋ค.
์์ 4)
| Logger name | ์ง์ ๋ ๋ ๋ฒจ | ์ ์ฉ๋๋ ๋ ๋ฒจ |
|---|---|---|
| root | DEBUG | DEBUG |
| X | INFO | INFO |
| 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 < ERRORPlaintext
์ถ์ฒ 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>XMLListener๋ <configuration>์ ์๋จ์ ๋ฐฐ์นํ์ฌ ๋ฑ๋กํ๋ ๊ฒ์ ๊ถ์ฅํ๋ค. ์ถ๊ฐ๋ก OnErrorConsoleStatusListener๋ OnFileStatusListener๋ฅผ ๋ฑ๋กํ ์ ์๋ค.
debug=true๋ฅผ ์ง์ ํ์ฌ ์ ์ค์ ์ ๊ฐ๋จํ๊ฒ ์ง์ ํ ์๋ ์๋ค.
<configuration debug="true">
...
</configuration>XMLdebug=”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
Plaintextconfiguration 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> ํ๊ทธ ๊ตฌ์กฐ๋ค.


๊ธฐ๋ณธ์ ์ธ 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" appBash<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/sebastienPlaintext<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>XMLvariable scope ์์ฑ์ด ์๋๋ฐ 3๊ฐ์ง ์ ์๊ฐ ์๋ค.
- local : ๊ตฌ์ฑ ํ์ผ์์ ์ ์๋ ์์ ๋ถํฐ ํด๋น ๊ตฌ์ฑ ํ์ผ์ ํด์/์คํ์ด ๋๋ ๋๊น์ง ์กด์ฌํ๋ค.
- context : context์ ํด๋น ๋ณ์๊ฐ ์ฝ์ ๋๋ฉฐ context๊ฐ ์ญ์ ๋ ๋๊น์ง ์ ์ง๋๋ค. ์๊ฒฉ ํธ์คํธ๋ก ์ ์ก๋๋ ์ด๋ฒคํธ๋ฅผ ํฌํจํ์ฌ ๋ชจ๋ ๋ก๊น ์ด๋ฒคํธ์์ ์ฌ์ฉํ ์ ์๋ค.
- system : JVM์ system property์ ์ฝ์ ๋๋ฉฐ JVM์ด ์ง์๋๋ ๋์ ์ ์ง๋๋ค.
<springProperty> ์์๋ฅผ ์ฌ์ฉํ์ฌ scope์ ์ง์ ํ์ฌ ์ฌ์ฉํ๋ ๊ฒฝ์ฐ์๋ ๋์ผํ๊ฒ ์ ์ฉ๋๋ ๋ฏํ๋ค.
# application.yml
spring:
application:
name: logging-testYAML<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>XMLPKG_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>XMLclass 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 ์์ฑ์ ๋ํ ์์ ํ์ด๋ค.

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์ ๋ํ ๋ฌธ์ ๋งํฌ ์ฐ๊ฒฐํด ๋์๋ค.
- OutputStreamAppender (logback-core)
- ConsoleAppender (logback-core)
- FileAppender (logback-core)
- RollingFileAppender (logback-core)
- SocketAppender and SSLSocketAppender (logback-classic)
- ServerSocketAppender and SSLServerSocketAppender (logback-classic)
- SMTPAppender (logback-classic)
- DBAppender (logback-classic)
- SyslogAppender (logback-classic)
- SiftingAppender (logback-classic)
- AsyncAppender (logback-classic)
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 Name | Type | Description |
|---|---|---|
| file | String | null์ธ ๊ฒฝ์ฐ ๋ก๊ทธ๋ RollingPolicy์ ์ง์ ๋ ๋์์๋ง ๊ธฐ๋ก๋๋ค. |
| append | boolean | true์ธ ๊ฒฝ์ฐ ๊ธฐ์กด ํ์ผ ๋์ ๋ก๊ทธ๊ฐ ์ถ๊ฐ๋๋ค. false์ธ ๊ฒฝ์ฐ ๊ธฐ์กด ํ์ผ์ truncate ๋๋ค. |
| encoder | Encoder | ๋ก๊ทธ ์ด๋ฒคํธ ๊ธฐ๋ก๋๋ ๋ฐฉ์์ ๊ฒฐ์ ํ๋ค. Encoder ํ์ด์ง๋ฅผ ์ฐธ๊ณ . |
| rollingPolicy | RollingPolicy | ๋กค์ค๋ฒ๊ฐ ๋ฐ์ํ ๋ RollingFileAppender์ ๋์์ ์ค์ ํ๋ ์ปดํฌ๋ํธ์ด๋ค. |
| triggeringPolicy | TriggeringPolicy | ๋กค์ค๋ฒ๊ฐ ๋ฐ์ํ ์กฐ๊ฑด์ ์ค์ ํ๋ ์ปดํฌ๋ํธ์ด๋ค. |
| prudent | boolean | prudent ๋ชจ๋๋ ๋์ผํ ํ์ผ์ ์ฐ๋ ๋ชจ๋ 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>Javaexample
<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>XMLTimeBasedRollingPolicy์ ๋ํ ์์ธํ ์คํ์ ํด๋น ๋งํฌ๋ฅผ ์ฐธ๊ณ ํ๊ธฐ ๋ฐ๋๋ค.
- 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 ์ธํฐํ์ด์ค๋ฅผ ๊ตฌํํ๋ ๊ตฌํ์ฒด๋ ์๋์ ๊ฐ๋ค.

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>XMLLayout
- 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>XMLtest.html ํ์ผ์ด ์์ฑ๋๋ฉฐ ํ์ผ์ ๋ด์ฉ์ ๋ค์๊ณผ ๊ฐ์ ํ์์ด ๋ ๊ฒ์ด๋ค.

์ง๊ธ๊น์ง ๋ด์ฉ ์ธ์๋ ๊ด๋ จ๋ ๋ด์ฉ์ด ์๋นํ ๋ง์๋ฐ ํด๋น ๋ด์ฉ์ 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%nPlaintext์ค์ ํญ๋ชฉ์์ ์ง์ํ ์ ์๊ฒ ์ง๋ง 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
