169 lines
		
	
	
		
			4.3 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
			
		
		
	
	
			169 lines
		
	
	
		
			4.3 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
<?php declare(strict_types = 1);
 | 
						|
/**
 | 
						|
 * Timing and profiling collector.
 | 
						|
 *
 | 
						|
 * @package query-monitor
 | 
						|
 */
 | 
						|
 | 
						|
if ( ! defined( 'ABSPATH' ) ) {
 | 
						|
	exit;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
 * @extends QM_DataCollector<QM_Data_Timing>
 | 
						|
 */
 | 
						|
class QM_Collector_Timing extends QM_DataCollector {
 | 
						|
 | 
						|
	/**
 | 
						|
	 * @var string
 | 
						|
	 */
 | 
						|
	public $id = 'timing';
 | 
						|
 | 
						|
	/**
 | 
						|
	 * @var array<string, QM_Timer>
 | 
						|
	 */
 | 
						|
	private $track_timer = array();
 | 
						|
 | 
						|
	/**
 | 
						|
	 * @var array<string, QM_Timer>
 | 
						|
	 */
 | 
						|
	private $start = array();
 | 
						|
 | 
						|
	/**
 | 
						|
	 * @var array<string, QM_Timer>
 | 
						|
	 */
 | 
						|
	private $stop = array();
 | 
						|
 | 
						|
	public function get_storage(): QM_Data {
 | 
						|
		return new QM_Data_Timing();
 | 
						|
	}
 | 
						|
 | 
						|
	/**
 | 
						|
	 * @return void
 | 
						|
	 */
 | 
						|
	public function set_up() {
 | 
						|
		parent::set_up();
 | 
						|
 | 
						|
		add_action( 'qm/start', array( $this, 'action_function_time_start' ), 10, 1 );
 | 
						|
		add_action( 'qm/stop', array( $this, 'action_function_time_stop' ), 10, 1 );
 | 
						|
		add_action( 'qm/lap', array( $this, 'action_function_time_lap' ), 10, 2 );
 | 
						|
	}
 | 
						|
 | 
						|
	/**
 | 
						|
	 * @return void
 | 
						|
	 */
 | 
						|
	public function tear_down() {
 | 
						|
		remove_action( 'qm/start', array( $this, 'action_function_time_start' ), 10 );
 | 
						|
		remove_action( 'qm/stop', array( $this, 'action_function_time_stop' ), 10 );
 | 
						|
		remove_action( 'qm/lap', array( $this, 'action_function_time_lap' ), 10 );
 | 
						|
 | 
						|
		parent::tear_down();
 | 
						|
	}
 | 
						|
 | 
						|
	/**
 | 
						|
	 * @param string $function
 | 
						|
	 * @return void
 | 
						|
	 */
 | 
						|
	public function action_function_time_start( $function ) {
 | 
						|
		$this->track_timer[ $function ] = new QM_Timer();
 | 
						|
		$this->start[ $function ] = $this->track_timer[ $function ]->start();
 | 
						|
	}
 | 
						|
 | 
						|
	/**
 | 
						|
	 * @param string $function
 | 
						|
	 * @return void
 | 
						|
	 */
 | 
						|
	public function action_function_time_stop( $function ) {
 | 
						|
		if ( ! isset( $this->track_timer[ $function ] ) ) {
 | 
						|
			$trace = new QM_Backtrace();
 | 
						|
			$this->data->warning[] = array(
 | 
						|
				'function' => $function,
 | 
						|
				'message' => __( 'Timer not started', 'query-monitor' ),
 | 
						|
				'filtered_trace' => $trace->get_filtered_trace(),
 | 
						|
				'component' => $trace->get_component(),
 | 
						|
			);
 | 
						|
			return;
 | 
						|
		}
 | 
						|
		$this->stop[ $function ] = $this->track_timer[ $function ]->stop();
 | 
						|
		$this->calculate_time( $function );
 | 
						|
	}
 | 
						|
 | 
						|
	/**
 | 
						|
	 * @param string $function
 | 
						|
	 * @param string $name
 | 
						|
	 * @return void
 | 
						|
	 */
 | 
						|
	public function action_function_time_lap( $function, $name = null ) {
 | 
						|
		if ( ! isset( $this->track_timer[ $function ] ) ) {
 | 
						|
			$trace = new QM_Backtrace();
 | 
						|
			$this->data->warning[] = array(
 | 
						|
				'function' => $function,
 | 
						|
				'message' => __( 'Timer not started', 'query-monitor' ),
 | 
						|
				'filtered_trace' => $trace->get_filtered_trace(),
 | 
						|
				'component' => $trace->get_component(),
 | 
						|
			);
 | 
						|
			return;
 | 
						|
		}
 | 
						|
		$this->track_timer[ $function ]->lap( array(), $name );
 | 
						|
	}
 | 
						|
 | 
						|
	/**
 | 
						|
	 * @param string $function
 | 
						|
	 * @return void
 | 
						|
	 */
 | 
						|
	public function calculate_time( $function ) {
 | 
						|
		$trace = $this->track_timer[ $function ]->get_trace();
 | 
						|
		$function_time = $this->track_timer[ $function ]->get_time();
 | 
						|
		$function_memory = $this->track_timer[ $function ]->get_memory();
 | 
						|
		$function_laps = $this->track_timer[ $function ]->get_laps();
 | 
						|
		$start_time = $this->track_timer[ $function ]->get_start_time();
 | 
						|
		$end_time = $this->track_timer[ $function ]->get_end_time();
 | 
						|
 | 
						|
		$this->data->timing[] = array(
 | 
						|
			'function' => $function,
 | 
						|
			'function_time' => $function_time,
 | 
						|
			'function_memory' => $function_memory,
 | 
						|
			'laps' => $function_laps,
 | 
						|
			'filtered_trace' => $trace->get_filtered_trace(),
 | 
						|
			'component' => $trace->get_component(),
 | 
						|
			'start_time' => ( $start_time - $_SERVER['REQUEST_TIME_FLOAT'] ),
 | 
						|
			'end_time' => ( $end_time - $_SERVER['REQUEST_TIME_FLOAT'] ),
 | 
						|
		);
 | 
						|
	}
 | 
						|
 | 
						|
	/**
 | 
						|
	 * @return void
 | 
						|
	 */
 | 
						|
	public function process() {
 | 
						|
		foreach ( $this->start as $function => $value ) {
 | 
						|
			if ( ! isset( $this->stop[ $function ] ) ) {
 | 
						|
				$trace = $this->track_timer[ $function ]->get_trace();
 | 
						|
				$this->data->warning[] = array(
 | 
						|
					'function' => $function,
 | 
						|
					'message' => __( 'Timer not stopped', 'query-monitor' ),
 | 
						|
					'filtered_trace' => $trace->get_filtered_trace(),
 | 
						|
					'component' => $trace->get_component(),
 | 
						|
				);
 | 
						|
			}
 | 
						|
		}
 | 
						|
 | 
						|
		if ( ! empty( $this->data->timing ) ) {
 | 
						|
			usort( $this->data->timing, array( $this, 'sort_by_start_time' ) );
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	/**
 | 
						|
	 * @param mixed[] $a
 | 
						|
	 * @param mixed[] $b
 | 
						|
	 * @return int
 | 
						|
	 * @phpstan-return -1|0|1
 | 
						|
	 */
 | 
						|
	public function sort_by_start_time( array $a, array $b ) {
 | 
						|
		return $a['start_time'] <=> $b['start_time'];
 | 
						|
	}
 | 
						|
 | 
						|
}
 | 
						|
 | 
						|
# Load early in case a plugin is setting the function to be checked when it initialises instead of after the `plugins_loaded` hook
 | 
						|
QM_Collectors::add( new QM_Collector_Timing() );
 |