48 lines
2.6 KiB
Python
Executable File
48 lines
2.6 KiB
Python
Executable File
"""Selected counters from existing authenticated APIs, without traffic records."""
|
|
from __future__ import annotations
|
|
|
|
import json
|
|
import time
|
|
|
|
|
|
def traffic_analytics_snapshot(rust, timeout=2):
|
|
"""Read global analytics queue loss; never retain paths, IPs or user agents.
|
|
|
|
queue_dropped is process-global even when the API's vhost query is used.
|
|
recorded_requests is asynchronous analytics work, not an HTTP success count.
|
|
Call outside a timed load interval so this control-plane read is not charged
|
|
to the request path being measured.
|
|
"""
|
|
status, _, body = rust.admin("/api/traffic", timeout=timeout)
|
|
if status != 200:
|
|
raise RuntimeError(f"traffic analytics counter capture failed: HTTP {status}")
|
|
payload = json.loads(body)
|
|
if not isinstance(payload, dict) or payload.get("scope") != "*" or payload.get("since") != "process_start":
|
|
raise RuntimeError("traffic analytics requires the global process-start scope")
|
|
analytics = payload.get("analytics")
|
|
if not isinstance(analytics, dict) or analytics.get("scope") != "*":
|
|
raise RuntimeError("traffic analytics response lacks the global queue view")
|
|
data = analytics.get("data")
|
|
if not isinstance(data, dict):
|
|
raise RuntimeError("traffic analytics response lacks the recorded counters")
|
|
values = {"queue_capacity": analytics.get("queue_capacity"),
|
|
"queue_dropped": analytics.get("queue_dropped"),
|
|
"recorded_requests": data.get("requests")}
|
|
if any(type(value) is not int or value < 0 for value in values.values()) or not values["queue_capacity"]:
|
|
raise RuntimeError("traffic analytics queue counters are absent or malformed")
|
|
return {"endpoint": "/api/traffic", "scope": "*", "since": "process_start",
|
|
"pid": rust.process.pid, "observed_monotonic": time.monotonic(), **values}
|
|
|
|
|
|
def traffic_analytics_delta(before, after):
|
|
"""Keep telemetry loss separate from failed HTTP requests and log rotation."""
|
|
for key in ["pid", "endpoint", "scope", "since", "queue_capacity"]:
|
|
if before[key] != after[key]:
|
|
raise RuntimeError(f"traffic analytics identity changed during capture: {key}")
|
|
result = {"queue_dropped_delta": after["queue_dropped"] - before["queue_dropped"],
|
|
"recorded_requests_delta": after["recorded_requests"] - before["recorded_requests"],
|
|
"interval_seconds": after["observed_monotonic"] - before["observed_monotonic"]}
|
|
if any(value < 0 for value in result.values()):
|
|
raise RuntimeError("traffic analytics counters or clock reset during capture")
|
|
return result
|