5 ๋ถ„ ์†Œ์š”

Logger?

ํ”„๋กœ์ ํŠธ๋ฅผ ์ง„ํ–‰ํ•˜๋‹ค๋ณด๋ฉด ์—ฌ๋Ÿฌ ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•œ๋‹ค.

์ด๊ฑธ ํ•˜๋‚˜ํ•˜๋‚˜ print() ๋ฅผ ์‚ฌ์šฉํ•ด์„œ ์„œ๋ฒ„ ์˜ค๋ฅ˜์— ์ฐ๋Š”๊ฒŒ ๊ณผ์—ฐ ๋งž์„๊นŒ?

์ด๋Ÿด ๋•Œ ์‚ฌ์šฉํ•˜๋Š”๊ฒŒ logging์ด๋‹ค!

logging์€ ์‹œ์Šคํ…œ์˜ ์ƒํƒœ, ์—๋Ÿฌ๋ฅผ ๊ธฐ๋ก ๋ฐ ๊ด€๋ฆฌํ•ด์ฃผ๋Š” ๊ฒƒ์„ ์˜๋ฏธํ•œ๋‹ค.

Django๋Š” ๋กœ๊น… ๋ชจ๋“ˆ์ด ์กด์žฌํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์ด๊ฑธ ์‚ฌ์šฉํ•˜๋ฉด ๋œ๋‹ค!

settings

(... ์ƒ๋žต ...)

# ๋กœ๊น…์„ค์ •
LOGGING = {
    'version': 1,
    'disable_existing_loggers': False,
    'filters': {
        'require_debug_false': {
            '()': 'django.utils.log.RequireDebugFalse',
        },
        'require_debug_true': {
            '()': 'django.utils.log.RequireDebugTrue',
        },
    },
    'formatters': {
        'django.server': {
            '()': 'django.utils.log.ServerFormatter',
            'format': '[{server_time}] {message}',
            'style': '{',
        },
    },
    'handlers': {
        'console': {
            'level': 'INFO',
            'filters': ['require_debug_true'],
            'class': 'logging.StreamHandler',
        },
        'django.server': {
            'level': 'INFO',
            'class': 'logging.StreamHandler',
            'formatter': 'django.server',
        },
        'mail_admins': {
            'level': 'ERROR',
            'filters': ['require_debug_false'],
            'class': 'django.utils.log.AdminEmailHandler'
        },
    },
    'loggers': {
        'django': {
            'handlers': ['console', 'mail_admins'],
            'level': 'INFO',
        },
        'django.server': {
            'handlers': ['django.server'],
            'level': 'INFO',
            'propagate': False,
        },
    }
}

์ถœ์ฒ˜: https://wikidocs.net/77522

version

version์€ ๊ณ ์ •๊ฐ’ 1์„ ์‚ฌ์šฉํ•œ๋‹ค.

๋ณ„ ์˜๋ฏธ ์—†๋Š” ์„ค์ •์ด ์•„๋‹ˆ๋ผ, logging๋ชจ๋“ˆ์ด ์—…๊ทธ๋ ˆ์ด๋“œ ๋˜์–ด๋„ ํ˜„์žฌ ์„ค์ •์„ ์œ ์ง€์‹œ์ผœ์ฃผ๋Š” ์•ˆ์ „์žฅ์น˜์ž„!

disable_existing_loggers

disable_existing_loggers ํ•ญ๋ชฉ์€ False๋กœ ์„ค์ •ํ•จ.

๋งŒ์•ฝ True๋กœ ์„ค์ •ํ•˜๋ฉด ๊ธฐ์กด์— ์„ค์ •๋œ ๋กœ๊ฑฐ๋“ค์„ ์‚ฌ์šฉํ•˜์ง€ ์•Š๋Š” ์„ค์ •์ด ๋จ.

๊ธฐ์กด ๋กœ๊ฑฐ ์„ค์ •์„ ๋ฒ„๋ฆฌ๋ ค๋ฉด True๋กœ!

filters

filters๋Š” ํŠน์ • ์กฐ๊ฑด์—์„œ ๋กœ๊ทธ๋ฅผ ์ถœ๋ ฅํ•˜๊ฑฐ๋‚˜ ์ถœ๋ ฅํ•˜์ง€ ์•Š๊ธฐ ์œ„ํ•œ ์˜ต์…˜์ž„.

require_debug_falseํ•„ํ„ฐ๋Š” DEBUG=False์ธ์ง€๋ฅผ ํŒ๋‹จํ•˜๋Š” ํ•„ํ„ฐ์ž„. (true๋Š” ๋‹น์—ฐํžˆ ๋ฐ˜๋Œ€ ํ•„ํ„ฐ์—์„œ!)

์กฐ๊ฑด ํŒ๋‹จ์„ ์œ„ํ•œ ํด๋ž˜์Šค์ธ django.utils.log.RequireDebugFalse & django.utils.log.RequireDebugTrue ๋ฅผ ํ˜ธ์ถœํ•˜์—ฌ DEBUG ์˜ต์…˜์˜ ๊ฐ’์„ ํ™•์ธํ•จ!

formatters

formatters๋Š” ๋กœ๊ทธ๋ฅผ ์ถœ๋ ฅํ•  ํ˜•์‹์„ ์ง€์ •ํ•œ๋‹ค!

์œ„ ์˜ˆ์‹œ์—์„œ๋Š” ์•„๋ž˜ ํ˜•์‹์„ ์‚ฌ์šฉํ–ˆ๋‹ค.

  • server_time: ์„œ๋ฒ„ ์‹œ๊ฐ„
  • message: ์ถœ๋ ฅ ๋‚ด์šฉ

handlers

handler๋Š” ๋กœ๊ทธ์˜ ์ถœ๋ ฅ ๋ฐฉ๋ฒ•์„ ์ •์˜ํ•จ.

๋‹ค์Œ์€ DEFAULT_LOGGING ์„ค์ •์— ๋“ฑ๋ก๋œ ํ•ธ๋“ค๋Ÿฌ์ž„.

  • console: ์ฝ˜์†”์— ๋กœ๊ทธ๋ฅผ ์ถœ๋ ฅํ•จ. ๋กœ๊ทธ ๋ ˆ๋ฒจ์ด INFO์ด์ƒ์ด๊ณ , DEBUG=True์ผ ๋•Œ๋งŒ ๋กœ๊ทธ๋ฅผ ์ถœ๋ ฅํ•จ.
  • django.server: python [manage.py](http://manage.py) runserver๋กœ ๋™์ž‘ํ•˜๋Š” ๊ฐœ๋ฐœ ์„œ๋ฒ„์—์„œ๋งŒ ์‚ฌ์šฉํ•˜๋Š” ํ•ธ๋“ค๋Ÿฌ๋กœ, ์ฝ˜์†”์— ๋กœ๊ทธ๋ฅผ ์ถœ๋ ฅํ•จ.
  • mail_admins: ๋กœ๊ทธ ๋‚ด์šฉ์„ ์ด๋ฉ”์ผ๋กœ ์ „์†กํ•˜๋Š” ํ•ธ๋“ค๋Ÿฌ๋กœ, ๋กœ๊ทธ ๋ ˆ๋ฒจ์ด ERROR ์ด์ƒ์ด๊ณ , DEBUG=False์ผ ๋•Œ๋งŒ ๋™์ž‘ํ•œ๋‹ค. ์ด ํ•ธ๋“ค๋Ÿฌ๋ฅผ ์‚ฌ์šฉํ•˜๋ ค๋ฉด ํ™˜๊ฒฝ์„ค์ • ํŒŒ์ผ์— ADMINS ํ•ญ๋ชฉ์„ ์ถ”๊ฐ€ํ•˜๊ณ , ๊ด€๋ฆฌ์ž ์ด๋ฉ”์ผ์„ ๋“ฑ๋กํ•ด์•ผ ํ•จ. (์˜ˆ: ADMINS = [โ€™aaa@test.orgโ€™]) ์ถ”๊ฐ€๋กœ ๋ฉ”์ผ ์ „์†ก์„ ์œ„ํ•œ SMTP ์„ค์ •์€ ํ•„์ˆ˜์ž„!

loggers

๋กœ๊ทธ๋ฅผ ์ถœ๋ ฅํ•˜๋Š” ํ”„๋กœ๊ทธ๋žจ์—์„œ ์‚ฌ์šฉํ•˜๋Š” ๋กœ๊ฑฐ(logger)๋ฅผ ์˜๋ฏธํ•จ!

DEFAULT_LOGGING ์„ค์ •์—๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๋กœ๊ฑฐ๋“ค์ด ๋“ฑ๋ก๋˜์–ด ์žˆ์Œ!

  • django: django๊ฐ€ ์‚ฌ์šฉํ•˜๋Š” ๋กœ๊ฑฐ์ž„. ๋กœ๊ทธ ๋ ˆ๋ฒจ์ด INFO์ด์ƒ์ผ ๊ฒฝ์šฐ์—๋งŒ ๋กœ๊ทธ๋ฅผ ์ถœ๋ ฅํ•จ.
  • django.server: ๊ฐœ๋ฐœ ์„œ๋ฒ„๊ฐ€ ์‚ฌ์šฉํ•˜๋Š” ๋กœ๊ฑฐ์ž„. ๋กœ๊ทธ ๋ ˆ๋ฒจ์ด INFO ์ด์ƒ์ผ ๊ฒฝ์šฐ์—๋งŒ ๋กœ๊ทธ๋ฅผ ์ถœ๋ ฅํ•จ. โ€™propagate: Falseโ€™๋Š” django.server๊ฐ€ ์ถœ๋ ฅํ•˜๋Š” ๋กœ๊ทธ๋ฅผ django ๋กœ๊ฑฐ๋กœ ์ „๋‹ฌํ•˜์ง€ ์•Š๋Š”๋‹ค๋Š” ์˜๋ฏธ์ž„. ๋งŒ์•ฝ ์ด๊ฒŒ True์ด๋ฉด ์ตœ์ƒ์œ„ ํŒจํ‚ค์ง€๋ช…์ด django๋กœ ๋™์ผํ•˜๊ธฐ ๋•Œ๋ฌธ์— django.server ํ•˜์œ„ ํŒจํ‚ค์ง€์—์„œ ์ถœ๋ ฅํ•˜๋Š” ๋กœ๊ฑฐ์—๋„ ์ถœ๋ ฅ๋˜๊ณ , django ๋กœ๊ฑฐ์—๋„ ์ถœ๋ ฅ๋˜์–ด ์ด์ค‘์œผ๋กœ ๋กœ๊น…๋จ. (์ด์ค‘ ๋กœ๊น… โ†’ ๊ตณ์ด?)

Logging Level?

์œ„์—์„œ ์ž๊พธ ๋กœ๊ทธ ๋ ˆ๋ฒจ์ด๋ผ๊ณ  ํ•˜๋Š”๋ฐ, ์ด๊ฒŒ ๋ญ˜๊นŒ?

๋กœ๊ทธ ๋ ˆ๋ฒจ์€ ๋ง ๊ทธ๋Œ€๋กœ ๋กœ๊ทธ๋ฅผ ์ฐ์„ ๋•Œ, ํ•ด๋‹น ๋กœ๊ทธ์˜ ์ˆ˜์ค€์„ ๋‚˜ํƒ€๋‚ธ๋‹ค.

์ด 5๋‹จ๊ณ„์˜ ๋ ˆ๋ฒจ๋กœ ๊ตฌ์„ฑ๋˜์–ด์žˆ๋‹ค.

  • [1๋‹จ๊ณ„] DEBUG: ๋””๋ฒ„๊น… ๋ชฉ์ ์œผ๋กœ ์‚ฌ์šฉ
  • [2๋‹จ๊ณ„] INFO: ์ผ๋ฐ˜ ์ •๋ณด ์ถœ๋ ฅ ๋ชฉ์ ์œผ๋กœ ์‚ฌ์šฉ
  • [3๋‹จ๊ณ„] WARNING: ๊ฒฝ๊ณ  ์ •๋ณด๋ฅผ ์ถœ๋ ฅํ•  ๋ชฉ์ ์œผ๋กœ ์‚ฌ์šฉ (๋น„๊ต์  ์ž‘์€ ๋ฌธ์ œ)
  • [4๋‹จ๊ณ„] ERROR: ์˜ค๋ฅ˜ ์ •๋ณด๋ฅผ ์ถœ๋ ฅํ•  ๋ชฉ์ ์œผ๋กœ ์‚ฌ์šฉ (๋น„๊ต์  ํฐ ๋ฌธ์ œ)
  • [5๋‹จ๊ณ„] CRITICAL: ์•„์ฃผ ์‹ฌ๊ฐํ•œ ๋ฌธ์ œ๋ฅผ ์ถœ๋ ฅํ•  ๋ชฉ์ ์œผ๋กœ ์‚ฌ์šฉ

DEBUG < INFO < WARNING < ERROR < CRITICAL

๋กœ๊ทธ ๋ ˆ๋ฒจ์€ ์–ด๋–ค ์ƒํ™ฉ์— ์ ์šฉํ•˜๋Š”๊ฒŒ ์ข‹์„๊นŒ? (ChatGPT)

๐Ÿ—ฃ๏ธย django logging์„ ์‚ฌ์šฉํ•˜๋Š”๋ฐ, ๊ฐ ๋กœ๊น… ๋ ˆ๋ฒจ (debug, info, warning, error, critical, exception โ€ฆ ) ๋ณ„๋กœ ์–ด๋–ค ์ƒํ™ฉ์— ์ ์šฉํ•˜๋Š”๊ฒŒ ์ข‹์€์ง€ ๊ถ๊ธˆํ•ด. ์˜ˆ๋ฅผ ๋“ค๋ฉด, try-except ๊ตฌ๋ฌธ ์•ˆ์—์„œ Order๋ผ๋Š” model์— ์ ‘๊ทผํ•ด ๋ฐ์ดํ„ฐ๋ฅผ ์กฐํšŒํ•˜๋Š” ์ƒํ™ฉ์ด ์žˆ๋‹ค๊ณ  ํ–ˆ์„ ๋•Œ, DoesNotExist ์˜ˆ์™ธ๊ฐ€ ๋ฐœ์ƒํ–ˆ์„ ๋•Œ ์–ด๋–ค ๋กœ๊ทธ ๋ ˆ๋ฒจ์„ ์‚ฌ์šฉํ•ด ๊ธฐ๋ก์„ ๋‚จ๊ธฐ๋Š”์ง€ ์•Œ๋ ค์ค˜.

๋ ˆ๋ฒจ ๋ฉ”์„œ๋“œ ์šฉ๋„ ์ถœ๋ ฅ ์˜ˆ์‹œ
DEBUG logger.debug(...) ๊ฐœ๋ฐœยท๋””๋ฒ„๊น… ๋‹จ๊ณ„์—์„œ๋งŒ ํ•„์š”ํ•œ, ์•„์ฃผ ์ƒ์„ธํ•œ ๋‚ด๋ถ€ ์ƒํƒœ ์ •๋ณด ํ•จ์ˆ˜ ์ง„์ž…/์ข…๋ฃŒ, ๋ณ€์ˆ˜๊ฐ’, SQL ์ฟผ๋ฆฌ ๊ฒฐ๊ณผ ๋“ฑ
INFO logger.info(...) ์šด์˜ ์‹œ์—๋„ ์•Œ์•„๋‘๋ฉด ์ข‹์€, ์ •์ƒ์ ์ธ ํ๋ฆ„ ๋‚ด ์ด๋ฒคํŠธ ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜ ์‹œ์ž‘/์ข…๋ฃŒ, ์ฃผ์š” ๋น„์ฆˆ๋‹ˆ์Šค ์ด๋ฒคํŠธ(์ฃผ๋ฌธ ์ƒ์„ฑ ์™„๋ฃŒ ๋“ฑ)
WARNING logger.warning(...) ์˜ˆ์ƒ์€ ํ•˜์ง€๋งŒ ์ฃผ์˜๊ฐ€ ํ•„์š”ํ•œ ์ƒํ™ฉ ์กด์žฌํ•˜์ง€ ์•Š๋Š” ์ฃผ๋ฌธ ์กฐํšŒ ์‹œ๋„, ์™ธ๋ถ€ API ์ง€์—ฐ ์‘๋‹ต ๋“ฑ
ERROR logger.error(...) ์‹ค์ œ ์˜ค๋ฅ˜(์˜ˆ์™ธ) ๋ฐœ์ƒ, ์ฒ˜๋ฆฌ๋Š” ๋˜์—ˆ์ง€๋งŒ ๋ฌธ์ œ๋กœ ์ด์–ด์งˆ ์ˆ˜ ์žˆ๋Š” ์ƒํ™ฉ DB ์“ฐ๊ธฐ ์‹คํŒจ, ๋„คํŠธ์›Œํฌ ์š”์ฒญ ์‹คํŒจ ๋“ฑ
EXCEPTION logger.exception(...) ERROR์™€ ๋™์ผํ•˜๋‚˜, ์Šคํƒ ํŠธ๋ ˆ์ด์Šค(traceback)๊นŒ์ง€ ํ•จ๊ป˜ ์ฐ์Œ (์˜ˆ์™ธ ํ•ธ๋“ค๋ง ๋ธ”๋ก ๋‚ด์—์„œ ์‚ฌ์šฉ) ์˜ˆ์ƒ์น˜ ๋ชปํ•œ ์˜ˆ์™ธ๊ฐ€ ๋ฐœ์ƒํ•ด ํŠธ๋ ˆ์ด์Šค๋ฐฑ์ด ํ•„์š”ํ•  ๋•Œ
CRITICAL logger.critical(...) ์„œ๋น„์Šค ์ „์ฒด๋ฅผ ์ค‘๋‹จ์‹œํ‚ฌ ์ˆ˜ ์žˆ๋Š” ์น˜๋ช…์  ์˜ค๋ฅ˜ ์ธํ”„๋ผ(๋””์Šคํฌ ํ’€๋ถ€์กฑ, ๋ฉ”๋ชจ๋ฆฌ OOM) ๋“ฑ

DoesNotExist ์˜ˆ์™ธ๊ฐ€ ๋ฐœ์ƒํ•˜๋Š”๊ฑด ๊ฐœ๋ฐœ์ž๊ฐ€ ์‚ฌ์šฉ์ž ์š”์ฒญ ํ๋ฆ„์—์„œ ์ถฉ๋ถ„ํžˆ ์˜ˆ์ƒ ๊ฐ€๋Šฅํ•œ ๋ฌธ์ œ์ด๋ฏ€๋กœ WARGNING์„ ์‚ฌ์šฉํ•˜๋ฉด ๋œ๋‹ค. ์ด ์™ธ์˜ ์˜ˆ์™ธ ์ค‘, ์˜ˆ์ƒ์น˜ ๋ชปํ•œ ์—๋Ÿฌ์— ๋Œ€ํ•ด์„œ๋Š” EXCEPTION์„ ์‚ฌ์šฉํ•˜๋ฉด ๋œ๋‹ค. (์ด ๋•Œ๋Š” ์–ด๋–ค ์˜ˆ์™ธ๊ฐ€ ๋ฐœ์ƒํ–ˆ๋Š”์ง€ ์Šคํƒ ํŠธ๋ ˆ์ด์Šค๊ฐ€ ํ•„์š”ํ•จ)

๋ ˆ๋ฒจ ๋ณ„ ์ถœ๋ ฅ ๊ฐ€์ด๋“œ๋ผ์ธ

  • DEBUG
    • ๋Œ€์ƒ: ๊ฐœ๋ฐœ์ž
    • ๋‚ด์šฉ: ๋‚ด๋ถ€ ๋ณ€์ˆ˜, ํ•จ์ˆ˜ ์ง„์ž…/์ข…๋ฃŒ, SQL ์ฟผ๋ฆฌ, ํƒ€์ด๋ฐ ์ธก์ • ๋“ฑ
    • ํ™œ์šฉ: ๋กœ์ปฌ ๊ฐœ๋ฐœ ํ™˜๊ฒฝ์—์„œ๋งŒ ํ™œ์„ฑํ™”. ์šด์˜ ํ™˜๊ฒฝ์—์„  ๋ณดํ†ต ๊บผ๋‘ .
  • INFO
    • ๋Œ€์ƒ: ์šด์˜์ž/๊ฐœ๋ฐœ์ž
    • ๋‚ด์šฉ: ์ •์ƒ์ ์ธ ๋น„์ฆˆ๋‹ˆ์Šค ์ด๋ฒคํŠธ(์ฃผ๋ฌธ ์ ‘์ˆ˜, ์ด๋ฉ”์ผ ๋ฐœ์†ก ์„ฑ๊ณต ๋“ฑ)
    • ํ™œ์šฉ: ์šด์˜ ๋กœ๊ทธ์— ๋‚จ๊ฒจ๋†“์•„, ์„œ๋น„์Šค ํ๋ฆ„ ๋ชจ๋‹ˆํ„ฐ๋ง์— ํ™œ์šฉ.
  • WARNING
    • ๋Œ€์ƒ: ์šด์˜์ž
    • ๋‚ด์šฉ: ๋น„์ •์ƒ์ ์ด์ง€๋งŒ ์น˜๋ช…์ ์ด์ง€ ์•Š์€ ์ƒํ™ฉ(์กด์žฌํ•˜์ง€ ์•Š๋Š” ๋ฆฌ์†Œ์Šค ์กฐํšŒ ๋“ฑ)
    • ํ™œ์šฉ: ๋„ˆ๋ฌด ์žฆ์œผ๋ฉด ๋…ธ์ด์ฆˆ๊ฐ€ ๋  ์ˆ˜ ์žˆ์œผ๋‹ˆ, ์ •๋ง โ€œ์ฃผ์˜๊ฐ€ ํ•„์š”ํ•œโ€ ๊ฒฝ์šฐ๋งŒ.
  • ERROR
    • ๋Œ€์ƒ: ์šด์˜์ž
    • ๋‚ด์šฉ: ์˜ˆ์™ธ ๋ฐœ์ƒ์œผ๋กœ ํŠน์ • ๊ธฐ๋Šฅ์ด ์‹คํŒจํ–ˆ์œผ๋‚˜, ์ „์ฒด ์„œ๋น„์Šค๋Š” ์ง€์†๋˜๋Š” ์ˆ˜์ค€
    • ํ™œ์šฉ: SentryยทELK ๊ฐ™์€ ์—๋Ÿฌ ๋ชจ๋‹ˆํ„ฐ๋ง ์‹œ์Šคํ…œ๊ณผ ์—ฐ๋™ํ•ด ๊ฒฝ๊ณ ยท์•Œ๋ฆผ.
  • EXCEPTION
    • ๋Œ€์ƒ: ์šด์˜์žยท๊ฐœ๋ฐœ์ž
    • ๋‚ด์šฉ: ERROR + ์Šคํƒ ํŠธ๋ ˆ์ด์Šค. ์˜ˆ์™ธ์˜ ์›์ธ ํŒŒ์•…์ด ํ•„์š”ํ•  ๋•Œ
    • ํ™œ์šฉ: except Exception: ๋ธ”๋ก ์•ˆ์—์„œ ์˜ˆ์™ธ ๋””๋ฒ„๊น…์šฉ์œผ๋กœ ์‚ฌ์šฉ.
  • CRITICAL
    • ๋Œ€์ƒ: ์šด์˜์ž
    • ๋‚ด์šฉ: ์ „์ฒด ์„œ๋น„์Šค ์ค‘๋‹จ ๊ฐ€๋Šฅ์„ฑ ์žˆ๋Š” ์˜ค๋ฅ˜
    • ํ™œ์šฉ: ์•Œ๋ฆผยท์ž๋™ ์žฅ์• ๋ณต๊ตฌ ํŠธ๋ฆฌ๊ฑฐ์— ์—ฐ๊ฒฐ.

์‹ค์ œ ์ ์šฉ

settings.py

...

LOG_DIR = os.path.join(BASE_DIR, 'logs')
os.makedirs(LOG_DIR, exist_ok=True)  # logs ๋””๋ ‰ํ† ๋ฆฌ ์—†์œผ๋ฉด ์ž๋™ ์ƒ์„ฑ

LOGGING = {
    'version': 1,
    'disable_existing_loggers': False,  # Django ๊ธฐ๋ณธ ๋กœ๊ฑฐ ๋„์ง€ ์•Š์Œ
    'formatters': {
        'custom': {
            'format': '[{asctime}] [{filename}:{lineno}] [{levelname}] {message}',
            'style': '{',
            'datefmt': '%Y-%m-%d %H:%M:%S',  # ์„œ๋ฒ„ ์‹œ๊ฐ„ ํ˜•์‹
        },
    },
    'handlers': {
        'console': { # ์ฝ˜์†”์— ์ถœ๋ ฅ
            'class': 'logging.StreamHandler',
            'formatter': 'custom', # formatters์˜ custom์„ ๋”ฐ๋ฆ„
            'level': 'INFO', # INFO ์ด์ƒ๋งŒ ์ถœ๋ ฅ
        },
        'file': { # ํŒŒ์ผ์— ์ถœ๋ ฅ
            'class': 'logging.FileHandler',
            'formatter': 'custom',
            'filename': os.path.join(LOG_DIR, 'django.log'),
            'level': 'DEBUG', # DEBUG ์ด์ƒ๋งŒ ์ถœ๋ ฅ
        },
    },
    'loggers': {
        '': {  # root logger
            'handlers': ['console', 'file'],
            'level': 'INFO',
            'propagate': False,
        },
        'django': {  # Django ๋‚ด๋ถ€ ๋กœ๊ฑฐ๋„ ํฌํ•จํ•˜๋ ค๋ฉด ์ด ํ•ญ๋ชฉ ์œ ์ง€
            'handlers': ['console', 'file'],
            'level': 'INFO',
            'propagate': False,
        },
    }
}

  • LOG_DIR: ๋กœ๊ทธ๋ฅผ ์ €์žฅํ•  ์œ„์น˜๋ฅผ ์ง€์ •ํ•จ
  • os.makedirs: ์—†์œผ๋ฉด ์ƒ์„ฑํ•˜๋„๋ก
  • format: ๋กœ๊ทธ ํ•œ ์ค„์˜ ์ถœ๋ ฅ ํฌ๋งท
    • {asctime}: ๋กœ๊ทธ ์ถœ๋ ฅ ์‹œ๊ฐ (์„œ๋ฒ„ ์‹œ๊ฐ„)
    • {filename}: ๋กœ๊ทธ๋ฅผ ํ˜ธ์ถœํ•œ ํŒŒ์ผ๋ช…
    • {lineno}: ํ˜ธ์ถœํ•œ ๋ผ์ธ ๋ฒˆํ˜ธ
    • {levelname}: ๋กœ๊ทธ ๋ ˆ๋ฒจ (INFO, ERROR ๋“ฑ)
    • {message}: ์‹ค์ œ ๋กœ๊ทธ ๋ฉ”์‹œ์ง€
  • style: ๋ฌธ์ž์—ด ํฌ๋งท ์Šคํƒ€์ผ์„ str.format() ๋ฐฉ์‹์œผ๋กœ ์ง€์ • ({} ์‚ฌ์šฉ ๊ฐ€๋Šฅ)
  • datefmt: ์‹œ๊ฐ„ ์ถœ๋ ฅ ํ˜•์‹ (strftime ํ˜•์‹)
  • handler
    • StreamHandler: ํ„ฐ๋ฏธ๋„(์ฝ˜์†”)๋กœ ์ถœ๋ ฅ
    • formatter: ์œ„์—์„œ ๋งŒ๋“  custom ํฌ๋งท ์‚ฌ์šฉ
    • FileHandler: ์ง€์ •๋œ ํŒŒ์ผ(logs/django.log)์— ๋กœ๊ทธ ์ถœ๋ ฅ
  • loggers
    • ''
      • ์ด๋ฆ„์ด ๋นˆ ๋ฌธ์ž์—ด ''์ธ ๊ฒƒ์€ ๋ชจ๋“  ์•ฑ๊ณผ ๋ชจ๋“ˆ์— ๊ณตํ†ต ์ ์šฉ๋˜๋Š” ๋ฃจํŠธ ๋กœ๊ฑฐ์ž„
      • handlers: ์ฝ˜์†”๊ณผ ํŒŒ์ผ ๋ชจ๋‘์— ๋กœ๊ทธ ์ถœ๋ ฅ
      • level: INFO ์ด์ƒ๋งŒ ์ถœ๋ ฅ
      • propagate=False: ๋กœ๊ทธ๊ฐ€ ์ค‘๋ณต ์ „ํŒŒ๋˜์ง€ ์•Š๋„๋ก ์„ค์ • (์ƒ์œ„ ๋กœ๊ฑฐ๋กœ ์•ˆ ๋ณด๋‚ด๊ฒŒ ๋ง‰์Œ)
    • django
      • Django ๋‚ด๋ถ€ ๋™์ž‘ (์˜ˆ: ์š”์ฒญ ์ฒ˜๋ฆฌ, static serve ๋“ฑ)์˜ ๋กœ๊ทธ ์ถœ๋ ฅ
      • INFO ์ด์ƒ์˜ ๋กœ๊ทธ๊ฐ€ console๊ณผ file๋กœ ๋ชจ๋‘ ๊ธฐ๋ก๋จ

๋กœ๊ทธ ์ถœ๋ ฅ ์˜ˆ์‹œ

[2025-04-14 15:32:00] [views.py:42] [INFO] SUPER_ADMIN ์š”์ฒญ, ์ „์ฒด ์œ ์ € ์ˆ˜: 87

๋งŒ์•ฝ ๋กœ๊ทธ ํŒŒ์ผ์„ ๋ถ„๋ฆฌํ•ด์„œ ์ €์žฅํ•˜๊ณ  ์‹ถ๋‹ค๋ฉด?

ChatGPT๋Š” ์‹ ์ด๋‹ค.

๊ธฐ์กด settings.py์—์„œ file ์„ค์ •์„ ์•„๋ž˜์ฒ˜๋Ÿผ ์ˆ˜์ •ํ•ด๋ณผ ์ˆ˜ ์žˆ๋‹ค.

'file': {
    'class': 'logging.handlers.TimedRotatingFileHandler',
    'formatter': 'custom',
    'filename': os.path.join(LOG_DIR, 'django.log'), # logs/django.log ๋ผ๋Š” ์ด๋ฆ„์œผ๋กœ ์ €์žฅ๋จ
    'when': 'midnight',            # ๋งค์ผ ์ž์ •๋งˆ๋‹ค ํšŒ์ „
    'interval': 1,
    'backupCount': 7,              # 7์ผ๊ฐ„ ๋ฐฑ์—… ํŒŒ์ผ ๋ณด๊ด€
    'encoding': 'utf-8',
    'level': 'INFO',
},
  • logging.handlers.TimedRotatingFileHandler: ์‹œ๊ฐ„(๋‚ ์งœ) ๊ธฐ์ค€์œผ๋กœ ํŒŒ์ผ์„ ํšŒ์ „์‹œํ‚ค๋Š” ํด๋ž˜์Šค
  • when: ์–ธ์ œ๋งˆ๋‹ค ํšŒ์ „ ์‹œํ‚ฌ๊ฑด์ง€?
  • backupCount: ๋ฉฐ์น ๊ฐ„์˜ ๋ฐฑ์—… ํŒŒ์ผ์„ ๋ณด๊ด€ํ• ๊ฑด์ง€?

์•„๋ž˜์ฒ˜๋Ÿผ ๋ฐ”๊พธ๋ฉด ์ผ์ • ์šฉ๋Ÿ‰์ด ๋„˜์–ด๊ฐ€๋ฉด ๋ฐ”๊พธ๋„๋ก ํ•  ์ˆ˜๋„ ์žˆ์Œ!

'class': 'logging.handlers.RotatingFileHandler',
'maxBytes': 1024 * 1024 * 5,  # 5MB
'backupCount': 5,             # 5๊ฐœ๊นŒ์ง€ ๋ณด๊ด€
  • logging.handlers.RotatingFileHandler: ๋กœ๊ทธ ํŒŒ์ผ์˜ ์šฉ๋Ÿ‰์ด ์ผ์ • ์šฉ๋Ÿ‰์ด ๋„˜์–ด๊ฐ€๋ฉด ํšŒ์ „์‹œํ‚ค๋Š” ํด๋ž˜์Šค
  • maxBytes: ์ตœ๋Œ€ ์šฉ๋Ÿ‰ ์ง€์ •
  • backupCount: ์ตœ๋Œ€ ๋ณด๊ด€ ๊ฐœ์ˆ˜

์ฐธ๊ณ  ์ž๋ฃŒ

Logging Django documentation

4-14 ๋กœ๊น…

Django์—์„œ logging ์‚ฌ์šฉํ•˜๊ธฐ

ํƒœ๊ทธ: ,

์นดํ…Œ๊ณ ๋ฆฌ:

์—…๋ฐ์ดํŠธ:

๋Œ“๊ธ€๋‚จ๊ธฐ๊ธฐ