66 lines
2.0 KiB
Python
66 lines
2.0 KiB
Python
import logging
|
|
import os
|
|
import sys
|
|
|
|
import pydantic
|
|
|
|
from .console_formatter import ColoredConsoleFormatter
|
|
from .json_formatter import JSONFormatter
|
|
|
|
|
|
class LoggerConfig(pydantic.BaseModel):
|
|
APP_NAME: str
|
|
APP_VERSION: str
|
|
LEVEL: int = logging.INFO
|
|
PRETTY_CONSOLE: bool = False
|
|
|
|
@pydantic.field_validator('APP_VERSION')
|
|
@classmethod
|
|
def normalize_app_version(cls, v: str) -> str:
|
|
parts = v.removeprefix('v').split('.')
|
|
if len(parts) < 2 or any(not part.isdigit() for part in parts):
|
|
raise ValueError('APP_VERSION must look like 1.2.0')
|
|
commit_count = _get_git_commit_count()
|
|
if not commit_count:
|
|
return f'v{".".join(parts)}'
|
|
parts[-1] = commit_count
|
|
return f'v{".".join(parts)}'
|
|
|
|
|
|
def _get_git_commit_count() -> str | None:
|
|
commit_count = os.getenv('GIT_COMMIT_COUNT')
|
|
if commit_count is None:
|
|
return None
|
|
normalized = commit_count.strip()
|
|
return normalized or None
|
|
|
|
|
|
def init(config: LoggerConfig) -> None:
|
|
root_logger = logging.getLogger()
|
|
root_logger.setLevel(config.LEVEL)
|
|
root_logger.handlers.clear()
|
|
|
|
handler = logging.StreamHandler(sys.stdout)
|
|
handler.setLevel(config.LEVEL)
|
|
|
|
formatter = ColoredConsoleFormatter() if config.PRETTY_CONSOLE else JSONFormatter()
|
|
handler.setFormatter(formatter)
|
|
root_logger.addHandler(handler)
|
|
|
|
for logger_name in ['uvicorn', 'uvicorn.access', 'uvicorn.error']:
|
|
uvicorn_logger = logging.getLogger(logger_name)
|
|
uvicorn_logger.handlers = [handler]
|
|
uvicorn_logger.propagate = False
|
|
|
|
old_factory = logging.getLogRecordFactory()
|
|
|
|
def record_factory(*args: object, **kwargs: object) -> logging.LogRecord:
|
|
record = old_factory(*args, **kwargs)
|
|
record.app_name = config.APP_NAME
|
|
record.app_version = config.APP_VERSION
|
|
return record
|
|
|
|
logging.setLogRecordFactory(record_factory)
|
|
|
|
logging.info('Logger initialized', extra={'app': config.APP_NAME, 'version': config.APP_VERSION})
|