SeoulNative / naengboo

naengboo backend repo
2 stars 2 forks source link

flask Logging 전략 #18

Open do168 opened 3 years ago

do168 commented 3 years ago

What

flask에서의 로깅 레벨 및 로깅 전략

Description

Python에서는 logging 모듈을 기본적으로 제공

1-1. Log Level

image

image

1-2. Root Logger

import logging
logging.warning('This is a warning message')
# 아래와 같은 메시지가 콘솔에 출력됩니다
# WARNING:root:This is a warning message

logging.info('This is an info message')
# 아무 것도 프린트 되지 않습니다
import logging
logging.basicConfig(level=logging.INFO)

logging.info('This is an info message')
# 아래와 같은 메시지가 출력됩니다!
# INFO:root:This is an info message
import logging
logging.basicConfig(filename='dummy.log', level=logging.INFO)
logging.debug('this is a debug')
logging.info('this is an info')
logging.warning('this is a warning')
    [dummy.log]
    INFO:root:this is an info
    WARNING:root:this is a warning
import logging
logging.basicConfig(
  format = '%(asctime)s:%(levelname)s:%(message)s',
  datefmt = '%m/%d/%Y %I:%M:%S %p',
  level = logging.DEBUG
)
logging.debug('This is a formatted debug message')

# 03/12/2019 05:20:12 PM:DEBUG:This is a formatted debug message

Custom Logging Module

Logger

  1. 로그를 생성할 수 있는 method를 제공해줍니다. (Logger.debug()Logger.info(), …)
  2. 로그 레벨과 Logger에 적용된 filter를 바탕으로 처리해야 할 메시지를 판단합니다.
  3. 적절한 Handler들에게 로그 메시지에 부가정보가 더해진 LogRecord 인스턴스를 전달해줍니다.

logger Object = logging.getLogger(name)

logging range

image

Handler

Handler는 로그 메시지를 출력하는 역할

import logging
logger = logging.getLogger(__name__)
logger.setLevel(logging.INFO)

stream_handler = logging.StreamHandler()
logger.addHandler(stream_handler)

logger.info('This is an INFO message')
# This is an INFO message
import logging
logger = logging.getLogger(__name__)
logger.setLevel(logging.INFO)

file_handler = logging.FileHandler('dummy.log')
logger.addHandler(file_handler)

logger.info('This is an INFO message. Hello dummy!')

Formatter

Formatter는 최종적으로 출력 될 로그 메시지의 formatting에 관여

import logging
logging.Formatter(
  fmt = None, # 메시지 출력 형태. None일 경우 raw 메시지를 출력.
  datefmt = None, # 날짜 출력 형태. None일 경우 '%Y-%m-%d %H:%M:%S'.
  style = '%' # '%', '{', '$' 중 하나. `fmt`의 style을 결정.
)

Example

import logging

logger = logging.getLogger(__name__)
logger.setLevel(logging.DEBUG) # 모든 레벨의 로그를 Handler들에게 전달해야 합니다.

formatter = logging.Formatter('%(asctime)s:%(module)s:%(levelname)s:%(message)s', '%Y-%m-%d %H:%M:%S')

# INFO 레벨 이상의 로그를 콘솔에 출력하는 Handler
console_handler = logging.StreamHandler()
console_handler.setLevel(logging.INFO)
console_handler.setFormatter(formatter)
logger.addHandler(console_handler)

# DEBUG 레벨 이상의 로그를 `debug.log`에 출력하는 Handler
file_debug_handler = logging.FileHandler('debug.log')
file_debug_handler.setLevel(logging.DEBUG)
file_debug_handler.setFormatter(formatter)
logger.addHandler(file_debug_handler)

# ERROR 레벨 이상의 로그를 `error.log`에 출력하는 Handler
file_error_handler = logging.FileHandler('error.log')
file_error_handler.setLevel(logging.ERROR)
file_error_handler.setFormatter(formatter)
logger.addHandler(file_error_handler)

ToJson

{
  "version": 1,
  "disable_existing_loggers": false,
  "formatters": {
    "basic": {
      "format": "%(asctime)s:%(module)s:%(levelname)s:%(message)s",
      "datefmt": "%Y-%m-%d %H:%M:%S"
    }
  },
  "handlers": {
    "console": {
      "class": "logging.StreamHandler",
      "level": "INFO",
      "formatter": "basic"
    },
    "file_debug": {
      "class": "logging.FileHandler",
      "level": "DEBUG",
      "formatter": "basic",
      "filename": "debug.log"
    },
    "file_error": {
      "class": "logging.FileHandler",
      "level": "ERROR",
      "formatter": "basic",
      "filename": "error.log"
    }
  },
  "loggers": {
    "__main__": {
      "level": "DEBUG",
      "handlers": ["console", "file_debug", "file_error"],
      "propagate": true
    }
  }
}
import logging
import logging.config
import json

config = json.load(open('./logger.json'))
logging.config.dictConfig(config)

logger = logging.getLogger(__name__)

TimeRotationFileHandler

위의 FileHandler에 time을 적용한 TimedRotationFileHandler

Daily Log File 생성

handler = TimedRotatingFileHandler('log/flask_server.log', when="D", interval=1)
handler.suffix = "%Y-%m-%d_%H-%M-%S"

프로젝트 진행 시 하루마다 Log File을 생성하면 어떨까 싶습니다. 다양한 의견 부탁드립니다

Related

https://docs.python.org/3.7/howto/logging.html#when-to-use-logging Logging HOWTO - Python 3.9.5 documentation https://docs.python.org/3/library/logging.handlers.html#logging.handlers.TimedRotatingFileHandler