-
Notifications
You must be signed in to change notification settings - Fork 186
Commit
* enable timeout for http transports Attempt to do our own discovery for some well-known PSR-18 clients, which allows for configuring timeout (and in future certificates, keys etc). This is not complete and a prototype for feedback, but I've updated an example to show that it works for Guzzle and Symfony http clients * improve client discovery * refactor, test, add more implementations * add timeout for logs and metrics
- Loading branch information
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,73 @@ | ||
<?php | ||
|
||
declare(strict_types=1); | ||
|
||
namespace OpenTelemetry\SDK\Common\Http\Psr\Client; | ||
|
||
use Generator; | ||
use Http\Discovery\Psr18ClientDiscovery; | ||
use OpenTelemetry\SDK\Common\Http\Psr\Client\Discovery\Buzz; | ||
use OpenTelemetry\SDK\Common\Http\Psr\Client\Discovery\CurlClient; | ||
use OpenTelemetry\SDK\Common\Http\Psr\Client\Discovery\DiscoveryInterface; | ||
use OpenTelemetry\SDK\Common\Http\Psr\Client\Discovery\Guzzle; | ||
use OpenTelemetry\SDK\Common\Http\Psr\Client\Discovery\Symfony; | ||
use Psr\Http\Client\ClientInterface; | ||
|
||
class Discovery | ||
{ | ||
private static ?array $discoverers; | ||
|
||
/** | ||
* @var list<class-string<DiscoveryInterface>> | ||
*/ | ||
private const DEFAULTS = [ | ||
Guzzle::class, | ||
Symfony::class, | ||
Buzz::class, | ||
CurlClient::class, | ||
]; | ||
|
||
/** | ||
* Attempt discovery of a configurable psr-18 http client, falling back to Psr18ClientDiscovery. | ||
*/ | ||
public static function find(array $options = []): ClientInterface | ||
{ | ||
$options = array_filter($options); | ||
|
||
foreach (self::discoverers() as $clientDiscovery) { | ||
/** @var DiscoveryInterface $clientDiscovery */ | ||
if ($clientDiscovery->available()) { | ||
return $clientDiscovery->create($options); | ||
} | ||
} | ||
|
||
return Psr18ClientDiscovery::find(); | ||
} | ||
|
||
/** | ||
* @internal | ||
*/ | ||
public static function setDiscoverers(array $discoverers): void | ||
{ | ||
self::$discoverers = $discoverers; | ||
} | ||
|
||
/** | ||
* @internal | ||
*/ | ||
public static function reset(): void | ||
{ | ||
self::$discoverers = null; | ||
} | ||
|
||
private static function discoverers(): Generator | ||
{ | ||
foreach (self::$discoverers ?? self::DEFAULTS as $discoverer) { | ||
if (is_string($discoverer)) { | ||
yield new $discoverer(); | ||
} else { | ||
yield $discoverer; | ||
} | ||
} | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
<?php | ||
|
||
declare(strict_types=1); | ||
|
||
namespace OpenTelemetry\SDK\Common\Http\Psr\Client\Discovery; | ||
|
||
use Buzz\Client\FileGetContents; | ||
Check warning on line 7 in src/SDK/Common/Http/Psr/Client/Discovery/Buzz.php GitHub Actions / php (8.2, false)
Check warning on line 7 in src/SDK/Common/Http/Psr/Client/Discovery/Buzz.php GitHub Actions / php (8.3, false)
Check warning on line 7 in src/SDK/Common/Http/Psr/Client/Discovery/Buzz.php GitHub Actions / php (8.1, false)
|
||
use Http\Discovery\Psr17FactoryDiscovery; | ||
use Psr\Http\Client\ClientInterface; | ||
|
||
class Buzz implements DiscoveryInterface | ||
{ | ||
/** | ||
* @phan-suppress PhanUndeclaredClassReference | ||
*/ | ||
public function available(): bool | ||
{ | ||
return class_exists(FileGetContents::class); | ||
Check warning on line 18 in src/SDK/Common/Http/Psr/Client/Discovery/Buzz.php GitHub Actions / php (8.2, false)
Check warning on line 18 in src/SDK/Common/Http/Psr/Client/Discovery/Buzz.php GitHub Actions / php (8.3, false)
Check warning on line 18 in src/SDK/Common/Http/Psr/Client/Discovery/Buzz.php GitHub Actions / php (8.1, false)
|
||
} | ||
|
||
/** | ||
* @phan-suppress PhanUndeclaredClassReference,PhanTypeMismatchReturn,PhanUndeclaredClassMethod | ||
*/ | ||
public function create(mixed $options): ClientInterface | ||
{ | ||
return new FileGetContents(Psr17FactoryDiscovery::findResponseFactory(), $options); | ||
Check warning on line 26 in src/SDK/Common/Http/Psr/Client/Discovery/Buzz.php GitHub Actions / php (8.2, false)
Check warning on line 26 in src/SDK/Common/Http/Psr/Client/Discovery/Buzz.php GitHub Actions / php (8.3, false)
Check warning on line 26 in src/SDK/Common/Http/Psr/Client/Discovery/Buzz.php GitHub Actions / php (8.1, false)
|
||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
<?php | ||
|
||
declare(strict_types=1); | ||
|
||
namespace OpenTelemetry\SDK\Common\Http\Psr\Client\Discovery; | ||
|
||
use Http\Client\Curl\Client; | ||
use Psr\Http\Client\ClientInterface; | ||
|
||
class CurlClient implements DiscoveryInterface | ||
{ | ||
/** | ||
* @phan-suppress PhanUndeclaredClassReference | ||
*/ | ||
public function available(): bool | ||
{ | ||
return extension_loaded('curl') && class_exists(Client::class); | ||
} | ||
|
||
/** | ||
* @phan-suppress PhanUndeclaredClassReference,PhanTypeMismatchReturn,PhanUndeclaredClassMethod | ||
* @psalm-suppress UndefinedClass,InvalidReturnType,InvalidReturnStatement | ||
*/ | ||
public function create(mixed $options): ClientInterface | ||
{ | ||
$options = [ | ||
\CURLOPT_TIMEOUT => $options['timeout'] ?? null, | ||
]; | ||
|
||
/** @phpstan-ignore-next-line */ | ||
return new Client(options: array_filter($options)); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
<?php | ||
|
||
declare(strict_types=1); | ||
|
||
namespace OpenTelemetry\SDK\Common\Http\Psr\Client\Discovery; | ||
|
||
use Psr\Http\Client\ClientInterface; | ||
|
||
interface DiscoveryInterface | ||
{ | ||
public function available(): bool; | ||
public function create(mixed $options): ClientInterface; | ||
} |