Logger(로거)
역할
- 역할 : 로깅 시스템의 진입점이자 구심점이 되는 객체. 개발자가 로깅 메시지를 생성하고 관리하는 역할을 한다.
주요 기능
- 로깅 메시지 생성 :
logger.debug(), logger.error() 등 메서드를 사용해 로그 레코드를 생성한다.
- 레벨 검사 : 자신에게 설정된 로그 레벨 미만의 메시지는 처리하지 않고 무시한다.
- 핸들러 전달 : 생성 및 레벨 검사에서 통과된 로그 레코드를 하나 이상의 Handler 에 전달한다.
- 계층 구조 : 로거는 계층적 구조를 가질 수 있으며(e.g.
main.sub) 메시지는 기본적으로 상위 로거로 전파(propagation) 된다.
로거 사용하기
사용 예시
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
| import logging
def about_logger():
# 로거 인스턴스를 생성
# getLogger 는 이름이 제공되면 해당 이름을 가진 로거 인스턴스를 반환한다.
# 그렇지 않으면 루트 인스턴스를 반환한다.
# 서로 다른 이름의 로거는 각기 다른 메모리 주소를 가진다.
logger_name = "about_logger"
logger = logging.getLogger(logger_name)
# setLevel
# 로거가 처리할 가장 낮은 심각도의 로그 레벨을 지정
# 로그 레벨은 logging.INFO 처럼 쓰거나, 로그 레벨에 해당하는 정수값을 넣어도 된다. (아래 둘은 동일)
logger.setLevel(logging.INFO)
logger.setLevel(20)
# addHandler
# 핸들러를 로거에 할당한다.
# Hnadler에 대해서는 Handler 소개 글에서 자세히 다루겠다.
handler = logging.StreamHandler()
handler.setLevel(level = logging.INFO)
formatter = logging.Formatter()
handler.setFormatter(formatter)
logger.addHandler(handler)
# 로그 레코드 생성 및 핸들러에 전달
# debug(), info(), error().. 등의 메서드를 통해 로그 레코드를 생성하고, 핸들러에 전달한다.
# 각각의 메서드는 자신의 이름과 동일한 레벨의 로그 레벨을 가진 로그 레코드를 만들게 된다.
# 예를 들어, debug() 메서드는 logging.DEBUG 레벨의 로그 레코드를 만든다.
logger.debug("debug message")
logger.error("error message")
|
로거 생성 흐름
| No |
흐름 |
설명 |
| 1 |
로거 생성 |
로깅을 수행할 로거를 생성하고, 로그레벨 등 관련 설정을 수행한다. |
| 2 |
핸들러 생성 |
로거가 만든 로그 레코드를 전송하는 핸들러를 생성하고, 로그레벨 등 관련 설정을 수행한다. |
| 3 |
포매터 생성 |
로그 레코드를 지정 형식의 로그 메시지로 만드는 포매터를 생성하고, 관련 설정을 수행한다. |
| 4 |
포매터 할당 |
핸들러에 포매터를 할당한다. |
| 5 |
핸들러 할당 |
로거에 핸들러를 할당한다. |
로거의 메서드
| 메서드 |
설명 |
| logger.addHandler(handler) |
핸들러를 로거에 할당한다. |
| logger.debug(m) |
logging.DEBUG 레벨의 로그 레코드를 생성한다. |
| logger.info(m) |
logging.INFO 레벨의 로그 레코드를 생성한다. |
| logger.warning(m) |
logging.WARNING 레벨의 로그 레코드를 생성한다. |
| logger.error(m) |
logging.ERROR 레벨의 로그 레코드를 생성한다. |
| logger.critical(m) |
logging.CRITICAL 레벨의 로그 레코드를 생성한다. |
로거 이름에 따른 인스턴스 구분
- 로거는
logger_name 에 따라 각기 다른 인스턴스로 구분된다.
- 각각의 인스턴스는 각각의 메모리 주소를 갖는다.
1
2
3
4
5
6
7
8
9
10
11
12
| # ... 위 코드 생략
# logger 이름에 따른 인스턴스 생성
# logger 인스턴스는 "이름"에 따라 생성되며 관리된다.
# 이름이 다르면 서로 다른 로거 인스턴스이다.
# 서로 다른 인스턴스는 당연히 서로 다른 메모리 주소를 갖는다.
print(f"{logger_name} 로거의 id : {id(logger)}")
new_logger_name = "new_logger"
logger = logging.getLogger("new_logger")
print(f"{new_logger_name} 로거의 id : {id(logger)}")
logger = logging.getLogger(logger_name)
print(f"다시 돌아온 {logger_name} 로거의 id : {id(logger)}")
|
1
2
3
4
| # 출력 결과
about_logger 로거의 id : 4364629968
new_logger 로거의 id : 4364864304
다시 돌아온 about_logger 로거의 id : 4364629968
|
Reference
https://docs.python.org/3/library/logging.html
https://docs.python.org/ko/3/howto/logging.html
Comments