diff --git a/packages/php/examples/laravel/config/readme.php b/packages/php/examples/laravel/config/readme.php index c379dd31e8..7a4cb3f2e9 100644 --- a/packages/php/examples/laravel/config/readme.php +++ b/packages/php/examples/laravel/config/readme.php @@ -16,8 +16,8 @@ /** * Since ReadMe doesn't want to take your API down if you happen to be - * unable to send metrics to us, development mode is enabled by default and - * will do two things: + * unable to send metrics to us, fire and forget mode is enabled by default + * and will do two things: * * - Make all API requests asynchronously. * - Silence all possible errors in transit. @@ -26,6 +26,12 @@ * enabling this option so you can see any possible error that may be * present in your payload before you deploy to production. */ + 'fire_and_forget' => true, + + /** + * When true, the log will be marked as a development log. This is great for + * separating staging or test data from data coming from customers. + */ 'development_mode' => false, /** diff --git a/packages/php/src/Metrics.php b/packages/php/src/Metrics.php index ed8c43aded..4c480139ee 100644 --- a/packages/php/src/Metrics.php +++ b/packages/php/src/Metrics.php @@ -20,6 +20,7 @@ class Metrics protected const README_API = 'https://dash.readme.com'; private bool $development_mode = false; + private bool $fire_and_forget = true; private array $denylist = []; private array $allowlist = []; private string|null $base_log_url = null; @@ -44,6 +45,9 @@ public function __construct(public string $api_key, public string $group_handler $this->development_mode = array_key_exists('development_mode', $options) ? (bool)$options['development_mode'] : false; + $this->fire_and_forget = array_key_exists('fire_and_forget', $options) + ? (bool)$options['fire_and_forget'] + : true; if (isset($options['denylist']) && is_array($options['denylist'])) { $this->denylist = $options['denylist']; @@ -61,11 +65,11 @@ public function __construct(public string $api_key, public string $group_handler $this->base_log_url = $options['base_log_url']; } - // In development mode, requests are sent asynchronously (as well as PHP can without directly invoking + // In fire_and_forget mode, requests are sent asynchronously (as well as PHP can without directly invoking // shell cURL commands), so a very small timeout here ensures that the Metrics code will finish as fast as // possible, send the POST request to the background and continue on with whatever else the application // needs to execute. - $curl_timeout = (!$this->development_mode) ? 0.2 : 0; + $curl_timeout = (!$this->fire_and_forget) ? 0.2 : 0; $this->curl_handler = new CurlMultiHandler(); $this->client = (isset($options['client'])) ? $options['client'] : new Client([ @@ -113,8 +117,8 @@ public function track(Request $request, Response &$response): void 'User-Agent' => $this->user_agent ]; - // If not in development mode, all requests should be async. - if (!$this->development_mode) { + // If not in fire_and_forget mode, all requests should be async. + if ($this->fire_and_forget) { try { $promise = $this->client->postAsync('/v1/request', [ 'headers' => $headers, @@ -200,11 +204,11 @@ private function getProjectBaseUrl(): ?string $cache->base_url = $json->baseUrl; $cache->last_updated = time(); } catch (\Exception $e) { - // If we're running in development mode, toss any errors that happen when we try to call the ReadMe API. - // + // If we're running in fire_and_forget mode, toss any errors that happen when we try to call the + // ReadMe API. // These errors will likely be from invalid API keys, so it'll be good to surface those to users before // it hits production. - if ($this->development_mode) { + if (!$this->fire_and_forget) { try { // If we don't have a ClientException here, throw again so we end up below and handle this // exception as a non-HTTP response problem. @@ -278,6 +282,11 @@ public function isInDevelopmentMode(): bool return $this->development_mode; } + public function isInFireAndForgetMode(): bool + { + return $this->fire_and_forget; + } + public function getDenylist(): array { return $this->denylist; diff --git a/packages/php/src/Middleware.php b/packages/php/src/Middleware.php index fc36f8622f..bb68e1500e 100644 --- a/packages/php/src/Middleware.php +++ b/packages/php/src/Middleware.php @@ -16,6 +16,7 @@ public function __construct() 'blacklist' => config('readme.blacklist', []), 'whitelist' => config('readme.whitelist', []), 'base_log_url' => config('readme.base_log_url'), + 'fire_and_forget' => config('readme.fire_and_forget', true), ] ); } diff --git a/packages/php/src/config.dist.php b/packages/php/src/config.dist.php index dd6dacbb72..402975e554 100644 --- a/packages/php/src/config.dist.php +++ b/packages/php/src/config.dist.php @@ -16,8 +16,8 @@ /** * Since ReadMe doesn't want to take your API down if you happen to be - * unable to send metrics to us, development mode is enabled by default and - * will do two things: + * unable to send metrics to us, fire and forget mode is enabled by default + * and will do two things: * * - Make all API requests asynchronously. * - Silence all possible errors in transit. @@ -26,7 +26,14 @@ * enabling this option so you can see any possible error that may be * present in your payload before you deploy to production. */ - 'development_mode' => true, + 'fire_and_forget' => true, + + + /** + * When true, the log will be marked as a development log. This is great for + * separating staging or test data from data coming from customers. + */ + 'development_mode' => false, /** * An array of keys from your API requests and responses that you wish to diff --git a/packages/php/tests/ConfigTest.php b/packages/php/tests/ConfigTest.php index 007f0f1d16..5376e8c1af 100644 --- a/packages/php/tests/ConfigTest.php +++ b/packages/php/tests/ConfigTest.php @@ -11,10 +11,11 @@ public function testConfigFileHasExpectedData(): void $this->assertSame([ 'api_key', 'group_handler', + 'fire_and_forget', 'development_mode', 'denylist', 'allowlist', - 'base_log_url' + 'base_log_url', ], array_keys($config)); } } diff --git a/packages/php/tests/MetricsTest.php b/packages/php/tests/MetricsTest.php index 61dab32c5b..fa45ef23b2 100644 --- a/packages/php/tests/MetricsTest.php +++ b/packages/php/tests/MetricsTest.php @@ -143,11 +143,11 @@ public function testTrack(bool $development_mode): void /** * @group track - * @dataProvider providerDevelopmentModeToggle + * @dataProvider providerFireAndForgetModeToggle */ - public function testTrackHandlesApiErrors(bool $development_mode): void + public function testTrackHandlesApiErrors(bool $fire_and_forget): void { - if ($development_mode) { + if (!$fire_and_forget) { $this->expectException(MetricsException::class); // `RequestModel` from the API response should get swapped out with `ValidationError`. $this->expectExceptionMessage('ValidationError: queryString.0.value: Path `value` is required.'); @@ -173,7 +173,7 @@ public function testTrackHandlesApiErrors(bool $development_mode): void ); $this->metrics = new Metrics($this->readme_api_key, $this->group_handler, [ - 'development_mode' => $development_mode, + 'fire_and_forget' => $fire_and_forget, 'client' => new Client(['handler' => $handlers->metrics]), 'client_readme' => new Client(['handler' => $handlers->readme]) ]); @@ -183,7 +183,7 @@ public function testTrackHandlesApiErrors(bool $development_mode): void $this->metrics->track($request, $response); - if (!$development_mode) { + if ($fire_and_forget) { $this->assertTrue( true, 'When not in development mode, exceptions should not have been thrown so this assertion should pass.' @@ -193,12 +193,12 @@ public function testTrackHandlesApiErrors(bool $development_mode): void /** * @group track - * @dataProvider providerDevelopmentModeToggle + * @dataProvider providerFireAndForgetModeToggle */ - public function testTrackHandlesApiServerUnavailability(bool $development_mode): void + public function testTrackHandlesApiServerUnavailability(bool $fire_and_forget): void { // Exceptions **should** be thrown under development mode! - if ($development_mode) { + if (!$fire_and_forget) { $this->expectException(ServerException::class); $this->expectExceptionMessageMatches('/500 Internal Server Error/'); } @@ -209,7 +209,7 @@ public function testTrackHandlesApiServerUnavailability(bool $development_mode): ); $this->metrics = new Metrics($this->readme_api_key, $this->group_handler, [ - 'development_mode' => $development_mode, + 'fire_and_forget' => $fire_and_forget, 'client' => new Client(['handler' => $handlers->metrics]), 'client_readme' => new Client(['handler' => $handlers->readme]) ]); @@ -219,7 +219,7 @@ public function testTrackHandlesApiServerUnavailability(bool $development_mode): $this->metrics->track($request, $response); - if (!$development_mode) { + if ($fire_and_forget) { $this->assertTrue( true, 'When not in development mode, exceptions should not be thrown which means this assertion should pass.' @@ -351,7 +351,7 @@ public function testProjectBaseUrlDataCacheIsRefreshedIfStale(bool $development_ /** * @group getProjectBaseUrl */ - public function testProjectBaseUrlIsTemporarilyNullIfReadMeCallFailsWhileNotInDevelopmentMode(): void + public function testProjectBaseUrlIsTemporarilyNullIfReadMeCallFailsWhileInFireAndForgetMode(): void { $handlers = $this->getMockHandlers( new \GuzzleHttp\Psr7\Response(200), @@ -367,7 +367,7 @@ public function testProjectBaseUrlIsTemporarilyNullIfReadMeCallFailsWhileNotInDe ); $this->metrics = new Metrics($this->readme_api_key, $this->group_handler, [ - 'development_mode' => false, + 'fire_and_forget' => true, 'client' => new Client(['handler' => $handlers->metrics]), 'client_readme' => new Client(['handler' => $handlers->readme]) ]); @@ -407,7 +407,7 @@ public function testProjectBaseUrlFailsInDevelopmentModeIfReadMeCallHasErrorResp ); $this->metrics = new Metrics($this->readme_api_key, $this->group_handler, [ - 'development_mode' => true, + 'fire_and_forget' => false, 'client' => new Client(['handler' => $handlers->metrics]), 'client_readme' => new Client(['handler' => $handlers->readme]) ]); @@ -432,7 +432,7 @@ public function testProjectBaseUrlFailsInDevelopmentModeIfItCantTalkToReadMe(): ); $this->metrics = new Metrics($this->readme_api_key, $this->group_handler, [ - 'development_mode' => true, + 'fire_and_forget' => false, 'client' => new Client(['handler' => $handlers->metrics]), 'client_readme' => new Client(['handler' => $handlers->readme]) ]); @@ -511,4 +511,12 @@ public function providerDevelopmentModeToggle(): array 'development mode off' => [false], ]; } + + public function providerFireAndForgetModeToggle(): array + { + return [ + 'fireAndForget mode on' => [true], + 'fireAndForget mode off' => [false], + ]; + } }