/** * Stops XHProf profiling and saves profile data in var/log/xhprof * * @return mixed false|string (the run_id)|true (when nosave==true) */ public static function stop($dosave = true) { if (!extension_loaded('xhprof')) { eZPerfLoggerDebug::writeWarning('Extension xhprof not loaded, can not stop profiling', __METHOD__); return false; } if (!self::$profilingRunning) { return false; } $xhprofData = xhprof_disable(); self::$profilingRunning = false; if (!$dosave) { return true; } if (!is_dir(self::$logdir)) { mkdir(self::$logdir); } $logger = new XHProfRuns_Default(self::$logdir); $runId = $logger->save_run($xhprofData, "xhprof"); if ($runId) { // beside profiling data, save extra info in another file to make it more useful later file_put_contents(self::$logdir . "/{$runId}.info", eZPerfLoggerApacheLogger::apacheLogLine('combined')); self::$runs[] = $runId; } return $runId; }
/** Executes the needed operator(s). Checks operator names, and calls the appropriate functions. */ function modify($tpl, $operatorName, $operatorParameters, $rootNamespace, $currentNamespace, &$operatorValue, $namedParameters) { switch ($operatorName) { case 'xhprof_start': eZXHProfLogger::start($namedParameters['flags'], $namedParameters['options']); $operatorValue = null; break; case 'xhprof_stop': eZXHProfLogger::stop($namedParameters['dosave']); $operatorValue = null; break; case 'record_value': eZPerfLogger::recordValue($namedParameters['name'], $operatorValue); $operatorValue = null; break; case 'make_global': /// @todo investigate: shal we use copy if $operatorValue is an object? $GLOBALS[$namedParameters['name']] = $namedParameters['value']; $operatorValue = null; } }
unset($params[$k]); } } ////echo "<html>"; ////echo "<head><title>XHProf: Hierarchical Profiler Report</title>"; ////xhprof_include_js_css(); ////echo "</head>"; ////echo "<body>"; $vbar = ' class="vbar"'; $vwbar = ' class="vwbar"'; $vwlbar = ' class="vwlbar"'; $vbbar = ' class="vbbar"'; $vrbar = ' class="vrbar"'; $vgbar = ' class="vgbar"'; $xhprof_runs_impl = new XHProfRuns_Default(eZXHProfLogger::logDir()); displayXHProfReport($xhprof_runs_impl, $params, $GLOBALS['source'], $GLOBALS['run'], $GLOBALS['wts'], $GLOBALS['symbol'], $GLOBALS['sort'], $GLOBALS['run1'], $GLOBALS['run2']); ////echo "</body>"; ////echo "</html>"; $body = ob_get_clean(); $info = false; $infoFile = eZXHProfLogger::logDir() . "/{$GLOBALS['run']}.info"; if (file_exists($infoFile)) { $info = eZPerfLoggerApacheLogger::parseLogLine(file_get_contents($infoFile)); } $tpl = eZTemplate::factory(); $tpl->setVariable('body', $body); $tpl->setVariable('error', $error); $tpl->setVariable('run', $GLOBALS['run']); $tpl->setVariable('info', $info); $Result['content'] = $tpl->fetch('design:xhprof/view.tpl'); $Result['path'] = array(array('text' => 'XHProf', 'url' => 'xhprof/list'), array('text' => 'Run: ' . $GLOBALS['run'], 'url' => 'xhprof/view?run=' . $GLOBALS['run']));
/** * This method is called to allow this class to provide values for the perf * variables it caters to. * In this case, it actually gets called by self::filter(). * To avoid unnecessary overhead, it cheats a little bit, and it does not provide * values for ALL variables it supports, but only for the ones it knows will * be logged. * @param string $output * @param $returnCode * @return array */ public static function measure($output, $returnCode = null) { global $scriptStartTime; // This var we want to save as it is used for logs even when not present in TrackVariables. // Also using ga / piwik logs do alter $output, making length calculation in doLog() unreliable /// @todo this way of passing data around is not really beautiful... self::$outputSize = strlen($output); if ($returnCode !== null) { self::$returnCode = (int) $returnCode; } else { // for cli scripts, set default response status to 0 instead of 200 if (eZSys::isShellExecution()) { self::$returnCode = 0; } } $out = array(); $vars = eZPerfLoggerINI::variable('GeneralSettings', 'TrackVariables'); foreach ($vars as $var) { switch ($var) { case 'output_size': // some bugs persist forever... // some bugs persist forever... case 'ouput_size': $out[$var] = self::$outputSize; break; case 'execution_time': // This global var does not exist anymore in eZP LS 5.0. // We prefer using it when available as it is slightly more accurate if ($scriptStartTime == 0) { $debug = eZDebug::instance(); $scriptStartTime = $debug->ScriptStart; } $out[$var] = round(microtime(true) - $scriptStartTime, 3); break; case 'mem_usage': $out[$var] = round(memory_get_peak_usage(true), -3); break; case 'db_queries': // (nb: only works when debug is enabled. // Also does most likely not work when logging is done directly from the eZ5 stack /// @todo fix to run from eZ5 context $dbini = eZINI::instance(); // we cannot use $db->databasename() because we get the same for mysql and mysqli $type = preg_replace('/^ez/', '', $dbini->variable('DatabaseSettings', 'DatabaseImplementation')); $type .= '_query'; // read accumulator $debug = eZDebug::instance(); if (isset($debug->TimeAccumulatorList[$type])) { $queries = $debug->TimeAccumulatorList[$type]['count']; } else { // NB: to tell difference between 0 db reqs per page and no debug we could look for ezdebug::isenabled, // but what if it was enabled at some point and later disabled?... $queries = "0"; } $out[$var] = $queries; break; case 'xhkprof_runs': $out[$var] = implode(',', eZXHProfLogger::runs()); break; case 'user_id': $out[$var] = eZUser::currentUser()->attribute('contentobject_id'); break; case 'unique_id': $out[$var] = $_SERVER['UNIQUE_ID']; break; //case 'content/nodeid': // $out[$var] = self::$nodeId; // break; //case 'content/nodeid': // $out[$var] = self::$nodeId; // break; default: // wildcard-based naming: // content-info things, useful to help group/filter recorded data if (strpos($var, 'content_info/') === 0 || strpos($var, 'module_result/') === 0) { $out[$var] = self::getModuleResultData($var); break; } // standard accumulators /// @todo fix to run from eZ5 context if (strpos($var, 'accumulators/') === 0) { $parts = explode('/', $var, 3); $type = $parts[1]; $debug = eZDebug::instance(); if (isset($debug->TimeAccumulatorList[$type])) { if (@$parts[2] === 'count') { $out[$var] = $debug->TimeAccumulatorList[$type]['count']; } else { $out[$var] = round($debug->TimeAccumulatorList[$type]['time'], 3); } } else { $out[$var] = -1; } break; } // everything in $_SERVER if (strpos($var, '_server/') === 0) { $parts = explode('/', $var, 2); $val = @$_SERVER[$parts[1]]; $out[$var] = $val; break; } } } return $out; }
* * @author Changhao Jiang (cjiang@facebook.com) */ $ini = eZINI::instance('ezperformancelogger.ini'); $GLOBALS['dotcmd'] = $ini->variable('XHProfSettings', 'DotCommand'); // by default assume that xhprof_html & xhprof_lib directories // are at the same level. $GLOBALS['XHPROF_LIB_ROOT'] = __DIR__ . '/../../lib/xhprof'; include_once $GLOBALS['XHPROF_LIB_ROOT'] . '/display/xhprof.php'; ini_set('max_execution_time', 100); $params = array('run' => array(XHPROF_STRING_PARAM, ''), 'source' => array(XHPROF_STRING_PARAM, 'xhprof'), 'func' => array(XHPROF_STRING_PARAM, ''), 'type' => array(XHPROF_STRING_PARAM, 'png'), 'threshold' => array(XHPROF_FLOAT_PARAM, 0.01), 'critical' => array(XHPROF_BOOL_PARAM, true), 'run1' => array(XHPROF_STRING_PARAM, ''), 'run2' => array(XHPROF_STRING_PARAM, '')); // pull values of these params, and create named globals for each param xhprof_param_init($params); // if invalid value specified for threshold, then use the default if ($GLOBALS['threshold'] < 0 || $GLOBALS['threshold'] > 1) { $GLOBALS['threshold'] = $params['threshold'][1]; } // if invalid value specified for type, use the default if (!array_key_exists($GLOBALS['type'], $xhprof_legal_image_types)) { $GLOBALS['type'] = $params['type'][1]; // default image type. } $xhprof_runs_impl = new XHProfRuns_Default(eZXHProfLogger::logDir()); if (!empty($GLOBALS['run'])) { // single run call graph image generation xhprof_render_image($xhprof_runs_impl, $GLOBALS['run'], $GLOBALS['type'], $GLOBALS['threshold'], $GLOBALS['func'], $GLOBALS['source'], $GLOBALS['critical']); } else { // diff report call graph image generation xhprof_render_diff_image($xhprof_runs_impl, $GLOBALS['run1'], $GLOBALS['run2'], $GLOBALS['type'], $GLOBALS['threshold'], $GLOBALS['source']); } eZExecution::cleanExit();
<?php // This is a sample of php code which can be added at the start of your // config.php file to activate profiling with XHPROF. // Profiling of a web page will only be triggered when the url used to acces it // contains in the query string ?STARTXHPROF=1 // // NOTE: maybe it is not a good idea to use this code in production: you would be giving your end users the possibility to slow down // your site and fill your hard disk just by using a "hacked" url. // // Another useful workflow could be to enable profiling on 1 page every 100, using a random-variable test. // This way you would be able to get statistically useful data from real-life users while avoiding slowing down every sigle page if (isset($_GET['STARTXHPROF'])) { /// NB: php class autoloading is not yet set up at this point include 'extension/ezperformancelogger/classes/ezxhproflogger.php'; eZXHProfLogger::start(); }
<?php /** * @author Gaetano Giunta * @copyright (C) eZ Systems AS 2009-2016 * @license code licensed under the GPL License: see README */ $limit = 25; $offset = (int) $Params['Offset']; list($runsList, $count) = eZXHProfLogger::savedRuns($offset, $limit); $tpl = eZTemplate::factory(); $tpl->setVariable('runs_list', $runsList); $tpl->setVariable('limit', $limit); $tpl->setVariable('count', $count); $tpl->setVariable('view_parameters', array('offset' => $offset)); $Result['content'] = $tpl->fetch('design:xhprof/list.tpl'); $Result['path'] = array(array('text' => 'XHProf', 'url' => 'xhprof/list'));
<?php /** * @author G. Giunta * @copyright (C) eZ Systems AS 2012-2016 * @license Licensed under GNU General Public License v2.0. See file license.txt */ if (!$isQuiet) { $cli->output("Removing XHProf saved runs data..."); } eZXHProfLogger::removeSavedRuns(); if (!$isQuiet) { $cli->output("XHProf saved runs data removed"); }