Skip to content

Commit

Permalink
Merge pull request #107 from matomo-org/more-ga-error
Browse files Browse the repository at this point in the history
Show last GA error if there was one in exception message when cannot reach GA.
  • Loading branch information
diosmosis authored Aug 13, 2020
2 parents 087d5dd + 876382e commit 7502430
Show file tree
Hide file tree
Showing 2 changed files with 93 additions and 3 deletions.
29 changes: 26 additions & 3 deletions Google/GoogleAnalyticsQueryService.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@

class GoogleAnalyticsQueryService
{
const MAX_ATTEMPTS = 30;
const DEFAULT_MAX_ATTEMPTS = 30;
const MAX_BACKOFF_TIME = 60;
const PING_MYSQL_EVERY = 25;
const DEFAULT_MIN_BACKOFF_TIME = 2; // start at 2s since GA seems to have trouble w/ the 10 requests per 100s limit w/ 1
Expand All @@ -32,6 +32,11 @@ class GoogleAnalyticsQueryService
'ga:hits',
];

/**
* @var int
*/
private $maxAttempts = self::DEFAULT_MAX_ATTEMPTS;

/**
* @var \Google_Service_Analytics
*/
Expand Down Expand Up @@ -147,10 +152,11 @@ private function gaBatchGet(Date $date, $metricNamesChunk, $options, $orderByMet

$request = $this->googleQueryObjectFactory->make($this->viewId, $date, $metricNamesChunk, $options);

$lastGaError = null;
$this->currentBackoffTime = self::DEFAULT_MIN_BACKOFF_TIME;

$attempts = 0;
while ($attempts < self::MAX_ATTEMPTS) {
while ($attempts < $this->maxAttempts) {
try {
$this->issuePointlessMysqlQuery();

Expand Down Expand Up @@ -189,14 +195,23 @@ private function gaBatchGet(Date $date, $metricNamesChunk, $options, $orderByMet

$this->logger->info("Google Analytics API returned error: {$ex->getMessage()}. Waiting one minute before trying again...");

$messageContent = @json_decode($ex->getMessage(), true);
if (isset($messageContent['error']['message'])) {
$lastGaError = $messageContent['error']['message'];
}

$this->backOff();
} else {
throw $ex;
}
}
}

throw new \Exception("Failed to reach GA after " . self::MAX_ATTEMPTS . " attempts. Restart the import later.");
$message = "Failed to reach GA after " . $this->maxAttempts . " attempts. Restart the import later.";
if (!empty($lastGaError)) {
$message .= ' Last GA error message: ' . $lastGaError;
}
throw new \Exception($message);
}

/**
Expand All @@ -207,6 +222,14 @@ public function setOnQueryMade($onQueryMade)
$this->onQueryMade = $onQueryMade;
}

/**
* @param int $maxAttempts
*/
public function setMaxAttempts($maxAttempts)
{
$this->maxAttempts = $maxAttempts;
}

/**
* Used to keep the mysql connection alive in case GA API makes us wait for too long.
*/
Expand Down
67 changes: 67 additions & 0 deletions tests/Integration/Google/GoogleAnalyticsQueryServiceTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
<?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\Plugins\GoogleAnalyticsImporter\tests\Integration\Google;


use Piwik\Container\StaticContainer;
use Piwik\Date;
use Piwik\Metrics;
use Piwik\Plugins\GoogleAnalyticsImporter\Google\GoogleAnalyticsQueryService;
use Piwik\Plugins\GoogleAnalyticsImporter\Google\GoogleQueryObjectFactory;
use Piwik\Tests\Framework\Fixture;
use Piwik\Tests\Framework\TestCase\IntegrationTestCase;
use Psr\Log\LoggerInterface;

class GoogleAnalyticsQueryServiceTest extends IntegrationTestCase
{
public function getTestDataForGaErrorTest()
{
return [
[new \Exception(json_encode([
'error' => [
'message' => 'this is a test exception',
],
]), 503), 'Failed to reach GA after 2 attempts. Restart the import later. Last GA error message: this is a test exception'],
[new \Exception(json_encode([
'error' => [
],
]), 503), 'Failed to reach GA after 2 attempts. Restart the import later.'],
[new \Exception('lakjdsflsdj', 503), 'Failed to reach GA after 2 attempts. Restart the import later.'],
];
}

/**
* @dataProvider getTestDataForGaErrorTest
*/
public function test_query_returnsGaMessageWhenGaReturnsPersistentError($testEx, $expectedMessage)
{
Fixture::createWebsite('2012-02-02 00:00:00');

$client = new \Google_Client();
$mockReportingService = new \Google_Service_AnalyticsReporting($client);

$builder = $this->getMockBuilder(\Google_Service_AnalyticsReporting_Resource_Reports::class);
$mockReportingService->reports = $builder
->disableOriginalConstructor()
->onlyMethods([ 'batchGet' ])
->getMock();
$mockReportingService->reports->method('batchGet')->willThrowException($testEx);

$this->getMockBuilder(\Google_Service_AnalyticsReporting::class);
$gaQueryService = new GoogleAnalyticsQueryService($mockReportingService, 'testviewid', [], 1, 'testuser',
StaticContainer::get(GoogleQueryObjectFactory::class), StaticContainer::get(LoggerInterface::class));
$gaQueryService->setMaxAttempts(2);

$this->expectException(\Exception::class);
$this->expectExceptionMessage($expectedMessage);

$gaQueryService->query(Date::factory('2020-03-04'), ['somedimension'], [Metrics::INDEX_NB_VISITS]);
}
}

0 comments on commit 7502430

Please sign in to comment.