Lines
92.85%
26 / 28
Methods
77.77%
7 / 9
Classes
0.00%
0 / 1
| Name | Lines | Methods | CRAP | ||||
|---|---|---|---|---|---|---|---|
| __construct | 100.00% | 4 / 4 | 100.00% | 1 / 1 | 3 | ||
| recordActivityReports | 100.00% | 8 / 8 | 100.00% | 1 / 1 | 2 | ||
| recordFinishedCall | 100.00% | 1 / 1 | 100.00% | 1 / 1 | 1 | ||
| recordRefusedCall | 0.00% | 0 / 1 | 0.00% | 0 / 1 | 2 | ||
| recordExposedCommand | 0.00% | 0 / 1 | 0.00% | 0 / 1 | 2 | ||
| recordLastFailure | 100.00% | 10 / 10 | 100.00% | 1 / 1 | 1 | ||
| listRunningTotals | 100.00% | 1 / 1 | 100.00% | 1 / 1 | 1 | ||
| findAppRunningTotals | 100.00% | 1 / 1 | 100.00% | 1 / 1 | 1 | ||
| findOrCreateRunningTotals | 100.00% | 1 / 1 | 100.00% | 1 / 1 | 1 | ||
| 21 | final class AppMetrics | |
| 22 | { | |
| 23 | /** @var array<string, AppRunningTotals> */ | |
| 24 | private array $runningTotals = []; | |
| 25 | ||
| 26 | /** @var WeakMap<WorkerHandle, array<string, AppActivityReport>> */ | |
| 27 | private WeakMap $lastActivityReports; | |
| 28 | ||
| 29 | public function __construct( | |
| 30 | WorkerSlotCollection $workerSlots, | |
| 31 | private readonly Clock $clock, | |
| 32 | ) { | |
| 33 | $this->lastActivityReports = new WeakMap(); | |
| 34 | ||
| 35 | foreach ($workerSlots as $slot) { | |
| 36 | foreach ($slot->apps as $app) { | |
| 37 | $this->runningTotals[$app->id->value] = AppRunningTotals::forApp($app->id, $app->class, $slot->workerId); | |
| 38 | } | |
| 39 | } | |
| 40 | } | |
| 41 | ||
| 42 | public function recordActivityReports(WorkerHandle $handle, Pong $pong): void | |
| 43 | { | |
| 44 | // A respawned worker counts from zero, so its first report is all new activity. | |
| 45 | $previous = $this->lastActivityReports[$handle] ?? []; | |
| 46 | $latest = []; | |
| 47 | $at = $this->clock->getNow(); | |
| 48 | ||
| 49 | foreach ($pong->apps as $report) { | |
| 50 | $scope = $report->scope->wireValue(); | |
| 51 | $this->findOrCreateRunningTotals($handle->id, $report->scope)->recordActivityReport($report, $previous[$scope] ?? null, $at); | |
| 52 | $latest[$scope] = $report; | |
| 53 | } | |
| 54 | ||
| 55 | $this->lastActivityReports[$handle] = $latest; | |
| 56 | } | |
| 57 | ||
| 58 | public function recordFinishedCall(WorkerId $workerId, ResourceScope $scope, ServiceCallOutcome $outcome, Duration $latency): void | |
| 59 | { | |
| 60 | $this->findOrCreateRunningTotals($workerId, $scope)->recordCall($outcome, $latency); | |
| 61 | } | |
| 62 | ||
| 63 | public function recordRefusedCall(WorkerId $workerId, ResourceScope $scope): void | |
| 64 | { | |
| 65 | $this->findOrCreateRunningTotals($workerId, $scope)->recordCall(ServiceCallOutcome::Refused, null); | |
| 66 | } | |
| 67 | ||
| 68 | public function recordExposedCommand(AppId $appId, ExposedCommandOutcome $outcome): void | |
| 69 | { | |
| 70 | $this->findAppRunningTotals($appId)?->recordExposedCommand($outcome); | |
| 71 | } | |
| 72 | ||
| 73 | public function recordLastFailure(WorkerId $workerId, AppFailed $failure): void | |
| 74 | { | |
| 75 | $this->findOrCreateRunningTotals($workerId, $failure->scope)->recordLastFailure( | |
| 76 | new FailureReport( | |
| 77 | $failure->phase, | |
| 78 | $failure->class, | |
| 79 | $failure->message, | |
| 80 | $failure->origin, | |
| 81 | $failure->details?->reason, | |
| 82 | $this->clock->getNow(), | |
| 83 | ), | |
| 84 | ); | |
| 85 | } | |
| 86 | ||
| 87 | /** @return list<AppRunningTotals> */ | |
| 88 | public function listRunningTotals(): array | |
| 89 | { | |
| 90 | return array_values($this->runningTotals); | |
| 91 | } | |
| 92 | ||
| 93 | public function findAppRunningTotals(AppId $appId): ?AppRunningTotals | |
| 94 | { | |
| 95 | return $this->runningTotals[$appId->value] ?? null; | |
| 96 | } | |
| 97 | ||
| 98 | private function findOrCreateRunningTotals(WorkerId $workerId, ResourceScope $scope): AppRunningTotals | |
| 99 | { | |
| 100 | return $this->runningTotals[AppRunningTotals::buildMetricsKey($scope, $workerId)] ??= AppRunningTotals::forScope($scope, $workerId); | |
| 101 | } | |
| 102 | } |