*/ private static array $entries = []; /** @var array */ private static array $pendingEvents = []; /** * Enable audit logging. */ public static function enable(): void { self::$enabled = true; } /** * Disable audit logging. */ public static function disable(): void { self::$enabled = false; } /** * Check if audit logging is enabled. */ public static function isEnabled(): bool { return self::$enabled; } /** * Enable writing audit entries to Laravel log. */ public static function enableLog(): void { self::$logEnabled = true; } /** * Disable writing audit entries to Laravel log. */ public static function disableLog(): void { self::$logEnabled = false; } /** * Record the start of event handling. */ public static function recordStart(string $eventClass, string $handlerClass): void { if (! self::$enabled) { return; } $key = "{$eventClass}:{$handlerClass}"; self::$pendingEvents[$key] = microtime(true); } /** * Record successful completion of event handling. */ public static function recordSuccess(string $eventClass, string $handlerClass): void { if (! self::$enabled) { return; } $key = "{$eventClass}:{$handlerClass}"; $startTime = self::$pendingEvents[$key] ?? microtime(true); $duration = (microtime(true) - $startTime) * 1000; unset(self::$pendingEvents[$key]); $entry = [ 'event' => $eventClass, 'handler' => $handlerClass, 'duration_ms' => round($duration, 2), 'failed' => false, 'timestamp' => microtime(true), ]; self::$entries[] = $entry; if (self::$logEnabled) { Log::debug('Lifecycle event handled', $entry); } } /** * Record a failed event handler. */ public static function recordFailure(string $eventClass, string $handlerClass, \Throwable $error): void { if (! self::$enabled) { return; } $key = "{$eventClass}:{$handlerClass}"; $startTime = self::$pendingEvents[$key] ?? microtime(true); $duration = (microtime(true) - $startTime) * 1000; unset(self::$pendingEvents[$key]); $entry = [ 'event' => $eventClass, 'handler' => $handlerClass, 'duration_ms' => round($duration, 2), 'failed' => true, 'error' => $error->getMessage(), 'timestamp' => microtime(true), ]; self::$entries[] = $entry; if (self::$logEnabled) { Log::warning('Lifecycle event handler failed', $entry); } } /** * Get all recorded entries. * * @return array */ public static function entries(): array { return self::$entries; } /** * Get entries for a specific event class. * * @return array */ public static function entriesFor(string $eventClass): array { return array_values( array_filter(self::$entries, fn ($entry) => $entry['event'] === $eventClass) ); } /** * Get only failed entries. * * @return array */ public static function failures(): array { return array_values( array_filter(self::$entries, fn ($entry) => $entry['failed']) ); } /** * Get summary statistics. * * @return array{total: int, failed: int, total_duration_ms: float, events: array} */ public static function summary(): array { $eventCounts = []; $totalDuration = 0.0; $failedCount = 0; foreach (self::$entries as $entry) { $eventCounts[$entry['event']] = ($eventCounts[$entry['event']] ?? 0) + 1; $totalDuration += $entry['duration_ms']; if ($entry['failed']) { $failedCount++; } } return [ 'total' => count(self::$entries), 'failed' => $failedCount, 'total_duration_ms' => round($totalDuration, 2), 'events' => $eventCounts, ]; } /** * Clear all recorded entries. */ public static function clear(): void { self::$entries = []; self::$pendingEvents = []; } /** * Reset to initial state (disable and clear). */ public static function reset(): void { self::$enabled = false; self::$logEnabled = false; self::clear(); } }