|
| 1 | +import logging |
1 | 2 | import os
|
2 | 3 | from typing import Any, Callable, Iterable, Type
|
3 | 4 |
|
|
21 | 22 | from py_spring_core.core.application.context.application_context_config import (
|
22 | 23 | ApplicationContextConfig,
|
23 | 24 | )
|
| 25 | +from py_spring_core.core.application.loguru_config import LogFormat |
24 | 26 | from py_spring_core.core.entities.bean_collection import BeanCollection
|
25 | 27 | from py_spring_core.core.entities.component import Component, ComponentLifeCycle
|
26 | 28 | from py_spring_core.core.entities.controllers.rest_controller import RestController
|
@@ -97,14 +99,16 @@ def __configure_logging(self):
|
97 | 99 | config = self.app_config.loguru_config
|
98 | 100 | if not config.log_file_path:
|
99 | 101 | return
|
100 |
| - |
| 102 | + |
| 103 | + # Use the format field from config which contains the actual format string |
101 | 104 | logger.add(
|
102 | 105 | config.log_file_path,
|
103 |
| - format=config.log_format, |
104 | 106 | level=config.log_level,
|
105 | 107 | rotation=config.log_rotation,
|
106 | 108 | retention=config.log_retention,
|
| 109 | + serialize=config.format == LogFormat.JSON, |
107 | 110 | )
|
| 111 | + self.__configure_uvicorn_logging() |
108 | 112 |
|
109 | 113 | def _get_system_managed_classes(self) -> Iterable[Type[Component]]:
|
110 | 114 | return [
|
@@ -209,11 +213,40 @@ def __init_controllers(self) -> None:
|
209 | 213 | self.fastapi.include_router(router)
|
210 | 214 | controller.register_middlewares()
|
211 | 215 |
|
| 216 | + def __configure_uvicorn_logging(self): |
| 217 | + """Configure Uvicorn to use Loguru instead of default logging.""" |
| 218 | + |
| 219 | + |
| 220 | + # Intercept standard logging and redirect to loguru |
| 221 | + class InterceptHandler(logging.Handler): |
| 222 | + def emit(self, record): |
| 223 | + # Get corresponding Loguru level if it exists |
| 224 | + try: |
| 225 | + level = logger.level(record.levelname).name |
| 226 | + except ValueError: |
| 227 | + level = record.levelno |
| 228 | + |
| 229 | + # Find caller from where originated the logged message |
| 230 | + frame, depth = logging.currentframe(), 2 |
| 231 | + while frame and frame.f_code.co_filename == logging.__file__: |
| 232 | + frame = frame.f_back |
| 233 | + depth += 1 |
| 234 | + |
| 235 | + logger.opt(depth=depth, exception=record.exc_info).log(level, record.getMessage()) |
| 236 | + |
| 237 | + # Remove default uvicorn logger and add intercept handler |
| 238 | + logging.basicConfig(handlers=[InterceptHandler()], level=0, force=True) |
| 239 | + |
212 | 240 | def __run_server(self) -> None:
|
| 241 | + # Configure Uvicorn to use Loguru |
| 242 | + |
| 243 | + |
| 244 | + # Run uvicorn server |
213 | 245 | uvicorn.run(
|
214 | 246 | self.fastapi,
|
215 | 247 | host=self.app_config.server_config.host,
|
216 | 248 | port=self.app_config.server_config.port,
|
| 249 | + log_config=None, # Disable uvicorn's default logging |
217 | 250 | )
|
218 | 251 |
|
219 | 252 | def run(self) -> None:
|
|
0 commit comments