Lines 88.23% 15 / 17
Functions and Methods 50.00% 1 / 2
Classes and Traits 0.00% 0 / 1
Name Lines Functions and Methods CRAP Classes and Traits
AppFailureReporter 88.23% 15 / 17 50.00% 1 / 2 4.03 0.00% 0 / 1
 __construct 100.00% 1 / 1 100.00% 1 / 1 1
 report 87.50% 14 / 16 0.00% 0 / 1 3.02
1<?php
2
3declare(strict_types=1);
4
5namespace Stewart\Runtime\Worker;
6
7use Stewart\Runtime\Ipc\Message\AppFailed;
8use Stewart\Runtime\Ipc\Transport;
9use Stewart\Runtime\Lifecycle\AppFailurePhase;
10use Stewart\Runtime\Model\ExceptionDetails;
11use Stewart\Runtime\Model\ResourceScope;
12use Throwable;
13
14final readonly class AppFailureReporter
15{
16    public function __construct(
17        private Transport $transport,
18        private StderrFallback $stderr,
19        private AppActivityCounters $activityCounters,
20        private HandlerFailureSampler $sampler,
21    ) {}
22
23    public function report(ResourceScope $scope, AppFailurePhase $phase, Throwable $error, ?string $origin = null): void
24    {
25        $this->activityCounters->findOrCreateActivityForScope($scope)->recordFailure();
26        $occurrence = $this->sampler->recordFailure($scope, $phase, $error);
27
28        if (!$this->sampler->isSampled($occurrence)) {
29            return;
30        }
31
32        try {
33            $this->transport->send(new AppFailed(
34                scope: $scope,
35                phase: $phase,
36                class: $error::class,
37                message: $error->getMessage(),
38                trace: $error->getTraceAsString(),
39                origin: $origin,
40                occurrence: $occurrence,
41                details: ExceptionDetails::fromThrowable($error),
42            ));
43        } catch (Throwable) {
44            // The channel is gone; stderr still records why the app failed.
45            $this->stderr->writeLine($scope, \sprintf('%s %s: %s', $origin ?? $phase->value, $error::class, $error->getMessage()));
46        }
47    }
48}