반응형
Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
Tags
- Litmus
- Kubernetes 인증
- CI/CD
- serving
- Continuous Deployment
- Kubeflow
- Kubernetes
- blue/green
- Pulumi
- MLflow
- seldon core
- Argo
- mlops
- 오퍼레이터
- 카오스 엔지니어링
- opensearch
- keda
- gitea
- kubernetes operator
- argo rollout
- operator
- CANARY
- tekton
- opentelemetry
- knative
- Model Serving
- nginx ingress
- argocd
- Kopf
- gitops
Archives
- Today
- Total
Kubernetes 이야기
Loguru 본문
반응형
Python 에는 Logging 라는 표준 로깅 라이브러리가 있다. Logging은 구성의 복잡성, 다양한 수준의 로깅 설정 및 로그 파일 회전의 불편함 때문에 Loguru 라는 로깅 라이브러리를 많이 사용한다.
주요기능
- 회전/보존/압축으로 더 쉬운 파일 로깅
- 색상 지정으로 예쁜 로깅
- 비동기식, 스레드 안전, 다중 프로세스 안전
- Backtrace 및 Diagnose 옵션
- 사용자 정의 가능한 레벨
- 날짜/시간 처리 개선
- 표준 로깅과 완전히 호환
- 환경 변수를 통해 개인화 가능한 기본값
- notifiers 와 연동하여 알람 기능
설치
pip install loguru
주요설정
1) 기본설정
logger.remove() # 기본 logger 삭제
logger.add(sys.stderr, format="{time} {level} {message}", filter="my_module", level="INFO")
2) 로깅 로테이션
logger.add("file_1.log", rotation="500 MB") # Automatically rotate too big file
logger.add("file_2.log", rotation="12:00") # New file is created each day at noon
logger.add("file_3.log", rotation="1 week") # Once the file is too old, it's rotated
logger.add("file_X.log", retention="10 days") # Cleanup after some time
logger.add("file_Y.log", compression="zip") # Save some loved space
3) 로깅 포맷 및 레벨
logger.add(sys.stderr, level="INFO")
로깅 레벨이나 포맷은 환경변수에 지정하면 기본값을 지정할 수도 있다.
export LOGURU_FORMAT="{time} | <lvl>{message}</lvl>"
export LOGURU_LEVEL="INFO"
4) 날짜 포맷
export LOGURU_FORMAT="<green>[{time:YYYY-MM-DD HH:mm:ss}]</green>[<level>{level: <8}</level>][<cyan>{name}</cyan>:<cyan>{function}</cyan>:<cyan>{line}</cyan>] <level>{message}</level>"
5) Backtrace 및 Diagnose
아래의 코드를 일반적인 로그로 출력해 보자.
from loguru import logger
async def test_all(x: int = 0):
try:
logger.info("test")
a = 3/x
return a
except Exception as e:
logger.error(e)
[실행결과]
[2023-01-24 17:43:48][INFO ][app.api.routes.auth:test_all:40] test
[2023-01-24 17:43:48][ERROR ][app.api.routes.auth:test_all:44] division by zero
위의 44 line은 logger.error(e) 부분 이다. try 구문에서 어떤 문제때문에 발생된 에러인지 정확히 판단하기가 어렵다.
이제 loguru 설정을 다음과 같이 추가해 보자.
logger.remove()
logger.add(sys.stdout, format="<green>[{time:YYYY-MM-DD HH:mm:ss}]</green>[<level>{level: <8}</level>][<cyan>{name}</cyan>:<cyan>{function}</cyan>:<cyan>{line}</cyan>] <level>{message}</level>", backtrace=False, diagnose=False)
그 다음 excect 부분에 logger 출력을 다음과 같이 변경한다.
async def test_all(x: int = 0):
try:
logger.info("test")
a = 3/x
return a
except Exception as e:
#logger.error(e)
logger.exception("")
[실행결과]
[2023-01-24 17:48:34][INFO ][app.api.routes.auth:test_all:40] test
[2023-01-24 17:48:34][ERROR ][app.api.routes.auth:test_all:45]
Traceback (most recent call last):
File "/mnt/d/develop/kubevital/kubevital/app/api/routes/auth.py", line 41, in test_all
a = 3/x
ZeroDivisionError: division by zero
위와 같이 상세한 오류 위치를 확인할 수 있다. 설정을 다음과 같이 True로 하는 경우는
export LOGURU_BACKTRACE="True"
export LOGURU_DIAGNOSE="True"
[실행결과]
[2023-01-24 17:50:06][INFO ][app.api.routes.auth:test_all:40] test
[2023-01-24 17:50:06][ERROR ][app.api.routes.auth:test_all:45]
Traceback (most recent call last):
File "<string>", line 1, in <module>
File "/usr/lib/python3.11/multiprocessing/spawn.py", line 120, in spawn_main
exitcode = _main(fd, parent_sentinel)
│ │ └ 4
│ └ 7
└ <function _main at 0x7f112f854e00>
File "/usr/lib/python3.11/multiprocessing/spawn.py", line 133, in _main
return self._bootstrap(parent_sentinel)
...
[2023-01-24 17:50:06][INFO ][app.api.routes.auth:test_all:40] test
[2023-01-24 17:50:06][ERROR ][app.api.routes.auth:test_all:45]
Traceback (most recent call last):
exitcode = _main(fd, parent_sentinel)
│ │ └ 4
│ └ 7
└ <function _main at 0x7f112f854e00>
File "/usr/lib/python3.11/multiprocessing/spawn.py", line 133, in _main
return self._bootstrap(parent_sentinel)
위와 같이 상세한 Trace정보를 확인할 수 있다.
만약, unexpected exception 을 처리하는 경우에는 다음과 같이 할 수 있다.
@logger.catch()
async def test_all(x: int = 0):
logger.info("test")
a = 3/x
return a
참고
반응형
'개발 > python' 카테고리의 다른 글
Kopf (소개) (0) | 2023.02.03 |
---|---|
Ubuntu에서 pipenv 실행 시 FileNotFoundError 오류 (0) | 2023.01.28 |
Fastapi 모범 사례 (0) | 2023.01.22 |
fastapi 개발 환경 구성 (0) | 2023.01.22 |
Pipenv로 Python 가상환경 구성 및 패키지 관리하기 (0) | 2023.01.22 |
Comments