Created
March 13, 2024 20:43
-
-
Save n05tr0m0/2693ed0e072eb1541a300093abedba53 to your computer and use it in GitHub Desktop.
FastAPI + Uvicorn + loguru configuration
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
"""Classes and functions to customize logs.""" | |
import logging | |
import sys | |
from loguru import logger | |
from app.config import AppSettings # originaly this is BaseSettings from Pydantic | |
class InterceptHandler(logging.Handler): | |
"""Logging handler interceptor from loguru documentation. | |
For more info see "https://loguru.readthedocs.io/en/stable/overview.html#entirely-compatible-with-standard-logging" | |
""" | |
def emit(self, record: logging.LogRecord) -> None: | |
"""Log the specified logging record by loguru logger.""" | |
try: | |
# Get corresponding Loguru level if it exists | |
level = logger.level(record.levelname).name | |
except ValueError: | |
level = str(record.levelno) | |
# Find caller from where originated the logged message | |
frame, depth = logging.currentframe().f_back, 2 | |
while frame.f_code.co_filename in (logging.__file__): | |
frame = frame.f_back | |
depth += 1 | |
logger.opt(depth=depth, exception=record.exc_info).log( | |
level, | |
record.getMessage(), | |
) | |
def configure_logger(settings: AppSettings) -> None: | |
"""Add some loggers to loguru and config logging level.""" | |
logging.getLogger().handlers = [InterceptHandler()] | |
logging.getLogger("uvicorn").setLevel(settings.LOG_LEVEL) | |
logging.getLogger("uvicorn.asgi").setLevel(settings.LOG_LEVEL) | |
logging.getLogger("uvicorn.error").setLevel(settings.LOG_LEVEL) | |
logging.getLogger("uvicorn.access").setLevel(settings.LOG_LEVEL) | |
logger.configure( | |
handlers=[ | |
{ | |
"sink": sys.stdout, | |
"level": settings.LOG_LEVEL, | |
"enqueue": True, | |
"format": ( | |
"<green>{time:YYYY-MM-DD HH:mm:ss.SSS}</green> | " | |
"<level>{level: <8}</level> | " | |
"<cyan>{name}</cyan>:<cyan>{function}</cyan>:<cyan>{line}</cyan> - <level>{message}</level> | " | |
"<yellow>{extra}</yellow>" | |
), | |
}, | |
], | |
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import uvicorn | |
from uvicorn.config import LOGGING_CONFIG | |
... | |
if __name__ == "__main__": | |
# NOTE: "app.logger.InterceptHandler" is the path to your logger's InterceptHandler class | |
LOGGING_CONFIG.update( | |
{ | |
"loggers": { | |
"handlers": {"default": {"class": "app.logger.InterceptHandler"}} | |
} | |
} | |
) | |
uvicorn.run( | |
"app.main:app", | |
... | |
log_config=LOGGING_CONFIG, | |
) | |
# Log example: | |
# 2024-03-13 13:13:12.997 | INFO | uvicorn.main:run:522 - Will watch for changes in these directories: ['/webapp'] | {} | |
# 2024-03-13 13:13:12.998 | INFO | uvicorn.main:run:581 - Uvicorn running on http://0.0.0.0:8000 (Press CTRL+C to quit) | {} | |
# 2024-03-13 13:13:12.998 | INFO | uvicorn.supervisors.basereload:run:51 - Started reloader process [1] using StatReload | {} | |
# 2024-03-13 13:13:13.475 | INFO | asyncio.events:_run:84 - Started server process [9] | {} | |
# 2024-03-13 13:13:13.475 | INFO | uvicorn.server:startup:90 - Waiting for application startup. | {} | |
# 2024-03-13 13:13:13.478 | INFO | uvicorn.server:startup:90 - Application startup complete. | {} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment