diff options
author | diosmosis <diosmosis@users.noreply.github.com> | 2018-08-01 00:48:07 +0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-08-01 00:48:07 +0300 |
commit | 6cb6548c19a93b3c9c173d6bb9c1a9f68835f252 (patch) | |
tree | ba39c77ddd6cd53f19cfd26e8fa5e8605f391b3d /core/CronArchive | |
parent | 8210ff8e201f9635dbdc2e9bde63c11f169fbd83 (diff) |
Add some simple profiling output to core:archive command (#13215)
* Initial code to gather performance measurements across processes.
* Get proof of concept to work.
* couple tweaks
* Modified to use a custom log file instead of option table.
* add peak memory value
Diffstat (limited to 'core/CronArchive')
-rw-r--r-- | core/CronArchive/Performance/Logger.php | 119 | ||||
-rw-r--r-- | core/CronArchive/Performance/Measurement.php | 165 |
2 files changed, 284 insertions, 0 deletions
diff --git a/core/CronArchive/Performance/Logger.php b/core/CronArchive/Performance/Logger.php new file mode 100644 index 0000000000..8de01364f9 --- /dev/null +++ b/core/CronArchive/Performance/Logger.php @@ -0,0 +1,119 @@ +<?php +/** + * Piwik - free/libre analytics platform + * + * @link http://piwik.org + * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later + */ + +namespace Piwik\CronArchive\Performance; + +use Piwik\ArchiveProcessor; +use Piwik\Common; +use Piwik\Config; +use Piwik\Option; +use Piwik\Timer; +use Piwik\Url; +use Psr\Log\LoggerInterface; + +class Logger +{ + /** + * @var int + */ + private $isEnabled; + + /** + * @var LoggerInterface + */ + private $logger; + + /** + * @var int + */ + private $archivingRunId; + + public function __construct(Config $config, LoggerInterface $logger = null) + { + $this->isEnabled = $config->Debug['archiving_profile'] == 1; + $this->logger = $logger; + + $this->archivingRunId = $this->getArchivingRunId(); + if (empty($this->archivingRunId)) { + $this->isEnabled = false; + } + } + + public function logMeasurement($category, $name, ArchiveProcessor\Parameters $activeArchivingParams, Timer $timer) + { + if (!$this->isEnabled || !$this->logger) { + return; + } + + $measurement = new Measurement($category, $name, $activeArchivingParams->getSite()->getId(), + $activeArchivingParams->getPeriod()->getRangeString(), $activeArchivingParams->getPeriod()->getLabel(), + $activeArchivingParams->getSegment()->getString(), $timer->getTime(), $timer->getMemoryLeakValue(), + $timer->getPeakMemoryValue()); + + $params = array_merge($_GET); + unset($params['pid']); + unset($params['runid']); + + $this->logger->info("[runid={runid},pid={pid}] {request}: {measurement}", [ + 'pid' => Common::getRequestVar('pid', false), + 'runid' => $this->getArchivingRunId(), + 'request' => Url::getQueryStringFromParameters($params), + 'measurement' => $measurement, + ]); + } + + public static function getMeasurementsFor($runId, $childPid) + { + $profilingLogFile = preg_replace('/[\'"]/', '', Config::getInstance()->Debug['archive_profiling_log']); + if (!is_readable($profilingLogFile)) { + return []; + } + + $runId = self::cleanId($runId); + $childPid = self::cleanId($childPid); + + $lineIdentifier = "[runid=$runId,pid=$childPid]"; + $lines = `grep "$childPid" "$profilingLogFile"`; + $lines = explode("\n", $lines); + $lines = array_map(function ($line) use ($lineIdentifier) { + $index = strpos($line, $lineIdentifier); + if ($index === false) { + return null; + } + $line = substr($line, $index + strlen($lineIdentifier)); + return trim($line); + }, $lines); + $lines = array_filter($lines); + $lines = array_map(function ($line) { + $parts = explode(":", $line, 2); + $parts = array_map('trim', $parts); + return $parts; + }, $lines); + + $data = []; + foreach ($lines as $line) { + if (count($line) != 2) { + continue; + } + + list($request, $measurement) = $line; + $data[$request][] = $measurement; + } + return $data; + } + + private function getArchivingRunId() + { + return Common::getRequestVar('runid', false); + } + + private static function cleanId($id) + { + return preg_replace('/[^a-zA-Z0-9_-]/', '', $id); + } +} diff --git a/core/CronArchive/Performance/Measurement.php b/core/CronArchive/Performance/Measurement.php new file mode 100644 index 0000000000..9405e7ffbc --- /dev/null +++ b/core/CronArchive/Performance/Measurement.php @@ -0,0 +1,165 @@ +<?php +/** + * Piwik - free/libre analytics platform + * + * @link http://piwik.org + * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later + */ + +namespace Piwik\CronArchive\Performance; + +class Measurement +{ + /** + * @var string + */ + private $category; + + /** + * @var string + */ + private $measuredName; + + /** + * @var string + */ + private $idSite; + + /** + * @var string + */ + private $dateRange; + + /** + * @var string + */ + private $periodType; + + /** + * @var string + */ + private $segment; + + /** + * @var float + */ + private $time; + + /** + * @var string + */ + private $memory; + + /** + * @var string + */ + private $peakMemory; + + public function __construct($category, $name, $idSite, $dateRange, $periodType, $segment, $time, $memory, $peakMemory) + { + $this->category = $category; + $this->measuredName = $name; + $this->idSite = $idSite; + $this->dateRange = $dateRange; + $this->periodType = $periodType; + $this->segment = trim($segment); + $this->time = $time; + $this->memory = $memory; + $this->peakMemory = $peakMemory; + } + + public function __toString() + { + $parts = [ + ucfirst($this->category) . ": {$this->measuredName}", + "idSite: {$this->idSite}", + "period: {$this->periodType} ({$this->dateRange})", + "segment: " . (!empty($this->segment) ? $this->segment : 'none'), + "duration: {$this->time}s", + "memory leak: {$this->memory}", + "peak memory usage: {$this->peakMemory}", + ]; + + return implode(', ', $parts); + } + + /** + * @return string + */ + public function getCategory() + { + return $this->category; + } + + /** + * @param string $category + */ + public function setCategory($category) + { + $this->category = $category; + } + + /** + * @return string + */ + public function getMeasuredName() + { + return $this->measuredName; + } + + /** + * @param string $measuredName + */ + public function setMeasuredName($measuredName) + { + $this->measuredName = $measuredName; + } + + /** + * @return string + */ + public function getIdSite() + { + return $this->idSite; + } + + /** + * @param string $idSite + */ + public function setIdSite($idSite) + { + $this->idSite = $idSite; + } + + /** + * @return string + */ + public function getDateRange() + { + return $this->dateRange; + } + + /** + * @param string $dateRange + */ + public function setDateRange($dateRange) + { + $this->dateRange = $dateRange; + } + + /** + * @return string + */ + public function getPeriodType() + { + return $this->periodType; + } + + /** + * @param string $periodType + */ + public function setPeriodType($periodType) + { + $this->periodType = $periodType; + } +}
\ No newline at end of file |