Working on that new profiler
Gotta figure out what's going on with the database portion, it's going all crazy on me.
This commit is contained in:
parent
506ff1fd45
commit
ee8bd63a08
3 changed files with 72 additions and 254 deletions
|
@ -311,22 +311,6 @@ class Database extends Object
|
||||||
// Checks if the query is blank
|
// Checks if the query is blank
|
||||||
if ($sql != '')
|
if ($sql != '')
|
||||||
{
|
{
|
||||||
// Builds out stack trace for queries
|
|
||||||
$files = [];
|
|
||||||
|
|
||||||
$backtrace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS);
|
|
||||||
krsort($backtrace);
|
|
||||||
|
|
||||||
foreach ($backtrace as $file)
|
|
||||||
{
|
|
||||||
if (isset($file['class'], $file['line']))
|
|
||||||
{
|
|
||||||
$files[] = $file['class'] . ':' . $file['line'];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$sql .= "\n" . '/* [' . implode('|', $files) . '] */';
|
|
||||||
|
|
||||||
// Establishes if we're working on an EXPLAIN
|
// Establishes if we're working on an EXPLAIN
|
||||||
if ($this->config['pickles']['profiler'])
|
if ($this->config['pickles']['profiler'])
|
||||||
{
|
{
|
||||||
|
|
278
src/Profiler.php
278
src/Profiler.php
|
@ -25,18 +25,13 @@ namespace Pickles;
|
||||||
* config.ini for a site. Out of the box the profiler will report on every
|
* config.ini for a site. Out of the box the profiler will report on every
|
||||||
* class object in the system that extends the code Object class.
|
* class object in the system that extends the code Object class.
|
||||||
*
|
*
|
||||||
* Note: I really wanted to use PHP Quick Profiler by Ryan Campbell of
|
|
||||||
* Particletree but it kept barking out errors when I tried to use it with
|
|
||||||
* E_STRICT turned on. Here's a link anyway since it looks awesome:
|
|
||||||
* http://particletree.com/features/php-quick-profiler/
|
|
||||||
*
|
|
||||||
* @usage <code>Profiler::log('some action you want to track');</code>
|
* @usage <code>Profiler::log('some action you want to track');</code>
|
||||||
* @usage <code>Profiler::log($object, 'methodName');</code>
|
* @usage <code>Profiler::log($object, 'methodName');</code>
|
||||||
*/
|
*/
|
||||||
class Profiler
|
class Profiler
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* Profile
|
* Logs
|
||||||
*
|
*
|
||||||
* Array of logged events
|
* Array of logged events
|
||||||
*
|
*
|
||||||
|
@ -44,18 +39,7 @@ class Profiler
|
||||||
* @access private
|
* @access private
|
||||||
* @var array
|
* @var array
|
||||||
*/
|
*/
|
||||||
private static $profile = [];
|
private static $logs = [];
|
||||||
|
|
||||||
/**
|
|
||||||
* Queries
|
|
||||||
*
|
|
||||||
* Number of queries that have been logged
|
|
||||||
*
|
|
||||||
* @static
|
|
||||||
* @access private
|
|
||||||
* @var integer
|
|
||||||
*/
|
|
||||||
private static $queries = 0;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Timers
|
* Timers
|
||||||
|
@ -68,41 +52,6 @@ class Profiler
|
||||||
*/
|
*/
|
||||||
private static $timers = [];
|
private static $timers = [];
|
||||||
|
|
||||||
/**
|
|
||||||
* Enabled
|
|
||||||
*
|
|
||||||
* Checks if the profiler is set to boolean true or if the passed type is
|
|
||||||
* specified in the profiler configuration value.
|
|
||||||
*
|
|
||||||
* @param array $type type(s) to check
|
|
||||||
* @return boolean whether or not the type is enabled
|
|
||||||
*/
|
|
||||||
public static function enabled(/* polymorphic */)
|
|
||||||
{
|
|
||||||
$config = Config::getInstance();
|
|
||||||
$config = $config['pickles']['profiler'];
|
|
||||||
|
|
||||||
// Checks if we're set to boolean true
|
|
||||||
if ($config === true)
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
$types = func_get_args();
|
|
||||||
|
|
||||||
foreach ($types as $type)
|
|
||||||
{
|
|
||||||
if (stripos($config, $type) !== false)
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Log
|
* Log
|
||||||
*
|
*
|
||||||
|
@ -125,21 +74,23 @@ class Profiler
|
||||||
switch ($data_type)
|
switch ($data_type)
|
||||||
{
|
{
|
||||||
case 'array':
|
case 'array':
|
||||||
$log = '<pre>' . print_r($data, true) . '</pre>';
|
$details = print_r($data, true);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'object':
|
case 'object':
|
||||||
$log = '<span style="color:#666">[</span><span style="color:#777">' . get_parent_class($data) . '</span><span style="color:#666">]</span> '
|
$details['class'] = get_class($data);
|
||||||
. '<span style="color:#69c">' . get_class($data) . '</span>'
|
|
||||||
. ($method != '' ? '<span style="color:#666">-></span><span style="color:#4eed9e">' . $method . '</span><span style="color:#666">()</span>' : '');
|
|
||||||
|
|
||||||
$data_type = '<span style="color:Peru">' . $data_type . '</span>';
|
if ($method != '')
|
||||||
|
{
|
||||||
|
$details['method'] = $method . '()';
|
||||||
|
}
|
||||||
|
|
||||||
|
$data_type = $data_type;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'timer':
|
case 'timer':
|
||||||
$log = $method;
|
$details = $method;
|
||||||
|
$data_type = $data_type;
|
||||||
$data_type = '<span style="color:#6c0">' . $data_type . '</span>';
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'string':
|
case 'string':
|
||||||
|
@ -149,16 +100,16 @@ class Profiler
|
||||||
$data_type = $type;
|
$data_type = $type;
|
||||||
}
|
}
|
||||||
|
|
||||||
$log = $data;
|
$details = $data;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
self::$profile[] = [
|
self::$logs[] = [
|
||||||
'log' => $log,
|
|
||||||
'type' => $data_type,
|
'type' => $data_type,
|
||||||
'time' => $time,
|
'timestamp' => $time,
|
||||||
'elapsed' => $time - $_SERVER['REQUEST_TIME_FLOAT'],
|
'elapsed_time' => $time - $_SERVER['REQUEST_TIME_FLOAT'],
|
||||||
'memory' => memory_get_usage(),
|
'memory_usage' => memory_get_usage(),
|
||||||
|
'details' => $details,
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -175,41 +126,39 @@ class Profiler
|
||||||
*/
|
*/
|
||||||
public static function logQuery($query, $input_parameters = false, $explain = false, $duration = false)
|
public static function logQuery($query, $input_parameters = false, $explain = false, $duration = false)
|
||||||
{
|
{
|
||||||
self::$queries++;
|
$log = [];
|
||||||
|
|
||||||
$log = '';
|
|
||||||
|
|
||||||
|
/*
|
||||||
if ($input_parameters != 'false' && is_array($input_parameters))
|
if ($input_parameters != 'false' && is_array($input_parameters))
|
||||||
{
|
{
|
||||||
$log .= '<br>';
|
|
||||||
|
|
||||||
foreach ($input_parameters as $key => $value)
|
foreach ($input_parameters as $key => $value)
|
||||||
{
|
{
|
||||||
$log .= '<br><span style="color:#a82222">' . $key . '</span> <span style="color:#666">=></span> <span style="color:#ffff7f">' . $value . '</span>';
|
$log .= $key . ' => ' . $value;
|
||||||
|
|
||||||
$query = str_replace($key, '<span style="color:#a82222">' . $key . '</span>', $query);
|
$query = str_replace($key, $key, $query);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$log = '<span style="color:#009600">' . $query . '</span>' . $log;
|
$log = $query . ' ' . $log;
|
||||||
|
|
||||||
if (is_array($explain))
|
if (is_array($explain))
|
||||||
{
|
{
|
||||||
$log .= '<br>';
|
|
||||||
|
|
||||||
foreach ($explain as $table)
|
foreach ($explain as $table)
|
||||||
{
|
{
|
||||||
$log .= '<br><span style="color:RoyalBlue">Possible Keys</span> <span style="color:#666">=></span> <span style="color:DarkGoldenRod">' . ($table['possible_keys'] == '' ? '<em style="color:red">NONE</em>' : $table['possible_keys']) . '</span>'
|
$log .= 'Possible Keys => ' . ($table['possible_keys'] == '' ? 'NONE' : $table['possible_keys'])
|
||||||
. '<br><span style="color:RoyalBlue">Key</span> <span style="color:#666">=></span> <span style="color:DarkGoldenRod">' . ($table['key'] == '' ? '<em style="color:red">NONE</em>' : $table['key']) . '</span>'
|
. 'Key => ' . ($table['key'] == '' ? 'NONE' : $table['key'])
|
||||||
. '<br><span style="color:RoyalBlue">Type</span> <span style="color:#666">=></span> <span style="color:DarkGoldenRod">' . $table['type'] . '</span>'
|
. 'Type => ' . $table['type']
|
||||||
. '<br><span style="color:RoyalBlue">Rows</span> <span style="color:#666">=></span> <span style="color:DarkGoldenRod">' . $table['rows'] . '</span>'
|
. 'Rows => ' . $table['rows']
|
||||||
. ($table['Extra'] != '' ? '<br><span style="color:RoyalBlue">Extra</span> <span style="color:#666">=></span> <span style="color:DarkGoldenRod">' . $table['Extra'] . '</span>' : '');
|
. ($table['Extra'] != '' ? 'Extra => ' . $table['Extra'] : '');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$log .= '<br><br><span style="color:DarkKhaki">Speed:</span> ' . number_format($duration * 100, 3) . ' ms';
|
$log .= 'query_time: ' . $duration;
|
||||||
|
*/
|
||||||
|
|
||||||
self::log($log, false, '<span style="color:DarkCyan">database</span>');
|
$log = [$query, $input_parameters, $explain, $duration];
|
||||||
|
|
||||||
|
self::log($log, false, 'database');
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -221,27 +170,28 @@ class Profiler
|
||||||
* @return boolean whether or not timer profiling is enabled
|
* @return boolean whether or not timer profiling is enabled
|
||||||
*/
|
*/
|
||||||
public static function timer($timer)
|
public static function timer($timer)
|
||||||
{
|
|
||||||
if (self::enabled('timers'))
|
|
||||||
{
|
{
|
||||||
// Starts the timer
|
// Starts the timer
|
||||||
if (!isset(self::$timers[$timer]))
|
if (!isset(self::$timers[$timer]))
|
||||||
{
|
{
|
||||||
self::$timers[$timer] = microtime(true);
|
self::$timers[$timer] = microtime(true);
|
||||||
self::Log('timer', '<span style="color:Orchid">Started timer</span> <span style="color:Yellow">' . $timer . '</span>');
|
|
||||||
|
self::Log('timer', [
|
||||||
|
'action' => 'start',
|
||||||
|
'name' => $timer
|
||||||
|
]);
|
||||||
}
|
}
|
||||||
// Ends the timer
|
// Ends the timer
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
self::Log('timer', '<span style="color:Orchid">Stopped timer</span> <span style="color:Yellow">' . $timer . '</span> <span style="color:#666">=></span> <span style="color:DarkKhaki">Time Elapsed:</span> ' . number_format((microtime(true) - self::$timers[$timer]) * 100, 3) . ' ms');
|
self::Log('timer', [
|
||||||
|
'action' => 'stop',
|
||||||
|
'name' => $timer,
|
||||||
|
'elapsed_time' => (microtime(true) - self::$timers[$timer])
|
||||||
|
]);
|
||||||
|
|
||||||
unset(self::$timers[$timer]);
|
unset(self::$timers[$timer]);
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -250,142 +200,24 @@ class Profiler
|
||||||
* Generates the Profiler report that is displayed by the Controller.
|
* Generates the Profiler report that is displayed by the Controller.
|
||||||
* Contains all the HTML needed to display the data properly inline on the
|
* Contains all the HTML needed to display the data properly inline on the
|
||||||
* page. Will generally be displayed after the closing HTML tag.
|
* page. Will generally be displayed after the closing HTML tag.
|
||||||
*
|
|
||||||
* @todo Thinking this should return the report and not necessarily echo it
|
|
||||||
*/
|
*/
|
||||||
public static function report()
|
public static function report()
|
||||||
{
|
{
|
||||||
?>
|
$report = [
|
||||||
<style>
|
'request_time' => $_SERVER['REQUEST_TIME_FLOAT'],
|
||||||
#pickles-profiler
|
'execution_time' => self::$logs[count(self::$logs) - 1]['timestamp']
|
||||||
{
|
- $_SERVER['REQUEST_TIME_FLOAT'],
|
||||||
background: #212121;
|
'peak_memory_usage' => memory_get_peak_usage(),
|
||||||
width: 800px;
|
'max_execution_time' => ini_get('max_execution_time'),
|
||||||
margin: 0 auto;
|
'memory_limit' => ini_get('memory_limit'),
|
||||||
margin-top: 20px;
|
'included_files' => count(get_included_files()),
|
||||||
margin-bottom: 20px;
|
'logs' => self::$logs,
|
||||||
-moz-border-radius: 20px;
|
];
|
||||||
-webkit-border-radius: 20px;
|
|
||||||
border-radius: 20px;
|
|
||||||
-moz-box-shadow: 0 3px 4px rgba(0,0,0,0.5);
|
|
||||||
-webkit-box-shadow: 0 3px 4px rgba(0,0,0,0.5);
|
|
||||||
box-shadow: 0 3px 4px rgba(0,0,0,0.5);
|
|
||||||
border: 6px solid #666;
|
|
||||||
padding: 10px 20px 20px;
|
|
||||||
font-family: monospace;
|
|
||||||
font-size: 12px;
|
|
||||||
text-align: left;
|
|
||||||
}
|
|
||||||
#pickles-profiler table
|
|
||||||
{
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
#pickles-profiler table tr th, #pickles-profiler table tr td
|
|
||||||
{
|
|
||||||
padding: 10px;
|
|
||||||
}
|
|
||||||
#pickles-profiler .even
|
|
||||||
{
|
|
||||||
background-color: #323232;
|
|
||||||
}
|
|
||||||
#pickles-profiler, #pickles-profiler table tr td, #pickles-profiler table tr th
|
|
||||||
{
|
|
||||||
color: #efefe8;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
<div id="pickles-profiler">
|
|
||||||
<strong style="font-size:1.5em">PICKLES Profiler</strong><br><br>
|
|
||||||
<?php
|
|
||||||
if (count(self::$profile) == 0)
|
|
||||||
{
|
|
||||||
echo '<em style="line-height:18px">There is nothing to profile. This often happens when the profiler configuration is set to either "queries" or "explains" and there are no database queries on the page (common on pages that only have a template). You may want to set the profiler to boolean true to ensure you get a profile of the page.</em>';
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
$start_time = $_SERVER['REQUEST_TIME_FLOAT'];
|
|
||||||
$peak_usage = self::formatSize(memory_get_peak_usage());
|
|
||||||
$end_time = self::$profile[count(self::$profile) - 1]['time']; // @todo No idea what though?
|
|
||||||
$duration = ($end_time - $start_time);
|
|
||||||
|
|
||||||
$logs = count(self::$profile);
|
self::$logs = [];
|
||||||
$logs .= ' Log' . ($logs == 1 ? '' : 's');
|
|
||||||
|
|
||||||
$files = count(get_included_files());
|
|
||||||
$files .= ' File' . ($files == 1 ? '' : 's');
|
|
||||||
|
|
||||||
$queries = self::$queries . ' Quer'. (self::$queries == 1 ? 'y' : 'ies');
|
|
||||||
?>
|
|
||||||
<table style="border-collapse:separate;border-spacing:1px;border-radius:10px;text-shadow:1px 1px 1px #000">
|
|
||||||
<tr>
|
|
||||||
<td style="text-align:center;background:#480000">
|
|
||||||
<span style="font-weight:bold;">Console</span>
|
|
||||||
<div style="color:#ff7f7f;font-size:1.2em;padding-top:10px"><?= $logs; ?></div>
|
|
||||||
</td>
|
|
||||||
<td style="text-align:center;background:#552200">
|
|
||||||
<span style="font-weight:bold;">Load Time</span>
|
|
||||||
<div style="color:#ffa366;font-size:1.2em;padding-top:10px"><?= number_format($duration * 100, 3) . ' ms / ' . ini_get('max_execution_time'); ?></div>
|
|
||||||
</td>
|
|
||||||
<td style="text-align:center;background:#545500">
|
|
||||||
<span style="font-weight:bold;">Memory Usage</span>
|
|
||||||
<div style="color:#ffff6d;font-size:1.2em;padding-top:10px"><?= $peak_usage . ' / ' . ini_get('memory_limit'); ?></div>
|
|
||||||
</td>
|
|
||||||
<td style="text-align:center;background:#004200">
|
|
||||||
<span style="font-weight:bold;">Database</span>
|
|
||||||
<div style="color:#7dff7d;font-size:1.2em;padding-top:10px"><?= $queries; ?></div>
|
|
||||||
</td>
|
|
||||||
<td style="text-align:center;background:#000048">
|
|
||||||
<span style="font-weight:bold;">Includes</span>
|
|
||||||
<div style="color:#c4c4ff;font-size:1.2em;padding-top:10px"><?= $files; ?></div>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
<table>
|
|
||||||
<tr>
|
|
||||||
<th style="text-align:left" colspan="2">Console</th>
|
|
||||||
<th style="text-align:right">Memory</th>
|
|
||||||
<th style="text-align:right">Time</th>
|
|
||||||
</tr>
|
|
||||||
<?php
|
|
||||||
foreach (self::$profile as $key => $entry)
|
|
||||||
{
|
|
||||||
?>
|
|
||||||
<tr>
|
|
||||||
<td style="font-weight:bold;color:#999"><?= $entry['type']; ?></td>
|
|
||||||
<td><?= $entry['log']; ?></td>
|
|
||||||
<td style="text-align:right" nowrap="nowrap"><?= self::formatSize($entry['memory']); ?></td>
|
|
||||||
<td style="text-align:right" nowrap="nowrap"><?= number_format($entry['elapsed'] * 100, 3); ?> ms</td>
|
|
||||||
</tr>
|
|
||||||
<?php
|
|
||||||
}
|
|
||||||
?>
|
|
||||||
</table>
|
|
||||||
<?php
|
|
||||||
}
|
|
||||||
?>
|
|
||||||
</div>
|
|
||||||
<br><br>
|
|
||||||
<?php
|
|
||||||
self::$profile = [];
|
|
||||||
self::$queries = 0;
|
|
||||||
self::$timers = [];
|
self::$timers = [];
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
return $report;
|
||||||
* Format Size
|
|
||||||
*
|
|
||||||
* Formats the passed size into a human readable string
|
|
||||||
*
|
|
||||||
* @static
|
|
||||||
* @access private
|
|
||||||
* @param float $filesize size of the file
|
|
||||||
* @return string formatted number string
|
|
||||||
* @todo Probably can move this elsewhere and make it public
|
|
||||||
*/
|
|
||||||
private static function formatSize($filesize)
|
|
||||||
{
|
|
||||||
$units = ['bytes', 'kB', 'MB', 'GB'];
|
|
||||||
|
|
||||||
return number_format(round($filesize / pow(1024, ($i = floor(log($filesize, 1024)))), 2), 2) . ' ' . $units[$i];
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -326,23 +326,20 @@ class Resource extends Object
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/*
|
|
||||||
// Starts a timer before the resource is executed
|
// Starts a timer before the resource is executed
|
||||||
if ($this->config['pickles']['profiler'])
|
if ($this->config['pickles']['profiler'])
|
||||||
{
|
{
|
||||||
Profiler::timer('resource ' . $method);
|
$timer = get_class($this) . '->' . $method . '()';
|
||||||
|
Profiler::timer($timer);
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
|
|
||||||
$this->response = $this->$method();
|
$this->response = $this->$method();
|
||||||
|
|
||||||
/*
|
|
||||||
// Stops the resource timer
|
// Stops the resource timer
|
||||||
if ($this->config['pickles']['profiler'])
|
if ($this->config['pickles']['profiler'])
|
||||||
{
|
{
|
||||||
Profiler::timer('resource ' . $method);
|
Profiler::timer($timer);
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -402,6 +399,11 @@ class Resource extends Object
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ($this->config['pickles']['profiler'])
|
||||||
|
{
|
||||||
|
$response['profiler'] = Profiler::report();
|
||||||
|
}
|
||||||
|
|
||||||
$pretty = isset($_REQUEST['pretty']) ? JSON_PRETTY_PRINT : false;
|
$pretty = isset($_REQUEST['pretty']) ? JSON_PRETTY_PRINT : false;
|
||||||
|
|
||||||
echo json_encode($response, $pretty);
|
echo json_encode($response, $pretty);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue