Last active
August 9, 2023 05:23
-
-
Save felixarntz/63c05392dbf7d51cc7f8f4a424b1ff39 to your computer and use it in GitHub Desktop.
Mini WordPress plugin that uses the Server Timing API of the Performance Lab plugin (also see https://github.com/WordPress/performance/pull/553) to capture additional metrics
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
/** | |
* Plugin Name: Server Timing Extra | |
* Plugin URI: https://gist.github.com/felixarntz/63c05392dbf7d51cc7f8f4a424b1ff39 | |
* Description: Exposes additional Server-Timing metrics using the Performance Lab plugin's Server Timing API. | |
* Requires at least: 6.1 | |
* Requires PHP: 5.6 | |
* Version: 0.1.0 | |
* Author: Felix Arntz | |
* Author URI: https://felix-arntz.me | |
* License: GPLv2 or later | |
* License URI: https://www.gnu.org/licenses/old-licenses/gpl-2.0.html | |
* Text Domain: server-timing-extra | |
* | |
* @package server-timing-extra | |
*/ | |
/** | |
* Measures the total time for a given action hook. | |
* | |
* @param string $hookname The action hook name. | |
*/ | |
function stx_measure_action( $hookname ) { | |
$metric_slug = stx_hookname_to_metric_slug( $hookname ); | |
$measure_callback = function( $metric ) use ( $hookname ) { | |
$metric->measure_before(); | |
add_action( $hookname, array( $metric, 'measure_after' ), PHP_INT_MAX, 0 ); | |
}; | |
// If action is already running, at least measure the remainder. | |
if ( doing_action( $hookname ) ) { | |
perflab_server_timing_register_metric( | |
$metric_slug, | |
array( | |
'measure_callback' => $measure_callback, | |
'access_cap' => 'exist', | |
) | |
); | |
} else { | |
add_action( | |
$hookname, | |
function() use ( $metric_slug, $measure_callback ) { | |
perflab_server_timing_register_metric( | |
$metric_slug, | |
array( | |
'measure_callback' => $measure_callback, | |
'access_cap' => 'exist', | |
) | |
); | |
}, | |
defined( 'PHP_INT_MIN' ) ? PHP_INT_MIN : -9999 | |
); | |
} | |
} | |
/** | |
* Measures the total time for a given filter hook. | |
* | |
* @param string $hookname The filter hook name. | |
*/ | |
function stx_measure_filter( $hookname ) { | |
$metric_slug = stx_hookname_to_metric_slug( $hookname ); | |
$measure_callback = function( $metric ) use ( $hookname ) { | |
$metric->measure_before(); | |
add_filter( | |
$hookname, | |
function( $passthrough ) use ( $metric ) { | |
$metric->measure_after(); | |
return $passthrough; | |
}, | |
PHP_INT_MAX | |
); | |
}; | |
add_filter( | |
$hookname, | |
function( $passthrough ) use ( $metric_slug, $measure_callback ) { | |
perflab_server_timing_register_metric( | |
$metric_slug, | |
array( | |
'measure_callback' => $measure_callback, | |
'access_cap' => 'exist', | |
) | |
); | |
return $passthrough; | |
}, | |
defined( 'PHP_INT_MIN' ) ? PHP_INT_MIN : -9999 | |
); | |
} | |
/** | |
* Measures the times for every callback of a given action or filter hook. | |
* | |
* @param string $hookname The action or filter hook name. | |
*/ | |
function stx_profile_hook_callbacks( $hookname ) { | |
global $wp_filter; | |
if ( ! isset( $wp_filter[ $hookname ] ) ) { | |
return; | |
} | |
foreach ( $wp_filter[ $hookname ]->callbacks as $priority => $callbacks ) { | |
foreach ( $callbacks as $idx => $callback ) { | |
$metric_slug = stx_hookname_to_metric_slug( $hookname ) . '--' . stx_hookname_to_metric_slug( $idx ); | |
$wp_filter[ $hookname ]->callbacks[ $priority ][ $idx ]['function'] = perflab_wrap_server_timing( | |
$wp_filter[ $hookname ]->callbacks[ $priority ][ $idx ]['function'], | |
$metric_slug, | |
'exist' | |
); | |
} | |
} | |
} | |
/** | |
* Gets a Server-Timing metric slug name based on the given hook name. | |
* | |
* @param string $hookname The action or filter hook name. | |
* @return string Corresponding metric slug. | |
*/ | |
function stx_hookname_to_metric_slug( $hookname ) { | |
return str_replace( '_', '-', str_replace( 'wp_', '', $hookname ) ); | |
} | |
/** | |
* Defines and configures extra metrics to capture. | |
*/ | |
function stx_capture_extra_metrics() { | |
if ( ! function_exists( 'perflab_server_timing_register_metric' ) ) { | |
return; | |
} | |
/* More actions can be added here. */ | |
$action_hooks = array( | |
'plugins_loaded', | |
'after_setup_theme', | |
'init', | |
'widgets_init', | |
'wp_loaded', | |
'template_redirect', | |
); | |
if ( perflab_server_timing_use_output_buffer() ) { | |
$action_hooks[] = 'wp_head'; | |
$action_hooks[] = 'wp_enqueue_scripts'; | |
$action_hooks[] = 'wp_footer'; | |
} | |
array_walk( $action_hooks, 'stx_measure_action' ); | |
/* More filters can be added here. */ | |
$filter_hooks = array(); | |
array_walk( $filter_hooks, 'stx_measure_filter' ); | |
// Measure all callbacks of the 'wp_enqueue_scripts' action individually. | |
add_action( | |
'template_redirect', | |
function() { | |
if ( perflab_server_timing_use_output_buffer() ) { | |
stx_profile_hook_callbacks( 'wp_enqueue_scripts' ); | |
} | |
} | |
); | |
// Time it takes to parse the request (including, but not exclusively, the 'parse_request' action). | |
add_filter( | |
'do_parse_request', | |
function( $passthrough ) { | |
perflab_server_timing_register_metric( | |
'parse-request', | |
array( | |
'measure_callback' => function( $metric ) { | |
$metric->measure_before(); | |
add_action( 'parse_request', array( $metric, 'measure_after' ), PHP_INT_MAX ); | |
}, | |
'access_cap' => 'exist', | |
) | |
); | |
return $passthrough; | |
}, | |
PHP_INT_MAX | |
); | |
// Time it takes to locate the template. | |
add_action( | |
'template_redirect', | |
function() { | |
perflab_server_timing_register_metric( | |
'locate-template', | |
array( | |
'measure_callback' => function( $metric ) { | |
$metric->measure_before(); | |
add_filter( | |
'template_include', | |
function( $passthrough ) use ( $metric ) { | |
$metric->measure_after(); | |
return $passthrough; | |
}, | |
defined( 'PHP_INT_MIN' ) ? PHP_INT_MIN : -9999 | |
); | |
}, | |
'access_cap' => 'exist', | |
) | |
); | |
}, | |
PHP_INT_MAX | |
); | |
} | |
add_action( 'plugins_loaded', 'stx_capture_extra_metrics', 0 ); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment