Добавлен сбор телеметрии на ВМ2

This commit is contained in:
mi
2026-08-26 15:12:51 +03:00
parent 728b9826a3
commit f989097484
32 changed files with 2029 additions and 134 deletions
@@ -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")