/** * Initializes Profiling via XHProf. * See: https://github.com/piwik/piwik/blob/master/tests/README.xhprof.md */ public static function setupProfilerXHProf($mainRun = false, $setupDuringTracking = false) { if (!$setupDuringTracking && SettingsServer::isTrackerApiRequest()) { // do not profile Tracker return; } if (self::$isXhprofSetup) { return; } $xhProfPath = PIWIK_INCLUDE_PATH . '/vendor/facebook/xhprof/extension/modules/xhprof.so'; if (!file_exists($xhProfPath)) { throw new Exception("Cannot find xhprof, run 'composer install --dev' and build the extension."); } if (!function_exists('xhprof_enable')) { throw new Exception("Cannot find xhprof_enable, make sure to add 'extension={$xhProfPath}' to your php.ini."); } $outputDir = ini_get("xhprof.output_dir"); if (empty($outputDir)) { throw new Exception("The profiler output dir is not set. Add 'xhprof.output_dir=...' to your php.ini."); } if (!is_writable($outputDir)) { throw new Exception("The profiler output dir '" . ini_get("xhprof.output_dir") . "' should exist and be writable."); } if (!function_exists('xhprof_error')) { function xhprof_error($out) { echo substr($out, 0, 300) . '...'; } } $currentGitBranch = SettingsPiwik::getCurrentGitBranch(); $profilerNamespace = "piwik"; if ($currentGitBranch != 'master') { $profilerNamespace .= "-" . $currentGitBranch; } if ($mainRun) { self::setProfilingRunIds(array()); } xhprof_enable(XHPROF_FLAGS_CPU + XHPROF_FLAGS_MEMORY); register_shutdown_function(function () use($profilerNamespace, $mainRun) { $xhprofData = xhprof_disable(); $xhprofRuns = new XHProfRuns_Default(); $runId = $xhprofRuns->save_run($xhprofData, $profilerNamespace); if (empty($runId)) { die('could not write profiler run'); } $runs = Profiler::getProfilingRunIds(); array_unshift($runs, $runId); if ($mainRun) { Profiler::aggregateXhprofRuns($runs, $profilerNamespace, $saveTo = $runId); $baseUrlStored = SettingsPiwik::getPiwikUrl(); $out = "\n\n"; $baseUrl = "http://" . @$_SERVER['HTTP_HOST'] . "/" . @$_SERVER['REQUEST_URI']; if (strlen($baseUrlStored) > strlen($baseUrl)) { $baseUrl = $baseUrlStored; } $baseUrl = $baseUrlStored . "vendor/facebook/xhprof/xhprof_html/?source={$profilerNamespace}&run={$runId}"; $out .= "Profiler report is available at:\n"; $out .= "<a href='{$baseUrl}'>{$baseUrl}</a>"; $out .= "\n\n"; if (Development::isEnabled()) { $out .= "WARNING: Development mode is enabled. Many runtime optimizations are not applied in development mode. "; $out .= "Unless you intend to profile Piwik in development mode, your profile may not be accurate."; $out .= "\n\n"; } echo $out; } else { Profiler::setProfilingRunIds($runs); } }); self::$isXhprofSetup = true; }