Skip to content

Commit 31c3d2f

Browse files
maxxgxCopilot
andauthored
chore (inspect): improve logs (add uvicorn handler) and add job_id to model (#3044)
* improve logs (add uvicorn handler) and add job_id to model Signed-off-by: Ma, Xiangxiang <xiangxiang.ma@intel.com> * Update application/backend/src/core/logging/setup.py Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> Signed-off-by: Max Xiang <maxx.rift@gmail.com> * Update application/backend/src/core/logging/setup.py Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> Signed-off-by: Max Xiang <maxx.rift@gmail.com> * Update application/backend/src/services/training_service.py Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> Signed-off-by: Max Xiang <maxx.rift@gmail.com> * train_job_id not nullable Signed-off-by: Ma, Xiangxiang <xiangxiang.ma@intel.com> * address copilot Signed-off-by: Ma, Xiangxiang <xiangxiang.ma@intel.com> --------- Signed-off-by: Ma, Xiangxiang <xiangxiang.ma@intel.com> Signed-off-by: Max Xiang <maxx.rift@gmail.com> Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
1 parent be6fe07 commit 31c3d2f

File tree

16 files changed

+331
-229
lines changed

16 files changed

+331
-229
lines changed

application/backend/src/core/lifecycle.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
from fastapi import FastAPI
1010
from loguru import logger
1111

12-
from core.logging import setup_logging
12+
from core.logging import setup_logging, setup_uvicorn_logging
1313
from core.scheduler import Scheduler
1414
from db import init_models
1515
from settings import get_settings
@@ -21,6 +21,7 @@ async def lifespan(app: FastAPI) -> AsyncGenerator[None]:
2121
"""FastAPI lifespan context manager"""
2222
# Startup
2323
setup_logging()
24+
setup_uvicorn_logging()
2425

2526
settings = get_settings()
2627
logger.info(f"Starting {settings.app_name} application...")

application/backend/src/core/logging.py

Lines changed: 0 additions & 211 deletions
This file was deleted.
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
# Copyright (C) 2025 Intel Corporation
2+
# SPDX-License-Identifier: Apache-2.0
3+
4+
from .log_config import LogConfig
5+
from .setup import global_log_config, setup_logging, setup_uvicorn_logging
6+
7+
__all__ = ["LogConfig", "global_log_config", "setup_logging", "setup_uvicorn_logging"]
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
# Copyright (C) 2025 Intel Corporation
2+
# SPDX-License-Identifier: Apache-2.0
3+
import inspect
4+
import logging
5+
6+
from loguru import logger
7+
8+
9+
class InterceptHandler(logging.Handler):
10+
"""
11+
This handler intercepts standard logging calls and forwards them to loguru
12+
while preserving the original caller information.
13+
"""
14+
15+
def emit(self, record: logging.LogRecord) -> None:
16+
# Get corresponding Loguru level if it exists.
17+
level: str | int
18+
try:
19+
level = logger.level(record.levelname).name
20+
except ValueError:
21+
level = record.levelno
22+
23+
# Find caller from where originated the logged message.
24+
frame, depth = inspect.currentframe(), 0
25+
while frame and (depth == 0 or frame.f_code.co_filename == logging.__file__):
26+
frame = frame.f_back
27+
depth += 1
28+
29+
logger.opt(depth=depth, exception=record.exc_info).log(level, record.getMessage())
30+
31+
32+
class LoggerStdoutWriter:
33+
"""Wrapper for redirecting stdout to logger"""
34+
35+
@staticmethod
36+
def write(msg: str) -> None:
37+
msg = msg.rstrip("\n")
38+
if msg:
39+
logger.info(msg)
40+
41+
@staticmethod
42+
def flush() -> None:
43+
pass
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
# Copyright (C) 2025 Intel Corporation
2+
# SPDX-License-Identifier: Apache-2.0
3+
4+
import os
5+
from dataclasses import dataclass
6+
7+
from workers import DispatchingWorker, InferenceWorker, StreamLoader, TrainingWorker
8+
9+
LOG_FOLDER = "logs"
10+
WORKERS_FOLDER = os.path.join(LOG_FOLDER, "workers")
11+
JOBS_FOLDER = os.path.join(LOG_FOLDER, "jobs")
12+
13+
14+
@dataclass
15+
class LogConfig:
16+
"""Configuration for logging behavior."""
17+
18+
rotation: str = "10 MB"
19+
retention: str = "10 days"
20+
level: str = "DEBUG"
21+
serialize: bool = True
22+
log_folder: str = LOG_FOLDER
23+
# Mapping of worker classes to their dedicated log files
24+
# None key is used for application-level logs that don't belong to any specific worker
25+
worker_log_info = {
26+
TrainingWorker.__name__: "training.log",
27+
InferenceWorker.__name__: "inference.log",
28+
DispatchingWorker.__name__: "dispatching.log",
29+
StreamLoader.__name__: "stream_loader.log",
30+
None: "app.log",
31+
}
32+
tensorboard_log_path: str = os.path.join(LOG_FOLDER, "tensorboard")

0 commit comments

Comments
 (0)