1, 'rid' => $requestId) : $timeline, array('reason' => $reason, 'state' => $found['state']) ); } catch (Throwable $e) { self::reportFailure('request timeline promote named failed: ' . $e->getMessage()); } } /** * Promote this request's own finished timeline when it is noteworthy: slow * start to shutdown, late start, retry, or an observed server/storage failure. * * @param int|null $elapsedMs request start to now, or null when the clock * was unavailable (slowness cannot then be judged). * @return void */ public static function promoteOwnIfNoteworthy(?int $elapsedMs): void { try { $timeline = ABJ_404_Solution_RequestPhaseTimeline::toArray(); $rid = isset($timeline['rid']) && is_string($timeline['rid']) ? $timeline['rid'] : ''; if ($rid === '') { return; } if (self::hasRecordedFailure($timeline)) { // The reason wire value also works with a ledger loaded before this update. self::record($timeline, 'failure'); } if ($elapsedMs !== null && $elapsedMs >= self::SLOW_REQUEST_MS) { self::record($timeline, ABJ_404_Solution_StrandedRequestLedger::REASON_SLOW); } $requestStart = $timeline['rt'] ?? null; $clientSent = $timeline['cs'] ?? null; if (is_int($requestStart) && is_int($clientSent) && ($requestStart - $clientSent) >= self::LATE_START_MS) { self::record($timeline, ABJ_404_Solution_StrandedRequestLedger::REASON_LATE_START); } if (($timeline['rc'] ?? 0) > 0) { self::record($timeline, ABJ_404_Solution_StrandedRequestLedger::REASON_RETRY); } } catch (Throwable $e) { self::reportFailure('request timeline promote own failed: ' . $e->getMessage()); } } /** * A successful HTTP response can still carry a failed query or diagnostic write. * * @param array $timeline */ private static function hasRecordedFailure(array $timeline): bool { $frame = is_array($timeline['failure_frame'] ?? null) ? $timeline['failure_frame'] : array(); $query = is_array($frame['query'] ?? null) ? $frame['query'] : array(); return ($frame['storage_status'] ?? '') === 'write_failed' || in_array($frame['terminal_state'] ?? '', array('error', 'sql_failure', 'sql_timeout'), true) || in_array($query['state'] ?? '', array('sql_failure', 'sql_timeout'), true); } /** * @param array $timeline * @param string $reason one of the ledger's REASON_* constants. * @return void */ private static function record(array $timeline, string $reason): void { ABJ_404_Solution_StrandedRequestLedger::recordTimeline($timeline, array('reason' => $reason)); } /** * @param string $message * @return void */ private static function reportFailure(string $message): void { if (function_exists('abj404_logPhpFallback')) { abj404_logPhpFallback('request-timeline-promoter', $message); } } }