refactor(observability): restructure into service-owned packages
This commit is contained in:
156
src/core/worker/observability/metrics.py
Normal file
156
src/core/worker/observability/metrics.py
Normal file
@@ -0,0 +1,156 @@
|
||||
from prometheus_client import (
|
||||
CollectorRegistry,
|
||||
Counter,
|
||||
Gauge,
|
||||
Histogram,
|
||||
generate_latest,
|
||||
)
|
||||
|
||||
from core.domain.errors import FailureReason
|
||||
from core.domain.models import NormalizedCDR
|
||||
|
||||
|
||||
class WorkerMetrics:
|
||||
def __init__(self) -> None:
|
||||
self.registry = CollectorRegistry()
|
||||
|
||||
self._processed = Counter(
|
||||
"cdr_processed_total",
|
||||
"Total CDRs successfully processed and stored.",
|
||||
labelnames=(
|
||||
"service_type",
|
||||
"radio_access_type",
|
||||
),
|
||||
registry=self.registry,
|
||||
)
|
||||
|
||||
self._dlq = Counter(
|
||||
"cdr_dlq_total",
|
||||
"Total CDRs routed to the DLQ.",
|
||||
labelnames=(
|
||||
"reason",
|
||||
),
|
||||
registry=self.registry,
|
||||
)
|
||||
|
||||
self._kafka_to_clickhouse_latency = Histogram(
|
||||
"cdr_kafka_to_clickhouse_latency_seconds",
|
||||
"Time from Kafka message creation to ClickHouse write.",
|
||||
buckets=(
|
||||
0.05,
|
||||
0.1,
|
||||
0.25,
|
||||
0.5,
|
||||
1,
|
||||
2.5,
|
||||
5,
|
||||
),
|
||||
registry=self.registry,
|
||||
)
|
||||
|
||||
self._batch_flush_duration = Histogram(
|
||||
"cdr_batch_flush_duration_seconds",
|
||||
"Duration of ClickHouse batch flushes.",
|
||||
registry=self.registry,
|
||||
)
|
||||
|
||||
self._batch_size = Histogram(
|
||||
"cdr_batch_size_at_flush",
|
||||
"Number of CDRs in each flushed batch.",
|
||||
buckets=(
|
||||
10,
|
||||
50,
|
||||
100,
|
||||
250,
|
||||
500,
|
||||
1000,
|
||||
),
|
||||
registry=self.registry,
|
||||
)
|
||||
|
||||
self._buffer_size = Gauge(
|
||||
"cdr_in_flight_buffer_size",
|
||||
"Current number of CDRs buffered for ClickHouse.",
|
||||
registry=self.registry,
|
||||
)
|
||||
|
||||
self._consumer_lag = Gauge(
|
||||
"cdr_kafka_consumer_lag",
|
||||
"Kafka consumer lag by partition.",
|
||||
labelnames=(
|
||||
"partition",
|
||||
),
|
||||
registry=self.registry,
|
||||
)
|
||||
|
||||
# Ensure all required DLQ reasons appear even before
|
||||
# their first failure.
|
||||
for reason in FailureReason:
|
||||
self._dlq.labels(
|
||||
reason=reason.value
|
||||
)
|
||||
|
||||
def record_processed(
|
||||
self,
|
||||
cdr: NormalizedCDR,
|
||||
) -> None:
|
||||
self._processed.labels(
|
||||
service_type=cdr.service_type,
|
||||
radio_access_type=cdr.radio_access_type,
|
||||
).inc()
|
||||
|
||||
def record_dlq(
|
||||
self,
|
||||
reason: str,
|
||||
) -> None:
|
||||
self._dlq.labels(
|
||||
reason=reason
|
||||
).inc()
|
||||
|
||||
def observe_kafka_to_clickhouse_latency(
|
||||
self,
|
||||
seconds: float,
|
||||
) -> None:
|
||||
self._kafka_to_clickhouse_latency.observe(
|
||||
max(seconds, 0.0)
|
||||
)
|
||||
|
||||
def observe_batch_flush_duration(
|
||||
self,
|
||||
seconds: float,
|
||||
) -> None:
|
||||
self._batch_flush_duration.observe(
|
||||
seconds
|
||||
)
|
||||
|
||||
def observe_batch_size(
|
||||
self,
|
||||
size: int,
|
||||
) -> None:
|
||||
self._batch_size.observe(
|
||||
size
|
||||
)
|
||||
|
||||
def set_buffer_size(
|
||||
self,
|
||||
size: int,
|
||||
) -> None:
|
||||
self._buffer_size.set(
|
||||
size
|
||||
)
|
||||
|
||||
def set_consumer_lag(
|
||||
self,
|
||||
partition: int,
|
||||
lag: int,
|
||||
) -> None:
|
||||
self._consumer_lag.labels(
|
||||
partition=str(partition)
|
||||
).set(
|
||||
max(lag, 0)
|
||||
)
|
||||
|
||||
def render(self) -> bytes:
|
||||
return generate_latest(
|
||||
self.registry
|
||||
)
|
||||
Reference in New Issue
Block a user