mirror of
https://hk.gh-proxy.com/https://github.com/wp-cli/profile-command.git
synced 2025-08-21 06:38:51 +08:00
Merge pull request #82 from runcommand/23-split-stage-hook
Split `wp profile` into `wp profile stage` and `wp profile hook`
This commit is contained in:
commit
8050917a52
6 changed files with 142 additions and 73 deletions
45
README.md
45
README.md
|
@ -84,26 +84,55 @@ Et voila! You've identified some of the sources of slowness.
|
|||
|
||||
## Using
|
||||
|
||||
This package implements the following commands:
|
||||
|
||||
### wp profile stage
|
||||
|
||||
Profile each stage of the WordPress load process (bootstrap, main_query, template).
|
||||
|
||||
~~~
|
||||
wp profile [--url=<url>] [--stage=<stage>] [--hook=<hook>] [--fields=<fields>] [--format=<format>]
|
||||
wp profile stage [<stage>] [--url=<url>] [--fields=<fields>] [--format=<format>]
|
||||
~~~
|
||||
|
||||
**OPTIONS**
|
||||
|
||||
[<stage>]
|
||||
Drill down into a specific stage.
|
||||
|
||||
[--url=<url>]
|
||||
Execute a request against a specified URL. Defaults to the home URL.
|
||||
|
||||
[--stage=<stage>]
|
||||
Drill down into a specific stage.
|
||||
[--fields=<fields>]
|
||||
Display one or more fields.
|
||||
|
||||
[--format=<format>]
|
||||
Render output in a particular format.
|
||||
---
|
||||
default: table
|
||||
options:
|
||||
- bootstrap
|
||||
- main_query
|
||||
- template
|
||||
- table
|
||||
- json
|
||||
- yaml
|
||||
- csv
|
||||
---
|
||||
|
||||
[--hook=<hook>]
|
||||
Drill down into a specific hook.
|
||||
|
||||
|
||||
### wp profile hook
|
||||
|
||||
Profile key metrics for a WordPress hook (action or filter).
|
||||
|
||||
~~~
|
||||
wp profile hook <hook> [--url=<url>] [--fields=<fields>] [--format=<format>]
|
||||
~~~
|
||||
|
||||
**OPTIONS**
|
||||
|
||||
<hook>
|
||||
WordPress hook (action or filter) to profile.
|
||||
|
||||
[--url=<url>]
|
||||
Execute a request against a specified URL. Defaults to the home URL.
|
||||
|
||||
[--fields=<fields>]
|
||||
Display one or more fields.
|
||||
|
|
|
@ -17,7 +17,8 @@
|
|||
},
|
||||
"extra": {
|
||||
"commands": [
|
||||
"profile"
|
||||
"profile stage",
|
||||
"profile hook"
|
||||
],
|
||||
"readme": {
|
||||
"shields": [
|
||||
|
|
|
@ -3,7 +3,7 @@ Feature: Profile a specific hook
|
|||
Scenario: Profile a hook before the template is loaded
|
||||
Given a WP install
|
||||
|
||||
When I run `wp profile --hook=plugins_loaded --fields=callback`
|
||||
When I run `wp profile hook plugins_loaded --fields=callback`
|
||||
Then STDOUT should be a table containing rows:
|
||||
| callback |
|
||||
And STDERR should be empty
|
||||
|
@ -11,7 +11,7 @@ Feature: Profile a specific hook
|
|||
Scenario: Profile a hook without any callbacks
|
||||
Given a WP install
|
||||
|
||||
When I run `wp profile --hook=setup_theme --fields=callback`
|
||||
When I run `wp profile hook setup_theme --fields=callback`
|
||||
Then STDOUT should be a table containing rows:
|
||||
| callback |
|
||||
| total |
|
||||
|
@ -20,7 +20,7 @@ Feature: Profile a specific hook
|
|||
Scenario: Profile a hook that has actions with output
|
||||
Given a WP install
|
||||
|
||||
When I run `wp profile --hook=wp_head --fields=callback`
|
||||
When I run `wp profile hook wp_head --fields=callback`
|
||||
Then STDOUT should be a table containing rows:
|
||||
| callback |
|
||||
And STDOUT should not contain:
|
||||
|
|
|
@ -1,9 +1,19 @@
|
|||
Feature: Profile the template render stage
|
||||
|
||||
Scenario: Profiler loads a summary table
|
||||
Given a WP install
|
||||
|
||||
When I run `wp profile stage --fields=stage`
|
||||
Then STDOUT should be a table containing rows:
|
||||
| stage |
|
||||
| bootstrap |
|
||||
| main_query |
|
||||
| template |
|
||||
|
||||
Scenario: Profiler loads a table with the correct hooks
|
||||
Given a WP install
|
||||
|
||||
When I run `wp profile --stage=template --fields=hook`
|
||||
When I run `wp profile stage template --fields=hook`
|
||||
Then STDOUT should be a table containing rows:
|
||||
| hook |
|
||||
| |
|
|
@ -1,15 +1,5 @@
|
|||
Feature: Basic profile usage
|
||||
|
||||
Scenario: Profiler loads a summary table
|
||||
Given a WP install
|
||||
|
||||
When I run `wp profile --fields=stage`
|
||||
Then STDOUT should be a table containing rows:
|
||||
| stage |
|
||||
| bootstrap |
|
||||
| main_query |
|
||||
| template |
|
||||
|
||||
Scenario: Error when SAVEQUERIES is defined to false
|
||||
Given an empty directory
|
||||
And WP files
|
||||
|
@ -23,7 +13,7 @@ Feature: Basic profile usage
|
|||
When I run `wp core install --url='https://localhost' --title='Test' --admin_user=wpcli --admin_email=admin@example.com --admin_password=1`
|
||||
Then the return code should be 0
|
||||
|
||||
When I try `wp profile`
|
||||
When I try `wp profile stage`
|
||||
Then STDERR should be:
|
||||
"""
|
||||
Error: 'SAVEQUERIES' is defined as false, and must be true. Please check your wp-config.php
|
||||
|
@ -32,7 +22,7 @@ Feature: Basic profile usage
|
|||
Scenario: Profile a hook without any callbacks
|
||||
Given a WP install
|
||||
|
||||
When I run `wp profile --hook=setup_theme --fields=callback,time`
|
||||
When I run `wp profile hook setup_theme --fields=callback,time`
|
||||
Then STDOUT should be a table containing rows:
|
||||
| callback | time |
|
||||
| total | |
|
||||
|
|
|
@ -8,34 +8,25 @@ use WP_CLI\Utils;
|
|||
class Command {
|
||||
|
||||
private $loggers = array();
|
||||
private $focus_stage;
|
||||
private $focus_stage = null;
|
||||
private $stage_hooks = array();
|
||||
private $focus_hook;
|
||||
private $focus_hook = null;
|
||||
private $current_filter_callbacks = array();
|
||||
private $focus_query_offset = 0;
|
||||
|
||||
private static $exception_message = "Need to bail, because can't restore the hooks";
|
||||
|
||||
/**
|
||||
* Quickly identify what's slow with WordPress.
|
||||
* Profile each stage of the WordPress load process (bootstrap, main_query, template).
|
||||
*
|
||||
* ## OPTIONS
|
||||
*
|
||||
* [<stage>]
|
||||
* : Drill down into a specific stage.
|
||||
*
|
||||
* [--url=<url>]
|
||||
* : Execute a request against a specified URL. Defaults to the home URL.
|
||||
*
|
||||
* [--stage=<stage>]
|
||||
* : Drill down into a specific stage.
|
||||
* ---
|
||||
* options:
|
||||
* - bootstrap
|
||||
* - main_query
|
||||
* - template
|
||||
* ---
|
||||
*
|
||||
* [--hook=<hook>]
|
||||
* : Drill down into a specific hook.
|
||||
*
|
||||
* [--fields=<fields>]
|
||||
* : Display one or more fields.
|
||||
*
|
||||
|
@ -52,29 +43,19 @@ class Command {
|
|||
*
|
||||
* @when before_wp_load
|
||||
*/
|
||||
public function __invoke( $args, $assoc_args ) {
|
||||
public function stage( $args, $assoc_args ) {
|
||||
global $wpdb;
|
||||
|
||||
$this->focus_stage = Utils\get_flag_value( $assoc_args, 'stage' );
|
||||
$this->focus_hook = Utils\get_flag_value( $assoc_args, 'hook' );
|
||||
|
||||
if ( ! isset( WP_CLI::get_runner()->config['url'] ) ) {
|
||||
WP_CLI::add_wp_hook( 'muplugins_loaded', function(){
|
||||
WP_CLI::set_url( home_url( '/' ) );
|
||||
});
|
||||
if ( isset( $args[0] ) ) {
|
||||
$this->focus_stage = $args[0];
|
||||
}
|
||||
WP_CLI::add_hook( 'after_wp_config_load', function() {
|
||||
if ( defined( 'SAVEQUERIES' ) && ! SAVEQUERIES ) {
|
||||
WP_CLI::error( "'SAVEQUERIES' is defined as false, and must be true. Please check your wp-config.php" );
|
||||
}
|
||||
if ( ! defined( 'SAVEQUERIES' ) ) {
|
||||
define( 'SAVEQUERIES', true );
|
||||
}
|
||||
});
|
||||
WP_CLI::add_wp_hook( 'all', array( $this, 'wp_hook_begin' ) );
|
||||
WP_CLI::add_wp_hook( 'pre_http_request', array( $this, 'wp_request_begin' ) );
|
||||
WP_CLI::add_wp_hook( 'http_api_debug', array( $this, 'wp_request_end' ) );
|
||||
$this->load_wordpress_with_template();
|
||||
|
||||
$valid_stages = array( 'bootstrap', 'main_query', 'template' );
|
||||
if ( $this->focus_stage && ! in_array( $this->focus_stage, $valid_stages, true ) ) {
|
||||
WP_CLI::error( 'Invalid stage. Must be one of: ' . implode( ', ', $valid_stages ) );
|
||||
}
|
||||
|
||||
$this->run_profiler();
|
||||
|
||||
if ( $this->focus_stage ) {
|
||||
$fields = array(
|
||||
|
@ -88,18 +69,6 @@ class Command {
|
|||
'request_time',
|
||||
'request_count',
|
||||
);
|
||||
} else if ( $this->focus_hook ) {
|
||||
$fields = array(
|
||||
'callback',
|
||||
'time',
|
||||
'query_time',
|
||||
'query_count',
|
||||
'cache_ratio',
|
||||
'cache_hits',
|
||||
'cache_misses',
|
||||
'request_time',
|
||||
'request_count',
|
||||
);
|
||||
} else {
|
||||
$fields = array(
|
||||
'stage',
|
||||
|
@ -119,6 +88,53 @@ class Command {
|
|||
$formatter->display_items( $this->loggers );
|
||||
}
|
||||
|
||||
/**
|
||||
* Profile key metrics for a WordPress hook (action or filter).
|
||||
*
|
||||
* ## OPTIONS
|
||||
*
|
||||
* <hook>
|
||||
* : WordPress hook (action or filter) to profile.
|
||||
*
|
||||
* [--url=<url>]
|
||||
* : Execute a request against a specified URL. Defaults to the home URL.
|
||||
*
|
||||
* [--fields=<fields>]
|
||||
* : Display one or more fields.
|
||||
*
|
||||
* [--format=<format>]
|
||||
* : Render output in a particular format.
|
||||
* ---
|
||||
* default: table
|
||||
* options:
|
||||
* - table
|
||||
* - json
|
||||
* - yaml
|
||||
* - csv
|
||||
* ---
|
||||
*
|
||||
* @when before_wp_load
|
||||
*/
|
||||
public function hook( $args, $assoc_args ) {
|
||||
|
||||
$this->focus_hook = $args[0];
|
||||
$this->run_profiler();
|
||||
|
||||
$fields = array(
|
||||
'callback',
|
||||
'time',
|
||||
'query_time',
|
||||
'query_count',
|
||||
'cache_ratio',
|
||||
'cache_hits',
|
||||
'cache_misses',
|
||||
'request_time',
|
||||
'request_count',
|
||||
);
|
||||
$formatter = new Formatter( $assoc_args, $fields );
|
||||
$formatter->display_items( $this->loggers );
|
||||
}
|
||||
|
||||
/**
|
||||
* Profiling verbosity at the beginning of every action and filter
|
||||
*/
|
||||
|
@ -145,7 +161,7 @@ class Command {
|
|||
|
||||
WP_CLI::add_wp_hook( $current_filter, array( $this, 'wp_hook_end' ), 9999 );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Wrap current filter callbacks with a timer
|
||||
*/
|
||||
|
@ -247,6 +263,29 @@ class Command {
|
|||
return $filter_value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Run the profiler against WordPress
|
||||
*/
|
||||
private function run_profiler() {
|
||||
if ( ! isset( WP_CLI::get_runner()->config['url'] ) ) {
|
||||
WP_CLI::add_wp_hook( 'muplugins_loaded', function(){
|
||||
WP_CLI::set_url( home_url( '/' ) );
|
||||
});
|
||||
}
|
||||
WP_CLI::add_hook( 'after_wp_config_load', function() {
|
||||
if ( defined( 'SAVEQUERIES' ) && ! SAVEQUERIES ) {
|
||||
WP_CLI::error( "'SAVEQUERIES' is defined as false, and must be true. Please check your wp-config.php" );
|
||||
}
|
||||
if ( ! defined( 'SAVEQUERIES' ) ) {
|
||||
define( 'SAVEQUERIES', true );
|
||||
}
|
||||
});
|
||||
WP_CLI::add_wp_hook( 'all', array( $this, 'wp_hook_begin' ) );
|
||||
WP_CLI::add_wp_hook( 'pre_http_request', array( $this, 'wp_request_begin' ) );
|
||||
WP_CLI::add_wp_hook( 'http_api_debug', array( $this, 'wp_request_end' ) );
|
||||
$this->load_wordpress_with_template();
|
||||
}
|
||||
|
||||
/**
|
||||
* Runs through the entirety of the WP bootstrap process
|
||||
*/
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue