014 add json logging
This commit is contained in:
@@ -1,9 +1,9 @@
|
||||
"""CDEK HTTP client and provider adapter."""
|
||||
|
||||
import asyncio
|
||||
import sys
|
||||
from collections.abc import Awaitable, Callable
|
||||
from typing import Any
|
||||
import logging
|
||||
|
||||
import httpx
|
||||
|
||||
@@ -13,16 +13,7 @@ from app.adapters.delivery_providers.cdek.mapper import map_cdek_response
|
||||
from app.config import AdapterConfig
|
||||
from app.schemas.request import DeliveryRequest
|
||||
from app.schemas.response import DeliveryPrice
|
||||
import logging
|
||||
|
||||
|
||||
logging.basicConfig(
|
||||
level=logging.INFO,
|
||||
format="%(asctime)s [%(levelname)s] %(name)s: %(message)s",
|
||||
handlers=[logging.StreamHandler(sys.stdout)] # важно: stdout, не stderr
|
||||
)
|
||||
log = logging.getLogger(__name__)
|
||||
log.info("test")
|
||||
|
||||
|
||||
class CDEKClientError(RuntimeError):
|
||||
|
||||
@@ -4,9 +4,11 @@ from fastapi import FastAPI
|
||||
|
||||
from app.config import Settings, get_settings
|
||||
from app.controllers.v1.delivery import router as delivery_router
|
||||
from app.runtime.logging import configure_logging
|
||||
|
||||
|
||||
def create_app(settings: Settings | None = None) -> FastAPI:
|
||||
configure_logging()
|
||||
resolved_settings = settings or get_settings()
|
||||
|
||||
application = FastAPI(title="G2S Aggregator", version="0.1.0")
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
"""Runtime support modules."""
|
||||
@@ -0,0 +1,78 @@
|
||||
"""Centralized runtime logging bootstrap."""
|
||||
|
||||
import logging
|
||||
import sys
|
||||
from collections.abc import Iterable
|
||||
from typing import TextIO
|
||||
|
||||
import structlog
|
||||
|
||||
|
||||
_UVICORN_LOGGER_NAMES = ("uvicorn", "uvicorn.error", "uvicorn.access")
|
||||
|
||||
|
||||
def configure_logging(
|
||||
*,
|
||||
log_level: int = logging.INFO,
|
||||
stream: TextIO | None = None,
|
||||
) -> None:
|
||||
resolved_stream = sys.stdout if stream is None else stream
|
||||
formatter = structlog.stdlib.ProcessorFormatter(
|
||||
foreign_pre_chain=list(_shared_processors()),
|
||||
processors=[
|
||||
structlog.stdlib.ProcessorFormatter.remove_processors_meta,
|
||||
structlog.processors.JSONRenderer(sort_keys=True),
|
||||
],
|
||||
)
|
||||
handler = logging.StreamHandler(resolved_stream)
|
||||
handler.setLevel(log_level)
|
||||
handler.setFormatter(formatter)
|
||||
|
||||
structlog.reset_defaults()
|
||||
structlog.configure(
|
||||
processors=[
|
||||
*_shared_processors(),
|
||||
structlog.stdlib.PositionalArgumentsFormatter(),
|
||||
structlog.processors.StackInfoRenderer(),
|
||||
structlog.processors.format_exc_info,
|
||||
structlog.stdlib.ProcessorFormatter.wrap_for_formatter,
|
||||
],
|
||||
logger_factory=structlog.stdlib.LoggerFactory(),
|
||||
wrapper_class=structlog.stdlib.BoundLogger,
|
||||
cache_logger_on_first_use=True,
|
||||
)
|
||||
|
||||
_configure_logger(logging.getLogger(), handler=handler, log_level=log_level)
|
||||
for logger_name in _UVICORN_LOGGER_NAMES:
|
||||
_configure_logger(
|
||||
logging.getLogger(logger_name),
|
||||
handler=handler,
|
||||
log_level=log_level,
|
||||
propagate=False,
|
||||
)
|
||||
|
||||
|
||||
def _shared_processors() -> tuple[structlog.types.Processor, ...]:
|
||||
return (
|
||||
structlog.stdlib.add_logger_name,
|
||||
structlog.stdlib.add_log_level,
|
||||
structlog.processors.TimeStamper(fmt="iso", utc=True),
|
||||
)
|
||||
|
||||
|
||||
def _configure_logger(
|
||||
logger: logging.Logger,
|
||||
*,
|
||||
handler: logging.Handler,
|
||||
log_level: int,
|
||||
propagate: bool = True,
|
||||
) -> None:
|
||||
_clear_handlers(logger.handlers)
|
||||
logger.setLevel(log_level)
|
||||
logger.handlers = [handler]
|
||||
logger.propagate = propagate
|
||||
|
||||
|
||||
def _clear_handlers(handlers: Iterable[logging.Handler]) -> None:
|
||||
for existing_handler in list(handlers):
|
||||
existing_handler.close()
|
||||
Reference in New Issue
Block a user