feat(cloud-api): add correlated lifecycle logging
This commit is contained in:
@@ -8,6 +8,7 @@ from dataclasses import dataclass
|
||||
from typing import Any
|
||||
|
||||
from fastapi import FastAPI, status
|
||||
from fastapi import Request
|
||||
from fastapi.responses import JSONResponse
|
||||
|
||||
from cloud.auth import create_auth_provider
|
||||
@@ -20,6 +21,13 @@ from cloud.control_config import (
|
||||
from cloud.database import CloudDatabase
|
||||
from cloud.internal_api.api import create_internal_router
|
||||
from cloud.plugins import PluginRegistry
|
||||
from cloud.observability import (
|
||||
CORRELATION_HEADER,
|
||||
bind_correlation_id,
|
||||
new_correlation_id,
|
||||
normalize_correlation_id,
|
||||
reset_correlation_id,
|
||||
)
|
||||
from cloud.pool import DevicePool
|
||||
from cloud.scheduler import TaskScheduler
|
||||
from cloud.schema import require_current_schema
|
||||
@@ -136,6 +144,28 @@ def create_app(
|
||||
|
||||
app = FastAPI(title="Device Cloud API", lifespan=lifespan)
|
||||
|
||||
@app.middleware("http")
|
||||
async def correlation_logging(request: Request, call_next):
|
||||
correlation_id = normalize_correlation_id(
|
||||
request.headers.get(CORRELATION_HEADER)
|
||||
)
|
||||
correlation_token = bind_correlation_id(correlation_id)
|
||||
try:
|
||||
response = await call_next(request)
|
||||
logger.info(
|
||||
"cloud request completed",
|
||||
extra={
|
||||
"correlation_id": correlation_id,
|
||||
"method": request.method,
|
||||
"path": request.url.path,
|
||||
"status_code": response.status_code,
|
||||
},
|
||||
)
|
||||
response.headers[CORRELATION_HEADER] = correlation_id
|
||||
return response
|
||||
finally:
|
||||
reset_correlation_id(correlation_token)
|
||||
|
||||
@app.get("/health/live")
|
||||
def health_live() -> dict[str, str]:
|
||||
return {"status": "live"}
|
||||
@@ -198,6 +228,7 @@ async def _run_scheduler_loop(
|
||||
interval_seconds: float,
|
||||
) -> None:
|
||||
while not stop.is_set():
|
||||
correlation_token = bind_correlation_id(new_correlation_id())
|
||||
try:
|
||||
services.scheduler.assign()
|
||||
except Exception:
|
||||
@@ -205,6 +236,8 @@ async def _run_scheduler_loop(
|
||||
"cloud lifecycle iteration failed",
|
||||
extra={"worker": "scheduler"},
|
||||
)
|
||||
finally:
|
||||
reset_correlation_id(correlation_token)
|
||||
if await _wait_for_stop(stop, interval_seconds):
|
||||
return
|
||||
|
||||
@@ -217,6 +250,7 @@ async def _run_lease_reaper_loop(
|
||||
max_attempts: int,
|
||||
) -> None:
|
||||
while not stop.is_set():
|
||||
correlation_token = bind_correlation_id(new_correlation_id())
|
||||
try:
|
||||
services.repository.reap_expired_leases(
|
||||
now=utc_now(),
|
||||
@@ -227,6 +261,8 @@ async def _run_lease_reaper_loop(
|
||||
"cloud lifecycle iteration failed",
|
||||
extra={"worker": "lease_reaper"},
|
||||
)
|
||||
finally:
|
||||
reset_correlation_id(correlation_token)
|
||||
if await _wait_for_stop(stop, interval_seconds):
|
||||
return
|
||||
|
||||
|
||||
Reference in New Issue
Block a user