feat(metrics): distinguish received and acknowledged CDRs

This commit is contained in:
2026-09-20 10:40:24 +03:30
parent 6ce567646b
commit f45c457dc8
5 changed files with 63 additions and 8 deletions

View File

@@ -10,27 +10,41 @@ class APIMetrics:
def __init__(self):
self._lock = threading.Lock()
self._received_total: int = 0
self._acknowledged_total: int = 0
def increment_received(self, count: int = 1) -> None:
with self._lock:
self._received_total += count
def increment_acknowledged(self, count: int = 1) -> None:
with self._lock:
self._acknowledged_total += count
@property
def total_received(self) -> int:
with self._lock:
return self._received_total
@property
def total_acknowledged(self) -> int:
with self._lock:
return self._acknowledged_total
def get_prometheus_metrics(self) -> str:
"""
Formats metrics into standard Prometheus text format.
"""
with self._lock:
val = self._received_total
val_received = self._received_total
val_ack = self._acknowledged_total
return (
"# HELP cdr_api_received_total Total CDRs received by the API\n"
"# TYPE cdr_api_received_total counter\n"
f"cdr_api_received_total {val}\n"
f"cdr_api_received_total {val_received}\n"
"# HELP cdr_api_acknowledged_total Total CDRs successfully acknowledged by Kafka\n"
"# TYPE cdr_api_acknowledged_total counter\n"
f"cdr_api_acknowledged_total {val_ack}\n"
)

View File

@@ -133,6 +133,7 @@ class IngestionAPIServer:
await self._error(writer, 404, "not_found", f"Cannot {method} {path}")
async def _handle_raw_cdr_ingestion(self, writer, body):
api_metrics.increment_received(1)
try:
payload = parse_payload(body)
validate_structure(payload)
@@ -158,7 +159,7 @@ class IngestionAPIServer:
logger.warning(str(exc), extra={"raw_id": payload["raw_id"], "event": "kafka_delivery_failed"})
await self._error(writer, 503, "broker_unavailable", "Delivery unconfirmed; retry with the same raw_id and payload")
return
api_metrics.increment_received(1)
api_metrics.increment_acknowledged(1)
await self._json(writer, 202, {"status": "accepted", "raw_id": payload["raw_id"], "queued": True})
async def _error(self, writer, status, error, detail):

View File

@@ -25,6 +25,7 @@ async def get_aggregated_pipeline_stats(worker_stats_url: str) -> Dict[str, Any]
from the Processing Worker.
"""
total_received = api_metrics.total_received
total_acknowledged = api_metrics.total_acknowledged
try:
loop = asyncio.get_running_loop()
@@ -38,6 +39,7 @@ async def get_aggregated_pipeline_stats(worker_stats_url: str) -> Dict[str, Any]
return {
"pipeline": {
"total_received": total_received,
"total_acknowledged": total_acknowledged,
"total_processed": pipeline_data.get("total_processed", 0),
"total_dlq": pipeline_data.get("total_dlq", 0),
"in_flight_buffer": pipeline_data.get("in_flight_buffer", 0),
@@ -58,6 +60,7 @@ async def get_aggregated_pipeline_stats(worker_stats_url: str) -> Dict[str, Any]
return {
"pipeline": {
"total_received": total_received,
"total_acknowledged": total_acknowledged,
"total_processed": 0,
"total_dlq": 0,
"in_flight_buffer": 0,