| from __future__ import annotations |
| import json, sys, os, logging |
| from logging.config import dictConfig |
| from uvicorn.config import LOG_LEVELS |
|
|
| SERVICE_NAME = os.getenv("SERVICE_NAME", "backend") |
| ENV = os.getenv("ENV", "production") |
|
|
| class JsonFormatter(logging.Formatter): |
| def format(self, record: logging.LogRecord) -> str: |
| base = { |
| "level": record.levelname, |
| "logger": record.name, |
| "msg": record.getMessage(), |
| "time": self.formatTime(record, self.datefmt), |
| "service": SERVICE_NAME, |
| "env": ENV, |
| } |
| if record.exc_info: |
| base["exc_info"] = self.formatException(record.exc_info) |
| return json.dumps(base, ensure_ascii=False) |
|
|
| def setup_logging(): |
| log_level = os.getenv("LOG_LEVEL", "INFO").upper() |
| if log_level not in LOG_LEVELS: |
| log_level = "INFO" |
|
|
| dictConfig({ |
| "version": 1, |
| "disable_existing_loggers": False, |
| "formatters": { |
| "json": {"()": JsonFormatter}, |
| "plain": {"format": "%(levelname)s:%(name)s:%(message)s"}, |
| }, |
| "handlers": { |
| "console": { |
| "class": "logging.StreamHandler", |
| "stream": sys.stdout, |
| "formatter": "json" if ENV == "production" else "plain", |
| "level": log_level, |
| }, |
| }, |
| "loggers": { |
| "uvicorn": {"handlers": ["console"], "level": log_level, "propagate": False}, |
| "uvicorn.error": {"handlers": ["console"], "level": log_level, "propagate": False}, |
| "uvicorn.access": {"handlers": ["console"], "level": log_level, "propagate": False}, |
| "fastapi": {"handlers": ["console"], "level": log_level, "propagate": False}, |
| "": {"handlers": ["console"], "level": log_level}, |
| }, |
| }) |