Добавлен сбор телеметрии на ВМ2
This commit is contained in:
@@ -3,6 +3,7 @@ from __future__ import annotations
|
||||
import hmac
|
||||
import json
|
||||
import uuid
|
||||
from time import perf_counter
|
||||
from typing import Annotated
|
||||
|
||||
from fastapi import Depends, FastAPI, Header, Request
|
||||
@@ -14,6 +15,7 @@ from app.db import TaskStatus
|
||||
from app.rate_limit import RateLimited
|
||||
from app.repository import ConflictError
|
||||
from app.service import CapabilityUnavailable, SafetyService, TaskFailed
|
||||
from app.telemetry import logger, record_poll
|
||||
|
||||
CHECK_ADAPTER = TypeAdapter(CheckRequest)
|
||||
MAX_BODY = 16_384
|
||||
@@ -53,14 +55,39 @@ def create_app(service: SafetyService, token: str) -> FastAPI:
|
||||
|
||||
@app.middleware("http")
|
||||
async def request_context(request: Request, call_next):
|
||||
started = perf_counter()
|
||||
supplied = request.headers.get("X-Request-ID")
|
||||
try:
|
||||
request.state.request_id = str(uuid.UUID(supplied)) if supplied else str(uuid.uuid4())
|
||||
except ValueError:
|
||||
request.state.request_id = str(uuid.uuid4())
|
||||
response = await call_next(request)
|
||||
try:
|
||||
response = await call_next(request)
|
||||
except Exception:
|
||||
logger.error(
|
||||
"Safety request failed",
|
||||
extra={
|
||||
"event": "http_request_failed",
|
||||
"request_id": request.state.request_id,
|
||||
"route": _route_template(request),
|
||||
"method": request.method,
|
||||
},
|
||||
)
|
||||
raise
|
||||
response.headers["X-Request-ID"] = request.state.request_id
|
||||
response.headers["Cache-Control"] = "no-store"
|
||||
if request.url.path != "/health/live":
|
||||
logger.info(
|
||||
"Safety request completed",
|
||||
extra={
|
||||
"event": "http_request_completed",
|
||||
"request_id": request.state.request_id,
|
||||
"route": _route_template(request),
|
||||
"method": request.method,
|
||||
"status_code": response.status_code,
|
||||
"duration_ms": round((perf_counter() - started) * 1000, 3),
|
||||
},
|
||||
)
|
||||
return response
|
||||
|
||||
@app.get("/health/live")
|
||||
@@ -197,8 +224,10 @@ def create_app(service: SafetyService, token: str) -> FastAPI:
|
||||
)
|
||||
task = await service.repository.task(parsed)
|
||||
if not task:
|
||||
record_poll("not_found")
|
||||
return error(404, "task_not_found", request.state.request_id)
|
||||
if task.status == TaskStatus.failed:
|
||||
record_poll("failed")
|
||||
return error(
|
||||
503,
|
||||
"task_failed",
|
||||
@@ -211,6 +240,7 @@ def create_app(service: SafetyService, token: str) -> FastAPI:
|
||||
},
|
||||
)
|
||||
if task.status in {TaskStatus.pending, TaskStatus.processing}:
|
||||
record_poll(task.status.value)
|
||||
result: Pending | Verdict = Pending(
|
||||
config_version=task.config_version,
|
||||
task_id=task.id,
|
||||
@@ -218,6 +248,7 @@ def create_app(service: SafetyService, token: str) -> FastAPI:
|
||||
rules_version=task.rules_version,
|
||||
)
|
||||
else:
|
||||
record_poll("terminal")
|
||||
result = service._verdict(
|
||||
task.status == TaskStatus.allowed,
|
||||
task.processing_mode,
|
||||
@@ -233,3 +264,8 @@ def create_app(service: SafetyService, token: str) -> FastAPI:
|
||||
return response
|
||||
|
||||
return app
|
||||
|
||||
|
||||
def _route_template(request: Request) -> str:
|
||||
route = request.scope.get("route")
|
||||
return getattr(route, "path", "unmatched")
|
||||
|
||||
Reference in New Issue
Block a user