refactor: update logger import paths to use rotoger

This commit is contained in:
grillazz
2026-03-09 18:05:05 +01:00
parent 07c98d79ae
commit 21c5953385
13 changed files with 21 additions and 108 deletions
+1 -1
View File
@@ -2,7 +2,7 @@ from typing import Annotated
from fastapi import APIRouter, Depends, Query, Request, status from fastapi import APIRouter, Depends, Query, Request, status
from pydantic import EmailStr from pydantic import EmailStr
from app.services.logging import get_logger from rotoger import get_logger
from starlette.concurrency import run_in_threadpool from starlette.concurrency import run_in_threadpool
from app.services.smtp import SMTPEmailService from app.services.smtp import SMTPEmailService
+1 -1
View File
@@ -2,7 +2,7 @@ from typing import Annotated
from fastapi import APIRouter, Depends, Form from fastapi import APIRouter, Depends, Form
from fastapi.responses import StreamingResponse from fastapi.responses import StreamingResponse
from app.services.logging import get_logger from rotoger import get_logger
from app.services.llm import get_llm_service from app.services.llm import get_llm_service
+1 -1
View File
@@ -1,7 +1,7 @@
from typing import Annotated from typing import Annotated
from fastapi import APIRouter, Depends, Form, HTTPException, Request, status from fastapi import APIRouter, Depends, Form, HTTPException, Request, status
from app.services.logging import get_logger from rotoger import get_logger
from sqlalchemy.ext.asyncio import AsyncSession from sqlalchemy.ext.asyncio import AsyncSession
from app.database import get_db from app.database import get_db
+1 -1
View File
@@ -1,7 +1,7 @@
from collections.abc import AsyncGenerator from collections.abc import AsyncGenerator
from fastapi.exceptions import ResponseValidationError from fastapi.exceptions import ResponseValidationError
from app.services.logging import get_logger from rotoger import get_logger
from sqlalchemy.exc import SQLAlchemyError from sqlalchemy.exc import SQLAlchemyError
from sqlalchemy.ext.asyncio import async_sessionmaker, create_async_engine from sqlalchemy.ext.asyncio import async_sessionmaker, create_async_engine
+1 -1
View File
@@ -1,7 +1,7 @@
import orjson import orjson
from attrs import define, field from attrs import define, field
from fastapi import Request from fastapi import Request
from app.services.logging import get_logger from rotoger import get_logger
logger = get_logger() logger = get_logger()
+1 -1
View File
@@ -2,7 +2,7 @@ from typing import Any
from asyncpg import UniqueViolationError from asyncpg import UniqueViolationError
from fastapi import HTTPException, status from fastapi import HTTPException, status
from app.services.logging import get_logger from rotoger import get_logger
from sqlalchemy.exc import IntegrityError, SQLAlchemyError from sqlalchemy.exc import IntegrityError, SQLAlchemyError
from sqlalchemy.ext.asyncio import AsyncSession from sqlalchemy.ext.asyncio import AsyncSession
from sqlalchemy.orm import DeclarativeBase, declared_attr from sqlalchemy.orm import DeclarativeBase, declared_attr
+2 -3
View File
@@ -1,11 +1,10 @@
from typing import Any from typing import Any, Callable
from uuid import UUID from uuid import UUID
from pydantic import BaseModel, ConfigDict, Field from pydantic import BaseModel, ConfigDict, Field, WrapValidator, ValidationError
config = ConfigDict(from_attributes=True) config = ConfigDict(from_attributes=True)
class RandomStuff(BaseModel): class RandomStuff(BaseModel):
chaos: dict[str, Any] = Field( chaos: dict[str, Any] = Field(
..., description="Pretty chaotic JSON data can be added here..." ..., description="Pretty chaotic JSON data can be added here..."
+1 -1
View File
@@ -3,7 +3,7 @@ import time
import jwt import jwt
from fastapi import HTTPException, Request from fastapi import HTTPException, Request
from fastapi.security import HTTPAuthorizationCredentials, HTTPBearer from fastapi.security import HTTPAuthorizationCredentials, HTTPBearer
from app.services.logging import get_logger from rotoger import get_logger
from app.config import settings as global_settings from app.config import settings as global_settings
from app.models.user import User from app.models.user import User
-86
View File
@@ -1,86 +0,0 @@
import logging
import os
from logging.handlers import RotatingFileHandler
from pathlib import Path
import orjson
import structlog
from whenever._whenever import Instant
# ---------------------------------------------------------------------------
# Constants / defaults
# ---------------------------------------------------------------------------
_DEFAULT_LOG_PATH = "."
_DEFAULT_MAX_BYTES = 10 * 1024 * 1024 # 10 MiB
_DEFAULT_BACKUP_COUNT = 5
# Generic registry: add any stdlib logger name + its desired level here.
_STDLIB_LOGGERS: dict[str, int] = {
"root": logging.INFO,
"uvicorn": logging.INFO,
"sqlalchemy": logging.WARNING,
}
# Shared processor chain used by both structlog and the stdlib formatter.
_SHARED_PROCESSORS: list[structlog.types.Processor] = [
structlog.contextvars.merge_contextvars,
structlog.stdlib.add_log_level,
structlog.stdlib.add_logger_name,
structlog.stdlib.PositionalArgumentsFormatter(),
structlog.processors.TimeStamper(fmt="iso", utc=True),
structlog.processors.format_exc_info,
]
def _build_handler() -> RotatingFileHandler:
log_dir = Path(os.getenv("ROTOGER_LOG_PATH", _DEFAULT_LOG_PATH))
log_dir.mkdir(parents=True, exist_ok=True)
log_path = log_dir / f"{Instant.now().py_datetime().strftime('%Y%m%d')}_{os.getpid()}.log"
handler = RotatingFileHandler(
filename=log_path,
maxBytes=int(os.getenv("ROTOGER_LOG_MAX_BYTES", _DEFAULT_MAX_BYTES)),
backupCount=int(os.getenv("ROTOGER_LOG_BACKUP_COUNT", _DEFAULT_BACKUP_COUNT)),
encoding="utf-8",
)
handler.setFormatter(
structlog.stdlib.ProcessorFormatter(
foreign_pre_chain=_SHARED_PROCESSORS,
processor=structlog.processors.JSONRenderer(
serializer=lambda *a, **kw: orjson.dumps(*a, **kw).decode()
),
)
)
return handler
def _configure_logger() -> structlog.BoundLogger:
"""Configure structlog + stdlib loggers and return a bound logger."""
structlog.configure(
processors=[
*_SHARED_PROCESSORS,
structlog.stdlib.ProcessorFormatter.wrap_for_formatter,
],
logger_factory=structlog.stdlib.LoggerFactory(),
wrapper_class=structlog.stdlib.BoundLogger,
cache_logger_on_first_use=True,
)
handler = _build_handler()
for name, level in _STDLIB_LOGGERS.items():
logger = logging.getLogger(name)
logger.addHandler(handler)
logger.propagate = False
logger.setLevel(level)
return structlog.get_logger()
# Module-level singleton
_logger_instance = _configure_logger()
def get_logger() -> structlog.BoundLogger:
"""Return the configured singleton logger instance."""
return _logger_instance
+1 -1
View File
@@ -3,7 +3,7 @@ from datetime import datetime
from apscheduler import AsyncScheduler from apscheduler import AsyncScheduler
from apscheduler.triggers.interval import IntervalTrigger from apscheduler.triggers.interval import IntervalTrigger
from attrs import define from attrs import define
from app.services.logging import get_logger from rotoger import get_logger
from sqlalchemy import text from sqlalchemy import text
from starlette.types import ASGIApp, Receive, Scope, Send from starlette.types import ASGIApp, Receive, Scope, Send
+1 -1
View File
@@ -5,7 +5,7 @@ from email.mime.text import MIMEText
from attrs import define, field from attrs import define, field
from fastapi.templating import Jinja2Templates from fastapi.templating import Jinja2Templates
from pydantic import EmailStr from pydantic import EmailStr
from app.services.logging import get_logger from rotoger import get_logger
from app.config import settings as global_settings from app.config import settings as global_settings
from app.utils.singleton import SingletonMetaNoArgs from app.utils.singleton import SingletonMetaNoArgs
+2 -2
View File
@@ -22,14 +22,14 @@ dependencies = [
"redis==7.1.0", "redis==7.1.0",
"bcrypt==5.0.0", "bcrypt==5.0.0",
"polars[pyarrow]==1.36.1", "polars[pyarrow]==1.36.1",
"python-multipart==0.0.20", "python-multipart==0.0.22",
"fastexcel==0.18.0", "fastexcel==0.18.0",
"inline-snapshot==0.31.1", "inline-snapshot==0.31.1",
"dirty-equals==0.11", "dirty-equals==0.11",
"polyfactory==3.1.0", "polyfactory==3.1.0",
"granian==2.6.0", "granian==2.6.0",
"apscheduler[redis,sqlalchemy]>=4.0.0a6", "apscheduler[redis,sqlalchemy]>=4.0.0a6",
"rotoger==0.2.1", "rotoger==0.3.0",
"pyinstrument>=5.1.2", "pyinstrument>=5.1.2",
] ]
Generated
+8 -8
View File
@@ -438,10 +438,10 @@ requires-dist = [
{ name = "pyjwt", specifier = "==2.10.1" }, { name = "pyjwt", specifier = "==2.10.1" },
{ name = "pytest", specifier = "==9.0.2" }, { name = "pytest", specifier = "==9.0.2" },
{ name = "pytest-cov", specifier = "==7.0.0" }, { name = "pytest-cov", specifier = "==7.0.0" },
{ name = "python-multipart", specifier = "==0.0.20" }, { name = "python-multipart", specifier = "==0.0.22" },
{ name = "redis", specifier = "==7.1.0" }, { name = "redis", specifier = "==7.1.0" },
{ name = "rich", specifier = "==14.2.0" }, { name = "rich", specifier = "==14.2.0" },
{ name = "rotoger", specifier = "==0.2.1" }, { name = "rotoger", specifier = "==0.3.0" },
{ name = "sqlalchemy", specifier = "==2.0.45" }, { name = "sqlalchemy", specifier = "==2.0.45" },
{ name = "uvicorn", extras = ["standard"], specifier = "==0.38.0" }, { name = "uvicorn", extras = ["standard"], specifier = "==0.38.0" },
{ name = "uvloop", specifier = "==0.22.1" }, { name = "uvloop", specifier = "==0.22.1" },
@@ -1075,11 +1075,11 @@ wheels = [
[[package]] [[package]]
name = "python-multipart" name = "python-multipart"
version = "0.0.20" version = "0.0.22"
source = { registry = "https://pypi.org/simple" } source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/f3/87/f44d7c9f274c7ee665a29b885ec97089ec5dc034c7f3fafa03da9e39a09e/python_multipart-0.0.20.tar.gz", hash = "sha256:8dd0cab45b8e23064ae09147625994d090fa46f5b0d1e13af944c331a7fa9d13", size = 37158, upload-time = "2024-12-16T19:45:46.972Z" } sdist = { url = "https://files.pythonhosted.org/packages/94/01/979e98d542a70714b0cb2b6728ed0b7c46792b695e3eaec3e20711271ca3/python_multipart-0.0.22.tar.gz", hash = "sha256:7340bef99a7e0032613f56dc36027b959fd3b30a787ed62d310e951f7c3a3a58", size = 37612, upload-time = "2026-01-25T10:15:56.219Z" }
wheels = [ wheels = [
{ url = "https://files.pythonhosted.org/packages/45/58/38b5afbc1a800eeea951b9285d3912613f2603bdf897a4ab0f4bd7f405fc/python_multipart-0.0.20-py3-none-any.whl", hash = "sha256:8a62d3a8335e06589fe01f2a3e178cdcc632f3fbe0d492ad9ee0ec35aab1f104", size = 24546, upload-time = "2024-12-16T19:45:44.423Z" }, { url = "https://files.pythonhosted.org/packages/1b/d0/397f9626e711ff749a95d96b7af99b9c566a9bb5129b8e4c10fc4d100304/python_multipart-0.0.22-py3-none-any.whl", hash = "sha256:2b2cd894c83d21bf49d702499531c7bafd057d730c201782048f7945d82de155", size = 24579, upload-time = "2026-01-25T10:15:54.811Z" },
] ]
[[package]] [[package]]
@@ -1196,7 +1196,7 @@ wheels = [
[[package]] [[package]]
name = "rotoger" name = "rotoger"
version = "0.2.1" version = "0.3.0"
source = { registry = "https://pypi.org/simple" } source = { registry = "https://pypi.org/simple" }
dependencies = [ dependencies = [
{ name = "attrs" }, { name = "attrs" },
@@ -1204,9 +1204,9 @@ dependencies = [
{ name = "structlog" }, { name = "structlog" },
{ name = "whenever" }, { name = "whenever" },
] ]
sdist = { url = "https://files.pythonhosted.org/packages/9d/ad/75a22ddd259505547fd47c36ea984688e3b56d9cbc49c0f98bb95c84c01b/rotoger-0.2.1.tar.gz", hash = "sha256:823bb39c781d6038d2aae1c2c3f6d74c0abb1e9f07b257c079028d6ae3f2589d", size = 1647, upload-time = "2025-11-13T16:12:27.833Z" } sdist = { url = "https://files.pythonhosted.org/packages/06/40/475df92ef562d22489a1b07bc41cf1094dce1d4d03475f59112b97070560/rotoger-0.3.0.tar.gz", hash = "sha256:e407e3f4cf4948886bd26b35bd54e635f58703db406f5a706e4c4579dc273241", size = 2714, upload-time = "2026-03-01T17:08:46.78Z" }
wheels = [ wheels = [
{ url = "https://files.pythonhosted.org/packages/e7/da/9422061c62499eaafcf90c4adf3e13c51031d4b593af899451825fa85a7b/rotoger-0.2.1-py3-none-any.whl", hash = "sha256:849ed131068ab724991c38c32fb63e4904efb79e29bf084f37ec11a31ec0c703", size = 2603, upload-time = "2025-11-13T16:12:26.895Z" }, { url = "https://files.pythonhosted.org/packages/72/85/2164d61cff7594366d5797cc6f33784a05e83a39841701860bbbc41631dc/rotoger-0.3.0-py3-none-any.whl", hash = "sha256:08d3c239f05c0551a9cdb682332f4c1e981844b1b0afa7b1e04c50730bbe2098", size = 3458, upload-time = "2026-03-01T17:08:47.684Z" },
] ]
[[package]] [[package]]