add piwik installation
This commit is contained in:
parent
90aa4ef157
commit
8c5d4f0c31
3197 changed files with 563902 additions and 0 deletions
304
www/analytics/core/ArchiveProcessor/Rules.php
Normal file
304
www/analytics/core/ArchiveProcessor/Rules.php
Normal file
|
|
@ -0,0 +1,304 @@
|
|||
<?php
|
||||
/**
|
||||
* Piwik - Open source web analytics
|
||||
*
|
||||
* @link http://piwik.org
|
||||
* @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
|
||||
*
|
||||
*/
|
||||
namespace Piwik\ArchiveProcessor;
|
||||
|
||||
use Exception;
|
||||
use Piwik\Common;
|
||||
use Piwik\Config;
|
||||
use Piwik\Date;
|
||||
use Piwik\Log;
|
||||
use Piwik\Option;
|
||||
use Piwik\Piwik;
|
||||
use Piwik\Plugins\CoreAdminHome\Controller;
|
||||
use Piwik\Plugins\CoreAdminHome\CoreAdminHome;
|
||||
use Piwik\Segment;
|
||||
use Piwik\SettingsPiwik;
|
||||
use Piwik\SettingsServer;
|
||||
use Piwik\Site;
|
||||
use Piwik\Tracker\Cache;
|
||||
|
||||
/**
|
||||
* This class contains Archiving rules/logic which are used when creating and processing Archives.
|
||||
*
|
||||
*/
|
||||
class Rules
|
||||
{
|
||||
const OPTION_TODAY_ARCHIVE_TTL = 'todayArchiveTimeToLive';
|
||||
|
||||
const OPTION_BROWSER_TRIGGER_ARCHIVING = 'enableBrowserTriggerArchiving';
|
||||
|
||||
const FLAG_TABLE_PURGED = 'lastPurge_';
|
||||
|
||||
/** Old Archives purge can be disabled (used in tests only) */
|
||||
static public $purgeDisabledByTests = false;
|
||||
|
||||
/** Flag that will forcefully disable the archiving process (used in tests only) */
|
||||
public static $archivingDisabledByTests = false;
|
||||
|
||||
/**
|
||||
* Returns the name of the archive field used to tell the status of an archive, (ie,
|
||||
* whether the archive was created successfully or not).
|
||||
*
|
||||
* @param Segment $segment
|
||||
* @param string $periodLabel
|
||||
* @param string $plugin
|
||||
* @return string
|
||||
*/
|
||||
public static function getDoneStringFlagFor(array $idSites, $segment, $periodLabel, $plugin, $isSkipAggregationOfSubTables)
|
||||
{
|
||||
if (!self::shouldProcessReportsAllPlugins($idSites, $segment, $periodLabel)) {
|
||||
return self::getDoneFlagArchiveContainsOnePlugin($segment, $plugin, $isSkipAggregationOfSubTables);
|
||||
}
|
||||
return self::getDoneFlagArchiveContainsAllPlugins($segment);
|
||||
}
|
||||
|
||||
public static function shouldProcessReportsAllPlugins(array $idSites, Segment $segment, $periodLabel)
|
||||
{
|
||||
if ($segment->isEmpty() && $periodLabel != 'range') {
|
||||
return true;
|
||||
}
|
||||
|
||||
return self::isSegmentPreProcessed($idSites, $segment);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $idSites
|
||||
* @return array
|
||||
*/
|
||||
private static function getSegmentsToProcess($idSites)
|
||||
{
|
||||
$knownSegmentsToArchiveAllSites = SettingsPiwik::getKnownSegmentsToArchive();
|
||||
|
||||
$segmentsToProcess = $knownSegmentsToArchiveAllSites;
|
||||
foreach ($idSites as $idSite) {
|
||||
$segmentForThisWebsite = SettingsPiwik::getKnownSegmentsToArchiveForSite($idSite);
|
||||
$segmentsToProcess = array_merge($segmentsToProcess, $segmentForThisWebsite);
|
||||
}
|
||||
$segmentsToProcess = array_unique($segmentsToProcess);
|
||||
return $segmentsToProcess;
|
||||
}
|
||||
|
||||
public static function getDoneFlagArchiveContainsOnePlugin(Segment $segment, $plugin, $isSkipAggregationOfSubTables = false)
|
||||
{
|
||||
$partial = self::isFlagArchivePartial($plugin, $isSkipAggregationOfSubTables);
|
||||
return 'done' . $segment->getHash() . '.' . $plugin . $partial ;
|
||||
}
|
||||
|
||||
private static function getDoneFlagArchiveContainsAllPlugins(Segment $segment)
|
||||
{
|
||||
return 'done' . $segment->getHash();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $plugin
|
||||
* @param $isSkipAggregationOfSubTables
|
||||
* @return string
|
||||
*/
|
||||
private static function isFlagArchivePartial($plugin, $isSkipAggregationOfSubTables)
|
||||
{
|
||||
$partialArchive = '';
|
||||
if ($plugin != "VisitsSummary" // VisitsSummary is always called when segmenting and should not have its own .partial archive
|
||||
&& $isSkipAggregationOfSubTables
|
||||
) {
|
||||
$partialArchive = '.partial';
|
||||
}
|
||||
return $partialArchive;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $plugins
|
||||
* @param $segment
|
||||
* @return array
|
||||
*/
|
||||
public static function getDoneFlags(array $plugins, Segment $segment, $isSkipAggregationOfSubTables)
|
||||
{
|
||||
$doneFlags = array();
|
||||
$doneAllPlugins = self::getDoneFlagArchiveContainsAllPlugins($segment);
|
||||
$doneFlags[$doneAllPlugins] = $doneAllPlugins;
|
||||
|
||||
$plugins = array_unique($plugins);
|
||||
foreach ($plugins as $plugin) {
|
||||
$doneOnePlugin = self::getDoneFlagArchiveContainsOnePlugin($segment, $plugin, $isSkipAggregationOfSubTables);
|
||||
$doneFlags[$plugin] = $doneOnePlugin;
|
||||
}
|
||||
return $doneFlags;
|
||||
}
|
||||
|
||||
/**
|
||||
* Given a monthly archive table, will delete all reports that are now outdated,
|
||||
* or reports that ended with an error
|
||||
*
|
||||
* @param \Piwik\Date $date
|
||||
* @return int|bool False, or timestamp indicating which archives to delete
|
||||
*/
|
||||
public static function shouldPurgeOutdatedArchives(Date $date)
|
||||
{
|
||||
if (self::$purgeDisabledByTests) {
|
||||
return false;
|
||||
}
|
||||
$key = self::FLAG_TABLE_PURGED . "blob_" . $date->toString('Y_m');
|
||||
$timestamp = Option::get($key);
|
||||
|
||||
// we shall purge temporary archives after their timeout is finished, plus an extra 6 hours
|
||||
// in case archiving is disabled or run once a day, we give it this extra time to run
|
||||
// and re-process more recent records...
|
||||
$temporaryArchivingTimeout = self::getTodayArchiveTimeToLive();
|
||||
$hoursBetweenPurge = 6;
|
||||
$purgeEveryNSeconds = max($temporaryArchivingTimeout, $hoursBetweenPurge * 3600);
|
||||
|
||||
// we only delete archives if we are able to process them, otherwise, the browser might process reports
|
||||
// when &segment= is specified (or custom date range) and would below, delete temporary archives that the
|
||||
// browser is not able to process until next cron run (which could be more than 1 hour away)
|
||||
if (self::isRequestAuthorizedToArchive()
|
||||
&& (!$timestamp
|
||||
|| $timestamp < time() - $purgeEveryNSeconds)
|
||||
) {
|
||||
Option::set($key, time());
|
||||
|
||||
if (self::isBrowserTriggerEnabled()) {
|
||||
// If Browser Archiving is enabled, it is likely there are many more temporary archives
|
||||
// We delete more often which is safe, since reports are re-processed on demand
|
||||
$purgeArchivesOlderThan = Date::factory(time() - 2 * $temporaryArchivingTimeout)->getDateTime();
|
||||
} else {
|
||||
// If archive.php via Cron is building the reports, we should keep all temporary reports from today
|
||||
$purgeArchivesOlderThan = Date::factory('today')->getDateTime();
|
||||
}
|
||||
return $purgeArchivesOlderThan;
|
||||
}
|
||||
|
||||
Log::info("Purging temporary archives: skipped.");
|
||||
return false;
|
||||
}
|
||||
|
||||
public static function getMinTimeProcessedForTemporaryArchive(
|
||||
Date $dateStart, \Piwik\Period $period, Segment $segment, Site $site)
|
||||
{
|
||||
$now = time();
|
||||
$minimumArchiveTime = $now - Rules::getTodayArchiveTimeToLive();
|
||||
|
||||
$idSites = array($site->getId());
|
||||
$isArchivingDisabled = Rules::isArchivingDisabledFor($idSites, $segment, $period->getLabel());
|
||||
if ($isArchivingDisabled) {
|
||||
if ($period->getNumberOfSubperiods() == 0
|
||||
&& $dateStart->getTimestamp() <= $now
|
||||
) {
|
||||
// Today: accept any recent enough archive
|
||||
$minimumArchiveTime = false;
|
||||
} else {
|
||||
// This week, this month, this year:
|
||||
// accept any archive that was processed today after 00:00:01 this morning
|
||||
$timezone = $site->getTimezone();
|
||||
$minimumArchiveTime = Date::factory(Date::factory('now', $timezone)->getDateStartUTC())->setTimezone($timezone)->getTimestamp();
|
||||
}
|
||||
}
|
||||
return $minimumArchiveTime;
|
||||
}
|
||||
|
||||
public static function setTodayArchiveTimeToLive($timeToLiveSeconds)
|
||||
{
|
||||
$timeToLiveSeconds = (int)$timeToLiveSeconds;
|
||||
if ($timeToLiveSeconds <= 0) {
|
||||
throw new Exception(Piwik::translate('General_ExceptionInvalidArchiveTimeToLive'));
|
||||
}
|
||||
Option::set(self::OPTION_TODAY_ARCHIVE_TTL, $timeToLiveSeconds, $autoLoad = true);
|
||||
}
|
||||
|
||||
public static function getTodayArchiveTimeToLive()
|
||||
{
|
||||
$uiSettingIsEnabled = Controller::isGeneralSettingsAdminEnabled();
|
||||
|
||||
if($uiSettingIsEnabled) {
|
||||
$timeToLive = Option::get(self::OPTION_TODAY_ARCHIVE_TTL);
|
||||
if ($timeToLive !== false) {
|
||||
return $timeToLive;
|
||||
}
|
||||
}
|
||||
return Config::getInstance()->General['time_before_today_archive_considered_outdated'];
|
||||
}
|
||||
|
||||
public static function isArchivingDisabledFor(array $idSites, Segment $segment, $periodLabel)
|
||||
{
|
||||
if ($periodLabel == 'range') {
|
||||
return false;
|
||||
}
|
||||
$processOneReportOnly = !self::shouldProcessReportsAllPlugins($idSites, $segment, $periodLabel);
|
||||
$isArchivingDisabled = !self::isRequestAuthorizedToArchive() || self::$archivingDisabledByTests;
|
||||
|
||||
if ($processOneReportOnly) {
|
||||
|
||||
// When there is a segment, we disable archiving when browser_archiving_disabled_enforce applies
|
||||
if (!$segment->isEmpty()
|
||||
&& $isArchivingDisabled
|
||||
&& Config::getInstance()->General['browser_archiving_disabled_enforce']
|
||||
&& !SettingsServer::isArchivePhpTriggered() // Only applies when we are not running archive.php
|
||||
) {
|
||||
Log::debug("Archiving is disabled because of config setting browser_archiving_disabled_enforce=1");
|
||||
return true;
|
||||
}
|
||||
|
||||
// Always allow processing one report
|
||||
return false;
|
||||
}
|
||||
return $isArchivingDisabled;
|
||||
}
|
||||
|
||||
protected static function isRequestAuthorizedToArchive()
|
||||
{
|
||||
return Rules::isBrowserTriggerEnabled() || SettingsServer::isArchivePhpTriggered();
|
||||
}
|
||||
|
||||
public static function isBrowserTriggerEnabled()
|
||||
{
|
||||
$uiSettingIsEnabled = Controller::isGeneralSettingsAdminEnabled();
|
||||
|
||||
if($uiSettingIsEnabled) {
|
||||
$browserArchivingEnabled = Option::get(self::OPTION_BROWSER_TRIGGER_ARCHIVING);
|
||||
if ($browserArchivingEnabled !== false) {
|
||||
return (bool)$browserArchivingEnabled;
|
||||
}
|
||||
}
|
||||
return (bool)Config::getInstance()->General['enable_browser_archiving_triggering'];
|
||||
}
|
||||
|
||||
public static function setBrowserTriggerArchiving($enabled)
|
||||
{
|
||||
if (!is_bool($enabled)) {
|
||||
throw new Exception('Browser trigger archiving must be set to true or false.');
|
||||
}
|
||||
Option::set(self::OPTION_BROWSER_TRIGGER_ARCHIVING, (int)$enabled, $autoLoad = true);
|
||||
Cache::clearCacheGeneral();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $idSites
|
||||
* @param Segment $segment
|
||||
* @return bool
|
||||
*/
|
||||
protected static function isSegmentPreProcessed(array $idSites, Segment $segment)
|
||||
{
|
||||
$segmentsToProcess = self::getSegmentsToProcess($idSites);
|
||||
|
||||
if (empty($segmentsToProcess)) {
|
||||
return false;
|
||||
}
|
||||
// If the requested segment is one of the segments to pre-process
|
||||
// we ensure that any call to the API will trigger archiving of all reports for this segment
|
||||
$segment = $segment->getString();
|
||||
|
||||
// Turns out the getString() above returns the URL decoded segment string
|
||||
$segmentsToProcessUrlDecoded = array_map('urldecode', $segmentsToProcess);
|
||||
|
||||
if (in_array($segment, $segmentsToProcess)
|
||||
|| in_array($segment, $segmentsToProcessUrlDecoded)
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue