diff --git a/composer.json b/composer.json index f3354301..5d9b6a17 100644 --- a/composer.json +++ b/composer.json @@ -11,6 +11,11 @@ "ext-openssl": "*", "ext-sockets": "*", "ext-zlib": "*", + "php-http/discovery": "^1.14", + "psr/http-client": "^1.0", + "psr/http-client-implementation": "^1.0", + "psr/http-factory": "^1.0", + "psr/http-message": "^1.0", "psr/log": "^1.0|^2.0|^3.0", "psr/simple-cache": "^1.0", "ralouphie/getallheaders": "^2.0.5|^3.0", @@ -21,6 +26,7 @@ "composer-plugin-api": "^2.0", "cache/array-adapter": "^1.1", "doctrine/coding-standard": "^8.2", + "guzzlehttp/guzzle": "^7.3", "laravel/framework": "^5.5.0|^6.0|^7.0|^8.0", "laravel/lumen-framework": "^5.5.0|^6.0|^7.0|^8.0", "monolog/monolog": "^1.26|^2.2.0", diff --git a/composer.lock b/composer.lock index d9c2a559..1551425b 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "b2c4384c511ad39f1b2e2a54ae8ba374", + "content-hash": "81f355dcfc2f8897206425b6a3a83a8c", "packages": [ { "name": "brick/math", @@ -66,6 +66,557 @@ ], "time": "2021-08-15T20:50:18+00:00" }, + { + "name": "guzzlehttp/guzzle", + "version": "7.4.1", + "source": { + "type": "git", + "url": "https://github.com/guzzle/guzzle.git", + "reference": "ee0a041b1760e6a53d2a39c8c34115adc2af2c79" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/guzzle/guzzle/zipball/ee0a041b1760e6a53d2a39c8c34115adc2af2c79", + "reference": "ee0a041b1760e6a53d2a39c8c34115adc2af2c79", + "shasum": "" + }, + "require": { + "ext-json": "*", + "guzzlehttp/promises": "^1.5", + "guzzlehttp/psr7": "^1.8.3 || ^2.1", + "php": "^7.2.5 || ^8.0", + "psr/http-client": "^1.0", + "symfony/deprecation-contracts": "^2.2 || ^3.0" + }, + "provide": { + "psr/http-client-implementation": "1.0" + }, + "require-dev": { + "bamarni/composer-bin-plugin": "^1.4.1", + "ext-curl": "*", + "php-http/client-integration-tests": "^3.0", + "phpunit/phpunit": "^8.5.5 || ^9.3.5", + "psr/log": "^1.1 || ^2.0 || ^3.0" + }, + "suggest": { + "ext-curl": "Required for CURL handler support", + "ext-intl": "Required for Internationalized Domain Name (IDN) support", + "psr/log": "Required for using the Log middleware" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "7.4-dev" + } + }, + "autoload": { + "psr-4": { + "GuzzleHttp\\": "src/" + }, + "files": [ + "src/functions_include.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Graham Campbell", + "email": "hello@gjcampbell.co.uk", + "homepage": "https://github.com/GrahamCampbell" + }, + { + "name": "Michael Dowling", + "email": "mtdowling@gmail.com", + "homepage": "https://github.com/mtdowling" + }, + { + "name": "Jeremy Lindblom", + "email": "jeremeamia@gmail.com", + "homepage": "https://github.com/jeremeamia" + }, + { + "name": "George Mponos", + "email": "gmponos@gmail.com", + "homepage": "https://github.com/gmponos" + }, + { + "name": "Tobias Nyholm", + "email": "tobias.nyholm@gmail.com", + "homepage": "https://github.com/Nyholm" + }, + { + "name": "Márk Sági-Kazár", + "email": "mark.sagikazar@gmail.com", + "homepage": "https://github.com/sagikazarmark" + }, + { + "name": "Tobias Schultze", + "email": "webmaster@tubo-world.de", + "homepage": "https://github.com/Tobion" + } + ], + "description": "Guzzle is a PHP HTTP client library", + "keywords": [ + "client", + "curl", + "framework", + "http", + "http client", + "psr-18", + "psr-7", + "rest", + "web service" + ], + "support": { + "issues": "https://github.com/guzzle/guzzle/issues", + "source": "https://github.com/guzzle/guzzle/tree/7.4.1" + }, + "funding": [ + { + "url": "https://github.com/GrahamCampbell", + "type": "github" + }, + { + "url": "https://github.com/Nyholm", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/guzzlehttp/guzzle", + "type": "tidelift" + } + ], + "time": "2021-12-06T18:43:05+00:00" + }, + { + "name": "guzzlehttp/promises", + "version": "1.5.1", + "source": { + "type": "git", + "url": "https://github.com/guzzle/promises.git", + "reference": "fe752aedc9fd8fcca3fe7ad05d419d32998a06da" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/guzzle/promises/zipball/fe752aedc9fd8fcca3fe7ad05d419d32998a06da", + "reference": "fe752aedc9fd8fcca3fe7ad05d419d32998a06da", + "shasum": "" + }, + "require": { + "php": ">=5.5" + }, + "require-dev": { + "symfony/phpunit-bridge": "^4.4 || ^5.1" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.5-dev" + } + }, + "autoload": { + "psr-4": { + "GuzzleHttp\\Promise\\": "src/" + }, + "files": [ + "src/functions_include.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Graham Campbell", + "email": "hello@gjcampbell.co.uk", + "homepage": "https://github.com/GrahamCampbell" + }, + { + "name": "Michael Dowling", + "email": "mtdowling@gmail.com", + "homepage": "https://github.com/mtdowling" + }, + { + "name": "Tobias Nyholm", + "email": "tobias.nyholm@gmail.com", + "homepage": "https://github.com/Nyholm" + }, + { + "name": "Tobias Schultze", + "email": "webmaster@tubo-world.de", + "homepage": "https://github.com/Tobion" + } + ], + "description": "Guzzle promises library", + "keywords": [ + "promise" + ], + "support": { + "issues": "https://github.com/guzzle/promises/issues", + "source": "https://github.com/guzzle/promises/tree/1.5.1" + }, + "funding": [ + { + "url": "https://github.com/GrahamCampbell", + "type": "github" + }, + { + "url": "https://github.com/Nyholm", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/guzzlehttp/promises", + "type": "tidelift" + } + ], + "time": "2021-10-22T20:56:57+00:00" + }, + { + "name": "guzzlehttp/psr7", + "version": "2.1.0", + "source": { + "type": "git", + "url": "https://github.com/guzzle/psr7.git", + "reference": "089edd38f5b8abba6cb01567c2a8aaa47cec4c72" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/guzzle/psr7/zipball/089edd38f5b8abba6cb01567c2a8aaa47cec4c72", + "reference": "089edd38f5b8abba6cb01567c2a8aaa47cec4c72", + "shasum": "" + }, + "require": { + "php": "^7.2.5 || ^8.0", + "psr/http-factory": "^1.0", + "psr/http-message": "^1.0", + "ralouphie/getallheaders": "^3.0" + }, + "provide": { + "psr/http-factory-implementation": "1.0", + "psr/http-message-implementation": "1.0" + }, + "require-dev": { + "bamarni/composer-bin-plugin": "^1.4.1", + "http-interop/http-factory-tests": "^0.9", + "phpunit/phpunit": "^8.5.8 || ^9.3.10" + }, + "suggest": { + "laminas/laminas-httphandlerrunner": "Emit PSR-7 responses" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.1-dev" + } + }, + "autoload": { + "psr-4": { + "GuzzleHttp\\Psr7\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Graham Campbell", + "email": "hello@gjcampbell.co.uk", + "homepage": "https://github.com/GrahamCampbell" + }, + { + "name": "Michael Dowling", + "email": "mtdowling@gmail.com", + "homepage": "https://github.com/mtdowling" + }, + { + "name": "George Mponos", + "email": "gmponos@gmail.com", + "homepage": "https://github.com/gmponos" + }, + { + "name": "Tobias Nyholm", + "email": "tobias.nyholm@gmail.com", + "homepage": "https://github.com/Nyholm" + }, + { + "name": "Márk Sági-Kazár", + "email": "mark.sagikazar@gmail.com", + "homepage": "https://github.com/sagikazarmark" + }, + { + "name": "Tobias Schultze", + "email": "webmaster@tubo-world.de", + "homepage": "https://github.com/Tobion" + }, + { + "name": "Márk Sági-Kazár", + "email": "mark.sagikazar@gmail.com", + "homepage": "https://sagikazarmark.hu" + } + ], + "description": "PSR-7 message implementation that also provides common utility methods", + "keywords": [ + "http", + "message", + "psr-7", + "request", + "response", + "stream", + "uri", + "url" + ], + "support": { + "issues": "https://github.com/guzzle/psr7/issues", + "source": "https://github.com/guzzle/psr7/tree/2.1.0" + }, + "funding": [ + { + "url": "https://github.com/GrahamCampbell", + "type": "github" + }, + { + "url": "https://github.com/Nyholm", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/guzzlehttp/psr7", + "type": "tidelift" + } + ], + "time": "2021-10-06T17:43:30+00:00" + }, + { + "name": "php-http/discovery", + "version": "1.14.1", + "source": { + "type": "git", + "url": "https://github.com/php-http/discovery.git", + "reference": "de90ab2b41d7d61609f504e031339776bc8c7223" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-http/discovery/zipball/de90ab2b41d7d61609f504e031339776bc8c7223", + "reference": "de90ab2b41d7d61609f504e031339776bc8c7223", + "shasum": "" + }, + "require": { + "php": "^7.1 || ^8.0" + }, + "conflict": { + "nyholm/psr7": "<1.0" + }, + "require-dev": { + "graham-campbell/phpspec-skip-example-extension": "^5.0", + "php-http/httplug": "^1.0 || ^2.0", + "php-http/message-factory": "^1.0", + "phpspec/phpspec": "^5.1 || ^6.1", + "puli/composer-plugin": "1.0.0-beta10" + }, + "suggest": { + "php-http/message": "Allow to use Guzzle, Diactoros or Slim Framework factories" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.9-dev" + } + }, + "autoload": { + "psr-4": { + "Http\\Discovery\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Márk Sági-Kazár", + "email": "mark.sagikazar@gmail.com" + } + ], + "description": "Finds installed HTTPlug implementations and PSR-7 message factories", + "homepage": "http://php-http.org", + "keywords": [ + "adapter", + "client", + "discovery", + "factory", + "http", + "message", + "psr7" + ], + "support": { + "issues": "https://github.com/php-http/discovery/issues", + "source": "https://github.com/php-http/discovery/tree/1.14.1" + }, + "time": "2021-09-18T07:57:46+00:00" + }, + { + "name": "psr/http-client", + "version": "1.0.1", + "source": { + "type": "git", + "url": "https://github.com/php-fig/http-client.git", + "reference": "2dfb5f6c5eff0e91e20e913f8c5452ed95b86621" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/http-client/zipball/2dfb5f6c5eff0e91e20e913f8c5452ed95b86621", + "reference": "2dfb5f6c5eff0e91e20e913f8c5452ed95b86621", + "shasum": "" + }, + "require": { + "php": "^7.0 || ^8.0", + "psr/http-message": "^1.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Http\\Client\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" + } + ], + "description": "Common interface for HTTP clients", + "homepage": "https://github.com/php-fig/http-client", + "keywords": [ + "http", + "http-client", + "psr", + "psr-18" + ], + "support": { + "source": "https://github.com/php-fig/http-client/tree/master" + }, + "time": "2020-06-29T06:28:15+00:00" + }, + { + "name": "psr/http-factory", + "version": "1.0.1", + "source": { + "type": "git", + "url": "https://github.com/php-fig/http-factory.git", + "reference": "12ac7fcd07e5b077433f5f2bee95b3a771bf61be" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/http-factory/zipball/12ac7fcd07e5b077433f5f2bee95b3a771bf61be", + "reference": "12ac7fcd07e5b077433f5f2bee95b3a771bf61be", + "shasum": "" + }, + "require": { + "php": ">=7.0.0", + "psr/http-message": "^1.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Http\\Message\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" + } + ], + "description": "Common interfaces for PSR-7 HTTP message factories", + "keywords": [ + "factory", + "http", + "message", + "psr", + "psr-17", + "psr-7", + "request", + "response" + ], + "support": { + "source": "https://github.com/php-fig/http-factory/tree/master" + }, + "time": "2019-04-30T12:38:16+00:00" + }, + { + "name": "psr/http-message", + "version": "1.0.1", + "source": { + "type": "git", + "url": "https://github.com/php-fig/http-message.git", + "reference": "f6561bf28d520154e4b0ec72be95418abe6d9363" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/http-message/zipball/f6561bf28d520154e4b0ec72be95418abe6d9363", + "reference": "f6561bf28d520154e4b0ec72be95418abe6d9363", + "shasum": "" + }, + "require": { + "php": ">=5.3.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Http\\Message\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" + } + ], + "description": "Common interface for HTTP messages", + "homepage": "https://github.com/php-fig/http-message", + "keywords": [ + "http", + "http-message", + "psr", + "psr-7", + "request", + "response" + ], + "support": { + "source": "https://github.com/php-fig/http-message/tree/master" + }, + "time": "2016-08-06T14:39:51+00:00" + }, { "name": "psr/log", "version": "1.1.4", @@ -388,6 +939,73 @@ ], "time": "2021-09-25T23:10:38+00:00" }, + { + "name": "symfony/deprecation-contracts", + "version": "v3.0.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/deprecation-contracts.git", + "reference": "c726b64c1ccfe2896cb7df2e1331c357ad1c8ced" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/c726b64c1ccfe2896cb7df2e1331c357ad1c8ced", + "reference": "c726b64c1ccfe2896cb7df2e1331c357ad1c8ced", + "shasum": "" + }, + "require": { + "php": ">=8.0.2" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "3.0-dev" + }, + "thanks": { + "name": "symfony/contracts", + "url": "https://github.com/symfony/contracts" + } + }, + "autoload": { + "files": [ + "function.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "A generic function and convention to trigger deprecation notices", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/deprecation-contracts/tree/v3.0.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2021-11-01T23:48:49+00:00" + }, { "name": "symfony/polyfill-ctype", "version": "v1.24.0", @@ -7537,73 +8155,6 @@ ], "time": "2021-12-29T10:10:35+00:00" }, - { - "name": "symfony/deprecation-contracts", - "version": "v3.0.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/deprecation-contracts.git", - "reference": "c726b64c1ccfe2896cb7df2e1331c357ad1c8ced" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/c726b64c1ccfe2896cb7df2e1331c357ad1c8ced", - "reference": "c726b64c1ccfe2896cb7df2e1331c357ad1c8ced", - "shasum": "" - }, - "require": { - "php": ">=8.0.2" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "3.0-dev" - }, - "thanks": { - "name": "symfony/contracts", - "url": "https://github.com/symfony/contracts" - } - }, - "autoload": { - "files": [ - "function.php" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "A generic function and convention to trigger deprecation notices", - "homepage": "https://symfony.com", - "support": { - "source": "https://github.com/symfony/deprecation-contracts/tree/v3.0.0" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2021-11-01T23:48:49+00:00" - }, { "name": "symfony/doctrine-bridge", "version": "v6.0.2", diff --git a/src/Errors/ScoutClient/GuzzleErrorReportingClient.php b/src/Errors/ScoutClient/GuzzleErrorReportingClient.php deleted file mode 100644 index 280ecedf..00000000 --- a/src/Errors/ScoutClient/GuzzleErrorReportingClient.php +++ /dev/null @@ -1,136 +0,0 @@ -client = $client; - $this->compressPayload = $compressPayload; - $this->config = $config; - $this->logger = $logger; - $this->findApplicationRoot = $findApplicationRoot; - } - - public function sendErrorToScout(ErrorEvent $errorEvent): void // @todo check if we want to bulk send them - probably - { - // @todo we're not exposing any async functionality here, but for those with an event loop, that would be better - $this->client - ->sendAsync($this->psrRequestFromEvents([$errorEvent])) - ->then( - function (ResponseInterface $response): void { - $statusCode = $response->getStatusCode(); - if ($statusCode !== self::SCOUT_ACCEPTED_STATUS_CODE) { - $this->logger->info( - sprintf('ErrorEvent sending returned unexpected status code %d', $statusCode), - [ - 'responseBody' => (string) $response->getBody(), - ] - ); - - return; - } - - $this->logger->debug('Sent an error payload to Scout Error Reporting'); - }, - function (RequestException $requestException): void { - $this->logger->warning( - sprintf('ErrorEvent could not be sent to Scout: %s', $requestException->getMessage()), - ['exception' => $requestException] - ); - } - ) - ->wait(); - } - - private function memoizedErrorsUrl(): string - { - if ($this->memoizedErrorsUrl === null) { - $this->memoizedErrorsUrl = rtrim((string) $this->config->get(ConfigKey::ERRORS_HOST), '/') . self::SCOUT_REPORTING_PATH; - } - - return $this->memoizedErrorsUrl; - } - - /** - * @param list $errorEvent - * // @todo Type check this to require at least one errorEvent - */ - private function psrRequestFromEvents(array $errorEvent): RequestInterface - { - return new Request( - 'POST', - $this->memoizedErrorsUrl() . '?' . http_build_query([ - 'key' => $this->config->get(ConfigKey::APPLICATION_KEY), - 'name' => $this->config->get(ConfigKey::APPLICATION_NAME), - ]), - [ - 'Agent-Hostname' => DetermineHostname::withConfig($this->config), - 'Content-Encoding' => 'gzip', // Must be gzipped - 'Content-Type' => 'application/json', - 'X-Error-Count' => (string) count($errorEvent), - ], - ($this->compressPayload)(json_encode([ - 'notifier' => 'scout_apm_php', - 'environment' => '', - 'root' => ($this->findApplicationRoot)(), - 'problems' => array_map( - function (ErrorEvent $errorEvent): array { - return $errorEvent->toJsonableArray( - $this->config, - Superglobals::session(), // @todo probably inject session/env - Superglobals::env(), // @todo probably inject session/env - Superglobals::request() // @todo probably inject session/env - ); - }, - $errorEvent - ), - ])) - ); - } -} diff --git a/src/Errors/ScoutClient/HttpErrorReportingClient.php b/src/Errors/ScoutClient/HttpErrorReportingClient.php new file mode 100644 index 00000000..93e33975 --- /dev/null +++ b/src/Errors/ScoutClient/HttpErrorReportingClient.php @@ -0,0 +1,141 @@ +client = $client; + $this->requestFactory = $requestFactory; + $this->streamFactory = $streamFactory; + $this->compressPayload = $compressPayload; + $this->config = $config; + $this->logger = $logger; + $this->findApplicationRoot = $findApplicationRoot; + } + + public function sendErrorToScout(ErrorEvent $errorEvent): void // @todo check if we want to bulk send them - probably + { + try { + $response = $this->client->sendRequest($this->psrRequestFromEvents([$errorEvent])); + } catch (ClientExceptionInterface $clientException) { + $this->logger->warning( + sprintf('ErrorEvent could not be sent to Scout [ClientException]: %s', $clientException->getMessage()), + ['exception' => $clientException] + ); + + return; + } + + $statusCode = $response->getStatusCode(); + if ($statusCode !== self::SCOUT_ACCEPTED_STATUS_CODE) { + $this->logger->info( + sprintf('ErrorEvent sending returned unexpected status code %d', $statusCode), + [ + 'responseBody' => (string) $response->getBody(), + ] + ); + + return; + } + + $this->logger->debug('Sent an error payload to Scout Error Reporting'); + } + + private function memoizedErrorsUrl(): string + { + if ($this->memoizedErrorsUrl === null) { + $this->memoizedErrorsUrl = rtrim((string) $this->config->get(ConfigKey::ERRORS_HOST), '/') . self::SCOUT_REPORTING_PATH; + } + + return $this->memoizedErrorsUrl; + } + + /** + * @param non-empty-list $errorEvent + */ + private function psrRequestFromEvents(array $errorEvent): RequestInterface + { + return $this->requestFactory + ->createRequest( + 'POST', + $this->memoizedErrorsUrl() . '?' . http_build_query([ + 'key' => $this->config->get(ConfigKey::APPLICATION_KEY), + 'name' => $this->config->get(ConfigKey::APPLICATION_NAME), + ]) + ) + ->withHeader('Agent-Hostname', DetermineHostname::withConfig($this->config)) + ->withHeader('Content-Encoding', 'gzip') // Must be gzipped + ->withHeader('Content-Type', 'application/json') + ->withHeader('X-Error-Count', (string) count($errorEvent)) + ->withBody($this->streamFactory->createStream( + ($this->compressPayload)(json_encode([ + 'notifier' => 'scout_apm_php', + 'environment' => '', + 'root' => ($this->findApplicationRoot)(), + 'problems' => array_map( + function (ErrorEvent $errorEvent): array { + return $errorEvent->toJsonableArray( + $this->config, + Superglobals::session(), // @todo probably inject session/env + Superglobals::env(), // @todo probably inject session/env + Superglobals::request() // @todo probably inject session/env + ); + }, + $errorEvent + ), + ])) + )); + } +} diff --git a/src/Errors/ScoutErrorHandling.php b/src/Errors/ScoutErrorHandling.php index 39afea18..49fb11c5 100644 --- a/src/Errors/ScoutErrorHandling.php +++ b/src/Errors/ScoutErrorHandling.php @@ -5,12 +5,13 @@ namespace Scoutapm\Errors; use ErrorException; -use GuzzleHttp\Client as GuzzleClient; +use Http\Discovery\Psr17FactoryDiscovery; +use Http\Discovery\Psr18ClientDiscovery; use Psr\Log\LoggerInterface; use Scoutapm\Config; use Scoutapm\Errors\ScoutClient\CompressPayload; use Scoutapm\Errors\ScoutClient\ErrorReportingClient; -use Scoutapm\Errors\ScoutClient\GuzzleErrorReportingClient; +use Scoutapm\Errors\ScoutClient\HttpErrorReportingClient; use Scoutapm\Events\Request\Request; use Scoutapm\Helper\FindApplicationRoot; use Scoutapm\Helper\LocateFileOrFolder; @@ -59,8 +60,10 @@ public function __construct(ErrorReportingClient $reportingClient, Config $confi public static function factory(Config $config, LoggerInterface $logger): self { return new self( - new GuzzleErrorReportingClient( - new GuzzleClient(), + new HttpErrorReportingClient( + Psr18ClientDiscovery::find(), + Psr17FactoryDiscovery::findRequestFactory(), + Psr17FactoryDiscovery::findStreamFactory(), new CompressPayload(), $config, $logger, diff --git a/tests/Unit/Errors/ScoutClient/GuzzleErrorReportingClientTest.php b/tests/Unit/Errors/ScoutClient/HttpErrorReportingClient.php similarity index 65% rename from tests/Unit/Errors/ScoutClient/GuzzleErrorReportingClientTest.php rename to tests/Unit/Errors/ScoutClient/HttpErrorReportingClient.php index 195a347b..e1dffe8c 100644 --- a/tests/Unit/Errors/ScoutClient/GuzzleErrorReportingClientTest.php +++ b/tests/Unit/Errors/ScoutClient/HttpErrorReportingClient.php @@ -6,8 +6,8 @@ use PHPUnit\Framework\TestCase; -/** @covers \Scoutapm\Errors\ScoutClient\GuzzleErrorReportingClient */ -final class GuzzleErrorReportingClientTest extends TestCase +/** @covers \Scoutapm\Errors\ScoutClient\HttpErrorReportingClient */ +final class HttpErrorReportingClient extends TestCase { public function testSendErrorToScout(): void {