Python의 logging에 대해 알아보자

류재환·2023년 2월 16일
0

https://docs.python.org/ko/3/howto/logging.html
해당 문서를 참고했습니다.

1. logging이란?

log의 의미

로그(log)에는 관찰과 읽은 것에 대한 기록 이라는 의미가 있다. 이는 배에서 중요 사건이나 항해를 기록한 logbook이라는 단어에서 기원되었다. logbook라는 이름은 주로 배의 속도를 측정하기 위해 사용되던 chip log라는 통나무 도구의 기록을 남기기 위해 사용하였던 것에서 유래되었다.

소프트웨어에서 로그는 특정 이벤트나 문제의 기록을 의미하며 이를 기록하는 행위를 로깅(logging)이라고 부른다. 소프트웨어 개발자는 코드를 추가하여 특정 이벤트에 대한 기록을 남길 수 있다. 각각의 기록은 중요도(level,severity)에 따라 분류될 수 있고 파이썬 로깅 모듈에서는 5가지 단계로 구분하고 있다.

log로 남길 수 있는 데이터의 종류

실제 서비스에서 로그로 남길 수 있는 데이터를 분류 할 수 있고 각각의 데이터에 따라 활용되는 방법이나 저장되는 저장소에 차이가 있다.

  1. 데이터베이스 데이터
    • 서비스를 운영하는데 반드시 필요한 데이터
      예) 제품 구입 정보, 유저 가입 정보
    • 주로 데이터베이스에 저장
  2. 사용자 행동 데이터
    • 서비스를 개선하기 위한 데이터 분석시 필요한 데이터
      다른 말로는 유저 로그라고 부름
    • 유저가 어떤 행동을 하는지 나타내는 데이터
      예) Click, view, 스와이프
    • 주로 Object storage나 Data warehouse에 저장
  3. 인프라 데이터
    • 서버가 제대로 동작하고 있는지 확인하기 위한 데이터
      예) DB 부하, Request 수, Response 수

2. Python logging module

logging level

파이썬에서는 기본 로깅 모듈을 제공한다.
import logging

로깅 함수에서는 이벤트의 level, severity에 따라 5단계로 구분한다.

수준설명
DEBUG상세한 정보가 필요할 경우 사용
INFO기본적인 작업이 정상적으로 작동하는 경우 사용
WARNING작업은 정상적으로 작동하지만, 예측하지 못한 일이 발생했거나, 앞으로 발생할 수 있는 문제
ERROR프로그램이 일부 기능을 수행하지 못할 정도의 문제
CRITICAL프로그램이 동작할 수 없을 정도의 심각한 문제

기본 로깅 레벨은 WARNING으로 WARNING 이상 레벨의 로그만 보여준다.

import logging

logging.debug("hello word1")
logging.info("hello world2")  
logging.warning("hello world3")
logging.error("hello world4")
logging.critical("hello world5")

출력 결과

WARNING:root:hello world3
ERROR:root:hello world4
CRITICAL:root:hello world5

logging component

  1. logger
  • 첫째, 응용 프로그램이 실행시간에 메시지를 기록 할 수 있도록 여러 메서드를 응용 프로그램 코드에 노출한다.
  • 둘째, 로거 객체는 심각도 (기본 필터링 장치) 또는 필터 객체에 따라 어떤 로그 메시지를 처리할지 결정한다.
  • 셋째, 로거 객체는 관련 로그 메시지를 관심 있는 모든 log handler로 전달한다.
  1. handler
  • 적절한 로그 메시지를 handler의 지정된 대상(파일 또는 콘솔)으로 전달하는 역할을 한다.
  • handler에서는 setLevel() 메서드를 사용하여 처리가가 전달하는 최소 수준을 설정할 수 있다. 그리고 setFormatter() 메서드 통해 포메터를 지정할 수 있고, addFilter() 메서드를 통해 필터를 설절할 수 있다.
  • 흔히 사용하는 handler는 StreamHandler, FileHandler, HTTPHandler 등이 있다.
  1. Formatter
  • 최종적으로 로그에 출력된 포멧을 지정할 수 있고, 날짜, 이름, 수준, 메세지, logger 이름 등의 정보를 출력 할 수 있다.
  1. Filter
  • Filter는 수준을 통해 제공되는 것보다 정교한 필터링을 통해 Handler와 Logger에서 허용될 로그를 결정한다.

logging flow

전반적인 로그 처리 흐름은 다음 사진과 같다.

(https://docs.python.org/ko/3/howto/logging.html)

logging 구성 예시

import logging

# Logger 생성
logger = logging.getLogger('simple_example')
logger.setLevel(logging.DEBUG)

# Handler 생성
ch = logging.StreamHandler()
ch.setLevel(logging.DEBUG)

# Formatter 생성
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')

# Handler에 Formatter 추가
ch.setFormatter(formatter)

# Logger에 Handler 추가
logger.addHandler(ch)

# Log 생성 예시
logger.debug('debug message')
logger.info('info message')
logger.warning('warn message')
logger.error('error message')
logger.critical('critical message')

출력 결과

2023-02-16 20:25:55,657 - simple_example - DEBUG - debug message
2023-02-16 20:25:55,657 - simple_example - INFO - info message
2023-02-16 20:25:55,657 - simple_example - WARNING - warn message
2023-02-16 20:25:55,657 - simple_example - ERROR - error message
2023-02-16 20:25:55,657 - simple_example - CRITICAL - critical message

로거에 대한 Handler, Formatter 설정 등은 다른 방식으로도 처리 가능하다.

  • fileConfig를 통한 설정
import logging
import logging.config

logging.config.fileConfig('logging.conf')

# create logger
logger = logging.getLogger('simpleExample')

logging.conf 예시

[loggers]
keys=root,simpleExample

[handlers]
keys=consoleHandler

[formatters]
keys=simpleFormatter

[logger_root]
level=DEBUG
handlers=consoleHandler

[logger_simpleExample]
level=DEBUG
handlers=consoleHandler
qualname=simpleExample
propagate=0

[handler_consoleHandler]
class=StreamHandler
level=DEBUG
formatter=simpleFormatter
args=(sys.stdout,)

[formatter_simpleFormatter]
format=%(asctime)s - %(name)s - %(levelname)s - %(message)s
  • dictConfig를 통한 설정
import logging
import logging.config

logger_dict = {
    "version": 1,  
    "disable_existing_loggers": True,  
    "formatters": {
        "simple": {"format": "%(asctime)s | %(levelname)s - %(message)s"},
    },
    "handlers": {
        "console": {
            "level": "DEBUG",
            "class": "logging.StreamHandler",
            "formatter": "simple",
        }
    },
    "loggers": {"example": {"level": "INFO", "handlers": ["console"]}},
}

logging.config.dictConfig(logger_dict)

# create logger
logger = logging.getLogger('simpleExample')
  • baseConfig를 통한 설정
import sys
import logging

logging.basicConfig(
    format="%(asctime)s - %(levelname)s - %(name)s -    %(message)s",
    datefmt="%m/%d/%Y %H:%M:%S",
    handlers=[logging.StreamHandler(sys.stdout)],
    level=logging.DEBUG,
)

# create logger
logger = logging.getLogger("simple_example")
profile
비전공자의 개발자 도전기

0개의 댓글