wpActionStartedAt = $now; } /** Record that the WordPress 'shutdown' action closed (latest-priority callback). */ public function noteWpActionEnd(float $now): void { $this->wpActionEndedAt = $now; } /** * The attribution fields for one teardown sentinel firing. * * Both millisecond readings are null rather than 0 when the WordPress * shutdown action was never observed (a fatal before it, a worker killed * inside it, or shutdown_action_hook removed): a fabricated zero would * silently blame every millisecond on the non-WordPress side. * * @param string $mechanism The firing sentinel's mechanism vocabulary (echoed back). * @param string $armedAt Where the sentinel was registered (echoed back). * @param bool $isShutdownFunction True when this sentinel is a register_shutdown_function * callback (runs below WordPress), false for a WordPress * 'shutdown' action callback. * @param float $now The sentinel's firing time. * @return array */ public function attribution(string $mechanism, string $armedAt, bool $isShutdownFunction, float $now): array { $attribution = array( 'mechanism' => $mechanism, 'armed_at' => $armedAt, 'teardown_ordinal' => ++$this->teardownCount, 'shutdown_function_ordinal' => $isShutdownFunction ? ++$this->shutdownFunctionCount : null, 'wp_shutdown_action_ms' => $this->wpActionStartedAt !== null && $this->wpActionEndedAt !== null ? max(0, (int)round(($this->wpActionEndedAt - $this->wpActionStartedAt) * 1000)) : null, 'non_wp_shutdown_ms' => $isShutdownFunction && $this->wpActionEndedAt !== null ? max(0, (int)round(($now - $this->wpActionEndedAt) * 1000)) : null, 'since_previous_shutdown_function_ms' => $isShutdownFunction && $this->lastShutdownFunctionAt !== null ? max(0, (int)round(($now - $this->lastShutdownFunctionAt) * 1000)) : null, ); if ($isShutdownFunction) { $this->lastShutdownFunctionAt = $now; } return $attribution; } }