|
# retoor <retoor@molodetz.nl>
|
|
|
|
from __future__ import annotations
|
|
|
|
import logging
|
|
from datetime import datetime, timedelta, timezone
|
|
from typing import Optional
|
|
|
|
from devplacepy.database import db
|
|
from devplacepy.services.openai_gateway.reliability import percentile
|
|
from devplacepy.services.openai_gateway.usage import (
|
|
GATEWAY_CONCURRENCY,
|
|
GATEWAY_LEDGER,
|
|
PER_MILLION,
|
|
Pricing,
|
|
)
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
MAX_WINDOW_HOURS = 168
|
|
|
|
|
|
def _now() -> datetime:
|
|
return datetime.now(timezone.utc)
|
|
|
|
|
|
def _iso(moment: datetime) -> str:
|
|
return moment.isoformat()
|
|
|
|
|
|
def _pset(values: list[float]) -> dict:
|
|
if not values:
|
|
return {
|
|
"avg": 0.0,
|
|
"p50": 0.0,
|
|
"p90": 0.0,
|
|
"p95": 0.0,
|
|
"p99": 0.0,
|
|
"max": 0.0,
|
|
"count": 0,
|
|
}
|
|
ordered = sorted(values)
|
|
return {
|
|
"avg": round(sum(ordered) / len(ordered), 3),
|
|
"p50": round(percentile(ordered, 0.50), 3),
|
|
"p90": round(percentile(ordered, 0.90), 3),
|
|
"p95": round(percentile(ordered, 0.95), 3),
|
|
"p99": round(percentile(ordered, 0.99), 3),
|
|
"max": round(ordered[-1], 3),
|
|
"count": len(ordered),
|
|
}
|
|
|
|
|
|
def _positive(rows: list[dict], field: str) -> list[float]:
|
|
return [float(r[field]) for r in rows if r.get(field) and float(r[field]) > 0]
|
|
|
|
|
|
def _top_group(rows: list[dict], key_fn, top_n: int) -> list[dict]:
|
|
agg: dict = {}
|
|
for r in rows:
|
|
key = key_fn(r)
|
|
bucket = agg.setdefault(
|
|
key,
|
|
{
|
|
"key": key,
|
|
"requests": 0,
|
|
"success": 0,
|
|
"cost_usd": 0.0,
|
|
"total_tokens": 0,
|
|
},
|
|
)
|
|
bucket["requests"] += 1
|
|
bucket["success"] += int(r.get("success") or 0)
|
|
bucket["cost_usd"] += float(r.get("cost_usd") or 0)
|
|
bucket["total_tokens"] += int(r.get("total_tokens") or 0)
|
|
out = sorted(agg.values(), key=lambda b: b["requests"], reverse=True)
|
|
for bucket in out:
|
|
bucket["cost_usd"] = round(bucket["cost_usd"], 6)
|
|
return out[:top_n] if top_n else out
|
|
|
|
|
|
def _ledger_rows(cutoff: str) -> list[dict]:
|
|
return list(
|
|
db.query(
|
|
f"SELECT * FROM {GATEWAY_LEDGER} WHERE created_at >= :cutoff ORDER BY created_at",
|
|
cutoff=cutoff,
|
|
)
|
|
)
|
|
|
|
|
|
def _concurrency(cutoff: str) -> dict:
|
|
if GATEWAY_CONCURRENCY not in db.tables:
|
|
return {"peak": 0, "avg": 0.0, "p95": 0.0, "samples": 0}
|
|
values = [
|
|
int(r["in_flight"] or 0)
|
|
for r in db.query(
|
|
f"SELECT in_flight FROM {GATEWAY_CONCURRENCY} WHERE created_at >= :cutoff",
|
|
cutoff=cutoff,
|
|
)
|
|
]
|
|
if not values:
|
|
return {"peak": 0, "avg": 0.0, "p95": 0.0, "samples": 0}
|
|
ordered = sorted(values)
|
|
return {
|
|
"peak": ordered[-1],
|
|
"avg": round(sum(ordered) / len(ordered), 2),
|
|
"p95": round(percentile(ordered, 0.95), 2),
|
|
"samples": len(ordered),
|
|
}
|
|
|
|
|
|
def empty_payload(hours: int = 48) -> dict:
|
|
return {
|
|
"window_hours": hours,
|
|
"generated_at": _iso(_now()),
|
|
"requests": 0,
|
|
"volume": {},
|
|
"tokens": {},
|
|
"latency": {},
|
|
"errors": {},
|
|
"cost": {},
|
|
"behavior": {},
|
|
"hourly": [],
|
|
"notes": {"ttft": "not available: gateway forwards non-streaming upstream"},
|
|
}
|
|
|
|
|
|
def build_analytics(
|
|
hours: int = 48, top_n: int = 10, pricing: Optional[Pricing] = None
|
|
) -> dict:
|
|
if GATEWAY_LEDGER not in db.tables:
|
|
return empty_payload(hours)
|
|
hours = max(1, min(hours, MAX_WINDOW_HOURS))
|
|
now = _now()
|
|
cutoff = _iso(now - timedelta(hours=hours))
|
|
rows = _ledger_rows(cutoff)
|
|
if not rows:
|
|
return empty_payload(hours)
|
|
|
|
requests = len(rows)
|
|
success = sum(int(r.get("success") or 0) for r in rows)
|
|
failed = requests - success
|
|
|
|
hour_start = now.strftime("%Y-%m-%dT%H")
|
|
day_cutoff = _iso(now - timedelta(hours=24))
|
|
|
|
minute_counts: dict = {}
|
|
for r in rows:
|
|
minute_counts[r["created_at"][:16]] = (
|
|
minute_counts.get(r["created_at"][:16], 0) + 1
|
|
)
|
|
peak_req_per_min = max(minute_counts.values()) if minute_counts else 0
|
|
|
|
first_hour: dict = {}
|
|
for r in rows:
|
|
owner = f"{r.get('owner_kind')}:{r.get('owner_id')}"
|
|
bucket = r["created_at"][:13]
|
|
if owner not in first_hour or bucket < first_hour[owner]:
|
|
first_hour[owner] = bucket
|
|
|
|
total_cost = sum(float(r.get("cost_usd") or 0) for r in rows)
|
|
input_cost = sum(float(r.get("input_cost_usd") or 0) for r in rows)
|
|
output_cost = sum(float(r.get("output_cost_usd") or 0) for r in rows)
|
|
cost_this_hour = sum(
|
|
float(r.get("cost_usd") or 0)
|
|
for r in rows
|
|
if r["created_at"][:13] == hour_start
|
|
)
|
|
cost_24h = sum(
|
|
float(r.get("cost_usd") or 0) for r in rows if r["created_at"] >= day_cutoff
|
|
)
|
|
|
|
prompt_total = sum(int(r.get("prompt_tokens") or 0) for r in rows)
|
|
completion_total = sum(int(r.get("completion_tokens") or 0) for r in rows)
|
|
total_tokens = sum(int(r.get("total_tokens") or 0) for r in rows)
|
|
cache_hit_total = sum(int(r.get("cache_hit_tokens") or 0) for r in rows)
|
|
cache_miss_total = sum(int(r.get("cache_miss_tokens") or 0) for r in rows)
|
|
reasoning_total = sum(int(r.get("reasoning_tokens") or 0) for r in rows)
|
|
|
|
caching_savings = 0.0
|
|
if pricing is not None:
|
|
rate_delta = pricing.chat_cache_miss_per_m - pricing.chat_cache_hit_per_m
|
|
chat_cache_hits = sum(
|
|
int(r.get("cache_hit_tokens") or 0)
|
|
for r in rows
|
|
if r.get("backend") == "chat"
|
|
)
|
|
caching_savings = chat_cache_hits / PER_MILLION * rate_delta
|
|
|
|
util_values = [
|
|
float(r["context_utilization"])
|
|
for r in rows
|
|
if r.get("context_utilization") is not None
|
|
]
|
|
|
|
owner_counts: dict = {}
|
|
for r in rows:
|
|
owner = f"{r.get('owner_kind')}:{r.get('owner_id')}"
|
|
owner_counts[owner] = owner_counts.get(owner, 0) + 1
|
|
per_owner = sorted(owner_counts.values())
|
|
|
|
ua_counts: dict = {}
|
|
for r in rows:
|
|
ua = r.get("user_agent") or "unknown"
|
|
ua_counts[ua] = ua_counts.get(ua, 0) + 1
|
|
user_agents = sorted(
|
|
[{"key": k, "requests": v} for k, v in ua_counts.items()],
|
|
key=lambda x: x["requests"],
|
|
reverse=True,
|
|
)[:top_n]
|
|
|
|
error_categories: dict = {}
|
|
for r in rows:
|
|
category = r.get("error_category")
|
|
if category:
|
|
error_categories[category] = error_categories.get(category, 0) + 1
|
|
count_4xx = sum(1 for r in rows if 400 <= int(r.get("status_code") or 0) < 500)
|
|
count_5xx = sum(1 for r in rows if int(r.get("status_code") or 0) >= 500)
|
|
|
|
temperatures = [
|
|
float(r["temperature"]) for r in rows if r.get("temperature") is not None
|
|
]
|
|
top_ps = [float(r["top_p"]) for r in rows if r.get("top_p") is not None]
|
|
|
|
hourly = _hourly(rows, first_hour)
|
|
|
|
volume = {
|
|
"requests": requests,
|
|
"success": success,
|
|
"failed": failed,
|
|
"requests_per_hour": round(requests / hours, 2),
|
|
"peak_requests_per_minute": peak_req_per_min,
|
|
"by_model": _top_group(rows, lambda r: r.get("model") or "unknown", top_n),
|
|
"by_endpoint": _top_group(
|
|
rows, lambda r: r.get("endpoint") or "unknown", top_n
|
|
),
|
|
"by_backend": _top_group(rows, lambda r: r.get("backend") or "unknown", 0),
|
|
"by_caller": _top_group(
|
|
rows, lambda r: f"{r.get('owner_kind')}:{r.get('owner_id')}", top_n
|
|
),
|
|
"concurrency": _concurrency(cutoff),
|
|
}
|
|
|
|
tokens = {
|
|
"prompt_total": prompt_total,
|
|
"completion_total": completion_total,
|
|
"total": total_tokens,
|
|
"cache_hit_total": cache_hit_total,
|
|
"cache_miss_total": cache_miss_total,
|
|
"reasoning_total": reasoning_total,
|
|
"cache_hit_rate": round(cache_hit_total / prompt_total, 4)
|
|
if prompt_total
|
|
else 0.0,
|
|
"input_output_ratio": round(prompt_total / completion_total, 3)
|
|
if completion_total
|
|
else 0.0,
|
|
"tokens_per_hour": round(total_tokens / hours, 1),
|
|
"context_utilization_avg": round(sum(util_values) / len(util_values), 4)
|
|
if util_values
|
|
else None,
|
|
"prompt": _pset(_positive(rows, "prompt_tokens")),
|
|
"completion": _pset(_positive(rows, "completion_tokens")),
|
|
"total_per_request": _pset(_positive(rows, "total_tokens")),
|
|
}
|
|
|
|
avg_upstream = sum(_positive(rows, "upstream_latency_ms")) / max(
|
|
len(_positive(rows, "upstream_latency_ms")), 1
|
|
)
|
|
avg_total = sum(_positive(rows, "total_latency_ms")) / max(
|
|
len(_positive(rows, "total_latency_ms")), 1
|
|
)
|
|
latency = {
|
|
"upstream_ms": _pset(_positive(rows, "upstream_latency_ms")),
|
|
"gateway_overhead_ms": _pset(_positive(rows, "gateway_overhead_ms")),
|
|
"queue_wait_ms": _pset(_positive(rows, "queue_wait_ms")),
|
|
"connect_ms": _pset(_positive(rows, "connect_ms")),
|
|
"total_ms": _pset(_positive(rows, "total_latency_ms")),
|
|
"tokens_per_second": _pset(_positive(rows, "tokens_per_second")),
|
|
"gateway_overhead_share": round((avg_total - avg_upstream) / avg_total, 4)
|
|
if avg_total
|
|
else 0.0,
|
|
"upstream_availability_pct": round(success / requests * 100, 2)
|
|
if requests
|
|
else 0.0,
|
|
"ttft_ms": None,
|
|
"inter_token_ms": None,
|
|
}
|
|
|
|
errors = {
|
|
"total": failed,
|
|
"error_rate_pct": round(failed / requests * 100, 2) if requests else 0.0,
|
|
"by_category": error_categories,
|
|
"count_4xx": count_4xx,
|
|
"count_5xx": count_5xx,
|
|
"timeouts": error_categories.get("timeout", 0),
|
|
"retries_attempted": sum(int(r.get("retries_attempted") or 0) for r in rows),
|
|
"retries_succeeded": sum(int(r.get("retry_succeeded") or 0) for r in rows),
|
|
"circuit_open_events": sum(int(r.get("circuit_open") or 0) for r in rows),
|
|
}
|
|
|
|
cost = {
|
|
"total_usd": round(total_cost, 6),
|
|
"input_usd": round(input_cost, 6),
|
|
"output_usd": round(output_cost, 6),
|
|
"this_hour_usd": round(cost_this_hour, 6),
|
|
"last_24h_usd": round(cost_24h, 6),
|
|
"projected_monthly_usd": round(cost_24h * 30, 2),
|
|
"effective_per_1k_tokens_usd": round(total_cost / total_tokens * 1000, 6)
|
|
if total_tokens
|
|
else 0.0,
|
|
"caching_savings_usd": round(caching_savings, 6),
|
|
"by_model": [
|
|
{"key": b["key"], "cost_usd": b["cost_usd"]}
|
|
for b in _top_group(rows, lambda r: r.get("model") or "unknown", top_n)
|
|
],
|
|
"by_caller": [
|
|
{"key": b["key"], "cost_usd": b["cost_usd"]}
|
|
for b in _top_group(
|
|
rows, lambda r: f"{r.get('owner_kind')}:{r.get('owner_id')}", top_n
|
|
)
|
|
],
|
|
}
|
|
|
|
behavior = {
|
|
"unique_callers": len(owner_counts),
|
|
"requests_per_caller": {
|
|
"avg": round(sum(per_owner) / len(per_owner), 2) if per_owner else 0.0,
|
|
"p95": round(percentile(per_owner, 0.95), 2) if per_owner else 0.0,
|
|
"max": per_owner[-1] if per_owner else 0,
|
|
},
|
|
"avg_temperature": round(sum(temperatures) / len(temperatures), 3)
|
|
if temperatures
|
|
else None,
|
|
"avg_top_p": round(sum(top_ps) / len(top_ps), 3) if top_ps else None,
|
|
"tool_call_requests": sum(int(r.get("has_tools") or 0) for r in rows),
|
|
"streaming_requests": sum(int(r.get("stream_requested") or 0) for r in rows),
|
|
"non_streaming_requests": requests
|
|
- sum(int(r.get("stream_requested") or 0) for r in rows),
|
|
"user_agents": user_agents,
|
|
}
|
|
|
|
return {
|
|
"window_hours": hours,
|
|
"generated_at": _iso(now),
|
|
"requests": requests,
|
|
"volume": volume,
|
|
"tokens": tokens,
|
|
"latency": latency,
|
|
"errors": errors,
|
|
"cost": cost,
|
|
"behavior": behavior,
|
|
"hourly": hourly,
|
|
"notes": {"ttft": "not available: gateway forwards non-streaming upstream"},
|
|
}
|
|
|
|
|
|
def _hourly(rows: list[dict], first_hour: dict) -> list[dict]:
|
|
buckets: dict = {}
|
|
for r in rows:
|
|
hour = r["created_at"][:13]
|
|
owner = f"{r.get('owner_kind')}:{r.get('owner_id')}"
|
|
bucket = buckets.setdefault(
|
|
hour,
|
|
{
|
|
"hour": hour,
|
|
"requests": 0,
|
|
"success": 0,
|
|
"failed": 0,
|
|
"prompt_tokens": 0,
|
|
"completion_tokens": 0,
|
|
"total_tokens": 0,
|
|
"cost_usd": 0.0,
|
|
"latency_sum": 0.0,
|
|
"latency_n": 0,
|
|
"owners": set(),
|
|
"new_owners": 0,
|
|
},
|
|
)
|
|
bucket["requests"] += 1
|
|
if int(r.get("success") or 0):
|
|
bucket["success"] += 1
|
|
else:
|
|
bucket["failed"] += 1
|
|
bucket["prompt_tokens"] += int(r.get("prompt_tokens") or 0)
|
|
bucket["completion_tokens"] += int(r.get("completion_tokens") or 0)
|
|
bucket["total_tokens"] += int(r.get("total_tokens") or 0)
|
|
bucket["cost_usd"] += float(r.get("cost_usd") or 0)
|
|
latency = float(r.get("upstream_latency_ms") or 0)
|
|
if latency > 0:
|
|
bucket["latency_sum"] += latency
|
|
bucket["latency_n"] += 1
|
|
bucket["owners"].add(owner)
|
|
|
|
for hour, bucket in buckets.items():
|
|
bucket["new_owners"] = sum(
|
|
1 for owner in bucket["owners"] if first_hour.get(owner) == hour
|
|
)
|
|
bucket["active_owners"] = len(bucket["owners"])
|
|
bucket["returning_owners"] = bucket["active_owners"] - bucket["new_owners"]
|
|
bucket["avg_latency_ms"] = (
|
|
round(bucket["latency_sum"] / bucket["latency_n"], 1)
|
|
if bucket["latency_n"]
|
|
else 0.0
|
|
)
|
|
bucket["cost_usd"] = round(bucket["cost_usd"], 6)
|
|
del bucket["owners"], bucket["latency_sum"], bucket["latency_n"]
|
|
|
|
return sorted(buckets.values(), key=lambda b: b["hour"], reverse=True)
|
|
|
|
|
|
def empty_user_usage(owner_id: str, hours: int = 24) -> dict:
|
|
return {
|
|
"owner_id": owner_id,
|
|
"window_hours": hours,
|
|
"generated_at": _iso(_now()),
|
|
"requests": 0,
|
|
"success": 0,
|
|
"failed": 0,
|
|
"success_pct": 0.0,
|
|
"error_pct": 0.0,
|
|
"tokens": {"prompt": 0, "completion": 0, "total": 0},
|
|
"cost": {
|
|
"window_usd": 0.0,
|
|
"per_hour_usd": 0.0,
|
|
"per_request_usd": 0.0,
|
|
"projected_30d_usd": 0.0,
|
|
},
|
|
"latency": {"avg_ms": 0.0, "avg_tps": 0.0},
|
|
"first_used": None,
|
|
"last_used": None,
|
|
"by_model": [],
|
|
"by_backend": [],
|
|
"hourly": [],
|
|
"notes": {
|
|
"projection": "30-day projection extrapolates the full 24h spend (24h cost x 30)"
|
|
},
|
|
}
|
|
|
|
|
|
def _user_hourly(rows: list[dict]) -> list[dict]:
|
|
buckets: dict = {}
|
|
for r in rows:
|
|
hour = r["created_at"][:13]
|
|
bucket = buckets.setdefault(
|
|
hour, {"hour": hour, "requests": 0, "cost_usd": 0.0, "total_tokens": 0}
|
|
)
|
|
bucket["requests"] += 1
|
|
bucket["cost_usd"] += float(r.get("cost_usd") or 0)
|
|
bucket["total_tokens"] += int(r.get("total_tokens") or 0)
|
|
out = sorted(buckets.values(), key=lambda b: b["hour"])
|
|
for bucket in out:
|
|
bucket["cost_usd"] = round(bucket["cost_usd"], 6)
|
|
return out
|
|
|
|
|
|
def build_user_usage(
|
|
owner_id: str, hours: int = 24, pricing: Optional[Pricing] = None
|
|
) -> dict:
|
|
hours = max(1, min(hours, MAX_WINDOW_HOURS))
|
|
if not owner_id or GATEWAY_LEDGER not in db.tables:
|
|
return empty_user_usage(owner_id, hours)
|
|
now = _now()
|
|
cutoff = _iso(now - timedelta(hours=hours))
|
|
rows = list(
|
|
db.query(
|
|
f"SELECT * FROM {GATEWAY_LEDGER} WHERE owner_id = :oid AND created_at >= :cutoff ORDER BY created_at",
|
|
oid=owner_id,
|
|
cutoff=cutoff,
|
|
)
|
|
)
|
|
if not rows:
|
|
return empty_user_usage(owner_id, hours)
|
|
|
|
requests = len(rows)
|
|
success = sum(int(r.get("success") or 0) for r in rows)
|
|
failed = requests - success
|
|
total_cost = sum(float(r.get("cost_usd") or 0) for r in rows)
|
|
prompt_total = sum(int(r.get("prompt_tokens") or 0) for r in rows)
|
|
completion_total = sum(int(r.get("completion_tokens") or 0) for r in rows)
|
|
total_tokens = sum(int(r.get("total_tokens") or 0) for r in rows)
|
|
latencies = _positive(rows, "upstream_latency_ms")
|
|
avg_latency = round(sum(latencies) / len(latencies), 1) if latencies else 0.0
|
|
tps = _positive(rows, "tokens_per_second")
|
|
avg_tps = round(sum(tps) / len(tps), 2) if tps else 0.0
|
|
cost_per_hour = total_cost / hours
|
|
cost_per_request = total_cost / requests if requests else 0.0
|
|
|
|
return {
|
|
"owner_id": owner_id,
|
|
"window_hours": hours,
|
|
"generated_at": _iso(now),
|
|
"requests": requests,
|
|
"success": success,
|
|
"failed": failed,
|
|
"success_pct": round(success / requests * 100, 1) if requests else 0.0,
|
|
"error_pct": round(failed / requests * 100, 1) if requests else 0.0,
|
|
"tokens": {
|
|
"prompt": prompt_total,
|
|
"completion": completion_total,
|
|
"total": total_tokens,
|
|
},
|
|
"cost": {
|
|
"window_usd": round(total_cost, 6),
|
|
"per_hour_usd": round(cost_per_hour, 6),
|
|
"per_request_usd": round(cost_per_request, 6),
|
|
"projected_30d_usd": round(cost_per_hour * 24 * 30, 2),
|
|
},
|
|
"latency": {"avg_ms": avg_latency, "avg_tps": avg_tps},
|
|
"first_used": rows[0]["created_at"],
|
|
"last_used": rows[-1]["created_at"],
|
|
"by_model": _top_group(rows, lambda r: r.get("model") or "unknown", 0),
|
|
"by_backend": _top_group(rows, lambda r: r.get("backend") or "unknown", 0),
|
|
"hourly": _user_hourly(rows),
|
|
"notes": {
|
|
"projection": "30-day projection extrapolates the full 24h spend (24h cost x 30)"
|
|
},
|
|
}
|
|
|
|
|
|
def summary_metrics() -> dict:
|
|
zero = {
|
|
"requests": 0,
|
|
"success_pct": 0.0,
|
|
"error_pct": 0.0,
|
|
"cost_hour": 0.0,
|
|
"cost_24h": 0.0,
|
|
"tokens_24h": 0,
|
|
"avg_latency_ms": 0.0,
|
|
"avg_tps": 0.0,
|
|
"peak_concurrency": 0,
|
|
"top_model": "-",
|
|
"top_caller": "-",
|
|
}
|
|
if GATEWAY_LEDGER not in db.tables:
|
|
return zero
|
|
now = _now()
|
|
cutoff = _iso(now - timedelta(hours=24))
|
|
hour_start = now.strftime("%Y-%m-%dT%H")
|
|
agg = list(
|
|
db.query(
|
|
f"SELECT COUNT(*) AS requests, COALESCE(SUM(success),0) AS ok, "
|
|
f"COALESCE(SUM(cost_usd),0) AS cost, COALESCE(SUM(total_tokens),0) AS tokens, "
|
|
f"COALESCE(AVG(upstream_latency_ms),0) AS avg_lat, "
|
|
f"COALESCE(AVG(NULLIF(tokens_per_second,0)),0) AS avg_tps "
|
|
f"FROM {GATEWAY_LEDGER} WHERE created_at >= :cutoff",
|
|
cutoff=cutoff,
|
|
)
|
|
)
|
|
row = agg[0] if agg else {}
|
|
requests = int(row.get("requests") or 0)
|
|
if not requests:
|
|
return zero
|
|
ok = int(row.get("ok") or 0)
|
|
hour_rows = list(
|
|
db.query(
|
|
f"SELECT COALESCE(SUM(cost_usd),0) AS c FROM {GATEWAY_LEDGER} WHERE created_at >= :h",
|
|
h=hour_start,
|
|
)
|
|
)
|
|
top_model = list(
|
|
db.query(
|
|
f"SELECT model, COUNT(*) AS n FROM {GATEWAY_LEDGER} WHERE created_at >= :cutoff "
|
|
f"GROUP BY model ORDER BY n DESC LIMIT 1",
|
|
cutoff=cutoff,
|
|
)
|
|
)
|
|
top_caller = list(
|
|
db.query(
|
|
f"SELECT owner_kind, owner_id, COUNT(*) AS n FROM {GATEWAY_LEDGER} WHERE created_at >= :cutoff "
|
|
f"GROUP BY owner_kind, owner_id ORDER BY n DESC LIMIT 1",
|
|
cutoff=cutoff,
|
|
)
|
|
)
|
|
peak = 0
|
|
if GATEWAY_CONCURRENCY in db.tables:
|
|
peak_rows = list(
|
|
db.query(
|
|
f"SELECT COALESCE(MAX(in_flight),0) AS m FROM {GATEWAY_CONCURRENCY} WHERE created_at >= :cutoff",
|
|
cutoff=cutoff,
|
|
)
|
|
)
|
|
peak = int(peak_rows[0]["m"]) if peak_rows else 0
|
|
return {
|
|
"requests": requests,
|
|
"success_pct": round(ok / requests * 100, 1),
|
|
"error_pct": round((requests - ok) / requests * 100, 1),
|
|
"cost_hour": round(float(hour_rows[0]["c"]) if hour_rows else 0.0, 6),
|
|
"cost_24h": round(float(row.get("cost") or 0), 6),
|
|
"tokens_24h": int(row.get("tokens") or 0),
|
|
"avg_latency_ms": round(float(row.get("avg_lat") or 0), 1),
|
|
"avg_tps": round(float(row.get("avg_tps") or 0), 2),
|
|
"peak_concurrency": peak,
|
|
"top_model": top_model[0]["model"]
|
|
if top_model and top_model[0].get("model")
|
|
else "-",
|
|
"top_caller": f"{top_caller[0]['owner_kind']}:{top_caller[0]['owner_id']}"
|
|
if top_caller
|
|
else "-",
|
|
}
|