| <?php |
|
|
| |
| |
| |
| |
| |
| |
|
|
| namespace Piwik\ArchiveProcessor; |
|
|
| use Piwik\ArchiveProcessor; |
| use Piwik\Container\StaticContainer; |
| use Piwik\CronArchive\Performance\Logger; |
| use Piwik\DataAccess\ArchiveWriter; |
| use Piwik\DataAccess\LogAggregator; |
| use Piwik\DataTable\Manager; |
| use Piwik\Metrics; |
| use Piwik\Piwik; |
| use Piwik\Plugin\Archiver; |
| use Piwik\Log; |
| use Piwik\Timer; |
| use Exception; |
|
|
| |
| |
| |
| |
| class PluginsArchiver |
| { |
| |
| |
| |
| private static $currentPluginBeingArchived = null; |
|
|
| |
| |
| |
| public $archiveProcessor; |
|
|
| |
| |
| |
| protected $params; |
|
|
| |
| |
| |
| private $logAggregator; |
|
|
| |
| |
| |
| |
| |
| public static $archivers = array(); |
|
|
| |
| |
| |
| |
| private $shouldAggregateFromRawData; |
|
|
| |
| |
| |
| private $archiveWriter; |
|
|
| public function __construct(Parameters $params, ?ArchiveWriter $archiveWriter = null) |
| { |
| $this->params = $params; |
| $this->archiveWriter = $archiveWriter ?: new ArchiveWriter($this->params); |
| $this->archiveWriter->initNewArchive(); |
|
|
| $this->logAggregator = new LogAggregator($params); |
| $this->logAggregator->allowUsageSegmentCache(); |
|
|
| $this->archiveProcessor = new ArchiveProcessor($this->params, $this->archiveWriter, $this->logAggregator); |
|
|
|
|
| $shouldAggregateFromRawData = $this->params->isSingleSiteDayArchive(); |
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| Piwik::postEvent('ArchiveProcessor.shouldAggregateFromRawData', array(&$shouldAggregateFromRawData, $this->params)); |
|
|
| $this->shouldAggregateFromRawData = $shouldAggregateFromRawData; |
| } |
|
|
| |
| |
| |
| |
| |
| public function callAggregateCoreMetrics() |
| { |
| $this->logAggregator->cleanup(); |
| $this->logAggregator->setQueryOriginHint('Core'); |
|
|
| if ($this->shouldAggregateFromRawData) { |
| $metrics = $this->aggregateDayVisitsMetrics(); |
| } else { |
| $metrics = $this->aggregateMultipleVisitsMetrics(); |
| } |
|
|
| if (empty($metrics)) { |
| return array( |
| 'nb_visits' => false, |
| 'nb_visits_converted' => false, |
| ); |
| } |
| return array( |
| 'nb_visits' => $metrics['nb_visits'], |
| 'nb_visits_converted' => $metrics['nb_visits_converted'], |
| ); |
| } |
|
|
| |
| |
| |
| |
| public function callAggregateAllPlugins($visits, $visitsConverted, $forceArchivingWithoutVisits = false) |
| { |
| Log::debug( |
| "PluginsArchiver::%s: Initializing archiving process for all plugins [visits = %s, visits converted = %s]", |
| __FUNCTION__, |
| $visits, |
| $visitsConverted |
| ); |
|
|
| |
| $performanceLogger = StaticContainer::get(Logger::class); |
|
|
| $this->archiveProcessor->setNumberOfVisits($visits, $visitsConverted); |
|
|
| $archivers = static::getPluginArchivers(); |
|
|
| $archiveOnlyPlugin = $this->params->getRequestedPlugin(); |
| $archiveOnlyReports = $this->params->getArchiveOnlyReport(); |
|
|
| foreach ($archivers as $pluginName => $archiverClass) { |
| |
| |
| |
| if ( |
| !empty($archiveOnlyReports) |
| && $archiveOnlyPlugin != $pluginName |
| ) { |
| continue; |
| } |
|
|
| |
| $latestUsedTableId = Manager::getInstance()->getMostRecentTableId(); |
|
|
| |
| $archiver = $this->makeNewArchiverObject($archiverClass, $pluginName); |
|
|
| if (!$archiver->isEnabled()) { |
| Log::debug("PluginsArchiver::%s: Skipping archiving for plugin '%s' (disabled).", __FUNCTION__, $pluginName); |
| continue; |
| } |
|
|
| if (!$forceArchivingWithoutVisits && !$visits && !$archiver->shouldRunEvenWhenNoVisits()) { |
| Log::debug("PluginsArchiver::%s: Skipping archiving for plugin '%s' (no visits).", __FUNCTION__, $pluginName); |
| continue; |
| } |
|
|
| if ($this->shouldProcessReportsForPlugin($pluginName)) { |
| $this->logAggregator->setQueryOriginHint($pluginName); |
|
|
| try { |
| self::$currentPluginBeingArchived = $pluginName; |
|
|
| $period = $this->params->getPeriod()->getLabel(); |
|
|
| $timer = new Timer(); |
| if ($this->shouldAggregateFromRawData) { |
| Log::debug("PluginsArchiver::%s: Archiving $period reports for plugin '%s' from raw data.", __FUNCTION__, $pluginName); |
|
|
| $archiver->callAggregateDayReport(); |
| } else { |
| Log::debug("PluginsArchiver::%s: Archiving $period reports for plugin '%s' using reports for smaller periods.", __FUNCTION__, $pluginName); |
|
|
| $archiver->callAggregateMultipleReports(); |
| } |
|
|
| $this->logAggregator->setQueryOriginHint(''); |
|
|
| $performanceLogger->logMeasurement('plugin', $pluginName, $this->params, $timer); |
|
|
| Log::debug( |
| "PluginsArchiver::%s: %s while archiving %s reports for plugin '%s' %s.", |
| __FUNCTION__, |
| $timer->getMemoryLeak(), |
| $this->params->getPeriod()->getLabel(), |
| $pluginName, |
| $this->params->getSegment() ? sprintf("(for segment = '%s')", $this->params->getSegment()->getString()) : '' |
| ); |
| } catch (Exception $e) { |
| throw new PluginsArchiverException($e->getMessage() . " - in plugin $pluginName.", $e->getCode(), $e); |
| } finally { |
| self::$currentPluginBeingArchived = null; |
| } |
| } else { |
| Log::debug("PluginsArchiver::%s: Not archiving reports for plugin '%s'.", __FUNCTION__, $pluginName); |
| } |
|
|
| Manager::getInstance()->deleteAll($latestUsedTableId); |
| unset($archiver); |
| } |
|
|
| $this->logAggregator->cleanup(); |
| } |
|
|
| public function finalizeArchive() |
| { |
| $this->params->logStatusDebug(); |
| $this->archiveWriter->finalizeArchive(); |
| $idArchive = $this->archiveWriter->getIdArchive(); |
|
|
| return $idArchive; |
| } |
|
|
| |
| |
| |
| public static function doesAnyPluginArchiveWithoutVisits() |
| { |
| $archivers = static::getPluginArchivers(); |
|
|
| foreach ($archivers as $pluginName => $archiverClass) { |
| if ($archiverClass::shouldRunEvenWhenNoVisits()) { |
| return true; |
| } |
| } |
|
|
| return false; |
| } |
|
|
| |
| |
| |
| |
| |
| protected static function getPluginArchivers() |
| { |
| if (empty(static::$archivers)) { |
| $pluginNames = \Piwik\Plugin\Manager::getInstance()->getActivatedPlugins(); |
| $archivers = array(); |
| foreach ($pluginNames as $pluginName) { |
| $archivers[$pluginName] = self::getPluginArchiverClass($pluginName); |
| } |
| static::$archivers = array_filter($archivers); |
| } |
| return static::$archivers; |
| } |
|
|
| private static function getPluginArchiverClass(string $pluginName): ?string |
| { |
| $klassName = 'Piwik\\Plugins\\' . $pluginName . '\\Archiver'; |
| if ( |
| class_exists($klassName) |
| && is_subclass_of($klassName, 'Piwik\\Plugin\\Archiver') |
| ) { |
| return $klassName; |
| } |
| if (Archiver::doesPluginHaveRecordBuilders($pluginName)) { |
| return Archiver::class; |
| } |
| return null; |
| } |
|
|
| |
| |
| |
| |
| |
| protected function shouldProcessReportsForPlugin($pluginName) |
| { |
| if ($this->params->getRequestedPlugin() == $pluginName) { |
| return true; |
| } |
|
|
| if ($this->params->shouldOnlyArchiveRequestedPlugin()) { |
| return false; |
| } |
|
|
| if ( |
| Rules::shouldProcessReportsAllPlugins( |
| [$this->params->getSite()->getId()], |
| $this->params->getSegment(), |
| $this->params->getPeriod()->getLabel() |
| ) |
| ) { |
| return true; |
| } |
|
|
| if ( |
| $this->params->getRequestedPlugin() && |
| !\Piwik\Plugin\Manager::getInstance()->isPluginLoaded($this->params->getRequestedPlugin()) |
| ) { |
| return false; |
| } |
|
|
| return false; |
| } |
|
|
| protected function aggregateDayVisitsMetrics() |
| { |
| $query = $this->archiveProcessor->getLogAggregator()->queryVisitsByDimension(); |
| $data = $query->fetch(); |
|
|
| $metrics = $this->convertMetricsIdToName($data); |
| $this->archiveProcessor->insertNumericRecords($metrics); |
| return $metrics; |
| } |
|
|
| protected function convertMetricsIdToName($data) |
| { |
| $metrics = array(); |
| foreach ($data as $metricId => $value) { |
| $readableMetric = Metrics::$mappingFromIdToName[$metricId]; |
| $metrics[$readableMetric] = $value; |
| } |
| return $metrics; |
| } |
|
|
| protected function aggregateMultipleVisitsMetrics() |
| { |
| $toSum = Metrics::getVisitsMetricNames(); |
| $metrics = $this->archiveProcessor->aggregateNumericMetrics($toSum); |
| return $metrics; |
| } |
|
|
|
|
| |
| |
| |
| |
| |
| private function makeNewArchiverObject($archiverClass, $pluginName) |
| { |
| if ($archiverClass === Archiver::class) { |
| $archiver = new Archiver($this->archiveProcessor, $pluginName); |
| } else { |
| $archiver = new $archiverClass($this->archiveProcessor); |
| } |
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| Piwik::postEvent('Archiving.makeNewArchiverObject', array($archiver, $pluginName, $this->params, false)); |
|
|
| return $archiver; |
| } |
|
|
| public static function isArchivingProcessActive() |
| { |
| return self::$currentPluginBeingArchived !== null; |
| } |
| } |
|
|