Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/matomo-org/matomo.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStefan Giehl <stefan@matomo.org>2020-03-15 22:35:27 +0300
committerGitHub <noreply@github.com>2020-03-15 22:35:27 +0300
commitc7dc542e63645f57886d49fc288b792ee60785d0 (patch)
treecc79c3f7e74281c3229bbd7417fe6d618cb854a6 /plugins
parent7b053e85b5b037619dbee4fbcf3e7a9ca2bf8589 (diff)
respect max execution time limit for transitions plugin (#15652)
Diffstat (limited to 'plugins')
-rw-r--r--plugins/Live/Model.php89
-rw-r--r--plugins/Live/tests/Integration/ModelTest.php11
-rw-r--r--plugins/Transitions/API.php58
3 files changed, 77 insertions, 81 deletions
diff --git a/plugins/Live/Model.php b/plugins/Live/Model.php
index 89c32d2b12..fe167fcf33 100644
--- a/plugins/Live/Model.php
+++ b/plugins/Live/Model.php
@@ -16,6 +16,7 @@ use Piwik\Config;
use Piwik\Container\StaticContainer;
use Piwik\Date;
use Piwik\Db;
+use Piwik\DbHelper;
use Piwik\Period;
use Piwik\Period\Range;
use Piwik\Piwik;
@@ -121,7 +122,7 @@ class Model
try {
$visits = $readerDb->fetchAll($sql, $bind);
} catch (Exception $e) {
- $this->handleMaxExecutionTimeError($readerDb, $e, $sql, $bind, $segment, $dateStart, $dateEnd, $minTimestamp, $limit);
+ $this->handleMaxExecutionTimeError($readerDb, $e, $segment, $dateStart, $dateEnd, $minTimestamp, $limit, ['sql' => $sql, 'bind' => $bind,]);
throw $e;
}
return $visits;
@@ -130,17 +131,16 @@ class Model
/**
* @param \Piwik\Tracker\Db|\Piwik\Db\AdapterInterface|\Piwik\Db $readerDb
* @param Exception $e
- * @param $sql
- * @param array $bind
* @param $segment
* @param $dateStart
* @param $dateEnd
* @param $minTimestamp
* @param $limit
+ * @param $parameters
*
* @throws MaxExecutionTimeExceededException
*/
- public function handleMaxExecutionTimeError($readerDb, $e, $sql, $bind, $segment, $dateStart, $dateEnd, $minTimestamp, $limit)
+ public static function handleMaxExecutionTimeError($readerDb, $e, $segment, $dateStart, $dateEnd, $minTimestamp, $limit, $parameters)
{
// we also need to check for the 'maximum statement execution time exceeded' text as the query might be
// aborted at different stages and we can't really know all the possible codes at which it may be aborted etc
@@ -148,39 +148,41 @@ class Model
|| $readerDb->isErrNo($e, DbMigration::ERROR_CODE_MAX_EXECUTION_TIME_EXCEEDED_SORT_ABORTED)
|| strpos($e->getMessage(), 'maximum statement execution time exceeded') !== false;
- if ($isMaxExecutionTimeError) {
- $message = '';
+ if (false === $isMaxExecutionTimeError) {
+ return;
+ }
+
+ $message = '';
- if ($this->isLookingAtMoreThanOneDay($dateStart, $dateEnd, $minTimestamp)) {
- $message .= ' ' . Piwik::translate('Live_QueryMaxExecutionTimeExceededReasonDateRange');
- }
+ if (self::isLookingAtMoreThanOneDay($dateStart, $dateEnd, $minTimestamp)) {
+ $message .= ' ' . Piwik::translate('Live_QueryMaxExecutionTimeExceededReasonDateRange');
+ }
- if (!empty($segment)) {
- $message .= ' ' . Piwik::translate('Live_QueryMaxExecutionTimeExceededReasonSegment');
- }
+ if (!empty($segment)) {
+ $message .= ' ' . Piwik::translate('Live_QueryMaxExecutionTimeExceededReasonSegment');
+ }
- $limitThatCannotBeSelectedInUiButOnlyApi = 550;
- if ($limit > $limitThatCannotBeSelectedInUiButOnlyApi) {
- $message .= ' ' . Piwik::translate('Live_QueryMaxExecutionTimeExceededLimit');
- }
+ $limitThatCannotBeSelectedInUiButOnlyApi = 550;
+ if ($limit > $limitThatCannotBeSelectedInUiButOnlyApi) {
+ $message .= ' ' . Piwik::translate('Live_QueryMaxExecutionTimeExceededLimit');
+ }
- if (empty($message)) {
- $message .= ' ' . Piwik::translate('Live_QueryMaxExecutionTimeExceededReasonUnknown');
- }
+ if (empty($message)) {
+ $message .= ' ' . Piwik::translate('Live_QueryMaxExecutionTimeExceededReasonUnknown');
+ }
- $message = Piwik::translate('Live_QueryMaxExecutionTimeExceeded') . ' ' . $message;
+ $message = Piwik::translate('Live_QueryMaxExecutionTimeExceeded') . ' ' . $message;
- $params = array(
- 'sql' => $sql, 'bind' => $bind, 'segment' => $segment, 'limit' => $limit
- );
+ $params = array_merge($parameters, [
+ 'segment' => $segment, 'limit' => $limit
+ ]);
- /**
- * @ignore
- * @internal
- */
- Piwik::postEvent('Live.queryMaxExecutionTimeExceeded', array($params));
- throw new MaxExecutionTimeExceededException($message);
- }
+ /**
+ * @ignore
+ * @internal
+ */
+ Piwik::postEvent('Live.queryMaxExecutionTimeExceeded', array($params));
+ throw new MaxExecutionTimeExceededException($message);
}
/**
@@ -190,7 +192,7 @@ class Model
* @return bool
* @throws Exception
*/
- public function isLookingAtMoreThanOneDay($dateStart, $dateEnd, $minTimestamp)
+ public static function isLookingAtMoreThanOneDay($dateStart, $dateEnd, $minTimestamp)
{
if (!$dateStart) {
if (!$minTimestamp) {
@@ -493,35 +495,14 @@ class Model
$bind = $innerQuery['bind'];
- $maxExecutionTimeHint = $this->getMaxExecutionTimeMySQLHint();
- if ($visitorId) {
+ if (!$visitorId) {
// for now let's not apply when looking for a specific visitor
- $maxExecutionTimeHint = '';
- }
- if ($maxExecutionTimeHint) {
- $innerQuery['sql'] = trim($innerQuery['sql']);
- $pos = stripos($innerQuery['sql'], 'SELECT');
- if ($pos !== false) {
- $innerQuery['sql'] = substr_replace($innerQuery['sql'], 'SELECT ' . $maxExecutionTimeHint, $pos, strlen('SELECT'));
- }
+ $innerQuery['sql'] = DbHelper::addMaxExecutionTimeHintToQuery($innerQuery['sql'], Config::getInstance()->General['live_query_max_execution_time']);
}
return array($innerQuery['sql'], $bind);
}
- private function getMaxExecutionTimeMySQLHint()
- {
- $general = Config::getInstance()->General;
- $maxExecutionTime = $general['live_query_max_execution_time'];
- $maxExecutionTimeHint = '';
- if (is_numeric($maxExecutionTime) && $maxExecutionTime > 0) {
- $timeInMs = $maxExecutionTime * 1000;
- $timeInMs = (int) $timeInMs;
- $maxExecutionTimeHint = ' /*+ MAX_EXECUTION_TIME('.$timeInMs.') */ ';
- }
- return $maxExecutionTimeHint;
- }
-
/**
* @param $idSite
* @return Site
diff --git a/plugins/Live/tests/Integration/ModelTest.php b/plugins/Live/tests/Integration/ModelTest.php
index eeede80c97..19bc97e82b 100644
--- a/plugins/Live/tests/Integration/ModelTest.php
+++ b/plugins/Live/tests/Integration/ModelTest.php
@@ -82,8 +82,7 @@ class ModelTest extends IntegrationTestCase
$dateEnd = Date::now();
$minTimestamp = 1;
$limit = 50;
- $model = new Model();
- $model->handleMaxExecutionTimeError($db, $e, $sql, $bind, $segment, $dateStart, $dateEnd, $minTimestamp, $limit);
+ Model::handleMaxExecutionTimeError($db, $e, $segment, $dateStart, $dateEnd, $minTimestamp, $limit, [$sql, $bind]);
$this->assertTrue(true);
}
@@ -102,8 +101,7 @@ class ModelTest extends IntegrationTestCase
$dateEnd = Date::now();
$minTimestamp = null;
$limit = 50;
- $model = new Model();
- $model->handleMaxExecutionTimeError($db, $e, $sql, $bind, $segment, $dateStart, $dateEnd, $minTimestamp, $limit);
+ Model::handleMaxExecutionTimeError($db, $e, $segment, $dateStart, $dateEnd, $minTimestamp, $limit, [$sql, $bind]);
}
/**
@@ -114,15 +112,12 @@ class ModelTest extends IntegrationTestCase
{
$db = Db::get();
$e = new \Exception('Query execution was interrupted, maximum statement execution time exceeded');
- $sql = 'SELECT 1';
- $bind = array();
$segment = 'userId>=1';
$dateStart = Date::now()->subDay(10);
$dateEnd = Date::now();
$minTimestamp = null;
$limit = 5000;
- $model = new Model();
- $model->handleMaxExecutionTimeError($db, $e, $sql, $bind, $segment, $dateStart, $dateEnd, $minTimestamp, $limit);
+ Model::handleMaxExecutionTimeError($db, $e, $segment, $dateStart, $dateEnd, $minTimestamp, $limit, ['param' => 'value']);
}
public function test_getStandAndEndDate()
diff --git a/plugins/Transitions/API.php b/plugins/Transitions/API.php
index 88bca868ef..b26b0bdc39 100644
--- a/plugins/Transitions/API.php
+++ b/plugins/Transitions/API.php
@@ -12,15 +12,18 @@ namespace Piwik\Plugins\Transitions;
use Exception;
use Piwik\ArchiveProcessor;
use Piwik\Common;
+use Piwik\Config;
use Piwik\DataAccess\LogAggregator;
use Piwik\DataArray;
use Piwik\DataTable;
use Piwik\DataTable\Row;
+use Piwik\Db;
use Piwik\Metrics;
use Piwik\Period;
use Piwik\Piwik;
use Piwik\Plugins\Actions\Actions;
use Piwik\Plugins\Actions\ArchivingHelper;
+use Piwik\Plugins\Live\Model;
use Piwik\RankingQuery;
use Piwik\Segment;
use Piwik\Segment\SegmentExpression;
@@ -81,25 +84,40 @@ class API extends \Piwik\Plugin\API
'date' => Period\Factory::build($period->getLabel(), $date)->getLocalizedShortString()
);
- $partsArray = explode(',', $parts);
- if ($parts == 'all' || in_array('internalReferrers', $partsArray)) {
- $this->addInternalReferrers($logAggregator, $report, $idaction, $actionType, $limitBeforeGrouping);
- }
- if ($parts == 'all' || in_array('followingActions', $partsArray)) {
- $includeLoops = $parts != 'all' && !in_array('internalReferrers', $partsArray);
- $this->addFollowingActions($logAggregator, $report, $idaction, $actionType, $limitBeforeGrouping, $includeLoops);
- }
- if ($parts == 'all' || in_array('externalReferrers', $partsArray)) {
- $this->addExternalReferrers($logAggregator, $report, $idaction, $actionType, $limitBeforeGrouping);
- }
+ try {
+ $partsArray = explode(',', $parts);
+ if ($parts == 'all' || in_array('internalReferrers', $partsArray)) {
+ $this->addInternalReferrers($logAggregator, $report, $idaction, $actionType, $limitBeforeGrouping);
+ }
+ if ($parts == 'all' || in_array('followingActions', $partsArray)) {
+ $includeLoops = $parts != 'all' && !in_array('internalReferrers', $partsArray);
+ $this->addFollowingActions($logAggregator, $report, $idaction, $actionType, $limitBeforeGrouping, $includeLoops);
+ }
+ if ($parts == 'all' || in_array('externalReferrers', $partsArray)) {
+ $this->addExternalReferrers($logAggregator, $report, $idaction, $actionType, $limitBeforeGrouping);
+ }
- // derive the number of exits from the other metrics
- if ($parts == 'all') {
- $report['pageMetrics']['exits'] = $report['pageMetrics']['pageviews']
- - $this->getTotalTransitionsToFollowingActions()
- - $report['pageMetrics']['loops'];
+ // derive the number of exits from the other metrics
+ if ($parts == 'all') {
+ $report['pageMetrics']['exits'] = $report['pageMetrics']['pageviews']
+ - $this->getTotalTransitionsToFollowingActions()
+ - $report['pageMetrics']['loops'];
+ }
+ } catch (\Exception $e) {
+ Model::handleMaxExecutionTimeError(
+ Db::getReader(),
+ $e,
+ $segment->getString(),
+ $period->getDateStart(),
+ $period->getDateEnd(),
+ 0,
+ Config::getInstance()->General['live_query_max_execution_time'],
+ ['method' => 'Transitions.getTransitionsForAction', 'actionName' => $actionName, 'actionType' => $actionType]
+ );
+ throw $e;
}
+
// replace column names in the data tables
$reportNames = array(
'previousPages' => true,
@@ -290,7 +308,8 @@ class API extends \Piwik\Plugin\API
$metrics,
$rankingQuery,
$joinLogActionColumn,
- $secondaryOrderBy = "`name`"
+ $secondaryOrderBy = "`name`",
+ Config::getInstance()->General['live_query_max_execution_time']
);
$dataTables = $this->makeDataTablesFollowingActions($types, $data);
@@ -342,7 +361,7 @@ class API extends \Piwik\Plugin\API
$where = 'visit_entry_idaction_' . $type . ' = ' . intval($idaction);
$metrics = array(Metrics::INDEX_NB_VISITS);
- $data = $logAggregator->queryVisitsByDimension($dimensions, $where, $selects, $metrics, $rankingQuery);
+ $data = $logAggregator->queryVisitsByDimension($dimensions, $where, $selects, $metrics, $rankingQuery, false, Config::getInstance()->General['live_query_max_execution_time']);
$referrerData = array();
$referrerSubData = array();
@@ -433,7 +452,8 @@ class API extends \Piwik\Plugin\API
$metrics,
$rankingQuery,
$joinLogActionOn,
- $secondaryOrderBy = "`name`"
+ $secondaryOrderBy = "`name`",
+ Config::getInstance()->General['live_query_max_execution_time']
);
$loops = 0;