Skip to content

Latest commit

ย 

History

History
743 lines (540 loc) ยท 27 KB

File metadata and controls

743 lines (540 loc) ยท 27 KB

๋ชฉ์ฐจ



Logback ์ดํ•ดํ•˜๊ธฐ

์ž๋ฐ” ๋กœ๊น… ํ”„๋ ˆ์ž„์›Œํฌ ํžˆ์Šคํ† ๋ฆฌ์™€ sl4fj ์ดํ•ดํ•˜๊ธฐ์— ์ด์–ด ์ด๋ฒˆ ๊ธ€์€ slf4j์˜ binding module์ค‘ ํ•˜๋‚˜์ธ Logback์„ ์ •๋ฆฌํ•ด๋ณด๊ณ ์žํ•œ๋‹ค.

ceki Gulcรผ๊ฐ€ ์ž๋ฐ” ๋กœ๊น… ํ”„๋ ˆ์ž„์›Œํฌ์˜ ํ‘œ์ค€ ์ธํ„ฐํŽ˜์ด์Šค ์ŠคํŽ™์ธ slf4j๋ฅผ ๊ฐœ๋ฐœํ•˜๋ฉด์„œ, ์ž์‹ ์ด ๊ฐœ๋ฐœํ•œ log4j์˜ ์—ฌ๋Ÿฌ๊ฐ€์ง€ ๋‹จ์ ์„ ๊ทน๋ณตํ•˜๊ธฐ์œ„ํ•ด slf4j ๊ตฌํ˜„์ฒด์ธ Logback๋„ ๊ฐ™์ด ๊ฐœ๋ฐœํ•˜์˜€๋‹ค๊ณ ํ•œ๋‹ค.

์ด๋ฒˆ ๊ธ€์€ Logback์˜ ๊ตฌ์กฐ๋ฅผ ๊ฐ„๋‹จํžˆ ์‚ดํŽด๋ณด๊ณ , ๊ฐ„๋‹จํ•œ ํ•™์Šต ํ…Œ์ŠคํŠธ์™€ ํ•จ๊ป˜ ์„ค์ •์„ ์–ด๋–ป๊ฒŒ ํ•˜๋Š”์ง€ ์‚ดํŽด๋ณธ๋‹ค.


1 Logback ๋ชจ๋“ˆ ๊ตฌ์กฐ

Logback์€ log4j์˜ ํ›„์† ํ”„๋กœ์ ํŠธ๋กœ log4j๊ฐ€ ๋– ๋‚˜๋Š” ์œ„์น˜๋ฅผ ์ด์–ด๋ฐ›๊ธฐ ์œ„ํ•ด ํƒ„์ƒํ•˜์˜€๋‹ค.

๊ทธ๋Ÿฌ๋ฏ€๋กœ Logback ์•„ํ‚คํ…์ฒ˜๋Š” ๋งŽ์€ ํ™˜๊ฒฝ์—์„œ ์ ์šฉ ๊ฐ€๋Šฅํ•  ์ •๋„๋กœ ์ผ๋ฐ˜์ ์ด๊ณ  ์œ ์—ฐํ•˜๋‹ค.

์ผ๋ฐ˜์ ์ด๊ณ  ์œ ์—ฐํ•œ ๊ตฌ์กฐ๋ฅผ ์œ„ํ•ด Logback์€ ์„ธ ๊ฐ€์ง€ ๋ชจ๋“ˆ๋กœ ๊ตฌ์„ฑ๋˜์–ด์žˆ๋‹ค.

  1. logback-core
    • ๋‹ค๋ฅธ ๋‘ ๋ชจ๋“ˆ์˜ ํ† ๋Œ€๋ฅผ ๋งˆ๋ จํ•œ๋‹ค. (๊ธฐ๋ฐ˜์ด ๋˜๋Š” ๋ชจ๋“ˆ)
    • Appender, Layout๋“ฑ Logback์„ ์‚ฌ์šฉํ•˜๋Š”๋ฐ ๊ผญ ํ•„์š”ํ•œ ๊ธฐ๋ฐ˜ ๋ชจ๋“ˆ์ด๋‹ค.
  2. logback-classic
    • logback-core๋ชจ๋“ˆ์„ ํ™•์žฅํ•œ ๋ชจ๋“ˆ๋กœ์„œ, slf4j api module๋ฅผ ๊ตฌํ˜„ํ•œ ๋ชจ๋“ˆ์ด๊ธฐ๋„ํ•˜๋‹ค.
    • ์‰ฝ๊ฒŒ ์–˜๊ธฐํ•ด logback-core์™€ slfj4 api ๋‘ ๋ชจ๋“ˆ์„ ํฌํ•จํ•˜๊ณ ์žˆ๋‹ค๊ณ  ๋ณด๋ฉด ๋œ๋‹ค.
      • ์ฐธ๊ณ ๋กœ slf4j api๊ฐ€ Logger์— ๋Œ€ํ•œ ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ํฌํ•จํ•˜๊ณ ์žˆ๋‹ค.
  3. logback-access
    • Tomcat์ด๋‚˜ Jetty์™€ ๊ฐ™์€ ์„œ๋ธ”๋ฆฟ ์ปจํ…Œ์ด๋„ˆ์™€ ํ†ตํ•ฉ๋ผ HTTP-Access ๋กœ๊ทธ ๊ธฐ๋Šฅ์„ ์ œ๊ณตํ•œ๋‹ค.

2 Logback ์„ค์ •

Logback์€ slf4j์˜ binding module๋กœ์จ slf4j๋ฅผ ๊ตฌํ˜„ํ•œ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์ด๋ฏ€๋กœ, ๋‹น์—ฐํžˆ slf4j์™€ ๊ฐ™์ด ์‚ฌ์šฉํ•˜๊ฒŒ๋œ๋‹ค.

๊ทธ๋ฆฌ๊ณ  Logback์€ ์„ธ ๊ฐ€์ง€ ์ฃผ์š” ํด๋ž˜์Šค๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ๋™์ž‘ํ•˜๊ฒŒ๋œ๋‹ค.

  • Logger (logback-classic ๋ชจ๋“ˆ์˜ ์ผ๋ถ€)
    • ์‹ค์ œ ๋กœ๊น…์„ ์ˆ˜ํ–‰ํ•˜๋Š” ํด๋ž˜์Šค.
    • LoggerFactory๋กœ๋ถ€ํ„ฐ Logger ๊ฐ์ฒด๋ฅผ ๋ถˆ๋Ÿฌ์™€ ๋กœ๊ทธ๋ฅผ ์ฐ๋Š” ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•œ๋‹ค.
  • Appender (logback-core ๋ชจ๋“ˆ์˜ ์ผ๋ถ€)
    • ๋กœ๊ทธ๋ฅผ ๊ธฐ๋ก (write)ํ•˜๋Š” ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•˜๋Š” ํด๋ž˜์Šค.
    • ๋กœ๊ทธ ๋ฉ”์‹œ์ง€๋ฅผ ์ถœ๋ ฅํ•  ๋Œ€์ƒ์„ ๊ฒฐ์ • ๋ฐ ์„ค์ •ํ•œ๋‹ค.
  • Layout (logback-core ๋ชจ๋“ˆ์˜ ์ผ๋ถ€)
    • ๋กœ๊ทธ๋ฅผ ์ง€์ •ํ•œ ํ˜•์‹์œผ๋กœ ๋ณ€ํ™˜ํ•˜๋Š” ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•˜๋Š” ํด๋ž˜์Šค. ํ˜„์žฌ๋Š” Encoder๋ฅผ ๋งŽ์ด ์‚ฌ์šฉํ•œ๋‹ค.
    • ๋กœ๊ทธ๋ฅผ ๋ฐ”์ดํŠธ ๋ฐฐ์—ด๋กœ ๋ณ€ํ™˜ํ•˜๊ณ , ๋ฐ”์ดํŠธ ๋ฐฐ์—ด์„ OutputStream์— ์“ฐ๊ธฐํ•˜๋Š” ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•˜๋Š”๋ฐ ์ด๋•Œ ์›ํ•˜๋Š” ํฌ๋งท์œผ๋กœ ๋ณ€ํ™˜ํ•  ์ˆ˜ ์žˆ๋‹ค.

์ด ์„ธ ๊ฐ€์ง€ ์ปดํฌ๋„ŒํŠธ๊ฐ€ ํ•จ๊ป˜ ๋™์ž‘ํ•จ์œผ๋กœ์จ ๋ฉ”์‹œ์ง€ ํƒ€์ž…์ด๋‚˜ ๋ ˆ๋ฒจ์— ๋”ฐ๋ผ ์ด๋ฅผ ๊ธฐ๋กํ•  ์ˆ˜ ์žˆ๊ณ , ๋ฉ”์‹œ์ง€์˜ ํฌ๋งท๊ณผ ๋ฆฌํฌํŒ… ์œ„์น˜๋ฅผ ์ œ์–ดํ•  ์ˆ˜ ์žˆ๋‹ค.


2-1 Logger

Logger๋Š” logback-classic ๋ชจ๋“ˆ์— ์œ„์น˜ํ•˜๊ณ ์žˆ๋Š”๋ฐ, ์ •ํ™•ํžˆ๋Š” slf4j-api ๋ชจ๋“ˆ์— ์œ„์น˜ํ•œ๋‹ค.

Logger.java

package org.slf4j; 
public interface Logger {

  // Printing methods: 
  public void trace(String message);
  public void debug(String message);
  public void info(String message); 
  public void warn(String message); 
  public void error(String message); 
}

๋‹ค์„ฏ ๊ฐ€์ง€์˜ ๋ ˆ๋ฒจ์„ ์ •์˜ํ•˜๊ณ ์žˆ์œผ๋ฉฐ ์•„๋ž˜์™€ ๊ฐ™์ด ์ฝ”๋“œ์—์„œ ๋กœ๊ทธ๋ฅผ ์ฐ๊ณ ์‹ถ์€ ๋ถ€๋ถ„์— ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

Slf4jApiModuleHelloWorld.java

Logger logger = LoggerFactory.getLogger(Slf4jApiModuleHelloWorld.class);
logger.trace("Trace Hello World");
logger.debug("Debug Hello World");
logger.info("Info Hello World");
logger.warn("Warn Hello World");
logger.error("Error Hello World");

๐Ÿ’โ€โ™‚๏ธ ๋ชจ๋“  ๋‹จ์ผ Logger๋Š” LoggerContext์— ์—ฐ๊ฒฐ๋˜๋ฉฐ, LoggerContext๋Š” Logger ๊ณ„์ธต ๊ตฌ์กฐ๋กœ ์ด๋“ค์„ ์ƒ์„ฑ ๋ฐ ์ •๋ ฌํ•˜๊ณ  ๊ด€๋ฆฌํ•œ๋‹ค.

LoggerContext์— ๋ชจ๋“  Logger๋“ค์ด ์—ฐ๊ฒฐ๋˜๋ฉฐ, Logger์˜ ์ƒ์„ฑ๊ณผ ๊ณ„์ธต ๊ตฌ์กฐ๋ฅผ ์„ค์ •ํ•  ์ˆ˜ ์žˆ๋‹ค.

์ด๋•Œ Logger๋Š” ๊ณ„์ธต์  ๋ช…๋ช… ๊ทœ์น™์„ ๋”ฐ๋ฅธ๋‹ค.

Logger์˜ ์ด๋ฆ„์ด .(dot)์— ์˜ํ•ด ํ•˜์œ„ Logger ์ด๋ฆ„์˜ ์ ‘๋‘์–ด๊ฐ€ ๋  ๊ฒฝ์šฐ ์ด๋Š” ๋‹ค๋ฅธ Logger์˜ ์กฐ์ƒ์ด๋˜๋Š” ๊ตฌ์กฐ๋‹ค. -> ๊ณ„์ธต๊ตฌ์กฐ

  • com.foo์˜ Logger๋Š” com.foo.Bar์ธ Logger์˜ ๋ถ€๋ชจ์ด๋‹ค.
  • java์˜ Logger๋Š” java.util์˜ ๋ถ€๋ชจ์ด์ž, java.util.Vector์˜ ์กฐ์ƒ์ด๋œ๋‹ค.

์ด๋Ÿฌํ•œ ํŠน์ง•์„ ์ด์šฉํ•˜์—ฌ ๊ฐœ๋ฐœ์ž๊ฐ€ ์„ค์ •ํ•œ ๋ถ„๋ฅ˜ ๊ธฐ์ค€์— ๋”ฐ๋ผ ๊ณ„์ธต๊ตฌ์กฐ๋ณ„ ํŠน์ • ๋ ˆ๋ฒจ์˜ ๋กœ๊ทธ๋ฅผ ํ™œ์„ฑํ™”/๋น„ํ™œ์„ฑํ™”ํ•  ์ˆ˜ ์žˆ๋‹ค.


์‰ฝ๊ฒŒ ์–˜๊ธฐํ•˜๋ฉด, ๋ชจ๋“  ๋กœ๊ทธ๋Š” ๋ ˆ๋ฒจ์„ ์„ค์ •ํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ, ๋ ˆ๋ฒจ์„ ์ƒ์†๋œ๋‹ค.

๋ชจ๋“  Logger๋Š” Level์„ ์ง€์ •ํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ, ๋ชจ๋“  ๋ ˆ๋ฒจ์€ ch.qos.logger.classic.level ํด๋ž˜์Šค์— ์ •์˜๋˜์–ด์žˆ๋‹ค.

๋งŒ์•ฝ ์ฃผ์–ด์ง„ Logger์˜ ๋ ˆ๋ฒจ์ด ์ง€์ •๋˜์ง€ ์•Š๋Š”๋‹ค๋ฉด ์ง€์ •๋œ ๋ ˆ๋ฒจ์„ ๊ฐ€์ง„ ๊ฐ€์žฅ ๊ฐ€๊นŒ์šด ์กฐ์ƒ์—์„œ ๋ ˆ๋ฒจ์„ ์ƒ์†๋ฐ›๋Š”๋‹ค.

์ฆ‰, ์ฃผ์–ด์ง„ Logger A์˜ ์œ ํšจ ๋ ˆ๋ฒจ์€ A๋กœ๋ถ€ํ„ฐ root๋ฅผ ํ–ฅํ•ด ๊ณ„์ธต ๊ตฌ์กฐ๋ฅผ ๊ฑฐ์Šฌ๋Ÿฌ ์˜ฌ๋ผ๊ฐ€๋ฉด์„œ ๋งŒ๋‚˜๋Š” ์ฒซ ๋ฒˆ์งธ null์ด ์•„๋‹Œ ๋ ˆ๋ฒจ๊ณผ ๊ฐ™๋‹ค.


๐Ÿ’โ€โ™‚๏ธ ๋ฃจํŠธ Logger

๋ฃจํŠธ Logger์˜ ๊ฒฝ์šฐ Logger ๊ณ„์ธต ๋งจ ์œ„์— ์œ„์น˜ํ•œ๋‹ค.

๊ทธ๋ฆฌ๊ณ  ๋ฃจํŠธ Logger๋Š” ์•„๋ž˜์™€ ๊ฐ™์ด ๊ฐ€์ ธ์˜ฌ ์ˆ˜ ์žˆ๋‹ค.

Logger rootLogger = LoggerFactory.getLogger(org.slf4j.Logger.ROOT_LOGGER_NAME);

๊ธฐํƒ€ Logger๋„ ์œ„์™€ ๊ฐ™์€ ์ฝ”๋“œ์™€ ๋™์ผํ•˜๊ฒŒ ๊ฐ€์ ธ์˜ฌ ์ˆ˜ ์žˆ๋‹ค. (๋งค๊ฐœ๋ณ€์ˆ˜๋งŒ ๋ฐ”๊ฟ”์ฃผ๋ฉด ๋œ๋‹ค.)


๐Ÿ’โ€โ™‚๏ธ ๋ ˆ๋ฒจ ์ˆœ์„œ

์–ด๋–ป๊ฒŒ ์ •์˜ํ•˜๋А๋ƒ์— ๋”ฐ๋ผ์„œ, ํ˜ธ์ถœ๋˜๋Š” ์ถœ๋ ฅ ๋ฉ”์„œ๋“œ๊ฐ€ ๋กœ๊น… ์š”์ฒญ ์ˆ˜์ค€์„ ๊ฒฐ์ •ํ•œ๋‹ค.

์˜ˆ๋ฅผ ๋“ค์–ด, log.info(...)๋Š” INFO ๋ ˆ๋ฒจ์˜ ๋กœ๊น… ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•œ ๊ฒƒ์ด๋‹ค.


์ด๋•Œ ๋งŒ์•ฝ ๋กœ๊น… ์š”์ฒญ ๋ ˆ๋ฒจ์ด ํ•ด๋‹น Logger์˜ ์œ ํšจ ๋ ˆ๋ฒจ ์ด์ƒ์ธ ๊ฒฝ์šฐ์—๋งŒ ํ•ด๋‹น ๋กœ๊ทธ๊ฐ€ ๋™์ž‘ํ•˜๋ฉฐ, ๊ทธ๋ ‡์ง€์•Š์œผ๋ฉด ์š”์ฒญ์€ ๋น„ํ™œ์„ฑํ™”๋œ๋‹ค.

์ฆ‰, ์œ ํšจ ๋ ˆ๋ฒจ q๋ฅผ ๊ฐ–๋Š” Logger์—์„œ ํ˜ธ์ถœ๋œ ๋ ˆ๋ฒจ p์˜ ๋กœ๊ทธ ์š”์ฒญ์€ p >= q์ธ ๊ฒฝ์šฐ์—๋งŒ ํ™œ์„ฑํ™”(๋กœ๊ทธ๊ฐ€ ์ฐํžŒ๋‹ค)๋œ๋‹ค.

์ด๋ฅผ ๊ฐ„๋‹จํžˆ ํ‘œ๋กœ ์ •๋ฆฌํ•˜๋ฉด ์•„๋ž˜์™€ ๊ฐ™๋‹ค.


์ถœ์ฒ˜: http://logback.qos.ch/manual/architecture.html#basic_selection

๊ฐ„๋‹จํžˆ ๋งํ•ด ๋กœ๊น… ๋ ˆ๋ฒจ์€ ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์ˆœ์„œ๋กœ ๋˜์–ด์žˆ๋‹ค: TRACE < DEBUG < INFO < WARN < ERROR

์˜ˆ์‹œ

import ch.qos.logback.classic.Level;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
....

// get a logger instance named "com.foo". Let us further assume that the
// logger is of type  ch.qos.logback.classic.Logger so that we can
// set its level
ch.qos.logback.โ€‹classic.Logger logger = 
        (ch.qos.logback.โ€‹classic.Logger) LoggerFactory.โ€‹getLogger("com.foo");
//set its Level to INFO. The setLevel() method requires a logback logger
logger.setLevel(Level. INFO);

Logger barlogger = LoggerFactory.โ€‹getLogger(โ€‹"com.foo.Bar");

// This request is enabled, because WARN >= INFO
logger.warn("Low fuel level.");

// This request is disabled, because DEBUG < INFO. 
logger.debug("Starting search for nearest gas station.");

// The logger instance barlogger, named "com.foo.Bar", 
// will inherit its level from the logger named 
// "com.foo" Thus, the following request is enabled 
// because INFO >= INFO. 
barlogger.info("Located nearest gas station.");

// This request is disabled, because DEBUG < INFO. 
barlogger.debug("Exiting gas station search");

๐Ÿ’โ€โ™‚๏ธ LoggerContext์˜ Logger๋Š” ์‹ฑ๊ธ€ํ†ค์œผ๋กœ ๋™์ž‘ํ•œ๋‹ค.

// ์•„๋ž˜ Logger๋Š” ๊ฐ™์€ ์ฃผ์†Œ๋ฅผ ๊ฐ€์ง„๋‹ค.
Logger x = LoggerFactory.getLogger("wombat"); 
Logger y = LoggerFactory.getLogger("wombat");

์œ„ ์˜ˆ์‹œ์™€ ๊ฐ™์ด LoggerFactory.getLogger ๋ฉ”์„œ๋“œ๋Š” ๊ฐ™์€ ์ด๋ฆ„์„ ๋งค๊ฐœ๋ณ€์ˆ˜๋กœ ๋„˜๊ธฐ๋ฉด ํ•ญ์ƒ ๊ฐ™์€ ์ธ์Šคํ„ด์Šค๋ฅผ ๋ฐ˜ํ™˜ํ•œ๋‹ค. (์‹ฑ๊ธ€ํ†ค)


2-2 Appender

Logback์€ ๋‹ค์–‘ํ•œ ๋ชฉ์ ์ง€๋กœ ๋กœ๊น… ๋‚ด์šฉ์„ ๋ณด๋‚ด๊ณ  ์ถœ๋ ฅํ•  ์ˆ˜ ์žˆ๋‹ค.

๊ทธ๋ฆฌ๊ณ  Logback์—์„  ์ด์™€ ๊ฐ™์ด ๋กœ๊ทธ ์ถœ๋ ฅ ๋ชฉ์ ์ง€์— ๊ธฐ๋กํ•˜๋Š”์—ญํ• ์„ Appender๊ฐ€ ๋‹ด๋‹นํ•œ๋‹ค.

๋กœ๊ทธ ๋ฉ”์‹œ์ง€๋ฅผ ์ถœ๋ ฅ, ์ €์žฅ, ์ „์†ก๋  ๋Œ€์ƒ์„ ๊ฒฐ์ •ํ•˜๋Š” ์—ญํ• .

๋ชจ๋“  Appender๋Š” ch.qos.logback.core.Appender๋ฅผ ๊ตฌํ˜„ํ•œ๋‹ค.

public interface Appender<E> extends LifeCycle, ContextAware, FilterAttachable {

  public String getName();
  public void setName(String name);
  void doAppend(E event);
}

doAppend๊ฐ€ ํ•ต์‹ฌ ๋ฉ”์„œ๋“œ์ด๋ฉฐ, ๋กœ๊น… ์ด๋ฒคํŠธ๋ฅผ ์ ์ ˆํ•œ ํ˜•์‹์œผ๋กœ ์ ์ ˆํ•œ ์ถœ๋ ฅ ์žฅ์น˜์— ์ถœ๋ ฅํ•˜๋Š” ์—ญํ• ์„ ์ˆ˜ํ–‰ํ•œ๋‹ค.

๊ด€๋ จ๋œ ๋” ์ž์„ธํ•œ ๋‚ด์šฉ์€ ๊ณต์‹ ๋ฌธ์„œ๋ฅผ ์ฐธ๊ณ .


๐Ÿ’โ€โ™‚๏ธ OutputStreamAppender์˜ ํ•˜์œ„ ํด๋ž˜์Šค๋“ค์ด ์ž์ฃผ ์‚ฌ์šฉ๋œ๋‹ค.


์ถœ์ฒ˜: https://logback.qos.ch/manual/appenders.html

OutputStreamAppender๋Š” ์ž์ฃผ ์‚ฌ์šฉ๋˜๋Š” ์•„๋ž˜ Appender๋“ค์˜ ์ƒ์œ„ ํด๋ž˜์Šค์ด๋‹ค.

  • UnsynchronizedAppenderBase
    • ๊ธฐ๋ณธ์ ์œผ๋กœ ์‚ฌ์šฉ๋˜๋Š” ์ถ”์ƒ ํด๋ž˜์Šค์ธ AppenderBase๋Š” doAppend()๊ฐ€ synchronized๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค.
    • ๋ฐ˜๋ฉด์—, UnsynchronizedAppenderBase๋Š” ๋™๊ธฐ๋กœ ๋™์ž‘ํ•˜๊ธธ์›์น˜์•Š์„๋•Œ ์‚ฌ์šฉ๋œ๋‹ค.
  • OutputStreamAppender
    • OutputStream์— ๋กœ๊ทธ ์ด๋ฒคํŠธ appendํ•˜๋Š” ์—ญํ• ์„ํ•œ๋‹ค.

๐Ÿ’โ€โ™‚๏ธ ConsoleAppender

๋กœ๊ทธ๋ฅผ OuputStream์— writeํ•˜์—ฌ, ์ตœ์ข…์ ์œผ๋กœ ์ฝ˜์†”์— ์ถœ๋ ฅ๋˜๋„๋กํ•œ๋‹ค.

<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>%-4relative [%thread] %-5level %logger{35} -%kvp- %msg %n</pattern>
    </encoder>
  </appender>

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

๐Ÿ’โ€โ™‚๏ธ FileAppender

๋กœ๊ทธ์˜ ๋‚ด์šฉ์„ ์ง€์ •๋œ File์— ์ €์žฅํ•œ๋‹ค.

๋งค ๋กœ๊ทธ๋งˆ๋‹ค ์œ ๋‹ˆํฌํ•œ ์ด๋ฆ„์˜ ์ƒˆ๋กœ์šด ๋กœ๊ทธ ํŒŒ์ผ์— ๊ธฐ๋กํ•˜๊ธฐ์œ„ํ•ด์„œ timestamp๋ฅผ ์ด์šฉํ•˜์—ฌ ํƒ€๊นƒ ํŒŒ์ผ์„ ๋™์ ์œผ๋กœ ์„ค์ •ํ•ด์ค„ ์ˆ˜ ์žˆ๋‹ค.

<configuration>

  <!-- Insert the current time formatted as "yyyyMMdd'T'HHmmss" under
       the key "bySecond" into the logger context. This value will be
       available to all subsequent configuration elements. -->
  <timestamp key="bySecond" datePattern="yyyyMMdd'T'HHmmss"/>

  <appender name="FILE" class="ch.qos.logback.core.FileAppender">
    <!-- use the previously created timestamp to create a uniquely
         named log file -->
    <file>log-${bySecond}.txt</file>
    <encoder>
      <pattern>%logger{35} -%kvp- %msg%n</pattern>
    </encoder>
  </appender>

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

๐Ÿ’โ€โ™‚๏ธ RollingFileAppender

FileAppender๋ฅผ ์ƒ์†๋ฐ›์€ Appender๋กœ, ๋‚ ์งœ, ์ตœ๋Œ€ ์šฉ๋Ÿ‰๋“ฑ์„ ์„ค์ •ํ•˜์—ฌ ์ง€์ •ํ•œ ํŒŒ์ผ๋ช… ํŒจํ„ด์— ๋”ฐ๋ผ ๋กœ๊ทธ๊ฐ€ ๋‹ค๋ฅธ ํŒŒ์ผ์— ๊ธฐ๋ก๋˜๋Š” ๊ธฐ๋Šฅ์„ ์ œ๊ณตํ•œ๋‹ค.

์˜ˆ๋ฅผ ๋“ค์–ด, ํŠน์ • ํŒŒ์ผ ์ด๋ฆ„์œผ๋กœ ๋กœ๊ทธ๋ฅผ appendํ•˜๋‹ค ํŠน์ • ์กฐ๊ฑด (์‹œ๊ฐ„, ์šฉ๋Ÿ‰)์— ๋‹ค๋‹ค๋ฅด๋ฉด, ์ด์ „ ํŒŒ์ผ์„ ์ €์žฅํ•˜๊ณ , ๋‹ค๋ฅธ ๋กœ๊ทธ ํƒ€๊ฒŸํŒŒ์ผ์„ ๋งŒ๋“ค์–ด ์ €์žฅํ•˜๋Š” ํ˜•์‹์ด๋‹ค.

์„œ๋ฒ„ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์—์„œ ๊ฐ€์žฅ ์ž์ฃผ ์‚ฌ์šฉ๋˜๋Š” Appender๋กœ ๋Œ€๋Ÿ‰ ๋กœ๊ทธ ๊ธฐ๋ก์— ํšจ๊ณผ์ ์ด๋‹ค.

2๊ฐ€์ง€์˜ Rolling ์ •์ฑ…์ด ์กด์žฌํ•˜๋ฉฐ, ๊ณตํ†ต์ ์œผ๋กœ ์•„๋ž˜ properties๋ฅผ ๊ฐ€์ง„๋‹ค.

  • file: ํƒ€๊นƒํŒŒ์ผ์˜ ์ด๋ฆ„.
  • append: append ์ •์ฑ….
    • true - ์ด์–ด์“ฐ๊ธฐ
    • false - ๋ฎ์–ด์“ฐ๊ธฐ
  • encoder: ๋กœ๊ทธ ์ด๋ฒคํŠธ๊ฐ€ OutputStreamAppender์— ๊ธฐ๋ก๋˜๋Š” ๋ฐฉ์‹.
    • ex. LogstashEncoder
  • rollingPolicy: rollover ๋ฐœ์ƒ์‹œ RollingFileAppender์˜ ํ–‰๋™์„ ์ •์˜.
  • triggerPolicy: rollover ํ™œ์„ฑํ™” ์‹œ์  ์ •์˜.
  • predent: prudent mode ์—ฌ๋ถ€.

TimeBasedRollingPolicy

์‹œ๊ฐ„์— ๊ธฐ๋ฐ˜ํ•˜์—ฌ Rolling ์ •์ฑ…์„ ์ •์˜ํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ, ๋ณดํ†ต ์ผ ๋˜๋Š” ์›” ๋‹จ์œ„๋กœ ์„ค์ •ํ•œ๋‹ค.

<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>

์œ„ ๋กœ๊ทธ ์„ค์ •์„ ํ•ด์„ํ•˜๋ฉด Application์ด ๋™์ž‘ํ•  ๋•Œ ํ™œ์„ฑํ™”๋œ logFile.log์— ๋กœ๊ทธ๊ฐ€ ์Œ“์ง€๋งŒ, ๋งค์ผ ์ž์ •์ด ์ง€๋‚˜๋ฉด logFile.2023-03-17.log์™€ ๊ฐ™์€ ์ด๋ฆ„์œผ๋กœ ์•„์นด์ด๋ธŒ๋œ๋‹ค.

์•„์นด์ด๋ธŒ ๋˜๋Š” ํŒŒ์ผ์˜ ๊ฐœ์ˆ˜๋Š” ์ตœ๋Œ€ 30๊ฐœ์ด๋ฉฐ, ์•„์นด์ด๋ธŒ ๋œ ํŒŒ์ผ์˜ ํฌ๊ธฐ๋Š” ์ด 3GB๋ฅผ ๋„˜์„ ์ˆ˜ ์—†๋‹ค.

์ด ์กฐ๊ฑด์„ ๋งŒ์กฑํ•˜์ง€ ๋ชปํ•  ๊ฒฝ์šฐ ์•„์นด์ด๋ธŒ๋œ ๋กœ๊ทธ ํŒŒ์ผ ์ค‘ ๊ฐ€์žฅ ์˜ค๋ž˜๋œ ํŒŒ์ผ์„ ์‚ญ์ œํ•œ๋‹ค.

์„ค์ •๋ณ„ ์ž์„ธํ•œ ์„ค๋ช…์€ ์•„๋ž˜๋ฅผ ์ฐธ๊ณ .

  • fileNamePattern (ํ•„์ˆ˜)
    • ์ €์žฅ๋  ๋กœ๊ทธ ํŒŒ์ผ์˜ ํŒจํ„ด์„ ์ •์˜.
    • %d๋ฅผ ์ด์šฉํ•ด ํŒŒ์ผ์˜ ์ ์ ˆํ•œ ๋ถ€๋ถ„์„ datetime ํŒจํ„ด์œผ๋กœ ์ •์˜ํ•œ๋‹ค. (ex. %d{yyyy-MM-dd})
  • maxHistory
    • ์ €์žฅ๋˜๋Š” ๋กœ๊ทธ ํŒŒ์ผ์˜ ์ตœ๋Œ€ ๊ฐœ์ˆ˜๋ฅผ ์ง€์ •.
    • ex. rollover์„ ํ•˜๋ฃจ ๋งˆ๋‹ค ๋œ๋‹ค๊ณ  ๊ฐ€์ •ํ•  ๋•Œ, maxHistory๋ฅผ 30์œผ๋กœ ์ง€์ •ํ•˜๋ฉด ์ €์žฅ๋˜๋Š” ํŒŒ์ผ์˜ ๊ฐœ์ˆ˜๋Š” ์ตœ๋Œ€ 30์ผ(30๊ฐœ)์ด๋‹ค.
  • totalSizeCap
    • ๋กœ๊ทธ ํŒŒ์ผ์„ ์ €์žฅํ•˜๋Š” ์ €์žฅ์†Œ(๋””๋ ‰ํ† ๋ฆฌ)์˜ ์ตœ๋Œ€ํฌ๊ธฐ๋ฅผ ์ง€์ •.
    • totalSizeCap์„ ์ดˆ๊ณผํ•˜๋ฉด ๊ฐ€์žฅ ์˜ค๋ž˜๋œ ํŒŒ์ผ์ด ์‚ญ์ œ๋˜๋Š” ๊ตฌ์กฐ.
    • maxHistory์™€ ๊ฐ™์ด ์‚ฌ์šฉ๋  ๊ฒฝ์šฐ, 1์ˆœ์œ„๋กœ maxHistory์— ๋Œ€ํ•˜์—ฌ ์ฒ˜๋ฆฌ๋œ ํ›„ totalSizeCap์ด ์ ์šฉ๋จ.
  • cleanHistoryOnStart
    • ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์ด ์‹œ์ž‘๋  ๋•Œ ๋กœ๊ทธ ํŒŒ์ผ์„ ๋ชจ๋‘ ์ง€์šด๋‹ค. (๋””ํดํŠธ๋Š” true)

fileNamePattern์— ๋”ฐ๋ผ rollover๋˜๋Š” ์ฃผ๊ธฐ๊ฐ€ ๋‹ฌ๋ผ์ง„๋‹ค.

  • .%d: default %d๋Š” yyyy-MM-dd. ๋งค์ผ ์ž์ •์— ์ƒˆ๋กœ์šด ๋กœ๊ทธ ํŒŒ์ผ๋กœ rollover๋œ๋‹ค.
  • .%d{yyyy-MM-dd_HH-mm}:๋งค ๋ถ„ ์ƒˆ๋กœ์šด ๋กœ๊ทธ ํŒŒ์ผ๋กœ rollover๋œ๋‹ค.
  • /%d{yyyy/MM}/foo.txt: ๋งค์›” ์ƒˆ๋กœ์šด ๋””๋ ‰ํ† ๋ฆฌ๋ฅผ ๋งŒ๋“ค์–ด ํ•˜์œ„์— foo.txt ํŒŒ์ผ๋กœ rolloverํ•œ๋‹ค.
  • .%d.gz: ๋งค์ผ ์ƒˆ๋กœ์šด ๋กœ๊ทธ ํŒŒ์ผ๋กœ rolloverํ•˜๊ณ , ์ด์ „ ๋กœ๊ทธํŒŒ์ผ์€ GZIP์œผ๋กœ ์••์ถ•๋œ๋‹ค.

SizeAndTimeBasedRollingPolicy

TimeBasedRollingPolicy์— ๋”ํ•ด ๊ฐ๊ฐ์˜ ๋กœ๊ทธ ํŒŒ์ผ์˜ ํฌ๊ธฐ์— ์ œํ•œ์„์ฃผ๋Š” RollingPolicy์ด๋‹ค.

TimeBasedRollingPolicy์™€ ๋‹ค๋ฅด๊ฒŒ fileNamePattern์— %i์™€ %d๊ฐ€ ํ•„์ˆ˜์ด๋ฉฐ, ๊ฐ๊ฐ์˜ ๋กœ๊ทธ ํŒŒ์ผ์ด ๊ฐ€์งˆ ์ˆ˜ ์žˆ๋Š” ์ตœ๋Œ€ ํฌ๊ธฐ๋ฅผ ์ œํ•œํ•˜๋Š” maxFileSize ์„ค์ •์ด ์ถ”๊ฐ€๋˜์—ˆ๋‹ค.

%i ํ† ํฐ์ด index ์—ญํ• ์„ํ•˜์—ฌ ๋‹ค์Œ ๋กœ๊ทธ ํŒŒ์ผ์˜ ์ด๋ฆ„์„ ๊ฒฐ์ •ํ•œ๋‹ค.

<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>

์ด์™ธ์˜ ๋‹ค์–‘ํ•œ Appender๋Š” ๊ณต์‹ ๋ฌธ์„œ๋ฅผ ์ฐธ๊ณ .


2-3 Encoder (Layout)

Encoder๋Š” ๋กœ๊ทธ๋ฅผ ๋ฐ”์ดํŠธ ๋ฐฐ์—ด๋กœ ๋ณ€ํ™˜ํ•˜๊ณ , ๋ฐ”์ดํŠธ ๋ฐฐ์—ด์„ OutputStream์— ์“ฐ๊ธฐํ•˜๋Š” ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•œ๋‹ค.

์ด๋•Œ ๋กœ๊ทธ๋ฅผ ๊ฐ ์ƒํ™ฉ๋ณ„ ์›ํ•˜๋Š” ํฌ๋งท์œผ๋กœ ๋ณ€ํ™˜ํ•  ์ˆ˜ ์žˆ๋‹ค.

logback 0.9.19๋ถ€ํ„ฐ๋Š” layout๋Š” Deprecated๋˜์—ˆ์œผ๋ฉฐ, Encoder ์‚ฌ์šฉ์„ ์ง€ํ–ฅํ•œ๋‹ค. ์ฐธ๊ณ 


Encoder.java

package ch.qos.logback.core.encoder;

public interface Encoder<E> extends ContextAware, LifeCycle {

   /**
   * This method is called when the owning appender starts or whenever output
   * needs to be directed to a new OutputStream, for instance as a result of a
   * rollover.
   */
  void init(OutputStream os) throws IOException;

  /**
   * Encode and write an event to the appropriate {@link OutputStream}.
   * Implementations are free to defer writing out of the encoded event and
   * instead write in batches.
   */
  void doEncode(E event) throws IOException;


  /**
   * This method is called prior to the closing of the underling
   * {@link OutputStream}. Implementations MUST not close the underlying
   * {@link OutputStream} which is the responsibility of the owning appender.
   */
  void close() throws IOException;
}

Encoder ์ธํ„ฐํŽ˜์ด์Šค๋Š” ์œ„์™€ ๊ฐ™์œผ๋ฉฐ, ์ž…๋ ฅ์œผ๋กœ ๋“ค์–ด์˜ค๋Š” ๋กœ๊ทธ Event๋ฅผ ๋ฐ”์ดํŠธ ๋ฐฐ์—ด๋กœ ๋ณ€ํ™˜ํ•˜๊ณ  ๊ฒฐ๊ณผ ๋ฐ”์ดํŠธ ๋ฐฐ์—ด์„ ์ ์ ˆํ•œ OutputStream์— ๊ธฐ๋กํ•œ๋‹ค.

์ด๋•Œ Appender๊ฐ€ ๊ด€๋ฆฌํ•˜๋Š” OutputStream์— ๋ฐ”์ดํŠธ ๋ฐฐ์—ด์„ ์–ธ์ œ ๋ฌด์—‡์„ ์“ฐ๊ธฐํ• ์ง€ ์ œ์–ดํ•  ์ˆ˜ ์žˆ๋‹ค.


๐Ÿ’โ€โ™‚๏ธ PatternLayoutEncoder

๋ณดํ†ต ๋กœ๊น…์šฉ์œผ๋กœ Logback์„ ์‚ฌ์šฉํ•  ๋•Œ PatternLayoutEncoder๊ฐ€ ์ผ๋ฐ˜์ ์œผ๋กœ ์‚ฌ์šฉ๋œ๋‹ค.

๊ธฐ์กด์˜ PatternLayout๋„ ๋ž˜ํ•‘ํ•œ ํด๋ž˜์Šค์ธ LayoutWrappingEncoder๋กœ ํ˜ธํ™˜๋˜๊ฒŒ๋งŒ๋“ค์—ˆ๋‹ค๊ณ ํ•œ๋‹ค.

PatternLayoutEncoder์˜ ์‚ฌ์šฉ๋ฒ•์€ ์•„๋ž˜์™€ ๊ฐ™๋‹ค.

<appender name="FILE" class="ch.qos.logback.core.FileAppender">
  <file>testFile.log</file>
  ...
  <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
    <pattern>%msg%n</pattern>
  </encoder>
</appender>

pattern์€ ๋‹ค์–‘ํ•˜๊ฒŒ ์„ค์ •๊ฐ€๋Šฅํ•˜๋ฉฐ ๊ด€๋ จ๋œ ๋‚ด์šฉ์€ ๊ณต์‹ ๋ฌธ์„œ๋ฅผ ์ฐธ๊ณ ํ•˜์ž.


3 Logback ์„ค์ •ํŒŒ์ผ ๊ตฌ์กฐ

์ง€๊ธˆ๊นŒ์ง€ Logback์˜ ์„ค์ •์€ ์–ด๋–ค ์š”์†Œ๋กœ ๊ตฌ์„ฑ๋˜์—ˆ๋Š”์ง€ ์•Œ์•„๋ณด์•˜์œผ๋‹ˆ, ์ด๋ฒˆ์—” ์–ด๋–ค ๊ตฌ์กฐ๋กœ ์„ค์ •๋˜๋Š”์ง€ ์‚ดํŽด๋ณธ๋‹ค.


3-1 Logback ์„ค์ •ํŒŒ์ผ ์ฐธ์กฐ ์ˆœ์„œ

์ผ๋ฐ˜์ ์ธ Java ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์— Logback ์˜์กด์„ฑ์„ ์ถ”๊ฐ€ํ•˜์—ฌ ์‚ฌ์šฉํ•  ๋•Œ, Logback์€ ContextInitializer.configureByResource ์˜ ๊ตฌํ˜„์—๋”ฐ๋ผ ์„ค์ •์„ ๋กœ๋“œํ•œ๋‹ค.

ํ™•์ธ๊ฒฐ๊ณผ ๋งค ๋ฒ„์ „๋งˆ๋‹ค ์กฐ๊ธˆ์”ฉ ๋‹ค๋ฅธ ๋“ฏํ•˜๋‹ค.

์‚ฌ์šฉํ•˜๋Š” ๋ฒ„์ „์„ ํ™•์ธํ•˜์—ฌ ํ•ด๋‹น ํด๋ž˜์Šค๋ฅผ ์ฐพ์•„ ์–ด๋–ค ์ˆœ์„œ์ธ์ง€ ํ™•์ธํ•˜๋Š” ๊ฒƒ์ด ์ข‹์„ ๋“ฏ ํ•˜๋‹ค.

ํ•„์ž์˜๊ฒฝ์šฐ ๋ณดํ†ต classpath์˜ logback.xml๋งŒ์„ ํ†ตํ•ด ์„ค์ •ํ•œ๋‹ค.


3-2 ์„ค์ •ํŒŒ์ผ ๊ตฌ์กฐ


์ถœ์ฒ˜: http://logback.qos.ch/manual/configuration.html

  • Configuration
  • Appender
    • 0๊ฐœ ํ˜น์€ ๊ทธ ์ด์ƒ
  • Logger
    • 0๊ฐœ ํ˜น์€ ๊ทธ ์ด์ƒ
  • Root
    • ์ตœ๋Œ€ 1๊ฐœ

๐Ÿ’โ€โ™‚๏ธ Appender ์„ค์ •


์ถœ์ฒ˜: http://logback.qos.ch/manual/configuration.html#configuringAppenders

  • <appender>๋ฅผ ์ด์šฉํ•ด์„œ Appender (๋กœ๊น… ๋ชฉ์ ์ง€)๋ฅผ ์„ค์ •ํ•  ์ˆ˜ ์žˆ๋‹ค.
  • <appender>์˜ ๋งค๊ฐœ๋ณ€์ˆ˜
    • name: appender์˜ ์ด๋ฆ„์„ ์„ค์ •ํ•œ๋‹ค.
    • class: appender์˜ ํด๋ž˜์Šค๋ฅผ FQCN์œผ๋กœ ์„ค์ •ํ•œ๋‹ค.
      • ConsoleAppender: ๋กœ๊ทธ๋ฅผ OuputStream์— writeํ•˜์—ฌ, ์ตœ์ข…์ ์œผ๋กœ ์ฝ˜์†”์— ์ถœ๋ ฅ๋˜๋„๋ก ํ•œ๋‹ค.
      • FileAppender: ๋กœ๊ทธ์˜ ๋‚ด์šฉ์„ ์ง€์ •๋œ File์— ์ €์žฅํ•œ๋‹ค.
      • RollingFileAppender: FileAppender๋ฅผ ์ƒ์†๋ฐ›์€ appender๋กœ, ๋‚ ์งœ, ์ตœ๋Œ€ ์šฉ๋Ÿ‰๋“ฑ์„ ์„ค์ •ํ•˜์—ฌ ์ง€์ •ํ•œ ํŒŒ์ผ๋ช… ํŒจํ„ด์— ๋”ฐ๋ผ ๋กœ๊ทธ๊ฐ€ ๋‹ค๋ฅธ ํŒŒ์ผ์— ๊ธฐ๋ก๋˜๋Š” ๊ธฐ๋Šฅ์„ ์ œ๊ณตํ•œ๋‹ค. -> ๋Œ€๋Ÿ‰ ๋กœ๊ทธ ๊ธฐ๋ก์— ํšจ๊ณผ์ .
      • ์ด์™ธ์—๋„ ๋‹ค์–‘ํ•œ appender๋ฅผ ์ œ๊ณตํ•œ๋‹ค. (DBAppender, SMTPAppender๋“ฑ๋“ฑ)
  • <appender>์˜ ์š”์†Œ
    • <layout>, <encoder>, <filter>

๐Ÿ’โ€โ™‚๏ธ Logger ์„ค์ •

  • <logger>๋ฅผ ์ด์šฉํ•ด์„œ Logger๋ฅผ ์„ค์ •ํ•  ์ˆ˜ ์žˆ๋‹ค.
    • ์ฆ‰, ์‹ค์ œ ๋กœ๊ทธ ๊ธฐ๋Šฅ์„ ์ˆ˜ํ–‰ํ•˜๋Š” ๊ฐ์ฒด์ธ Logger๋งˆ๋‹ค ์ด๋ฆ„์„ ๋ถ€์—ฌํ•˜๊ณ  ๋ ˆ๋ฒจ๋“ฑ์„ ์„ค์ •ํ•  ์ˆ˜ ์žˆ๋‹ค.
    • ํ•ด๋‹น ๋กœ๊ฑฐ๊ฐ€ ์‚ฌ์šฉ๋  ํŒจํ‚ค์ง€์™€ ๋กœ๊ทธ ๋ ˆ๋ฒจ์„ ์„ค์ •.
  • <logger>์˜ ๋งค๊ฐœ๋ณ€์ˆ˜
    • name: ๊ณ„์ธต์  Logger ์„ค์ •์— ์œ ์šฉํ•˜๊ฒŒ ์‚ฌ์šฉ๋œ๋‹ค. (ํ•˜๋‚˜)
    • level: ๋กœ๊ฑฐ์˜ ๋ ˆ๋ฒจ์„ ์„ค์ •ํ•œ๋‹ค. (optional)
    • additivity: appender๋ฅผ ์ƒ์†ํ•˜๋„๋ก ํ•  ๊ฒƒ์ธ์ง€ ์„ค์ •ํ•œ๋‹ค. (optional)
  • <logger>์˜ ์š”์†Œ
    • <appender-ref>: appender๋ฅผ ์„ค์ •ํ•  ๋•Œ ์‚ฌ์šฉ๋œ๋‹ค. ๊ฐ ์†Œ์Šค๋กœ๋ถ€ํ„ฐ ์ž…๋ ฅ๋ฐ›์€ ๋กœ๊น… ๋ฉ”์‹œ์ง€๋Š” ๋กœ๊ทธ ๋ ˆ๋ฒจ์— ๋”ฐ๋ผ Appender๋กœ ์ „๋‹ฌ๋œ๋‹ค.
  • ์ฃผ์˜ ์‚ฌํ•ญ
    • ๊ธฐ๋ณธ์ ์œผ๋กœ ์ตœ์ƒ์œ„ ๋กœ๊ฑฐ์ธ Root Logger๋ฅผ ์„ค์ •ํ•ด์ฃผ์–ด์•ผ ํ•œ๋‹ค.

๐Ÿ’โ€โ™‚๏ธ Root ์„ค์ •

  • <root>๋ฅผ ์ด์šฉํ•ด์„œ Root Logger๋ฅผ ์„ค์ •ํ•œ๋‹ค.
  • <root>์˜ ๋งค๊ฐœ๋ณ€์ˆ˜
    • level: ๋ ˆ๋ฒจ์„ ์„ค์ •ํ•œ๋‹ค.
  • <root>์˜ ์š”์†Œ
    • <appender-ref>: appender๋ฅผ ์„ค์ •ํ•  ์ˆ˜ ์žˆ๋‹ค. (<logger>์˜ appender-ref์™€ ๋™์ผ)
  • ์ฃผ์˜ ์‚ฌํ•ญ
    • Root Logger์˜ name์€ ROOT์ด๋ฉฐ, ๋‹ค๋ฅธ ์„ค์ •์„ ์ œ๊ณตํ•˜์ง€ ์•Š๋Š”๋‹ค.

3-3 ์—ฌ๋Ÿฌ๊ฐ€์ง€ ์„ค์ • ์˜ˆ์‹œ


์ฝ˜์†”์— ์ถœ๋ ฅํ•˜๋Š” ์„ค์ • ์˜ˆ์‹œ
<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} - %msg%n</pattern>
    </encoder>
  </appender>

  <logger name="chapters.configuration" level="INFO" />
  <logger name="chapters.configuration.Foo" level="DEBUG" />
  <logger name="{Logger ์ด๋ฆ„ => ํด๋ž˜์Šค ์ด๋ฆ„}" 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>


ํŒŒ์ผ์— ์ถœ๋ ฅํ•˜๋Š” ์„ค์ • ์˜ˆ์‹œ
<configuration>

  <appender name="FILE" class="ch.qos.logback.core.FileAppender">
    <file>{ํŒŒ์ผ ์œ„์น˜}.log</file>

    <encoder>
      <pattern>%date %level [%thread] %logger{10} [%file:%line] %msg%n</pattern>
    </encoder>
  </appender>

  <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
    <encoder>
      <pattern>%msg%n</pattern>
    </encoder>
  </appender>

  <root level="debug">
    <appender-ref ref="FILE" />
    <appender-ref ref="STDOUT" />
  </root>
</configuration>


RollingFileAppender ์„ค์ • ์˜ˆ์‹œ
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <!-- config ํŒŒ์ผ์—์„œ ์‚ฌ์šฉ๋  ์†์„ฑ -->
    <property name="LOGS_ABSOLUTE_PATH" value="/Users/binghe819/Desktop" />

    <!-- ์™ธ๋ถ€ ์„ค์ • ๊ฐ€์ ธ์˜ค๋Š” ์ฝ”๋“œ -->
    <include resource="org/springframework/boot/logging/logback/base.xml"/>

    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
        <layout class="ch.qos.logback.classic.PatternLayout">
            <Pattern>[%d{yyyy-MM-dd HH:mm:ss}:%-3relative][%thread] %-5level %logger{36} - %msg%n</Pattern>
        </layout>
    </appender>

    <appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <file>${LOGS_ABSOLUTE_PATH}/logback.log</file>
        <encoder>
            <pattern>[%d{yyyy-MM-dd HH:mm:ss}:%-3relative][%thread] %-5level %logger{35} - %msg%n</pattern>
        </encoder>
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <fileNamePattern>${LOGS_ABSOLUTE_PATH}/logback.%d{yyyy-MM-dd}.%i.log.gz</fileNamePattern>
            <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
                <maxFileSize>5MB</maxFileSize>
            </timeBasedFileNamingAndTriggeringPolicy>
            <maxHistory>30</maxHistory>
        </rollingPolicy>
    </appender>

    <logger name="org.springframework.web" level="DEBUG">
        <appender-ref ref="STDOUT" />
        <appender-ref ref="FILE" />
    </logger>

    <root level="INFO">
        <appender-ref ref="STDOUT" />
    </root>
</configuration>


include๋ฅผ ์ด์šฉํ•˜์—ฌ ์„ค์ • ๋ถ„๋ฆฌํ•œ ์˜ˆ์‹œ
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <property name="LOGS_ABSOLUTE_PATH" value="/Users/binghe819/Desktop" />
    <include resource="org/springframework/boot/logging/logback/base.xml"/>

    <!-- include๋ฅผ ํ†ตํ•œ ์„ค์ • -->
    <include resource="logback/stdout-appender.xml"/>
    <include resource="logback/file-appender.xml"/>

    <root level="INFO">
        <appender-ref ref="STDOUT" />
    </root>

    <logger name="org.springframework.web" level="DEBUG">
        <appender-ref ref="STDOUT" />
        <appender-ref ref="FILE" />
    </logger>
</configuration>
<!-- logback/file-appender.xml -->
<included>
  <appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
    <file>${LOGS_ABSOLUTE_PATH}/logback.log</file>
    <encoder>
      <pattern>[%d{yyyy-MM-dd HH:mm:ss}:%-3relative][%thread] %-5level %logger{35} - %msg%n</pattern>
    </encoder>
    <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
      <fileNamePattern>${LOGS_ABSOLUTE_PATH}/logback.%d{yyyy-MM-dd}.%i.log.gz</fileNamePattern>
      <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
        <maxFileSize>15MB</maxFileSize>
      </timeBasedFileNamingAndTriggeringPolicy>
      <maxHistory>30</maxHistory>
    </rollingPolicy>
  </appender>
</included>
<!-- logback/stdout-appender.xml -->
<included>
  <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
    <layout class="ch.qos.logback.classic.PatternLayout">
      <Pattern>[%d{yyyy-MM-dd HH:mm:ss}:%-3relative][%thread] %-5level %logger{36} - %msg%n</Pattern>
    </layout>
  </appender>
</included>


4 Spring Boot ๊ธฐ๋ฐ˜ Logback ์„ค์ • ๋ฐ ์ „๋žต

์•„๋งˆ ๋Œ€๋ถ€๋ถ„์˜ slf4j + Logback์„ ์‚ฌ์šฉํ•˜๋Š” ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์€ Spring์ผ ๊ฒƒ์ด๋‹ค.

Spring์—์„  ์–ด๋–ป๊ฒŒ Logback์„ ์„ค์ •ํ•˜๊ณ  ์ „๋žต์€ ์–ด๋–ป๊ฒŒ ๊ฐ€์ ธ๊ฐ€๋Š”์ง€ ์•Œ๊ณ ์‹ถ๋‹ค๋ฉด ๋‹ค์Œ ๊ธ€์„ ์ฐธ๊ณ ๋ฐ”๋žŒ.


์ถœ์ฒ˜