Добавлен сбор телеметрии на ВМ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
@@ -2,6 +2,7 @@ from __future__ import annotations
import uuid
from datetime import UTC, datetime, timedelta
from time import perf_counter
from app.config import ActiveConfig
from app.contracts import CheckRequest, FileCheck, Pending, TextCheck, Verdict
@@ -19,6 +20,14 @@ from app.normalization import normalize_text
from app.rate_limit import ConservativeRateLimiter
from app.repository import QueueFull, Repository
from app.settings import EmergencyMode
from app.telemetry import (
current_trace_fields,
record_cache,
record_check,
record_dependency,
record_file_rejection,
record_runtime_state,
)
from app.url_policy import DnsError, Resolver, canonicalize, check_url, extract_urls
@@ -54,6 +63,7 @@ class SafetyService:
self.rate_limiter = ConservativeRateLimiter(
config.document["rate"]["text_rps"], config.document["rate"]["file_rps"]
)
record_runtime_state("mock" if mode.mock else "standard", config.version)
def _verdict(
self,
@@ -74,6 +84,22 @@ class SafetyService:
)
async def check(self, request: CheckRequest) -> Verdict | Pending:
started = perf_counter()
outcome = "error"
try:
result = await self._check(request)
outcome = "pending" if isinstance(result, Pending) else result.verdict
return result
finally:
record_check(
request.content_kind,
"mock" if self.mode.mock else "standard",
outcome,
(perf_counter() - started) * 1000,
self.config.version,
)
async def _check(self, request: CheckRequest) -> Verdict | Pending:
digest = fingerprint(request)
existing = await self.repository.get_request(request.message_id)
if existing:
@@ -101,6 +127,7 @@ class SafetyService:
cache = await self.repository.text_cache(
normalized.analysis_sha256, self.config.rules_version
)
record_cache("text_rules", cache is not None)
if cache:
deny_rule = cache.deny_rule_id
else:
@@ -145,6 +172,7 @@ class SafetyService:
cached_link = await self.repository.link_cache(
canonical.digest, self.config.rules_version, self.config.version
)
record_cache("link_verdict", cached_link is not None)
if cached_link and cached_link.verdict == "deny":
return await self._persist_sync(
request,
@@ -160,7 +188,9 @@ class SafetyService:
_, rule = await check_url(
raw, self.resolver, self.config.document["link"]["dns_lookup_timeout_sec"]
)
record_dependency("dns", "resolve", "success")
except DnsError as exc:
record_dependency("dns", "resolve", "error")
raise CapabilityUnavailable("dns") from exc
if rule != "url.nxdomain" and not cached_link:
now = datetime.now(UTC)
@@ -200,6 +230,7 @@ class SafetyService:
set(self.config.document["file_policy"]["enabled_mime_types"]),
)
if rule:
record_file_rejection(rule)
return await self._persist_sync(
request, digest, self._verdict(False, "standard", rule, self.config.rules_version)
)
@@ -207,6 +238,7 @@ class SafetyService:
cached = await self.repository.file_cache(
content_digest, self.config, self.signatures_version
)
record_cache("file_verdict", cached is not None)
if cached:
return await self._persist_sync(
request,
@@ -220,6 +252,7 @@ class SafetyService:
)
now = datetime.now(UTC)
task_id = uuid.uuid4()
trace_id, span_id, trace_flags, tracestate = current_trace_fields()
task = SafetyTask(
id=task_id,
message_id=request.message_id,
@@ -243,6 +276,10 @@ class SafetyService:
detector_version=self.config.detector.version,
scanner_engine="clamav",
signatures_version=self.signatures_version,
origin_trace_id=trace_id,
origin_span_id=span_id,
origin_trace_flags=trace_flags,
origin_tracestate=tracestate,
created_at=now,
updated_at=now,
)
@@ -262,6 +299,7 @@ class SafetyService:
row, task, max_pending=self.config.document["task"]["max_pending"]
)
except QueueFull as exc:
record_dependency("postgresql", "queue_capacity", "full")
raise CapabilityUnavailable("queue_capacity") from exc
if created:
await self._audit(