diff --git a/.gitignore b/.gitignore index f5f7e613..a4bd6351 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,5 @@ *.phar .idea -*.sh *~ ci composer.lock @@ -23,3 +22,6 @@ test.php # phpenv .php-version + +# Sonarqube +.scannerwork diff --git a/.travis.yml b/.travis.yml index c36c876e..4219427a 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,5 +1,8 @@ language: php +git: + depth: false + env: global: - COMPOSER_DISABLE_XDEBUG_WARN=1 @@ -7,9 +10,11 @@ env: matrix: include: - dist: precise - php: '5.3' + php: '5.4' - dist: xenial php: '7.2' + after_success: + - bash sonar-scanner.sh services: - redis-server diff --git a/CHANGES.txt b/CHANGES.txt index 6b46353c..b4d237ac 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -1,3 +1,6 @@ +6.2.3 (Nov 1, 2019) + - Added flag `IPAddressesEnabled` into options to enable/disable sending MachineName and MachineIP when data is posted in headers. + 6.2.2 (Sep 18, 2019) - Fetch multiple splits at once on getTreatments/getTreatmentsWithConfig - Removed MatcherClient (DependencyMatcher now uses Evaluator directly) diff --git a/composer.json b/composer.json index 0fca956a..41a4cf24 100644 --- a/composer.json +++ b/composer.json @@ -27,9 +27,10 @@ "require-dev": { "phpunit/phpunit": "~4.0", "phpdocumentor/phpdocumentor": "2.*", - "squizlabs/php_codesniffer": "2.*" + "squizlabs/php_codesniffer": "2.*", + "rogervila/php-sonarqube-scanner": "0.4.0" }, - + "autoload": { "psr-4": { "SplitIO\\": "src/SplitIO/", diff --git a/sonar-scanner.sh b/sonar-scanner.sh new file mode 100755 index 00000000..c82e7fa6 --- /dev/null +++ b/sonar-scanner.sh @@ -0,0 +1,41 @@ +#/bin/bash -e + +sonar_scanner() { + local params="$@" + + vendor/bin/sonar-scanner \ + -Dsonar.host.url='https://sonarqube.split-internal.com' \ + -Dsonar.login="$SONAR_TOKEN" \ + -Dsonar.ws.timeout='300' \ + -Dsonar.sources='./src' \ + -Dsonar.projectName='php-client' \ + -Dsonar.exclusions='**/tests/**/*.*' \ + -Dsonar.links.ci='https://travis-ci.com/splitio/php-client' \ + -Dsonar.links.scm='https://github.com/splitio/php-client' \ + "${params}" + + return $? +} + +if [ "$TRAVIS_PULL_REQUEST" != "false" ]; then + sonar_scanner \ + -Dsonar.pullrequest.provider='GitHub' \ + -Dsonar.pullrequest.github.repository='splitio/php-client' \ + -Dsonar.pullrequest.key=$TRAVIS_PULL_REQUEST \ + -Dsonar.pullrequest.branch=$TRAVIS_PULL_REQUEST_BRANCH \ + -Dsonar.pullrequest.base=$TRAVIS_BRANCH +else + if [ "$TRAVIS_BRANCH" == 'master' ]; then + sonar_scanner \ + -Dsonar.branch.name=$TRAVIS_BRANCH + else + if [ "$TRAVIS_BRANCH" == 'develop' ]; then + TARGET_BRANCH='master' + else + TARGET_BRANCH='develop' + fi + sonar_scanner \ + -Dsonar.branch.name=$TRAVIS_BRANCH \ + -Dsonar.branch.target=$TARGET_BRANCH + fi +fi diff --git a/src/SplitIO/Component/Cache/ImpressionCache.php b/src/SplitIO/Component/Cache/ImpressionCache.php index b9d12624..9d1c5f4c 100644 --- a/src/SplitIO/Component/Cache/ImpressionCache.php +++ b/src/SplitIO/Component/Cache/ImpressionCache.php @@ -3,22 +3,19 @@ use SplitIO\Component\Common\Di; use SplitIO\Component\Cache\KeyFactory; +use SplitIO\Sdk\QueueMetadataMessage; class ImpressionCache { const IMPRESSIONS_QUEUE_KEY = "SPLITIO.impressions"; const IMPRESSION_KEY_DEFAULT_TTL = 3600; - public function logImpressions($impressions, $metadata) + public function logImpressions($impressions, QueueMetadataMessage $metadata) { $toStore = array_map( function ($imp) use ($metadata) { return json_encode(array( - "m" => array( - "s" => $metadata['sdkVersion'], - "i" => $metadata['machineIp'], - "n" => $metadata['machineName'], - ), + 'm' => $metadata->toArray(), "i" => array( "k" => $imp->getId(), "b" => $imp->getBucketingKey(), diff --git a/src/SplitIO/Sdk/Client.php b/src/SplitIO/Sdk/Client.php index 385af652..2a1581c7 100644 --- a/src/SplitIO/Sdk/Client.php +++ b/src/SplitIO/Sdk/Client.php @@ -7,7 +7,7 @@ use SplitIO\Component\Cache\MetricsCache; use SplitIO\Sdk\Events\EventDTO; use SplitIO\Sdk\Events\EventQueueMessage; -use SplitIO\Sdk\Events\EventQueueMetadataMessage; +use SplitIO\Sdk\QueueMetadataMessage; use SplitIO\Sdk\Impressions\Impression; use SplitIO\TreatmentImpression; use SplitIO\Sdk\Impressions\ImpressionLabel; @@ -38,6 +38,9 @@ public function __construct($options = array()) if (isset($options['impressionListener'])) { $this->impressionListener = new \SplitIO\Sdk\ImpressionListenerWrapper($options['impressionListener']); } + $this->queueMetadata = new QueueMetadataMessage( + isset($options['IPAddressesEnabled']) ? $options['IPAddressesEnabled'] : true + ); } /** @@ -305,7 +308,7 @@ private function doInputValidationForTreatments($key, $featureNames, array $attr private function registerData($impressions, $attributes, $metricName, $latency = null) { try { - TreatmentImpression::log($impressions); + TreatmentImpression::log($impressions, $this->queueMetadata); if (isset($this->impressionListener)) { $this->impressionListener->sendDataToClient($impressions, $attributes); } @@ -541,8 +544,7 @@ public function track($key, $trafficType, $eventType, $value = null, $properties try { $eventDTO = new EventDTO($key, $trafficType, $eventType, $value, $properties); - $eventMessageMetadata = new EventQueueMetadataMessage(); - $eventQueueMessage = new EventQueueMessage($eventMessageMetadata, $eventDTO); + $eventQueueMessage = new EventQueueMessage($this->queueMetadata, $eventDTO); return EventsCache::addEvent($eventQueueMessage); } catch (\Exception $exception) { // @codeCoverageIgnoreStart diff --git a/src/SplitIO/Sdk/Events/EventQueueMessage.php b/src/SplitIO/Sdk/Events/EventQueueMessage.php index b1fa0444..c4e6b9ee 100644 --- a/src/SplitIO/Sdk/Events/EventQueueMessage.php +++ b/src/SplitIO/Sdk/Events/EventQueueMessage.php @@ -1,6 +1,8 @@ metadata = $metadata; $this->event = $event; @@ -26,7 +28,7 @@ public function __construct(EventQueueMetadataMessage $metadata, EventDTO $event /** - * @return EventQueueMetadataMessage + * @return QueueMetadataMessage */ public function getMetadata() { @@ -36,7 +38,7 @@ public function getMetadata() /** * @param mixed $metadata */ - public function setMetadata(EventQueueMetadataMessage $metadata) + public function setMetadata(QueueMetadataMessage $metadata) { $this->metadata = $metadata; } diff --git a/src/SplitIO/Sdk/Events/EventQueueMetadataMessage.php b/src/SplitIO/Sdk/QueueMetadataMessage.php similarity index 68% rename from src/SplitIO/Sdk/Events/EventQueueMetadataMessage.php rename to src/SplitIO/Sdk/QueueMetadataMessage.php index d04a4684..b06af559 100644 --- a/src/SplitIO/Sdk/Events/EventQueueMetadataMessage.php +++ b/src/SplitIO/Sdk/QueueMetadataMessage.php @@ -1,7 +1,7 @@ sdkVersion = 'php-' . \SplitIO\version(); - $this->machineIP = \SplitIO\getHostIpAddress(); - $this->machineName = 'unknown'; + $this->machineIP = 'NA'; + $this->machineName = 'NA'; + if ($IPAddressesEnabled) { + $this->machineIP = \SplitIO\getHostIpAddress(); + if ($this->machineIP != 'unknown') { + $this->machineName = 'ip-' . str_replace('.', '-', $this->machineIP); + } else { + $this->machineName = 'unknown'; + } + } } - /** * @return mixed */ diff --git a/src/SplitIO/TreatmentImpression.php b/src/SplitIO/TreatmentImpression.php index aa955f29..bb4743e0 100644 --- a/src/SplitIO/TreatmentImpression.php +++ b/src/SplitIO/TreatmentImpression.php @@ -4,6 +4,7 @@ use SplitIO\Component\Cache\ImpressionCache; use SplitIO\Sdk\Impressions\Impression; use SplitIO\Component\Common\Di; +use SplitIO\Sdk\QueueMetadataMessage; class TreatmentImpression { @@ -11,22 +12,18 @@ class TreatmentImpression * @param \SplitIO\Sdk\Impressions\Impression $impressions * @return bool */ - public static function log($impressions) + public static function log($impressions, QueueMetadataMessage $metadata) { try { Di::getLogger()->debug($impressions); if (is_null($impressions) || (is_array($impressions) && 0 == count($impressions))) { - return; + return null; } $impressionCache = new ImpressionCache(); $toStore = (is_array($impressions)) ? $impressions : array($impressions); return $impressionCache->logImpressions( $toStore, - array( - 'sdkVersion' => 'php-' . \SplitIO\version(), - 'machineIp' => \SplitIO\getHostIpAddress(), - 'machineName' => null, // TODO - ) + $metadata ); } catch (\Exception $e) { Di::getLogger()->warning('Unable to write impression back to redis.'); diff --git a/src/SplitIO/Version.php b/src/SplitIO/Version.php index 2fd1fd7e..4b8ef846 100644 --- a/src/SplitIO/Version.php +++ b/src/SplitIO/Version.php @@ -3,5 +3,5 @@ class Version { - const CURRENT = '6.2.2'; + const CURRENT = '6.2.3'; } diff --git a/tests/Suite/Sdk/ImpressionsTest.php b/tests/Suite/Sdk/ImpressionsTest.php index 602e6db2..a7f7628a 100644 --- a/tests/Suite/Sdk/ImpressionsTest.php +++ b/tests/Suite/Sdk/ImpressionsTest.php @@ -6,6 +6,7 @@ use SplitIO\Sdk\Impressions\Impression; use SplitIO\Test\Suite\Redis\ReflectiveTools; use SplitIO\Component\Cache\ImpressionCache; +use SplitIO\Sdk\QueueMetadataMessage; class ImpressionsTest extends \PHPUnit_Framework_TestCase { @@ -26,6 +27,7 @@ public function testImpressionsAreAdded() $redisClient = ReflectiveTools::clientFromCachePool(Di::getCache()); $redisClient->del(ImpressionCache::IMPRESSIONS_QUEUE_KEY); + $queueMetadata = new QueueMetadataMessage(); TreatmentImpression::log(new Impression( 'someMatchingKey', @@ -35,7 +37,7 @@ public function testImpressionsAreAdded() 123456, 321654, 'someBucketingKey' - )); + ), $queueMetadata); // Assert that the TTL is within a 10-second range (between it was set and retrieved). $ttl = $redisClient->ttl(ImpressionCache::IMPRESSIONS_QUEUE_KEY); @@ -47,6 +49,7 @@ public function testImpressionsAreAdded() $this->assertEquals($decoded['m']['s'], 'php-'.\Splitio\version()); $this->assertEquals($decoded['m']['i'], 'unknown'); + $this->assertEquals($decoded['m']['n'], 'unknown'); $this->assertEquals($decoded['i']['k'], 'someMatchingKey'); $this->assertEquals($decoded['i']['b'], 'someBucketingKey'); $this->assertEquals($decoded['i']['f'], 'someFeature'); @@ -64,7 +67,8 @@ public function testExpirationOnlyOccursOnce() $sdkConfig = array( 'log' => array('adapter' => 'stdout'), - 'cache' => array('adapter' => 'predis', 'parameters' => $parameters, 'options' => $options) + 'cache' => array('adapter' => 'predis', 'parameters' => $parameters, 'options' => $options), + 'IPAddressEnabled' => false ); //Initializing the SDK instance. @@ -72,6 +76,7 @@ public function testExpirationOnlyOccursOnce() $redisClient = ReflectiveTools::clientFromCachePool(Di::getCache()); $redisClient->del(ImpressionCache::IMPRESSIONS_QUEUE_KEY); + $queueMetadata = new QueueMetadataMessage(false); TreatmentImpression::log(new Impression( 'someMatchingKey', @@ -81,7 +86,7 @@ public function testExpirationOnlyOccursOnce() 123456, 321654, 'someBucketingKey' - )); + ), $queueMetadata); sleep(3); @@ -93,11 +98,25 @@ public function testExpirationOnlyOccursOnce() 123456, 321654, 'someBucketingKey' - )); + ), $queueMetadata); $ttl = $redisClient->ttl(ImpressionCache::IMPRESSIONS_QUEUE_KEY); // $ttl should be lower than or equalt the default impressions TTL minus 3 seconds, // since it should have not been resetted with the last imrpession logged. $this->assertLessThanOrEqual(ImpressionCache::IMPRESSION_KEY_DEFAULT_TTL - 3, $ttl); + + $imp = $redisClient->rpop(ImpressionCache::IMPRESSIONS_QUEUE_KEY); + $decoded = json_decode($imp, true); + + $this->assertEquals($decoded['m']['s'], 'php-'.\Splitio\version()); + $this->assertEquals($decoded['m']['i'], 'NA'); + $this->assertEquals($decoded['m']['n'], 'NA'); + $this->assertEquals($decoded['i']['k'], 'someMatchingKey'); + $this->assertEquals($decoded['i']['b'], 'someBucketingKey'); + $this->assertEquals($decoded['i']['f'], 'someFeature'); + $this->assertEquals($decoded['i']['t'], 'on'); + $this->assertEquals($decoded['i']['r'], 'label1'); + $this->assertEquals($decoded['i']['m'], 123456); + $this->assertEquals($decoded['i']['c'], 321654); } } diff --git a/tests/Suite/Sdk/SdkClientTest.php b/tests/Suite/Sdk/SdkClientTest.php index 45535b0f..83975f65 100644 --- a/tests/Suite/Sdk/SdkClientTest.php +++ b/tests/Suite/Sdk/SdkClientTest.php @@ -209,13 +209,22 @@ public function testLocalClientYAML() ); } - private function validateLastImpression($redisClient, $feature, $key, $treatment) - { + private function validateLastImpression( + $redisClient, + $feature, + $key, + $treatment, + $machineName = 'unknown', + $machineIP = 'unknown' + ) { $raw = $redisClient->rpop(ImpressionCache::IMPRESSIONS_QUEUE_KEY); $parsed = json_decode($raw, true); + echo "parsed " . json_encode($parsed) . "\n"; $this->assertEquals($parsed['i']['f'], $feature); $this->assertEquals($parsed['i']['k'], $key); $this->assertEquals($parsed['i']['t'], $treatment); + $this->assertEquals($parsed['m']['i'], $machineIP); + $this->assertEquals($parsed['m']['n'], $machineName); } public function testClient() @@ -544,7 +553,8 @@ public function testGetTreatmentsWithDistinctFeatures() $sdkConfig = array( 'log' => array('adapter' => 'stdout'), - 'cache' => array('adapter' => 'predis', 'parameters' => $parameters, 'options' => $options) + 'cache' => array('adapter' => 'predis', 'parameters' => $parameters, 'options' => $options), + 'IPAddressesEnabled' => false ); //Initializing the SDK instance. @@ -565,7 +575,7 @@ public function testGetTreatmentsWithDistinctFeatures() //Check impressions generated $redisClient = ReflectiveTools::clientFromCachePool(Di::getCache()); - $this->validateLastImpression($redisClient, 'sample_feature', 'user1', 'on'); + $this->validateLastImpression($redisClient, 'sample_feature', 'user1', 'on', 'NA', 'NA'); } public function testGetTreatmentsWithRepeteadedFeatures() @@ -580,7 +590,8 @@ public function testGetTreatmentsWithRepeteadedFeatures() $sdkConfig = array( 'log' => array('adapter' => 'stdout'), - 'cache' => array('adapter' => 'predis', 'parameters' => $parameters, 'options' => $options) + 'cache' => array('adapter' => 'predis', 'parameters' => $parameters, 'options' => $options), + 'ipAddress' => '1.2.3.4' ); //Initializing the SDK instance. @@ -602,12 +613,13 @@ public function testGetTreatmentsWithRepeteadedFeatures() // Check impressions $redisClient = ReflectiveTools::clientFromCachePool(Di::getCache()); - $this->validateLastImpression($redisClient, 'sample_feature', 'user1', 'on'); + $this->validateLastImpression($redisClient, 'sample_feature', 'user1', 'on', 'ip-1-2-3-4', '1.2.3.4'); } public function testGetTreatmentsWithRepeteadedAndNullFeatures() { Di::set(Di::KEY_FACTORY_TRACKER, false); + Di::set('ipAddress', null); // unset ipaddress from previous test //Testing version string $this->assertTrue(is_string(\SplitIO\version())); @@ -680,5 +692,4 @@ public function testGetTreatmentsFetchesSplitsInOneCall() $client = new Client(); $client->getTreatments('key1', array('split1', 'split2', 'split3')); } - } diff --git a/tests/Suite/Sdk/SdkReadOnlyTest.php b/tests/Suite/Sdk/SdkReadOnlyTest.php index 229c5c86..adbe450a 100644 --- a/tests/Suite/Sdk/SdkReadOnlyTest.php +++ b/tests/Suite/Sdk/SdkReadOnlyTest.php @@ -9,6 +9,7 @@ use SplitIO\TreatmentImpression; use SplitIO\Grammar\Condition\Partition\TreatmentEnum; use SplitIO\Sdk\Impressions\Impression; +use SplitIO\Sdk\QueueMetadataMessage; class SdkReadOnlyTest extends \PHPUnit_Framework_TestCase { @@ -126,6 +127,6 @@ public function testException() 'something' ); - TreatmentImpression::log($impression); + TreatmentImpression::log($impression, new QueueMetadataMessage()); } }