Skip to content

Commit

Permalink
Merge pull request #17 from rollout/analytics
Browse files Browse the repository at this point in the history
Analytics
  • Loading branch information
andy-a-o authored Oct 7, 2021
2 parents 66614cc + 55936b4 commit 1df28e2
Show file tree
Hide file tree
Showing 13 changed files with 346 additions and 94 deletions.
4 changes: 1 addition & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,7 @@ PHP 5.6 or later.

The following extensions should be enabled in php.ini:

```
extension=php_openssl.dll # config signature check
```
* openssl

## Documentation

Expand Down
4 changes: 2 additions & 2 deletions demo.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@
use Rox\Server\RoxOptions;
use Rox\Server\RoxOptionsBuilder;

const DEFAULT_API_KEY = '5b3356d00d81206da3055bc0';
const DEFAULT_DEV_MODE_KEY = '01fcd0d21eeaed9923dff6d8';
const DEFAULT_API_KEY = '5e6a3533d3319d76d1ca33fd';
const DEFAULT_DEV_MODE_KEY = '297c23e7fcb68e54c513dcca';

require __DIR__ . '/vendor/autoload.php';

Expand Down
5 changes: 4 additions & 1 deletion src/Rox/Core/Core.php
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@
use Rox\Core\Roxx\PropertiesExtensions;
use Rox\Core\Security\APIKeyVerifier;
use Rox\Core\Security\SignatureVerifier;
use Rox\Core\XPack\Analytics\AnalyticsClient;
use Rox\Core\XPack\Client\XBUID;
use Rox\Core\XPack\Configuration\XConfigurationFetchedInvoker;
use Rox\Core\XPack\Network\StateSender;
Expand Down Expand Up @@ -240,7 +241,8 @@ public function setup(
$this->_stateSender = new StateSender($stateSenderHttpClient, $deviceProperties, $this->_flagRepository, $this->_customPropertyRepository);
$this->_configurationFetchedInvoker = new XConfigurationFetchedInvoker($this);
$this->_configurationFetcher = new ConfigurationFetcher($httpClient, $buid, $deviceProperties, $this->_configurationFetchedInvoker, $this->_errorReporter);
$this->_impressionInvoker = new XImpressionInvoker($this->_internalFlags, $this->_customPropertyRepository, null);
$this->_impressionInvoker = new XImpressionInvoker($this->_internalFlags, $this->_customPropertyRepository,
new AnalyticsClient($this->_deviceProperties, $this->_internalFlags, $httpClientFactory->createHttpClient()));
$signature = new XSignatureVerifier();
$apiKeyVerifier = new XAPIKeyVerifier($sdkSettings);
}
Expand Down Expand Up @@ -384,6 +386,7 @@ private function _createHttpClientFactory($options, $cacheTtl)
$httpClientOptions->setLogCacheHitsAndMisses($options
? $options->isLogCacheHitsAndMisses()
: false);
$httpClientOptions->setUserAgent("rox-php/{$this->_deviceProperties->getLibVersion()}");
return new GuzzleHttpClientFactory($httpClientOptions);
}
}
8 changes: 4 additions & 4 deletions src/Rox/Core/CustomProperties/CustomProperty.php
Original file line number Diff line number Diff line change
Expand Up @@ -63,22 +63,22 @@ public function getValue()
}

/**
* @return string
* @return array
*/
public function jsonSerialize()
{
return json_encode([
return [
"name" => $this->_name,
"type" => $this->_type->getType(),
"externalType" => $this->_type->getExternalType()
]);
];
}

/**
* @return string
*/
public function __toString()
{
return $this->jsonSerialize();
return json_encode($this->jsonSerialize());
}
}
95 changes: 56 additions & 39 deletions src/Rox/Core/Network/GuzzleHttpClient.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,6 @@
use GuzzleHttp\Psr7\Request;
use GuzzleHttp\Psr7\Uri;
use GuzzleHttp\RequestOptions;
use Psr\Http\Message\RequestInterface;
use Psr\Http\Message\ResponseInterface;
use Psr\Log\LoggerInterface;
use Rox\Core\Logging\LoggerFactory;

Expand Down Expand Up @@ -52,6 +50,11 @@ public function __construct($options = null)
}
$this->_logCacheHitsAndMisses = $options->isLogCacheHitsAndMisses();
$this->_noCachePaths = $options->getNoCachePaths();
if ($options->getUserAgent()) {
$config['headers'] = [
'User-Agent' => $options->getUserAgent()
];
}
}

$this->_client = new Client($config);
Expand All @@ -68,8 +71,32 @@ function sendGet(RequestData $requestData)
if ($requestData->getQueryParams() != null) {
$uri = Uri::withQueryValues($uri, $requestData->getQueryParams());
}
$response = $this->sendRequest(new Request('GET', $uri));
return new Psr7ResponseWrapper($response);
try {
$request = new Request('GET', $uri);
$noCache = $this->_isNoCacheRequest($uri);
if ($noCache) {
// Don't use Kevinrob/GuzzleCache lib constants here to make it optional in composer.json
$request = $request->withHeader('X-Kevinrob-GuzzleCache-ReValidation', true);
}
$response = $this->_client->send($request);
if (!$noCache && $this->_logCacheHitsAndMisses) {
$cacheState = $response->getHeader("X-Kevinrob-Cache");
if (is_array($cacheState) && !empty($cacheState)) {
switch ($cacheState[0]) {
case 'HIT':
$this->_log->debug("{$request->getUri()}: HIT");
break;

case 'MISS':
$this->_log->debug("{$request->getUri()}: MISS");
break;
}
}
}
return new Psr7ResponseWrapper($response);
} catch (GuzzleException $e) {
return $this->_handleError($request->getUri(), $e);
}
}

/**
Expand All @@ -88,50 +115,40 @@ function sendPost(RequestData $requestData)
*/
function postJson($uri, array $data)
{
$uriToSend = new Uri($uri);
return new Psr7ResponseWrapper($this->_client->post($uriToSend, [
RequestOptions::JSON => $data
]));
try {
return new Psr7ResponseWrapper($this->_client->post(new Uri($uri), [
RequestOptions::JSON => $data
]));
} catch (GuzzleException $e) {
$this->_log->error("Failed to send data to ${uri}: {$e->getMessage()}", [
'exception' => $e
]);
return new HttpErrorResponse($e->getCode(), $e->getMessage());
}
}

/**
* @param RequestInterface $request
* @return ResponseInterface
* @param string $uri
* @param GuzzleException $e
* @return HttpResponseInterface
*/
private function sendRequest($request)
private function _handleError($uri, GuzzleException $e)
{
try {
$noCache = $this->_isNoCacheRequest($request);
if ($noCache) {
// Don't use Kevinrob/GuzzleCache lib constants here to make it optional in composer.json
$request = $request->withHeader('X-Kevinrob-GuzzleCache-ReValidation', true);
}
$response = $this->_client->send($request);
if (!$noCache && $this->_logCacheHitsAndMisses) {
$cacheState = $response->getHeader("X-Kevinrob-Cache");
if (is_array($cacheState) && !empty($cacheState)) {
switch ($cacheState[0]) {
case 'HIT':
$this->_log->debug("{$request->getUri()}: HIT");
break;

case 'MISS':
$this->_log->debug("{$request->getUri()}: MISS");
break;
}
}
}
return $response;
} catch (GuzzleException $e) {
throw new HttpClientException("Failed to send request to {$request->getUri()}", $e);
}
$this->_log->error("Failed to send data to ${uri}: {$e->getMessage()}", [
'exception' => $e
]);
return new HttpErrorResponse($e->getCode(), $e->getMessage());
}

private function _isNoCacheRequest(RequestInterface $request)
/**
* @param string $uri
* @return bool
*/
private function _isNoCacheRequest($uri)
{
return is_array($this->_noCachePaths) &&
count(array_filter($this->_noCachePaths, function ($path) use ($request) {
return strpos((string)$request->getUri(), $path) !== false;
count(array_filter($this->_noCachePaths, function ($path) use ($uri) {
return strpos($uri, $path) !== false;
})) > 0;
}
}
23 changes: 23 additions & 0 deletions src/Rox/Core/Network/GuzzleHttpClientOptions.php
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,11 @@ class GuzzleHttpClientOptions
*/
private $_noCachePaths = [];

/**
* @var string $_userAgent
*/
private $_userAgent;

/**
* GuzzleHttpClientOptions constructor.
*/
Expand Down Expand Up @@ -109,4 +114,22 @@ public function setNoCachePaths(array $noCachePaths)
$this->_noCachePaths = $noCachePaths;
return $this;
}

/**
* @return string
*/
public function getUserAgent()
{
return $this->_userAgent;
}

/**
* @param string $userAgent
* @return GuzzleHttpClientOptions
*/
public function setUserAgent($userAgent)
{
$this->_userAgent = $userAgent;
return $this;
}
}
25 changes: 0 additions & 25 deletions src/Rox/Core/Network/HttpClientException.php

This file was deleted.

43 changes: 43 additions & 0 deletions src/Rox/Core/Network/HttpErrorResponse.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
<?php

namespace Rox\Core\Network;

class HttpErrorResponse extends AbstractHttpResponse
{
/**
* @var int $_statusCode
*/
private $_statusCode;

/**
* @var string $_content
*/
private $_content;

/**
* HttpErrorResponse constructor.
* @param int $_statusCode
* @param string $_content
*/
public function __construct($_statusCode, $_content)
{
$this->_statusCode = $_statusCode;
$this->_content = $_content;
}

/**
* @inheritDoc
*/
function getStatusCode()
{
return $this->_statusCode;
}

/**
* @inheritDoc
*/
function getContent()
{
return new StringResponseContent($this->_content);
}
}
28 changes: 28 additions & 0 deletions src/Rox/Core/Network/StringResponseContent.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
<?php

namespace Rox\Core\Network;

class StringResponseContent implements HttpResponseContentInterface
{
/**
* @var string $_content
*/
private $_content;

/**
* TestResponseContent constructor.
* @param string $content
*/
public function __construct($content)
{
$this->_content = $content;
}

/**
* @return string
*/
function readAsString()
{
return $this->_content;
}
}
Loading

0 comments on commit 1df28e2

Please sign in to comment.