InvoiceLogAlertChecker.php
Pfad: src/Operations/InvoiceLogAlertChecker.php
Ext: php
Größe: 2887 Bytes
Geändert: 2026-07-16 18:07:46+02
<?php
declare(strict_types=1);
namespace Demo\Operations;
use JsonException;
use RuntimeException;
final class InvoiceLogAlertChecker
{
/**
* @return array{events: int, alerts: list<array{runId: string, code: string, phase: string}>}
*/
public function check(string $path): array
{
$handle = @fopen($path, 'rb');
if ($handle === false) {
throw new RuntimeException('Audit-Log ist nicht lesbar.');
}
$events = 0;
$alerts = [];
try {
while (($line = fgets($handle)) !== false) {
if (trim($line) === '') {
continue;
}
++$events;
try {
$event = json_decode($line, true, 32, JSON_THROW_ON_ERROR);
} catch (JsonException) {
$alerts[] = $this->alert('unknown', 'UNKNOWN_LOG_FORMAT', 'audit');
continue;
}
if (!is_array($event)) {
$alerts[] = $this->alert('unknown', 'UNKNOWN_LOG_FORMAT', 'audit');
continue;
}
$runId = $this->scalar($event, ['runId', 'run_id', 'correlationId']) ?? 'unknown';
$code = $this->scalar($event, ['errorCode', 'error_code', 'code']) ?? '';
$phase = $this->scalar($event, ['phase']) ?? 'unknown';
if ($this->requiresAlert($code)) {
$alerts[] = $this->alert($runId, $code, $phase);
}
}
if (!feof($handle)) {
throw new RuntimeException('Audit-Log konnte nicht vollstaendig gelesen werden.');
}
} finally {
fclose($handle);
}
return ['events' => $events, 'alerts' => $alerts];
}
private function requiresAlert(string $code): bool
{
$code = strtoupper($code);
return str_contains($code, 'UNKNOWN') || str_contains($code, 'AUTH');
}
/**
* @param array<array-key, mixed> $values
* @param list<string> $keys
*/
private function scalar(array $values, array $keys): ?string
{
foreach ($keys as $key) {
$value = $values[$key] ?? null;
if (is_string($value) || is_int($value)) {
return (string) $value;
}
}
foreach ($values as $value) {
if (is_array($value)) {
$found = $this->scalar($value, $keys);
if ($found !== null) {
return $found;
}
}
}
return null;
}
/** @return array{runId: string, code: string, phase: string} */
private function alert(string $runId, string $code, string $phase): array
{
return ['runId' => $runId, 'code' => $code, 'phase' => $phase];
}
}