Lines 97.72% 43 / 44
Methods 0.00% 0 / 1
Classes 0.00% 0 / 1
Name Lines Methods CRAP
 collectMetrics 97.72% 43 / 44 0.00% 0 / 1 8
15final readonly class WorkerMetricSource implements RuntimeMetricSource
16{
17    /** @return list<MetricFamily> */
18    public function collectMetrics(RuntimeSnapshot $snapshot): array
19    {
20        $phases = new MetricFamily('stewart_worker_phase', 'Worker lifecycle phase; 1 for the current one.', MetricType::Gauge);
21        $ready = new MetricFamily('stewart_worker_ready', 'Whether the worker finished booting its apps; 1 or 0.', MetricType::Gauge);
22        $missedProbes = new MetricFamily('stewart_worker_missed_probes', 'Liveness probes the worker has not answered in a row.', MetricType::Gauge);
23        $loopLag = new MetricFamily('stewart_worker_loop_lag_seconds', 'Event loop lag the worker last reported.', MetricType::Gauge);
24        $memory = new MetricFamily('stewart_worker_memory_bytes', 'Memory the worker process last reported.', MetricType::Gauge);
25        $lastPong = new MetricFamily('stewart_worker_last_pong_timestamp_seconds', 'Unix time of the last liveness answer.', MetricType::Gauge);
26        $restartsInWindow = new MetricFamily('stewart_worker_restarts_in_window', 'Restarts inside the current restart budget window.', MetricType::Gauge);
27        $restarts = new MetricFamily('stewart_worker_restarts_total', 'Restarts scheduled since the daemon started.', MetricType::Counter);
28        $quarantines = new MetricFamily('stewart_worker_quarantines_total', 'Times the worker was quarantined after using up its restart budget.', MetricType::Counter);
29        $restartDue = new MetricFamily('stewart_worker_restart_due_timestamp_seconds', 'Unix time of the next scheduled restart.', MetricType::Gauge);
30        $inFlight = new MetricFamily('stewart_worker_service_calls_in_flight', 'Home Assistant calls of this worker awaiting an answer.', MetricType::Gauge);
31        $queued = new MetricFamily('stewart_worker_outbox_queued', 'Messages waiting in the outbox to the worker.', MetricType::Gauge);
32        $largestBatch = new MetricFamily('stewart_worker_outbox_largest_state_batch', 'Largest state change batch sent to the worker.', MetricType::Gauge);
33        $dropped = new MetricFamily('stewart_worker_outbox_dropped_total', 'Messages dropped because the worker outbox was full.', MetricType::Counter);
34        $coalesced = new MetricFamily('stewart_worker_outbox_coalesced_state_changes_total', 'State changes merged into a newer one before delivery.', MetricType::Counter);
35        $batchesSent = new MetricFamily('stewart_worker_outbox_state_batches_sent_total', 'State change batches sent to the worker.', MetricType::Counter);
36
37        foreach ($snapshot->workers as $worker) {
38            $labels = MetricLabels::fromLabel('worker', (string) $worker->workerId);
39
40            foreach (WorkerPhase::cases() as $phase) {
41                $phases->recordSample($labels->withLabel('phase', $phase->value), $phase === $worker->phase);
42            }
43
44            $ready->recordSample($labels, $worker->ready);
45            $missedProbes->recordSample($labels, $worker->missedProbes);
46            $restartsInWindow->recordSample($labels, $worker->restartsInWindow);
47            $restarts->recordSample($labels, $worker->restarts);
48            $quarantines->recordSample($labels, $worker->quarantines);
49            $inFlight->recordSample($labels, $worker->inFlightServiceCalls);
50
51            if ($worker->loopLag !== null) {
52                $loopLag->recordSample($labels, $worker->loopLag->toSeconds());
53            }
54
55            if ($worker->memoryBytes !== null) {
56                $memory->recordSample($labels, $worker->memoryBytes);
57            }
58
59            if ($worker->lastPongAt !== null) {
60                $lastPong->recordSample($labels, PrometheusNumber::convertToEpochSeconds($worker->lastPongAt));
61            }
62
63            if ($worker->restartDueAt !== null) {
64                $restartDue->recordSample($labels, PrometheusNumber::convertToEpochSeconds($worker->restartDueAt));
65            }
66
67            if ($worker->outbox !== null) {
68                $queued->recordSample($labels, $worker->outbox->queued);
69                $largestBatch->recordSample($labels, $worker->outbox->largestStateBatch);
70                $dropped->recordSample($labels, $worker->outbox->dropped);
71                $coalesced->recordSample($labels, $worker->outbox->coalescedStateChanges);
72                $batchesSent->recordSample($labels, $worker->outbox->stateBatchesSent);
73            }
74        }
75
76        return [
77            $phases, $ready, $missedProbes, $loopLag, $memory, $lastPong, $restartsInWindow, $restarts, $quarantines, $restartDue, $inFlight,
78            $queued, $largestBatch, $dropped, $coalesced, $batchesSent,
79        ];
80    }
81}