File: /home/d5123/myboofola_com/wp-content/plugins/code-profiler/lib/class-profiler.php
<?php
/*
+=====================================================================+
| ____ _ ____ __ _ _ |
| / ___|___ __| | ___ | _ \ _ __ ___ / _(_) | ___ _ __ |
| | | / _ \ / _` |/ _ \ | |_) | '__/ _ \| |_| | |/ _ \ '__| |
| | |__| (_) | (_| | __/ | __/| | | (_) | _| | | __/ | |
| \____\___/ \__,_|\___| |_| |_| \___/|_| |_|_|\___|_| |
| |
| (c) Jerome Bruandet ~ https://nintechnet.com/codeprofiler/ |
+=====================================================================+
*/
if (! defined('ABSPATH') ) { die('Forbidden'); }
// =====================================================================
class CodeProfiler_Profiler {
static $tick_list;
static $buffer;
static $metrics;
static $fh;
static $connections_list = [];
static $connections_start;
static $exclusions = [];
private $tmp_iostats;
private $tmp_summary;
private $tmp_diskio;
private $tmp_calls;
private $tmp_connections;
private $tmp_rerun;
/**
* Initialize
*/
public function __construct() {
$microtime = sanitize_file_name( $_REQUEST['CODE_PROFILER_ON'] );
$this->tmp_summary = CODE_PROFILER_UPLOAD_DIR ."/$microtime." .
CODE_PROFILER_TMP_SUMMARY_LOG;
$this->tmp_iostats = CODE_PROFILER_UPLOAD_DIR ."/$microtime." .
CODE_PROFILER_TMP_IOSTATS_LOG;
$this->tmp_calls = CODE_PROFILER_UPLOAD_DIR ."/$microtime." .
CODE_PROFILER_TMP_CALLS_LOG;
$this->tmp_diskio = CODE_PROFILER_UPLOAD_DIR ."/$microtime." .
CODE_PROFILER_TMP_DISKIO_LOG;
$this->tmp_connections = CODE_PROFILER_UPLOAD_DIR ."/$microtime." .
CODE_PROFILER_TMP_CONNECTIONS_LOG;
$this->tmp_rerun = CODE_PROFILER_UPLOAD_DIR ."/$microtime." .
CODE_PROFILER_TMP_RERUN_LOG;
if ( function_exists('hrtime') ) {
// PHP >=7.3
self::$metrics = 'hrtime';
} else {
self::$metrics = 'microtime';
}
// Select theme (stylesheet::template)
if (! empty( $_SERVER['HTTP_THEME'] ) ) {
$theme = explode('::', $_SERVER['HTTP_THEME'] );
if (! empty( $theme[1] ) ) {
define('CODE_PROFILER_STYLESHEET', sanitize_file_name( $theme[0] ) );
define('CODE_PROFILER_TEMPLATE', sanitize_file_name( $theme[1] ) );
if ( is_file( WP_CONTENT_DIR .'/themes/'. CODE_PROFILER_STYLESHEET .'/style.css' ) ) {
add_filter('pre_option_template', function () {
return CODE_PROFILER_TEMPLATE;
}, 1000 );
add_filter('pre_option_stylesheet', function () {
return CODE_PROFILER_STYLESHEET;
}, 1000 );
code_profiler_log_debug(
sprintf(
// We cannot load translation here.
'Setting theme to %s',
CODE_PROFILER_STYLESHEET
)
);
} else {
code_profiler_log_error(
sprintf(
// We cannot load translation here.
'Unable to switch theme, %s not found',
CODE_PROFILER_STYLESHEET
)
);
}
}
}
$cp_options = get_option('code-profiler');
if ( empty( $cp_options['accuracy'] ) ) {
define('CODE_PROFILER_TICKS', 1 );
} else {
define('CODE_PROFILER_TICKS', (int) $cp_options['accuracy'] );
}
define('CODE_PROFILER_LENGTH', 17 + strlen( (string) CODE_PROFILER_TICKS ) );
if ( empty( $cp_options['buffer'] ) ||
! preg_match('/^(?:[1-9]|10)$/', $cp_options['buffer'] ) ) {
$recommended = code_profiler_suggested_memory();
self::$buffer = (int) $recommended * 1000000;
} else {
self::$buffer = $cp_options['buffer'] * 1000000;
}
code_profiler_log_debug(
sprintf(
// We cannot load translation here.
'Setting size of memory buffer to %sMB',
self::$buffer / 1000000
)
);
// File & folder exclusions
if ( isset( $cp_options['exclusions'] ) ) {
self::$exclusions = json_decode( $cp_options['exclusions'] );
}
add_filter('pre_http_request', [ $this, 'pre_http_request'], 10000, 3 );
add_action('http_api_debug', [ $this, 'http_api_debug'], 10000, 5 );
register_shutdown_function( [ $this, 'code_profiler_shutdown'] );
code_profiler_log_debug(
// We cannot load translation here.
'Starting profiler'
);
require 'class-stream.php';
// Clear the temporary log because the buffer will be appended to it
if ( file_exists( $this->tmp_calls ) ) {
unlink( $this->tmp_calls );
}
self::$fh = fopen( $this->tmp_calls, 'wb');
CodeProfiler_Stream::start();
register_tick_function( array( $this, 'code_profiler_tick_handler') );
}
/**
* Save data and check for potential PHP errors.
*/
public function code_profiler_shutdown() {
CodeProfiler_Stream::stop();
fclose( self::$fh );
// Summary file (metadata)
$summary = [];
if ( is_file( $this->tmp_rerun ) ) {
$summary['rerun'] = json_decode( file_get_contents( $this->tmp_rerun ), true );
unlink( $this->tmp_rerun );
}
$summary['memory'] = memory_get_peak_usage();
$summary['queries'] = get_num_queries() - 2;
$summary['precision'] = CODE_PROFILER_TICKS;
file_put_contents( $this->tmp_summary, json_encode( $summary ) );
// Catch potential error
$e = error_get_last();
if ( isset( $e['type'] ) && $e['type'] === E_ERROR ) {
$err = str_replace( "\n", ' - ', $e['message'] );
code_profiler_log_error( sprintf(
/* Translators: Error message, line number and script */
esc_html__('Error: E_ERROR (%s - line %s in %s)', 'code-profiler'),
esc_html( $err ),
(int) $e['line'],
esc_html( $e['file'] )
));
}
$err_msg = esc_html__('Cannot open file for writting: %s', 'code-profiler');
$res = file_put_contents( $this->tmp_iostats, json_encode( CodeProfiler_Stream::$io_stats ) );
if ( $res === false ) {
$msg = sprintf( $err_msg, $this->tmp_iostats );
code_profiler_log_error( $msg );
}
$res = file_put_contents( $this->tmp_calls, self::$tick_list, FILE_APPEND );
if ( $res === false ) {
$msg = sprintf( $err_msg, $this->tmp_calls );
code_profiler_log_error( $msg );
}
$res = file_put_contents(
$this->tmp_diskio, "read\t". CodeProfiler_Stream::$io_read ."\nwrite\t".
CodeProfiler_Stream::$io_write
);
if (! empty( self::$connections_list ) ) {
file_put_contents( $this->tmp_connections, json_encode( self::$connections_list) );
}
}
/**
* Our tick handler.
*/
public function code_profiler_tick_handler() {
$start = $this->time();
$backtrace = debug_backtrace( DEBUG_BACKTRACE_IGNORE_ARGS, 2 );
if ( isset( $backtrace[1] ) ) {
$el = $backtrace[1];
} else {
$el = $backtrace[0];
}
if ( empty( $el['file'] ) ) {
if ( isset( $backtrace[0]['file'] ) ) {
$el['file'] = $backtrace[0]['file'];
} else {
return;
}
}
self::$tick_list .= "{$el['file']}\t";
if ( isset( $backtrace[0]['file'][0] ) ) {
self::$tick_list .= $backtrace[0]['file'];
} else {
self::$tick_list .= '-';
}
$backtrace = null;
// Buffer can grow *very* big hence we flush it every 10MB by default
if ( strlen( self::$tick_list ) > self::$buffer ) {
CodeProfiler_Stream::stop();
fwrite( self::$fh, self::$tick_list ."\t{$start}\t". $this->time() ."\n" );
CodeProfiler_Stream::start();
self::$tick_list = '';
} else {
self::$tick_list .="\t{$start}\t". $this->time() ."\n";
}
}
/**
* HTTP API request.
*/
public function pre_http_request( $preempt, $r, $url ) {
if ( empty( $url ) ) {
return false;
}
$backtrace = debug_backtrace( DEBUG_BACKTRACE_IGNORE_ARGS );
self::$connections_start = $this->time();
self::$connections_list[ self::$connections_start ]['bt'] = $backtrace;
return false;
}
/**
* HTTP API response.
*/
public function http_api_debug( $response, $context, $class, $parsed_args, $url ) {
self::$connections_list[ self::$connections_start ]['stop'] = $this->time();
}
/**
* Return time
*/
private function time() {
if ( self::$metrics == 'hrtime') {
return hrtime( true );
} else {
return microtime( true );
}
}
}
new CodeProfiler_Profiler();
// =====================================================================
// EOF