blog

파이썬 로깅 설정 Best Practice

아래는 확장성과 유지보수성을 극대화한 Python 로깅 설정파일입니다.
모든 Best Practice를 적용하여 파일 로깅, 콘솔 로깅, 원격 로깅, 로그 로테이션, JSON 포맷 로그, Slack 알림까지 포함한 설정을 만들었습니다.

🔹 주요 기능


🔹 logging_config.yaml (YAML 기반 설정파일)

version: 1

# 로그 포맷 정의
formatters:
  standard:
    format: "[%(asctime)s] [%(levelname)s] [%(name)s] [%(filename)s:%(lineno)d] - %(message)s"
    datefmt: "%Y-%m-%d %H:%M:%S"
  json:
    format: '{"time": "%(asctime)s", "level": "%(levelname)s", "logger": "%(name)s", "file": "%(filename)s", "line": %(lineno)d, "message": "%(message)s"}'
  detailed:
    format: "%(asctime)s | %(levelname)s | %(name)s | %(filename)s:%(lineno)d | %(message)s | %(process)d | %(threadName)s"

# 핸들러 정의
handlers:
  console:
    class: logging.StreamHandler
    level: DEBUG
    formatter: standard
    stream: ext://sys.stdout

  file:
    class: logging.handlers.RotatingFileHandler
    level: INFO
    formatter: standard
    filename: logs/app.log
    maxBytes: 10485760  # 10MB
    backupCount: 5
    encoding: utf-8

  timed_file:
    class: logging.handlers.TimedRotatingFileHandler
    level: INFO
    formatter: detailed
    filename: logs/app_timed.log
    when: midnight
    interval: 1
    backupCount: 7
    encoding: utf-8

  json_file:
    class: logging.FileHandler
    level: INFO
    formatter: json
    filename: logs/app.json
    encoding: utf-8

  slack:
    class: my_logging_handlers.SlackHandler
    level: ERROR
    formatter: standard
    token: "xoxb-..."  # Slack API Token
    channel: "#alerts"

  syslog:
    class: logging.handlers.SysLogHandler
    level: WARNING
    formatter: standard
    address: "/dev/log"

# 로거 정의
loggers:
  my_app:
    level: DEBUG
    handlers: [console, file, timed_file, json_file, slack, syslog]
    propagate: no

# 기본 로거 설정 (루트 로거)
root:
  level: WARNING
  handlers: [console, file]

🔹 설명

항목 설명
version: 1 로깅 설정 버전 (Python 표준)
Formatters 로그 출력 형식을 정의하는 부분
standard 기본 로그 포맷 (날짜, 로그레벨, 로거명, 파일명, 라인번호, 메시지)
json JSON 형식으로 로그 저장 가능
detailed 추가적인 정보(프로세스 ID, 쓰레드 정보)를 포함하는 포맷
Handlers 로그를 저장하는 방식
console 터미널(표준 출력)에 로그 출력
file 크기에 따라 파일을 회전하는 핸들러 (RotatingFileHandler)
timed_file 날짜에 따라 파일을 자동으로 회전하는 핸들러 (TimedRotatingFileHandler)
json_file JSON 형식으로 로그를 저장하는 핸들러
slack ERROR 이상 로그가 발생하면 Slack으로 전송
syslog 시스템 로그 서버(/dev/log)에 저장
Loggers 특정 로거에 대해 설정하는 부분
my_app my_app 네임스페이스의 모든 로그가 지정된 핸들러를 거쳐 출력
Root Logger 설정되지 않은 모든 로거가 따르는 기본 설정

🔹 SlackHandler (커스텀 핸들러)

Slack 알림을 위해 별도의 핸들러를 만들어야 합니다.

my_logging_handlers.py

import logging
import requests

class SlackHandler(logging.Handler):
    def __init__(self, token, channel):
        super().__init__()
        self.token = token
        self.channel = channel

    def emit(self, record):
        log_entry = self.format(record)
        payload = {
            "channel": self.channel,
            "text": f"🚨 {record.levelname}: {log_entry}",
        }
        headers = {
            "Authorization": f"Bearer {self.token}",
            "Content-Type": "application/json",
        }
        try:
            requests.post("https://slack.com/api/chat.postMessage", json=payload, headers=headers)
        except Exception as e:
            print(f"Slack logging failed: {e}")

🔹 사용법

import logging
import logging.config
import yaml

# YAML 로깅 설정 불러오기
with open("logging_config.yaml", "r") as f:
    config = yaml.safe_load(f)
    logging.config.dictConfig(config)

logger = logging.getLogger("my_app")

# 로깅 예제
logger.debug("이것은 디버그 메시지입니다")
logger.info("이것은 정보 메시지입니다")
logger.warning("이것은 경고 메시지입니다")
logger.error("이것은 에러 메시지입니다")
logger.critical("이것은 치명적 오류 메시지입니다")

🔹 확장 가능 포인트


🔹 결론