". */ const HOOKS = array('plugins_loaded', 'init', 'wp_loaded', 'wp', 'template_redirect'); /** * Register a PHP_INT_MIN callback on every hook in HOOKS, so each stamp * marks the moment the hook STARTED, before any other callback on it ran. * The gap between two consecutive stamps is the time spent in everything * that ran in that window. * * Not registered for AJAX: the census-instrumented requests are all * admin-ajax, and their timelines already spend the stamp cap on their * own stages. Call once, at plugin boot, after the timeline's * markPluginBoot(). * * @return void */ public static function register(): void { if (!function_exists('add_action')) { return; } if (function_exists('wp_doing_ajax') && wp_doing_ajax()) { return; } // Non-AJAX requests carry no request id, so the empty id makes this // bracket persist nothing; it exists because the diagnostics-wide guard // (DecisiveRecordManifestTest) requires every hook mutation here to // run inside traceBoundary(). (new ABJ_404_Solution_HookInstrumentationLifecycleTracer('', 'lifecycle_hook_stamps'))->traceBoundary( ABJ_404_Solution_HookInstrumentationLifecycleTracer::PHASE_REGISTRATION, 'plugins_loaded', static function (): void { foreach (self::HOOKS as $hook) { add_action($hook, array(self::class, 'stampCurrentHook'), PHP_INT_MIN); } }); } /** * Stamp the WordPress hook currently running, as "wp:". Reads * $GLOBALS['wp_current_filter'] directly, the array core's own * current_filter() reads. No-op when no hook is running. * * @return void */ public static function stampCurrentHook(): void { $stack = $GLOBALS['wp_current_filter'] ?? null; if (!is_array($stack) || $stack === array()) { return; } $hook = end($stack); if (is_string($hook)) { ABJ_404_Solution_RequestPhaseTimeline::stamp('wp:' . $hook); } } }