diff options
author | Andrew Dolgov <[email protected]> | 2023-10-20 17:12:29 +0300 |
---|---|---|
committer | Andrew Dolgov <[email protected]> | 2023-10-20 21:13:39 +0300 |
commit | cdd7ad020e165fe680703b6d3319b908b682fb7a (patch) | |
tree | b51eb09b7b4587e8fbc5624ac8d88d28cfcd0b04 /vendor/open-telemetry/sdk/Common | |
parent | 45a9ff0c88cbd33892ff16ab837e9059937d656e (diff) |
jaeger-client -> opentelemetry
Diffstat (limited to 'vendor/open-telemetry/sdk/Common')
69 files changed, 3907 insertions, 0 deletions
diff --git a/vendor/open-telemetry/sdk/Common/Adapter/HttpDiscovery/DependencyResolver.php b/vendor/open-telemetry/sdk/Common/Adapter/HttpDiscovery/DependencyResolver.php new file mode 100644 index 000000000..8ba992f9a --- /dev/null +++ b/vendor/open-telemetry/sdk/Common/Adapter/HttpDiscovery/DependencyResolver.php @@ -0,0 +1,83 @@ +<?php + +declare(strict_types=1); + +namespace OpenTelemetry\SDK\Common\Adapter\HttpDiscovery; + +use Http\Client\HttpAsyncClient; +use OpenTelemetry\SDK\Common\Http\DependencyResolverInterface; +use OpenTelemetry\SDK\Common\Http\HttpPlug\Client\ResolverInterface as HttpPlugClientResolverInterface; +use OpenTelemetry\SDK\Common\Http\Psr\Client\ResolverInterface as PsrClientResolverInterface; +use OpenTelemetry\SDK\Common\Http\Psr\Message\FactoryResolverInterface as MessageFactoryResolverInterface; +use Psr\Http\Client\ClientInterface; +use Psr\Http\Message\RequestFactoryInterface; +use Psr\Http\Message\ResponseFactoryInterface; +use Psr\Http\Message\ServerRequestFactoryInterface; +use Psr\Http\Message\StreamFactoryInterface; +use Psr\Http\Message\UploadedFileFactoryInterface; +use Psr\Http\Message\UriFactoryInterface; + +final class DependencyResolver implements DependencyResolverInterface +{ + private MessageFactoryResolverInterface $messageFactoryResolver; + private PsrClientResolverInterface $psrClientResolver; + private HttpPlugClientResolverInterface $httpPlugClientResolver; + + public function __construct( + ?MessageFactoryResolverInterface $messageFactoryResolver = null, + ?PsrClientResolverInterface $psrClientResolver = null, + ?HttpPlugClientResolverInterface $httpPlugClientResolver = null + ) { + $this->messageFactoryResolver = $messageFactoryResolver ?? MessageFactoryResolver::create(); + $this->psrClientResolver = $psrClientResolver ?? PsrClientResolver::create(); + $this->httpPlugClientResolver = $httpPlugClientResolver ?? HttpPlugClientResolver::create(); + } + + public static function create( + ?MessageFactoryResolverInterface $messageFactoryResolver = null, + ?PsrClientResolverInterface $psrClientResolver = null, + ?HttpPlugClientResolverInterface $httpPlugClientResolver = null + ): self { + return new self($messageFactoryResolver, $psrClientResolver, $httpPlugClientResolver); + } + + public function resolveRequestFactory(): RequestFactoryInterface + { + return $this->messageFactoryResolver->resolveRequestFactory(); + } + + public function resolveResponseFactory(): ResponseFactoryInterface + { + return $this->messageFactoryResolver->resolveResponseFactory(); + } + + public function resolveServerRequestFactory(): ServerRequestFactoryInterface + { + return $this->messageFactoryResolver->resolveServerRequestFactory(); + } + + public function resolveStreamFactory(): StreamFactoryInterface + { + return $this->messageFactoryResolver->resolveStreamFactory(); + } + + public function resolveUploadedFileFactory(): UploadedFileFactoryInterface + { + return $this->messageFactoryResolver->resolveUploadedFileFactory(); + } + + public function resolveUriFactory(): UriFactoryInterface + { + return $this->messageFactoryResolver->resolveUriFactory(); + } + + public function resolveHttpPlugAsyncClient(): HttpAsyncClient + { + return $this->httpPlugClientResolver->resolveHttpPlugAsyncClient(); + } + + public function resolvePsrClient(): ClientInterface + { + return $this->psrClientResolver->resolvePsrClient(); + } +} diff --git a/vendor/open-telemetry/sdk/Common/Adapter/HttpDiscovery/HttpPlugClientResolver.php b/vendor/open-telemetry/sdk/Common/Adapter/HttpDiscovery/HttpPlugClientResolver.php new file mode 100644 index 000000000..9751984ee --- /dev/null +++ b/vendor/open-telemetry/sdk/Common/Adapter/HttpDiscovery/HttpPlugClientResolver.php @@ -0,0 +1,29 @@ +<?php + +declare(strict_types=1); + +namespace OpenTelemetry\SDK\Common\Adapter\HttpDiscovery; + +use Http\Client\HttpAsyncClient; +use Http\Discovery\HttpAsyncClientDiscovery; +use OpenTelemetry\SDK\Common\Http\HttpPlug\Client\ResolverInterface; + +final class HttpPlugClientResolver implements ResolverInterface +{ + private ?HttpAsyncClient $httpAsyncClient; + + public function __construct(?HttpAsyncClient $httpAsyncClient = null) + { + $this->httpAsyncClient = $httpAsyncClient; + } + + public static function create(?HttpAsyncClient $httpAsyncClient = null): self + { + return new self($httpAsyncClient); + } + + public function resolveHttpPlugAsyncClient(): HttpAsyncClient + { + return $this->httpAsyncClient ??= HttpAsyncClientDiscovery::find(); + } +} diff --git a/vendor/open-telemetry/sdk/Common/Adapter/HttpDiscovery/MessageFactoryResolver.php b/vendor/open-telemetry/sdk/Common/Adapter/HttpDiscovery/MessageFactoryResolver.php new file mode 100644 index 000000000..6ed0895ff --- /dev/null +++ b/vendor/open-telemetry/sdk/Common/Adapter/HttpDiscovery/MessageFactoryResolver.php @@ -0,0 +1,88 @@ +<?php + +declare(strict_types=1); + +namespace OpenTelemetry\SDK\Common\Adapter\HttpDiscovery; + +use Http\Discovery\Psr17FactoryDiscovery; +use OpenTelemetry\SDK\Common\Http\Psr\Message\FactoryResolverInterface; +use Psr\Http\Message\RequestFactoryInterface; +use Psr\Http\Message\ResponseFactoryInterface; +use Psr\Http\Message\ServerRequestFactoryInterface; +use Psr\Http\Message\StreamFactoryInterface; +use Psr\Http\Message\UploadedFileFactoryInterface; +use Psr\Http\Message\UriFactoryInterface; + +final class MessageFactoryResolver implements FactoryResolverInterface +{ + private ?RequestFactoryInterface $requestFactory; + private ?ResponseFactoryInterface $responseFactory; + private ?ServerRequestFactoryInterface $serverRequestFactory; + private ?StreamFactoryInterface $streamFactory; + private ?UploadedFileFactoryInterface $uploadedFileFactory; + private ?UriFactoryInterface $uriFactory; + + public function __construct( + ?RequestFactoryInterface $requestFactory = null, + ?ResponseFactoryInterface $responseFactory = null, + ?ServerRequestFactoryInterface $serverRequestFactory = null, + ?StreamFactoryInterface $streamFactory = null, + ?UploadedFileFactoryInterface $uploadedFileFactory = null, + ?UriFactoryInterface $uriFactory = null + ) { + $this->requestFactory = $requestFactory; + $this->responseFactory = $responseFactory; + $this->serverRequestFactory = $serverRequestFactory; + $this->streamFactory = $streamFactory; + $this->uploadedFileFactory = $uploadedFileFactory; + $this->uriFactory = $uriFactory; + } + + public static function create( + ?RequestFactoryInterface $requestFactory = null, + ?ResponseFactoryInterface $responseFactory = null, + ?ServerRequestFactoryInterface $serverRequestFactory = null, + ?StreamFactoryInterface $streamFactory = null, + ?UploadedFileFactoryInterface $uploadedFileFactory = null, + ?UriFactoryInterface $uriFactory = null + ): self { + return new self( + $requestFactory, + $responseFactory, + $serverRequestFactory, + $streamFactory, + $uploadedFileFactory, + $uriFactory + ); + } + + public function resolveRequestFactory(): RequestFactoryInterface + { + return $this->requestFactory ??= Psr17FactoryDiscovery::findRequestFactory(); + } + + public function resolveResponseFactory(): ResponseFactoryInterface + { + return $this->responseFactory ??= Psr17FactoryDiscovery::findResponseFactory(); + } + + public function resolveServerRequestFactory(): ServerRequestFactoryInterface + { + return $this->serverRequestFactory ??= Psr17FactoryDiscovery::findServerRequestFactory(); + } + + public function resolveStreamFactory(): StreamFactoryInterface + { + return $this->streamFactory ??= Psr17FactoryDiscovery::findStreamFactory(); + } + + public function resolveUploadedFileFactory(): UploadedFileFactoryInterface + { + return $this->uploadedFileFactory ??= Psr17FactoryDiscovery::findUploadedFileFactory(); + } + + public function resolveUriFactory(): UriFactoryInterface + { + return $this->uriFactory ??= Psr17FactoryDiscovery::findUriFactory(); + } +} diff --git a/vendor/open-telemetry/sdk/Common/Adapter/HttpDiscovery/PsrClientResolver.php b/vendor/open-telemetry/sdk/Common/Adapter/HttpDiscovery/PsrClientResolver.php new file mode 100644 index 000000000..46fb36312 --- /dev/null +++ b/vendor/open-telemetry/sdk/Common/Adapter/HttpDiscovery/PsrClientResolver.php @@ -0,0 +1,29 @@ +<?php + +declare(strict_types=1); + +namespace OpenTelemetry\SDK\Common\Adapter\HttpDiscovery; + +use Http\Discovery\Psr18ClientDiscovery; +use OpenTelemetry\SDK\Common\Http\Psr\Client\ResolverInterface; +use Psr\Http\Client\ClientInterface; + +final class PsrClientResolver implements ResolverInterface +{ + private ?ClientInterface $client; + + public function __construct(?ClientInterface $client = null) + { + $this->client = $client; + } + + public static function create(?ClientInterface $client = null): self + { + return new self($client); + } + + public function resolvePsrClient(): ClientInterface + { + return $this->client ??= Psr18ClientDiscovery::find(); + } +} diff --git a/vendor/open-telemetry/sdk/Common/Attribute/AttributeValidator.php b/vendor/open-telemetry/sdk/Common/Attribute/AttributeValidator.php new file mode 100644 index 000000000..e9a1f7334 --- /dev/null +++ b/vendor/open-telemetry/sdk/Common/Attribute/AttributeValidator.php @@ -0,0 +1,58 @@ +<?php + +declare(strict_types=1); + +namespace OpenTelemetry\SDK\Common\Attribute; + +class AttributeValidator implements AttributeValidatorInterface +{ + private const PRIMITIVES = [ + 'string', + 'integer', + 'double', + 'boolean', + ]; + private const NUMERICS = [ + 'double', + 'integer', + ]; + + /** + * Validate whether a value is a primitive, or a homogeneous array of primitives (treating int/double as equivalent). + * @see https://github.com/open-telemetry/opentelemetry-specification/blob/v1.21.0/specification/common/README.md#attribute + */ + public function validate($value): bool + { + if (is_array($value)) { + return $this->validateArray($value); + } + + return in_array(gettype($value), self::PRIMITIVES); + } + + private function validateArray(array $value): bool + { + if ($value === []) { + return true; + } + $type = gettype(reset($value)); + if (!in_array($type, self::PRIMITIVES)) { + return false; + } + foreach ($value as $v) { + if (in_array(gettype($v), self::NUMERICS) && in_array($type, self::NUMERICS)) { + continue; + } + if (gettype($v) !== $type) { + return false; + } + } + + return true; + } + + public function getInvalidMessage(): string + { + return 'attribute with non-primitive or non-homogeneous array of primitives dropped'; + } +} diff --git a/vendor/open-telemetry/sdk/Common/Attribute/AttributeValidatorInterface.php b/vendor/open-telemetry/sdk/Common/Attribute/AttributeValidatorInterface.php new file mode 100644 index 000000000..afbfba6e7 --- /dev/null +++ b/vendor/open-telemetry/sdk/Common/Attribute/AttributeValidatorInterface.php @@ -0,0 +1,11 @@ +<?php + +declare(strict_types=1); + +namespace OpenTelemetry\SDK\Common\Attribute; + +interface AttributeValidatorInterface +{ + public function validate($value): bool; + public function getInvalidMessage(): string; +} diff --git a/vendor/open-telemetry/sdk/Common/Attribute/Attributes.php b/vendor/open-telemetry/sdk/Common/Attribute/Attributes.php new file mode 100644 index 000000000..bb131ce94 --- /dev/null +++ b/vendor/open-telemetry/sdk/Common/Attribute/Attributes.php @@ -0,0 +1,67 @@ +<?php + +declare(strict_types=1); + +namespace OpenTelemetry\SDK\Common\Attribute; + +use function array_key_exists; +use IteratorAggregate; +use Traversable; + +final class Attributes implements AttributesInterface, IteratorAggregate +{ + private array $attributes; + private int $droppedAttributesCount; + + /** + * @internal + */ + public function __construct(array $attributes, int $droppedAttributesCount) + { + $this->attributes = $attributes; + $this->droppedAttributesCount = $droppedAttributesCount; + } + + public static function create(iterable $attributes): AttributesInterface + { + return self::factory()->builder($attributes)->build(); + } + + public static function factory(?int $attributeCountLimit = null, ?int $attributeValueLengthLimit = null): AttributesFactoryInterface + { + return new AttributesFactory($attributeCountLimit, $attributeValueLengthLimit); + } + + public function has(string $name): bool + { + return array_key_exists($name, $this->attributes); + } + + public function get(string $name) + { + return $this->attributes[$name] ?? null; + } + + /** @psalm-mutation-free */ + public function count(): int + { + return \count($this->attributes); + } + + public function getIterator(): Traversable + { + foreach ($this->attributes as $key => $value) { + yield (string) $key => $value; + } + } + + public function toArray(): array + { + return $this->attributes; + } + + public function getDroppedAttributesCount(): int + { + return $this->droppedAttributesCount; + } +} diff --git a/vendor/open-telemetry/sdk/Common/Attribute/AttributesBuilder.php b/vendor/open-telemetry/sdk/Common/Attribute/AttributesBuilder.php new file mode 100644 index 000000000..5c1150638 --- /dev/null +++ b/vendor/open-telemetry/sdk/Common/Attribute/AttributesBuilder.php @@ -0,0 +1,120 @@ +<?php + +declare(strict_types=1); + +namespace OpenTelemetry\SDK\Common\Attribute; + +use function array_key_exists; +use function count; +use function is_array; +use function is_string; +use function mb_substr; +use OpenTelemetry\API\Behavior\LogsMessagesTrait; + +/** + * @internal + */ +final class AttributesBuilder implements AttributesBuilderInterface +{ + use LogsMessagesTrait; + + private array $attributes; + private ?int $attributeCountLimit; + private ?int $attributeValueLengthLimit; + private int $droppedAttributesCount; + private AttributeValidatorInterface $attributeValidator; + + public function __construct( + array $attributes, + ?int $attributeCountLimit, + ?int $attributeValueLengthLimit, + int $droppedAttributesCount, + ?AttributeValidatorInterface $attributeValidator + ) { + $this->attributes = $attributes; + $this->attributeCountLimit = $attributeCountLimit; + $this->attributeValueLengthLimit = $attributeValueLengthLimit; + $this->droppedAttributesCount = $droppedAttributesCount; + $this->attributeValidator = $attributeValidator ?? new AttributeValidator(); + } + + public function build(): AttributesInterface + { + return new Attributes($this->attributes, $this->droppedAttributesCount); + } + + public function offsetExists($offset): bool + { + return array_key_exists($offset, $this->attributes); + } + + /** + * @phan-suppress PhanUndeclaredClassAttribute + */ + #[\ReturnTypeWillChange] + public function offsetGet($offset) + { + return $this->attributes[$offset] ?? null; + } + + /** + * @phan-suppress PhanUndeclaredClassAttribute + */ + #[\ReturnTypeWillChange] + public function offsetSet($offset, $value) + { + if ($offset === null) { + return; + } + if ($value === null) { + unset($this->attributes[$offset]); + + return; + } + if (!$this->attributeValidator->validate($value)) { + self::logWarning($this->attributeValidator->getInvalidMessage() . ': ' . $offset); + $this->droppedAttributesCount++; + + return; + } + if (count($this->attributes) === $this->attributeCountLimit && !array_key_exists($offset, $this->attributes)) { + $this->droppedAttributesCount++; + + return; + } + + $this->attributes[$offset] = $this->normalizeValue($value); + //@todo "There SHOULD be a message printed in the SDK's log to indicate to the user that an attribute was + // discarded due to such a limit. To prevent excessive logging, the message MUST be printed at most + // once per <thing> (i.e., not per discarded attribute)." + } + + /** + * @phan-suppress PhanUndeclaredClassAttribute + */ + #[\ReturnTypeWillChange] + public function offsetUnset($offset) + { + unset($this->attributes[$offset]); + } + + private function normalizeValue($value) + { + if (is_string($value) && $this->attributeValueLengthLimit !== null) { + return mb_substr($value, 0, $this->attributeValueLengthLimit); + } + + if (is_array($value)) { + foreach ($value as $k => $v) { + $processed = $this->normalizeValue($v); + if ($processed !== $v) { + $value[$k] = $processed; + } + } + + return $value; + } + + return $value; + } +} diff --git a/vendor/open-telemetry/sdk/Common/Attribute/AttributesBuilderInterface.php b/vendor/open-telemetry/sdk/Common/Attribute/AttributesBuilderInterface.php new file mode 100644 index 000000000..7e3d64062 --- /dev/null +++ b/vendor/open-telemetry/sdk/Common/Attribute/AttributesBuilderInterface.php @@ -0,0 +1,12 @@ +<?php + +declare(strict_types=1); + +namespace OpenTelemetry\SDK\Common\Attribute; + +use ArrayAccess; + +interface AttributesBuilderInterface extends ArrayAccess +{ + public function build(): AttributesInterface; +} diff --git a/vendor/open-telemetry/sdk/Common/Attribute/AttributesFactory.php b/vendor/open-telemetry/sdk/Common/Attribute/AttributesFactory.php new file mode 100644 index 000000000..d53ab25aa --- /dev/null +++ b/vendor/open-telemetry/sdk/Common/Attribute/AttributesFactory.php @@ -0,0 +1,36 @@ +<?php + +declare(strict_types=1); + +namespace OpenTelemetry\SDK\Common\Attribute; + +/** + * @internal + */ +final class AttributesFactory implements AttributesFactoryInterface +{ + private ?int $attributeCountLimit; + private ?int $attributeValueLengthLimit; + + public function __construct(?int $attributeCountLimit = null, ?int $attributeValueLengthLimit = null) + { + $this->attributeCountLimit = $attributeCountLimit; + $this->attributeValueLengthLimit = $attributeValueLengthLimit; + } + + public function builder(iterable $attributes = [], ?AttributeValidatorInterface $attributeValidator = null): AttributesBuilderInterface + { + $builder = new AttributesBuilder( + [], + $this->attributeCountLimit, + $this->attributeValueLengthLimit, + 0, + $attributeValidator, + ); + foreach ($attributes as $key => $value) { + $builder[$key] = $value; + } + + return $builder; + } +} diff --git a/vendor/open-telemetry/sdk/Common/Attribute/AttributesFactoryInterface.php b/vendor/open-telemetry/sdk/Common/Attribute/AttributesFactoryInterface.php new file mode 100644 index 000000000..1b74461d4 --- /dev/null +++ b/vendor/open-telemetry/sdk/Common/Attribute/AttributesFactoryInterface.php @@ -0,0 +1,10 @@ +<?php + +declare(strict_types=1); + +namespace OpenTelemetry\SDK\Common\Attribute; + +interface AttributesFactoryInterface +{ + public function builder(iterable $attributes = [], ?AttributeValidatorInterface $attributeValidator = null): AttributesBuilderInterface; +} diff --git a/vendor/open-telemetry/sdk/Common/Attribute/AttributesInterface.php b/vendor/open-telemetry/sdk/Common/Attribute/AttributesInterface.php new file mode 100644 index 000000000..1af7dc8d9 --- /dev/null +++ b/vendor/open-telemetry/sdk/Common/Attribute/AttributesInterface.php @@ -0,0 +1,19 @@ +<?php + +declare(strict_types=1); + +namespace OpenTelemetry\SDK\Common\Attribute; + +use Countable; +use Traversable; + +interface AttributesInterface extends Traversable, Countable +{ + public function has(string $name): bool; + + public function get(string $name); + + public function getDroppedAttributesCount(): int; + + public function toArray(): array; +} diff --git a/vendor/open-telemetry/sdk/Common/Attribute/FilteredAttributesBuilder.php b/vendor/open-telemetry/sdk/Common/Attribute/FilteredAttributesBuilder.php new file mode 100644 index 000000000..d79cff96a --- /dev/null +++ b/vendor/open-telemetry/sdk/Common/Attribute/FilteredAttributesBuilder.php @@ -0,0 +1,77 @@ +<?php + +declare(strict_types=1); + +namespace OpenTelemetry\SDK\Common\Attribute; + +use function in_array; + +/** + * @internal + */ +final class FilteredAttributesBuilder implements AttributesBuilderInterface +{ + private AttributesBuilderInterface $builder; + private array $rejectedKeys; + private int $rejected = 0; + + /** + * @param list<string> $rejectedKeys + */ + public function __construct(AttributesBuilderInterface $builder, array $rejectedKeys) + { + $this->builder = $builder; + $this->rejectedKeys = $rejectedKeys; + } + + public function __clone() + { + $this->builder = clone $this->builder; + } + + public function build(): AttributesInterface + { + $attributes = $this->builder->build(); + $dropped = $attributes->getDroppedAttributesCount() + $this->rejected; + + return new Attributes($attributes->toArray(), $dropped); + } + + public function offsetExists($offset): bool + { + return $this->builder->offsetExists($offset); + } + + /** + * @phan-suppress PhanUndeclaredClassAttribute + */ + #[\ReturnTypeWillChange] + public function offsetGet($offset) + { + return $this->builder->offsetGet($offset); + } + + /** + * @phan-suppress PhanUndeclaredClassAttribute + */ + #[\ReturnTypeWillChange] + public function offsetSet($offset, $value) + { + if ($value !== null && in_array($offset, $this->rejectedKeys, true)) { + $this->rejected++; + + return; + } + + $this->builder->offsetSet($offset, $value); + } + + /** + * @phan-suppress PhanUndeclaredClassAttribute + */ + #[\ReturnTypeWillChange] + public function offsetUnset($offset) + { + $this->builder->offsetUnset($offset); + } +} diff --git a/vendor/open-telemetry/sdk/Common/Attribute/FilteredAttributesFactory.php b/vendor/open-telemetry/sdk/Common/Attribute/FilteredAttributesFactory.php new file mode 100644 index 000000000..1d9c4ae1c --- /dev/null +++ b/vendor/open-telemetry/sdk/Common/Attribute/FilteredAttributesFactory.php @@ -0,0 +1,33 @@ +<?php + +declare(strict_types=1); + +namespace OpenTelemetry\SDK\Common\Attribute; + +/** + * @internal + */ +final class FilteredAttributesFactory implements AttributesFactoryInterface +{ + private AttributesFactoryInterface $factory; + private array $rejectedKeys; + + /** + * @param list<string> $rejectedKeys + */ + public function __construct(AttributesFactoryInterface $factory, array $rejectedKeys) + { + $this->factory = $factory; + $this->rejectedKeys = $rejectedKeys; + } + + public function builder(iterable $attributes = [], ?AttributeValidatorInterface $attributeValidator = null): AttributesBuilderInterface + { + $builder = new FilteredAttributesBuilder($this->factory->builder([], $attributeValidator), $this->rejectedKeys); + foreach ($attributes as $attribute => $value) { + $builder[$attribute] = $value; + } + + return $builder; + } +} diff --git a/vendor/open-telemetry/sdk/Common/Attribute/LogRecordAttributeValidator.php b/vendor/open-telemetry/sdk/Common/Attribute/LogRecordAttributeValidator.php new file mode 100644 index 000000000..a09d26372 --- /dev/null +++ b/vendor/open-telemetry/sdk/Common/Attribute/LogRecordAttributeValidator.php @@ -0,0 +1,19 @@ +<?php + +declare(strict_types=1); + +namespace OpenTelemetry\SDK\Common\Attribute; + +class LogRecordAttributeValidator implements AttributeValidatorInterface +{ + public function validate($value): bool + { + return true; + } + + public function getInvalidMessage(): string + { + //not required as this validator always returns true + return 'unused'; + } +} diff --git a/vendor/open-telemetry/sdk/Common/Configuration/Configuration.php b/vendor/open-telemetry/sdk/Common/Configuration/Configuration.php new file mode 100644 index 000000000..58673fd98 --- /dev/null +++ b/vendor/open-telemetry/sdk/Common/Configuration/Configuration.php @@ -0,0 +1,182 @@ +<?php + +declare(strict_types=1); + +namespace OpenTelemetry\SDK\Common\Configuration; + +use InvalidArgumentException; +use OpenTelemetry\API\Behavior\LogsMessagesTrait; +use OpenTelemetry\SDK\Common\Configuration\Parser\BooleanParser; +use OpenTelemetry\SDK\Common\Configuration\Parser\ListParser; +use OpenTelemetry\SDK\Common\Configuration\Parser\MapParser; +use OpenTelemetry\SDK\Common\Configuration\Parser\RatioParser; +use OpenTelemetry\SDK\Common\Configuration\Resolver\CompositeResolver; +use OpenTelemetry\SDK\Common\Util\ClassConstantAccessor; +use UnexpectedValueException; + +/** + * Configuration can come from one or more of the following sources (from highest to lowest priority): + * - values defined in php.ini + * - environment variable ($_SERVER) + * - configuration file (todo) + */ +class Configuration +{ + use LogsMessagesTrait; + + public static function has(string $name): bool + { + return CompositeResolver::instance()->hasVariable($name); + } + + public static function getInt(string $key, int $default = null): int + { + return (int) self::validateVariableValue( + CompositeResolver::instance()->resolve( + self::validateVariableType($key, VariableTypes::INTEGER), + $default + ), + FILTER_VALIDATE_INT + ); + } + + public static function getString(string $key, string $default = null): string + { + return (string) self::validateVariableValue( + CompositeResolver::instance()->resolve( + self::validateVariableType($key, VariableTypes::STRING), + $default + ) + ); + } + + public static function getBoolean(string $key, bool $default = null): bool + { + $resolved = self::validateVariableValue( + CompositeResolver::instance()->resolve( + self::validateVariableType($key, VariableTypes::BOOL), + null === $default ? $default : ($default ? 'true' : 'false') + ) + ); + + try { + return BooleanParser::parse($resolved); + } catch (InvalidArgumentException $e) { + self::logWarning(sprintf('Invalid boolean value "%s" interpreted as "false" for %s', $resolved, $key)); + + return false; + } + } + + public static function getMixed(string $key, $default = null) + { + return self::validateVariableValue( + CompositeResolver::instance()->resolve( + $key, + $default + ) + ); + } + + public static function getMap(string $key, array $default = null): array + { + return MapParser::parse( + CompositeResolver::instance()->resolve( + self::validateVariableType($key, VariableTypes::MAP), + $default + ) + ); + } + + public static function getList(string $key, array $default = null): array + { + return ListParser::parse( + CompositeResolver::instance()->resolve( + self::validateVariableType($key, VariableTypes::LIST), + $default + ) + ); + } + + public static function getEnum(string $key, string $default = null): string + { + return (string) self::validateVariableValue( + CompositeResolver::instance()->resolve( + self::validateVariableType($key, VariableTypes::ENUM), + $default + ) + ); + } + + public static function getFloat(string $key, float $default = null): float + { + return (float) self::validateVariableValue( + CompositeResolver::instance()->resolve( + self::validateVariableType($key, VariableTypes::FLOAT), + $default + ), + FILTER_VALIDATE_FLOAT + ); + } + + public static function getRatio(string $key, float $default = null): float + { + return RatioParser::parse( + self::validateVariableValue( + CompositeResolver::instance()->resolve( + self::validateVariableType($key, VariableTypes::RATIO), + $default + ) + ) + ); + } + + public static function getKnownValues(string $variableName): ?array + { + return ClassConstantAccessor::getValue(KnownValues::class, $variableName); + } + + public static function getDefault(string $variableName) + { + return ClassConstantAccessor::getValue(Defaults::class, $variableName); + } + + public static function getType(string $variableName): ?string + { + return ClassConstantAccessor::getValue(ValueTypes::class, $variableName); + } + + public static function isEmpty($value): bool + { + // don't use 'empty()', since '0' is not considered to be empty + return $value === null || $value === ''; + } + + private static function validateVariableType(string $variableName, string $type): string + { + $variableType = self::getType($variableName); + + if ($variableType !== null && $variableType !== $type && $variableType !== VariableTypes::MIXED) { + throw new UnexpectedValueException( + sprintf('Variable "%s" is not supposed to be of type "%s" but type "%s"', $variableName, $type, $variableType) + ); + } + + return $variableName; + } + + private static function validateVariableValue($value, ?int $filterType = null) + { + if ($filterType !== null && filter_var($value, $filterType) === false) { + throw new UnexpectedValueException(sprintf('Value has invalid type "%s"', gettype($value))); + } + + if ($value === null || $value === '') { + throw new UnexpectedValueException( + 'Variable must not be null or empty' + ); + } + + return $value; + } +} diff --git a/vendor/open-telemetry/sdk/Common/Configuration/Defaults.php b/vendor/open-telemetry/sdk/Common/Configuration/Defaults.php new file mode 100644 index 000000000..7228270a6 --- /dev/null +++ b/vendor/open-telemetry/sdk/Common/Configuration/Defaults.php @@ -0,0 +1,122 @@ +<?php + +declare(strict_types=1); + +namespace OpenTelemetry\SDK\Common\Configuration; + +/** + * Default values for environment variables defined by the OpenTelemetry specification and language specific variables for the PHP SDK. + * @see https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/configuration/sdk-environment-variables.md + */ +interface Defaults +{ + /** + * General SDK Configuration + * @see https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/configuration/sdk-environment-variables.md#general-sdk-configuration + */ + public const OTEL_LOG_LEVEL = 'info'; + public const OTEL_PROPAGATORS = 'tracecontext,baggage'; + public const OTEL_TRACES_SAMPLER = 'parentbased_always_on'; + public const OTEL_SDK_DISABLED = 'false'; + /** + * Batch Span Processor + * @see https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/configuration/sdk-environment-variables.md#batch-span-processor + */ + public const OTEL_BSP_SCHEDULE_DELAY = 5000; + public const OTEL_BSP_EXPORT_TIMEOUT = 30000; + public const OTEL_BSP_MAX_QUEUE_SIZE = 2048; + public const OTEL_BSP_MAX_EXPORT_BATCH_SIZE = 512; + /** + * Batch LogRecord Processor + * @see https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/configuration/sdk-environment-variables.md#batch-logrecord-processor + */ + public const OTEL_BLRP_SCHEDULE_DELAY = 1000; + public const OTEL_BLRP_EXPORT_TIMEOUT = 30000; + public const OTEL_BLRP_MAX_QUEUE_SIZE = 2048; + public const OTEL_BLRP_MAX_EXPORT_BATCH_SIZE = 512; + /** + * Attribute Limits + * @see https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/configuration/sdk-environment-variables.md#attribute-limits + */ + public const OTEL_ATTRIBUTE_COUNT_LIMIT = 128; + public const OTEL_ATTRIBUTE_VALUE_LENGTH_LIMIT = PHP_INT_MAX; + /** + * Span Limits + * @see https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/configuration/sdk-environment-variables.md#span-limits + */ + public const OTEL_SPAN_ATTRIBUTE_COUNT_LIMIT = 128; + public const OTEL_SPAN_EVENT_COUNT_LIMIT = 128; + public const OTEL_SPAN_LINK_COUNT_LIMIT = 128; + public const OTEL_EVENT_ATTRIBUTE_COUNT_LIMIT = 128; + public const OTEL_LINK_ATTRIBUTE_COUNT_LIMIT = 128; + /** + * LogRecord Limits + * @see https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/configuration/sdk-environment-variables.md#logrecord-limits + */ + public const OTEL_LOGRECORD_ATTRIBUTE_VALUE_LENGTH_LIMIT = PHP_INT_MAX; + public const OTEL_LOGRECORD_ATTRIBUTE_COUNT_LIMIT = 128; + /** + * OTLP Exporter + * @see https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/protocol/exporter.md#configuration-options + */ + // Endpoint + public const OTEL_EXPORTER_OTLP_ENDPOINT = 'http://localhost:4318'; + public const OTEL_EXPORTER_OTLP_TRACES_ENDPOINT = 'http://localhost:4318'; + public const OTEL_EXPORTER_OTLP_METRICS_ENDPOINT = 'http://localhost:4318'; + public const OTEL_EXPORTER_OTLP_LOGS_ENDPOINT = 'http://localhost:4318'; + // Insecure + public const OTEL_EXPORTER_OTLP_INSECURE = 'false'; + public const OTEL_EXPORTER_OTLP_TRACES_INSECURE = 'false'; + public const OTEL_EXPORTER_OTLP_METRICS_INSECURE = 'false'; + public const OTEL_EXPORTER_OTLP_LOGS_INSECURE = 'false'; + // Timeout (seconds) + public const OTEL_EXPORTER_OTLP_TIMEOUT = 10; + public const OTEL_EXPORTER_OTLP_TRACES_TIMEOUT = 10; + public const OTEL_EXPORTER_OTLP_METRICS_TIMEOUT = 10; + public const OTEL_EXPORTER_OTLP_LOGS_TIMEOUT = 10; + // Protocol + public const OTEL_EXPORTER_OTLP_PROTOCOL = 'http/protobuf'; + public const OTEL_EXPORTER_OTLP_TRACES_PROTOCOL = 'http/protobuf'; + public const OTEL_EXPORTER_OTLP_METRICS_PROTOCOL = 'http/protobuf'; + public const OTEL_EXPORTER_OTLP_LOGS_PROTOCOL = 'http/protobuf'; + /** + * Zipkin Exporter + * @see https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/configuration/sdk-environment-variables.md#zipkin-exporter + */ + public const OTEL_EXPORTER_ZIPKIN_ENDPOINT = 'http://localhost:9411/api/v2/spans'; + // Timeout (seconds) + public const OTEL_EXPORTER_ZIPKIN_TIMEOUT = 10; + /** + * Prometheus Exporter + * @see https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/configuration/sdk-environment-variables.md#prometheus-exporter + */ + public const OTEL_EXPORTER_PROMETHEUS_HOST = '0.0.0.0'; + public const OTEL_EXPORTER_PROMETHEUS_PORT = 9464; + /** + * Exporter Selection + * @see https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/configuration/sdk-environment-variables.md#exporter-selection + */ + public const OTEL_TRACES_EXPORTER = 'otlp'; + public const OTEL_METRICS_EXPORTER = 'otlp'; + public const OTEL_LOGS_EXPORTER = 'otlp'; + /** + * Metrics SDK Configuration + * @see https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/configuration/sdk-environment-variables.md#metrics-sdk-configuration + */ + public const OTEL_METRICS_EXEMPLAR_FILTER = 'with_sampled_trace'; + public const OTEL_METRIC_EXPORT_INTERVAL = 60000; + public const OTEL_METRIC_EXPORT_TIMEOUT = 30000; + public const OTEL_EXPORTER_OTLP_METRICS_TEMPORALITY_PREFERENCE = 'cumulative'; + public const OTEL_EXPORTER_OTLP_METRICS_DEFAULT_HISTOGRAM_AGGREGATION = 'explicit_bucket_histogram'; + /** + * Language Specific Environment Variables + * @see https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/configuration/sdk-environment-variables.md#language-specific-environment-variables + */ + public const OTEL_PHP_TRACES_PROCESSOR = 'batch'; + public const OTEL_PHP_DETECTORS = 'all'; + public const OTEL_PHP_AUTOLOAD_ENABLED = 'false'; + public const OTEL_PHP_INTERNAL_METRICS_ENABLED = 'false'; + public const OTEL_PHP_DISABLED_INSTRUMENTATIONS = []; + public const OTEL_PHP_LOGS_PROCESSOR = 'batch'; + public const OTEL_PHP_LOG_DESTINATION = 'default'; +} diff --git a/vendor/open-telemetry/sdk/Common/Configuration/KnownValues.php b/vendor/open-telemetry/sdk/Common/Configuration/KnownValues.php new file mode 100644 index 000000000..8975b20f9 --- /dev/null +++ b/vendor/open-telemetry/sdk/Common/Configuration/KnownValues.php @@ -0,0 +1,208 @@ +<?php + +declare(strict_types=1); + +namespace OpenTelemetry\SDK\Common\Configuration; + +use Psr\Log\LogLevel; + +/** + * "Known values" for OpenTelemetry configurataion variables. + * @see https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/configuration/sdk-environment-variables.md + * Notice: Values specific to the PHP SDK have been added + */ +interface KnownValues +{ + public const VALUE_TRUE = 'true'; + public const VALUE_FALSE = 'false'; + public const VALUE_ON = 'on'; + public const VALUE_OFF = 'off'; + public const VALUE_1 = '1'; + public const VALUE_0 = '0'; + public const VALUE_ALL = 'all'; + public const VALUE_NONE = 'none'; + public const VALUE_TRACECONTEXT = 'tracecontext'; + public const VALUE_BAGGAGE = 'baggage'; + public const VALUE_B3 = 'b3'; + public const VALUE_B3_MULTI = 'b3multi'; + public const VALUE_XRAY = 'xray'; + public const VALUE_OTTRACE = 'ottrace'; + public const VALUE_ALWAYS_ON = 'always_on'; + public const VALUE_ALWAYS_OFF = 'always_off'; + public const VALUE_TRACE_ID_RATIO = 'traceidratio'; + public const VALUE_PARENT_BASED_ALWAYS_ON = 'parentbased_always_on'; + public const VALUE_PARENT_BASED_ALWAYS_OFF = 'parentbased_always_off'; + public const VALUE_PARENT_BASED_TRACE_ID_RATIO = 'parentbased_traceidratio'; + public const VALUE_GZIP = 'gzip'; + public const VALUE_GRPC = 'grpc'; + public const VALUE_HTTP_PROTOBUF = 'http/protobuf'; + public const VALUE_HTTP_JSON = 'http/json'; + public const VALUE_HTTP_NDJSON = 'http/ndjson'; + public const VALUE_OTLP = 'otlp'; + public const VALUE_ZIPKIN = 'zipkin'; + public const VALUE_PROMETHEUS = 'prometheus'; + public const VALUE_WITH_SAMPLED_TRACE = 'with_sampled_trace'; + public const VALUE_BATCH = 'batch'; + public const VALUE_SIMPLE = 'simple'; + public const VALUE_NOOP = 'noop'; + public const VALUE_LOG_EMERGENCY = LogLevel::EMERGENCY; + public const VALUE_LOG_ALERT = LogLevel::ALERT; + public const VALUE_LOG_CRITICAL = LogLevel::CRITICAL; + public const VALUE_LOG_ERROR = LogLevel::ERROR; + public const VALUE_LOG_WARNING = LogLevel::WARNING; + public const VALUE_LOG_NOTICE = LogLevel::NOTICE; + public const VALUE_LOG_INFO = LogLevel::INFO; + public const VALUE_LOG_DEBUG = LogLevel::DEBUG; + public const VALUE_TEMPORALITY_CUMULATIVE = 'cumulative'; + public const VALUE_TEMPORALITY_DELTA = 'delta'; + public const VALUE_TEMPORALITY_LOW_MEMORY = 'lowmemory'; + public const VALUE_HISTOGRAM_AGGREGATION_EXPLICIT = 'explicit_bucket_histogram'; + public const VALUE_HISTOGRAM_AGGREGATION_BASE2_EXPONENTIAL = 'base2_exponential_bucket_histogram'; + + public const VALUES_BOOLEAN = [ + self::VALUE_TRUE, + self::VALUE_FALSE, + ]; + + public const VALUES_COMPRESSION= [ + self::VALUE_GZIP, + self::VALUE_NONE, + ]; + + public const VALUES_OTLP_PROTOCOL = [ + self::VALUE_GRPC, + self::VALUE_HTTP_PROTOBUF, + self::VALUE_HTTP_JSON, + ]; + + public const VALUES_TEMPORALITY_PREFERENCE = [ + self::VALUE_TEMPORALITY_CUMULATIVE, + self::VALUE_TEMPORALITY_DELTA, + self::VALUE_TEMPORALITY_LOW_MEMORY, + ]; + + public const VALUES_HISTOGRAM_AGGREGATION = [ + self::VALUE_HISTOGRAM_AGGREGATION_EXPLICIT, + self::VALUE_HISTOGRAM_AGGREGATION_BASE2_EXPONENTIAL, + ]; + + /** + * General SDK Configuration + * @see https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/configuration/sdk-environment-variables.md#general-sdk-configuration + */ + public const OTEL_LOG_LEVEL = [ + self::VALUE_LOG_EMERGENCY, + self::VALUE_LOG_ALERT, + self::VALUE_LOG_CRITICAL, + self::VALUE_LOG_ERROR, + self::VALUE_LOG_WARNING, + self::VALUE_LOG_NOTICE, + self::VALUE_LOG_INFO, + self::VALUE_LOG_DEBUG, + ]; + public const OTEL_PROPAGATORS = [ + self::VALUE_TRACECONTEXT, // W3C Trace Context + self::VALUE_BAGGAGE, // W3C Baggage + self::VALUE_B3, // B3 Single + self::VALUE_B3_MULTI, // B3 Multi + self::VALUE_XRAY, // AWS X-Ray (third party) + self::VALUE_OTTRACE, // OT Trace (third party) + self::VALUE_NONE, // No automatically configured propagator. + ]; + public const OTEL_TRACES_SAMPLER = [ + self::VALUE_ALWAYS_ON, + self::VALUE_ALWAYS_OFF, + self::VALUE_TRACE_ID_RATIO, + self::VALUE_PARENT_BASED_ALWAYS_ON, + self::VALUE_PARENT_BASED_ALWAYS_OFF, + self::VALUE_PARENT_BASED_TRACE_ID_RATIO, + self::VALUE_XRAY, + ]; + /** + * OTLP Exporter + * @see https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/protocol/exporter.md#configuration-options + */ + // Insecure + public const OTEL_EXPORTER_OTLP_INSECURE = self::VALUES_BOOLEAN; + public const OTEL_EXPORTER_OTLP_TRACES_INSECURE = self::VALUES_BOOLEAN; + public const OTEL_EXPORTER_OTLP_METRICS_INSECURE = self::VALUES_BOOLEAN; + // Compression + public const OTEL_EXPORTER_OTLP_COMPRESSION = self::VALUES_COMPRESSION; + public const OTEL_EXPORTER_OTLP_TRACES_COMPRESSION = self::VALUES_COMPRESSION; + public const OTEL_EXPORTER_OTLP_METRICS_COMPRESSION = self::VALUES_COMPRESSION; + // Protocol + public const OTEL_EXPORTER_OTLP_PROTOCOL = self::VALUES_OTLP_PROTOCOL; + public const OTEL_EXPORTER_OTLP_TRACES_PROTOCOL = self::VALUES_OTLP_PROTOCOL; + public const OTEL_EXPORTER_OTLP_METRICS_PROTOCOL = self::VALUES_OTLP_PROTOCOL; + /** + * Exporter Selection + * @see https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/configuration/sdk-environment-variables.md#exporter-selection + */ + public const OTEL_TRACES_EXPORTER = [ + self::VALUE_OTLP, + self::VALUE_ZIPKIN, + self::VALUE_NONE, + ]; + public const OTEL_METRICS_EXPORTER = [ + self::VALUE_OTLP, + self::VALUE_PROMETHEUS, + self::VALUE_NONE, + ]; + public const OTEL_LOGS_EXPORTER = [ + self::VALUE_OTLP, + self::VALUE_NONE, + ]; + /** + * Metrics SDK Configuration + * @see https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/configuration/sdk-environment-variables.md#metrics-sdk-configuration + */ + public const OTEL_METRICS_EXEMPLAR_FILTER = [ + self::VALUE_WITH_SAMPLED_TRACE, + self::VALUE_ALL, + self::VALUE_NONE, + ]; + /** + * Language Specific Environment Variables + * @see https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/configuration/sdk-environment-variables.md#language-specific-environment-variables + */ + public const OTEL_PHP_TRACES_PROCESSOR = [ + self::VALUE_BATCH, + self::VALUE_SIMPLE, + self::VALUE_NOOP, + self::VALUE_NONE, + ]; + public const OTEL_PHP_AUTOLOAD_ENABLED = self::VALUES_BOOLEAN; + public const VALUE_ERROR_LOG = 'error_log'; + public const VALUE_STDERR = 'stderr'; + public const VALUE_STDOUT = 'stdout'; + public const VALUE_PSR3 = 'psr3'; + public const VALUE_EMPTY = ''; + public const VALUE_DETECTORS_ENVIRONMENT = 'env'; + public const VALUE_DETECTORS_HOST = 'host'; + public const VALUE_DETECTORS_OS = 'os'; + public const VALUE_DETECTORS_PROCESS = 'process'; + public const VALUE_DETECTORS_PROCESS_RUNTIME = 'process_runtime'; + public const VALUE_DETECTORS_SDK = 'sdk'; + public const VALUE_DETECTORS_SDK_PROVIDED = 'sdk_provided'; + public const VALUE_DETECTORS_COMPOSER = 'composer'; + public const OTEL_PHP_DETECTORS = [ + self::VALUE_ALL, + self::VALUE_DETECTORS_ENVIRONMENT, + self::VALUE_DETECTORS_HOST, + self::VALUE_DETECTORS_OS, + self::VALUE_DETECTORS_PROCESS, + self::VALUE_DETECTORS_PROCESS_RUNTIME, + self::VALUE_DETECTORS_SDK, + self::VALUE_DETECTORS_SDK_PROVIDED, + self::VALUE_DETECTORS_COMPOSER, + self::VALUE_NONE, + ]; + public const OTEL_PHP_LOG_DESTINATION = [ + self::VALUE_ERROR_LOG, + self::VALUE_STDERR, + self::VALUE_STDOUT, + self::VALUE_PSR3, + self::VALUE_EMPTY, + self::VALUE_NONE, + ]; +} diff --git a/vendor/open-telemetry/sdk/Common/Configuration/Parser/BooleanParser.php b/vendor/open-telemetry/sdk/Common/Configuration/Parser/BooleanParser.php new file mode 100644 index 000000000..4141c61ef --- /dev/null +++ b/vendor/open-telemetry/sdk/Common/Configuration/Parser/BooleanParser.php @@ -0,0 +1,34 @@ +<?php + +declare(strict_types=1); + +namespace OpenTelemetry\SDK\Common\Configuration\Parser; + +use InvalidArgumentException; + +class BooleanParser +{ + private const TRUE_VALUE = 'true'; + private const FALSE_VALUE = 'false'; + + /** + * @param string|bool $value + */ + public static function parse($value): bool + { + if (is_bool($value)) { + return $value; + } + if (strtolower($value) === self::TRUE_VALUE) { + return true; + } + + if (strtolower($value) === self::FALSE_VALUE) { + return false; + } + + throw new InvalidArgumentException( + sprintf('Value "%s" is a non-boolean value', $value) + ); + } +} diff --git a/vendor/open-telemetry/sdk/Common/Configuration/Parser/ListParser.php b/vendor/open-telemetry/sdk/Common/Configuration/Parser/ListParser.php new file mode 100644 index 000000000..f27b16597 --- /dev/null +++ b/vendor/open-telemetry/sdk/Common/Configuration/Parser/ListParser.php @@ -0,0 +1,28 @@ +<?php + +declare(strict_types=1); + +namespace OpenTelemetry\SDK\Common\Configuration\Parser; + +class ListParser +{ + private const DEFAULT_SEPARATOR = ','; + + /** + * @param string|array $value + */ + public static function parse($value): array + { + if (is_array($value)) { + return $value; + } + if (trim($value) === '') { + return []; + } + + return array_map( + fn ($value) => trim($value), + explode(self::DEFAULT_SEPARATOR, $value) + ); + } +} diff --git a/vendor/open-telemetry/sdk/Common/Configuration/Parser/MapParser.php b/vendor/open-telemetry/sdk/Common/Configuration/Parser/MapParser.php new file mode 100644 index 000000000..273d57c87 --- /dev/null +++ b/vendor/open-telemetry/sdk/Common/Configuration/Parser/MapParser.php @@ -0,0 +1,45 @@ +<?php + +declare(strict_types=1); + +namespace OpenTelemetry\SDK\Common\Configuration\Parser; + +use InvalidArgumentException; + +class MapParser +{ + private const VARIABLE_SEPARATOR = ','; + private const KEY_VALUE_SEPARATOR = '='; + + public static function parse($value): array + { + if (is_array($value)) { + return $value; + } + $result = []; + + if (null === $value || trim($value) === '') { + return $result; + } + + foreach (explode(self::VARIABLE_SEPARATOR, $value) as $pair) { + self::validateKeyValuePair($pair); + + [$key, $value] = explode(self::KEY_VALUE_SEPARATOR, $pair, 2); + $result[trim($key)] = trim($value); + } + + return $result; + } + + private static function validateKeyValuePair(string $pair) + { + if (strpos($pair, self::KEY_VALUE_SEPARATOR) === false) { + throw new InvalidArgumentException(sprintf( + 'Key-Value pair "%s" does not contain separator "%s"', + $pair, + self::KEY_VALUE_SEPARATOR + )); + } + } +} diff --git a/vendor/open-telemetry/sdk/Common/Configuration/Parser/RatioParser.php b/vendor/open-telemetry/sdk/Common/Configuration/Parser/RatioParser.php new file mode 100644 index 000000000..f0fe32100 --- /dev/null +++ b/vendor/open-telemetry/sdk/Common/Configuration/Parser/RatioParser.php @@ -0,0 +1,38 @@ +<?php + +declare(strict_types=1); + +namespace OpenTelemetry\SDK\Common\Configuration\Parser; + +use InvalidArgumentException; +use RangeException; + +class RatioParser +{ + private const MAX_VALUE = 1; + private const MIN_VALUE = 0; + + public static function parse($value): float + { + if (filter_var($value, FILTER_VALIDATE_FLOAT) === false) { + throw new InvalidArgumentException( + sprintf('Value "%s" contains non-numeric value', $value) + ); + } + + $result = (float) $value; + + if ($result > self::MAX_VALUE || $result < self::MIN_VALUE) { + throw new RangeException( + sprintf( + 'Value must not be lower than %s or higher than %s. Given: %s', + self::MIN_VALUE, + self::MAX_VALUE, + $value + ) + ); + } + + return $result; + } +} diff --git a/vendor/open-telemetry/sdk/Common/Configuration/Resolver/CompositeResolver.php b/vendor/open-telemetry/sdk/Common/Configuration/Resolver/CompositeResolver.php new file mode 100644 index 000000000..b72400b01 --- /dev/null +++ b/vendor/open-telemetry/sdk/Common/Configuration/Resolver/CompositeResolver.php @@ -0,0 +1,68 @@ +<?php + +declare(strict_types=1); + +namespace OpenTelemetry\SDK\Common\Configuration\Resolver; + +use OpenTelemetry\SDK\Common\Configuration\Configuration; + +/** + * @interal + */ +class CompositeResolver +{ + // @var array<ResolverInterface> + private array $resolvers = []; + + public static function instance(): self + { + static $instance; + $instance ??= new self([ + new PhpIniResolver(), + new EnvironmentResolver(), + ]); + + return $instance; + } + + public function __construct($resolvers) + { + foreach ($resolvers as $resolver) { + $this->addResolver($resolver); + } + } + + public function addResolver(ResolverInterface $resolver): void + { + $this->resolvers[] = $resolver; + } + + public function getResolvers(): array + { + return $this->resolvers; + } + + public function resolve(string $variableName, $default = '') + { + foreach ($this->resolvers as $resolver) { + if ($resolver->hasVariable($variableName)) { + return $resolver->retrieveValue($variableName); + } + } + + return Configuration::isEmpty($default) + ? Configuration::getDefault($variableName) + : $default; + } + + public function hasVariable(string $variableName): bool + { + foreach ($this->resolvers as $resolver) { + if ($resolver->hasVariable($variableName)) { + return true; + } + } + + return false; + } +} diff --git a/vendor/open-telemetry/sdk/Common/Configuration/Resolver/EnvironmentResolver.php b/vendor/open-telemetry/sdk/Common/Configuration/Resolver/EnvironmentResolver.php new file mode 100644 index 000000000..453f98e39 --- /dev/null +++ b/vendor/open-telemetry/sdk/Common/Configuration/Resolver/EnvironmentResolver.php @@ -0,0 +1,40 @@ +<?php + +declare(strict_types=1); + +namespace OpenTelemetry\SDK\Common\Configuration\Resolver; + +use OpenTelemetry\SDK\Common\Configuration\Configuration; + +/** + * @internal + */ +class EnvironmentResolver implements ResolverInterface +{ + public function hasVariable(string $variableName): bool + { + if (!Configuration::isEmpty($_SERVER[$variableName] ?? null)) { + return true; + } + $env = getenv($variableName); + if ($env === false) { + return false; + } + + return !Configuration::isEmpty($env); + } + + /** + * @psalm-suppress InvalidReturnStatement + * @psalm-suppress InvalidReturnType + */ + public function retrieveValue(string $variableName) + { + $value = getenv($variableName); + if ($value === false) { + $value = $_SERVER[$variableName] ?? null; + } + + return $value; + } +} diff --git a/vendor/open-telemetry/sdk/Common/Configuration/Resolver/PhpIniAccessor.php b/vendor/open-telemetry/sdk/Common/Configuration/Resolver/PhpIniAccessor.php new file mode 100644 index 000000000..a12b507e8 --- /dev/null +++ b/vendor/open-telemetry/sdk/Common/Configuration/Resolver/PhpIniAccessor.php @@ -0,0 +1,18 @@ +<?php + +declare(strict_types=1); + +namespace OpenTelemetry\SDK\Common\Configuration\Resolver; + +class PhpIniAccessor +{ + /** + * Mockable accessor for php.ini values + * @internal + * @return array|false|string + */ + public function get(string $variableName) + { + return get_cfg_var($variableName); + } +} diff --git a/vendor/open-telemetry/sdk/Common/Configuration/Resolver/PhpIniResolver.php b/vendor/open-telemetry/sdk/Common/Configuration/Resolver/PhpIniResolver.php new file mode 100644 index 000000000..c9a8f3b4e --- /dev/null +++ b/vendor/open-telemetry/sdk/Common/Configuration/Resolver/PhpIniResolver.php @@ -0,0 +1,41 @@ +<?php + +declare(strict_types=1); + +namespace OpenTelemetry\SDK\Common\Configuration\Resolver; + +use OpenTelemetry\SDK\Common\Configuration\Configuration; + +/** + * @interal + * @psalm-suppress TypeDoesNotContainType + */ +class PhpIniResolver implements ResolverInterface +{ + private PhpIniAccessor $accessor; + + public function __construct(?PhpIniAccessor $accessor = null) + { + $this->accessor = $accessor ?? new PhpIniAccessor(); + } + + public function retrieveValue(string $variableName) + { + $value = $this->accessor->get($variableName) ?: ''; + if (is_array($value)) { + return implode(',', $value); + } + + return $value; + } + + public function hasVariable(string $variableName): bool + { + $value = $this->accessor->get($variableName); + if ($value === []) { + return false; + } + + return $value !== false && !Configuration::isEmpty($value); + } +} diff --git a/vendor/open-telemetry/sdk/Common/Configuration/Resolver/ResolverInterface.php b/vendor/open-telemetry/sdk/Common/Configuration/Resolver/ResolverInterface.php new file mode 100644 index 000000000..4e88f3ff6 --- /dev/null +++ b/vendor/open-telemetry/sdk/Common/Configuration/Resolver/ResolverInterface.php @@ -0,0 +1,15 @@ +<?php + +declare(strict_types=1); + +namespace OpenTelemetry\SDK\Common\Configuration\Resolver; + +interface ResolverInterface +{ + /** + * @return mixed + */ + public function retrieveValue(string $variableName); + + public function hasVariable(string $variableName): bool; +} diff --git a/vendor/open-telemetry/sdk/Common/Configuration/ValueTypes.php b/vendor/open-telemetry/sdk/Common/Configuration/ValueTypes.php new file mode 100644 index 000000000..64a69f6a7 --- /dev/null +++ b/vendor/open-telemetry/sdk/Common/Configuration/ValueTypes.php @@ -0,0 +1,133 @@ +<?php + +declare(strict_types=1); + +namespace OpenTelemetry\SDK\Common\Configuration; + +/** + * Environment variables defined by the OpenTelemetry specification and language specific variables for the PHP SDK. + * @see https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/configuration/sdk-environment-variables.md + */ +interface ValueTypes +{ + /** + * General SDK Configuration + * @see https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/configuration/sdk-environment-variables.md#general-sdk-configuration + */ + public const OTEL_RESOURCE_ATTRIBUTES = VariableTypes::MAP; + public const OTEL_SERVICE_NAME = VariableTypes::STRING; + public const OTEL_LOG_LEVEL = VariableTypes::ENUM; + public const OTEL_PROPAGATORS = VariableTypes::LIST; + public const OTEL_TRACES_SAMPLER = VariableTypes::STRING; + public const OTEL_TRACES_SAMPLER_ARG = VariableTypes::MIXED; + /** + * Batch Span Processor + * @see https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/configuration/sdk-environment-variables.md#batch-span-processor + */ + public const OTEL_BSP_SCHEDULE_DELAY = VariableTypes::INTEGER; + public const OTEL_BSP_EXPORT_TIMEOUT = VariableTypes::INTEGER; + public const OTEL_BSP_MAX_QUEUE_SIZE = VariableTypes::INTEGER; + public const OTEL_BSP_MAX_EXPORT_BATCH_SIZE = VariableTypes::INTEGER; + /** + * Batch LogRecord Processor + * @see https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/configuration/sdk-environment-variables.md#batch-logrecord-processor + */ + public const OTEL_BLRP_SCHEDULE_DELAY = VariableTypes::INTEGER; + public const OTEL_BLRP_EXPORT_TIMEOUT = VariableTypes::INTEGER; + public const OTEL_BLRP_MAX_QUEUE_SIZE = VariableTypes::INTEGER; + public const OTEL_BLRP_MAX_EXPORT_BATCH_SIZE = VariableTypes::INTEGER; + /** + * Attribute Limits + * @see https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/configuration/sdk-environment-variables.md#attribute-limits + */ + public const OTEL_ATTRIBUTE_VALUE_LENGTH_LIMIT = VariableTypes::INTEGER; + public const OTEL_ATTRIBUTE_COUNT_LIMIT = VariableTypes::INTEGER; + /** + * Span Limits + * @see https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/configuration/sdk-environment-variables.md#span-limits + */ + public const OTEL_SPAN_ATTRIBUTE_VALUE_LENGTH_LIMIT = VariableTypes::INTEGER; + public const OTEL_SPAN_ATTRIBUTE_COUNT_LIMIT = VariableTypes::INTEGER; + public const OTEL_SPAN_EVENT_COUNT_LIMIT = VariableTypes::INTEGER; + public const OTEL_SPAN_LINK_COUNT_LIMIT = VariableTypes::INTEGER; + public const OTEL_EVENT_ATTRIBUTE_COUNT_LIMIT = VariableTypes::INTEGER; + public const OTEL_LINK_ATTRIBUTE_COUNT_LIMIT = VariableTypes::INTEGER; + /** + * LogRecord Limits + * @see https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/configuration/sdk-environment-variables.md#logrecord-limits + */ + public const OTEL_LOGRECORD_ATTRIBUTE_VALUE_LENGTH_LIMIT = VariableTypes::INTEGER; + public const OTEL_LOGRECORD_ATTRIBUTE_COUNT_LIMIT = VariableTypes::INTEGER; + /** + * OTLP Exporter + * @see https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/protocol/exporter.md#configuration-options + */ + // Endpoint + public const OTEL_EXPORTER_OTLP_ENDPOINT = VariableTypes::STRING; + public const OTEL_EXPORTER_OTLP_TRACES_ENDPOINT = VariableTypes::STRING; + public const OTEL_EXPORTER_OTLP_METRICS_ENDPOINT = VariableTypes::STRING; + // Insecure + public const OTEL_EXPORTER_OTLP_INSECURE = VariableTypes::BOOL; + public const OTEL_EXPORTER_OTLP_TRACES_INSECURE = VariableTypes::BOOL; + public const OTEL_EXPORTER_OTLP_METRICS_INSECURE = VariableTypes::BOOL; + // Certificate File + public const OTEL_EXPORTER_OTLP_CERTIFICATE = VariableTypes::STRING; + public const OTEL_EXPORTER_OTLP_TRACES_CERTIFICATE = VariableTypes::STRING; + public const OTEL_EXPORTER_OTLP_METRICS_CERTIFICATE = VariableTypes::STRING; + // Headers + public const OTEL_EXPORTER_OTLP_HEADERS = VariableTypes::MAP; + public const OTEL_EXPORTER_OTLP_TRACES_HEADERS = VariableTypes::MAP; + public const OTEL_EXPORTER_OTLP_METRICS_HEADERS = VariableTypes::MAP; + // Compression + public const OTEL_EXPORTER_OTLP_COMPRESSION = VariableTypes::ENUM; + public const OTEL_EXPORTER_OTLP_TRACES_COMPRESSION = VariableTypes::ENUM; + public const OTEL_EXPORTER_OTLP_METRICS_COMPRESSION = VariableTypes::ENUM; + // Timeout + public const OTEL_EXPORTER_OTLP_TIMEOUT = VariableTypes::INTEGER; + public const OTEL_EXPORTER_OTLP_TRACES_TIMEOUT = VariableTypes::INTEGER; + public const OTEL_EXPORTER_OTLP_METRICS_TIMEOUT = VariableTypes::INTEGER; + // Protocol + public const OTEL_EXPORTER_OTLP_PROTOCOL = VariableTypes::ENUM; + public const OTEL_EXPORTER_OTLP_TRACES_PROTOCOL = VariableTypes::ENUM; + public const OTEL_EXPORTER_OTLP_METRICS_PROTOCOL = VariableTypes::ENUM; + /** + * Zipkin Exporter + * @see https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/configuration/sdk-environment-variables.md#zipkin-exporter + */ + public const OTEL_EXPORTER_ZIPKIN_ENDPOINT = VariableTypes::STRING; + public const OTEL_EXPORTER_ZIPKIN_TIMEOUT = VariableTypes::INTEGER; + public const OTEL_EXPORTER_ZIPKIN_PROTOCOL = VariableTypes::STRING; + /** + * Prometheus Exporter + * @see https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/configuration/sdk-environment-variables.md#prometheus-exporter + */ + public const OTEL_EXPORTER_PROMETHEUS_HOST = VariableTypes::STRING; + public const OTEL_EXPORTER_PROMETHEUS_PORT = VariableTypes::INTEGER; + /** + * Exporter Selection + * @see https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/configuration/sdk-environment-variables.md#exporter-selection + */ + public const OTEL_TRACES_EXPORTER = VariableTypes::LIST; + public const OTEL_METRICS_EXPORTER = VariableTypes::LIST; + public const OTEL_LOGS_EXPORTER = VariableTypes::LIST; + /** + * Metrics SDK Configuration + * @see https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/configuration/sdk-environment-variables.md#metrics-sdk-configuration + */ + public const OTEL_METRICS_EXEMPLAR_FILTER = VariableTypes::ENUM; + public const OTEL_METRIC_EXPORT_INTERVAL = VariableTypes::INTEGER; + public const OTEL_METRIC_EXPORT_TIMEOUT = VariableTypes::INTEGER; + public const OTEL_EXPORTER_OTLP_METRICS_TEMPORALITY_PREFERENCE = VariableTypes::ENUM; + public const OTEL_EXPORTER_OTLP_METRICS_DEFAULT_HISTOGRAM_AGGREGATION = VariableTypes::ENUM; + /** + * Language Specific Environment Variables + * @see https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/configuration/sdk-environment-variables.md#language-specific-environment-variables + */ + public const OTEL_PHP_TRACES_PROCESSOR = VariableTypes::ENUM; + public const OTEL_PHP_LOGS_PROCESSOR = VariableTypes::LIST; + public const OTEL_PHP_DETECTORS = VariableTypes::LIST; + public const OTEL_PHP_AUTOLOAD_ENABLED = VariableTypes::BOOL; + public const OTEL_PHP_LOG_DESTINATION = VariableTypes::ENUM; + public const OTEL_PHP_INTERNAL_METRICS_ENABLED = VariableTypes::BOOL; + public const OTEL_PHP_DISABLED_INSTRUMENTATIONS = VariableTypes::LIST; +} diff --git a/vendor/open-telemetry/sdk/Common/Configuration/VariableTypes.php b/vendor/open-telemetry/sdk/Common/Configuration/VariableTypes.php new file mode 100644 index 000000000..471632e16 --- /dev/null +++ b/vendor/open-telemetry/sdk/Common/Configuration/VariableTypes.php @@ -0,0 +1,62 @@ +<?php + +declare(strict_types=1); + +namespace OpenTelemetry\SDK\Common\Configuration; + +interface VariableTypes +{ + /** + * A single boolean value represented as a string or integer ('true', 'false', 0, 1) + * example: value1 + */ + public const BOOL = 'bool'; + + /** + * A single string value + * example: value1 + */ + public const STRING = 'string'; + + /** + * A single integer value + * example: 5000 + */ + public const INTEGER = 'integer'; + + /** + * A single float value + * example: 10.5 + */ + public const FLOAT = 'float'; + + /** + * A single float value between 0.0 and 1.0 + * example: 0.5 + */ + public const RATIO = 'ratio'; + + /** + * A single string value from a fixed list of values + * example values: value1, value2, value3 + * example: value1 + */ + public const ENUM = 'enum'; + + /** + * A comma separated list of single string values + * example: value1,value2,value3 + */ + public const LIST = 'list'; + + /** + * A comma separated list of key-value pairs + * example: key1=value1,key2=value2 + */ + public const MAP = 'map'; + + /** + * Values of mixed type + */ + public const MIXED = 'mixed'; +} diff --git a/vendor/open-telemetry/sdk/Common/Configuration/Variables.php b/vendor/open-telemetry/sdk/Common/Configuration/Variables.php new file mode 100644 index 000000000..d0bb3c8ab --- /dev/null +++ b/vendor/open-telemetry/sdk/Common/Configuration/Variables.php @@ -0,0 +1,142 @@ +<?php + +declare(strict_types=1); + +namespace OpenTelemetry\SDK\Common\Configuration; + +/** + * Environment variables defined by the OpenTelemetry specification and language specific variables for the PHP SDK. + * @see https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/configuration/sdk-environment-variables.md + */ +interface Variables +{ + /** + * General SDK Configuration + * @see https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/configuration/sdk-environment-variables.md#general-sdk-configuration + */ + public const OTEL_RESOURCE_ATTRIBUTES = 'OTEL_RESOURCE_ATTRIBUTES'; + public const OTEL_SERVICE_NAME = 'OTEL_SERVICE_NAME'; + public const OTEL_LOG_LEVEL = 'OTEL_LOG_LEVEL'; + public const OTEL_PROPAGATORS = 'OTEL_PROPAGATORS'; + public const OTEL_TRACES_SAMPLER = 'OTEL_TRACES_SAMPLER'; + public const OTEL_TRACES_SAMPLER_ARG = 'OTEL_TRACES_SAMPLER_ARG'; + public const OTEL_SDK_DISABLED = 'OTEL_SDK_DISABLED'; + /** + * Batch Span Processor + * @see https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/configuration/sdk-environment-variables.md#batch-span-processor + */ + public const OTEL_BSP_SCHEDULE_DELAY = 'OTEL_BSP_SCHEDULE_DELAY'; + public const OTEL_BSP_EXPORT_TIMEOUT = 'OTEL_BSP_EXPORT_TIMEOUT'; + public const OTEL_BSP_MAX_QUEUE_SIZE = 'OTEL_BSP_MAX_QUEUE_SIZE'; + public const OTEL_BSP_MAX_EXPORT_BATCH_SIZE = 'OTEL_BSP_MAX_EXPORT_BATCH_SIZE'; + /** + * Batch LogRecord Processor + * @see https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/configuration/sdk-environment-variables.md#batch-logrecord-processor + */ + public const OTEL_BLRP_SCHEDULE_DELAY = 'OTEL_BLRP_SCHEDULE_DELAY'; + public const OTEL_BLRP_EXPORT_TIMEOUT = 'OTEL_BLRP_EXPORT_TIMEOUT'; + public const OTEL_BLRP_MAX_QUEUE_SIZE = 'OTEL_BLRP_MAX_QUEUE_SIZE'; + public const OTEL_BLRP_MAX_EXPORT_BATCH_SIZE = 'OTEL_BLRP_MAX_EXPORT_BATCH_SIZE'; + /** + * Attribute Limits + * @see https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/configuration/sdk-environment-variables.md#attribute-limits + */ + public const OTEL_ATTRIBUTE_VALUE_LENGTH_LIMIT = 'OTEL_ATTRIBUTE_VALUE_LENGTH_LIMIT'; + public const OTEL_ATTRIBUTE_COUNT_LIMIT = 'OTEL_ATTRIBUTE_COUNT_LIMIT'; + /** + * LogRecord limits + * @see https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/configuration/sdk-environment-variables.md#logrecord-limits + */ + public const OTEL_LOGRECORD_ATTRIBUTE_VALUE_LENGTH_LIMIT = 'OTEL_LOGRECORD_ATTRIBUTE_VALUE_LENGTH_LIMIT'; + public const OTEL_LOGRECORD_ATTRIBUTE_COUNT_LIMIT = 'OTEL_LOGRECORD_ATTRIBUTE_COUNT_LIMIT'; + /** + * Span Limits + * @see https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/configuration/sdk-environment-variables.md#span-limits + */ + public const OTEL_SPAN_ATTRIBUTE_VALUE_LENGTH_LIMIT = 'OTEL_SPAN_ATTRIBUTE_VALUE_LENGTH_LIMIT'; + public const OTEL_SPAN_ATTRIBUTE_COUNT_LIMIT = 'OTEL_SPAN_ATTRIBUTE_COUNT_LIMIT'; + public const OTEL_SPAN_EVENT_COUNT_LIMIT = 'OTEL_SPAN_EVENT_COUNT_LIMIT'; + public const OTEL_SPAN_LINK_COUNT_LIMIT = 'OTEL_SPAN_LINK_COUNT_LIMIT'; + public const OTEL_EVENT_ATTRIBUTE_COUNT_LIMIT = 'OTEL_EVENT_ATTRIBUTE_COUNT_LIMIT'; + public const OTEL_LINK_ATTRIBUTE_COUNT_LIMIT = 'OTEL_LINK_ATTRIBUTE_COUNT_LIMIT'; + /** + * OTLP Exporter + * @see https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/protocol/exporter.md#configuration-options + */ + // Endpoint + public const OTEL_EXPORTER_OTLP_ENDPOINT = 'OTEL_EXPORTER_OTLP_ENDPOINT'; + public const OTEL_EXPORTER_OTLP_TRACES_ENDPOINT = 'OTEL_EXPORTER_OTLP_TRACES_ENDPOINT'; + public const OTEL_EXPORTER_OTLP_METRICS_ENDPOINT = 'OTEL_EXPORTER_OTLP_METRICS_ENDPOINT'; + public const OTEL_EXPORTER_OTLP_LOGS_ENDPOINT = 'OTEL_EXPORTER_OTLP_LOGS_ENDPOINT'; + // Insecure + public const OTEL_EXPORTER_OTLP_INSECURE = 'OTEL_EXPORTER_OTLP_INSECURE'; + public const OTEL_EXPORTER_OTLP_TRACES_INSECURE = 'OTEL_EXPORTER_OTLP_TRACES_INSECURE'; + public const OTEL_EXPORTER_OTLP_METRICS_INSECURE = 'OTEL_EXPORTER_OTLP_METRICS_INSECURE'; + public const OTEL_EXPORTER_OTLP_LOGS_INSECURE = 'OTEL_EXPORTER_OTLP_LOGS_INSECURE'; + // Certificate File + public const OTEL_EXPORTER_OTLP_CERTIFICATE = 'OTEL_EXPORTER_OTLP_CERTIFICATE'; + public const OTEL_EXPORTER_OTLP_TRACES_CERTIFICATE = 'OTEL_EXPORTER_OTLP_TRACES_CERTIFICATE'; + public const OTEL_EXPORTER_OTLP_METRICS_CERTIFICATE = 'OTEL_EXPORTER_OTLP_METRICS_CERTIFICATE'; + public const OTEL_EXPORTER_OTLP_LOGS_CERTIFICATE = 'OTEL_EXPORTER_OTLP_LOGS_CERTIFICATE'; + // Headers + public const OTEL_EXPORTER_OTLP_HEADERS = 'OTEL_EXPORTER_OTLP_HEADERS'; + public const OTEL_EXPORTER_OTLP_TRACES_HEADERS = 'OTEL_EXPORTER_OTLP_TRACES_HEADERS'; + public const OTEL_EXPORTER_OTLP_METRICS_HEADERS = 'OTEL_EXPORTER_OTLP_METRICS_HEADERS'; + public const OTEL_EXPORTER_OTLP_LOGS_HEADERS = 'OTEL_EXPORTER_OTLP_LOGS_HEADERS'; + // Compression + public const OTEL_EXPORTER_OTLP_COMPRESSION = 'OTEL_EXPORTER_OTLP_COMPRESSION'; + public const OTEL_EXPORTER_OTLP_TRACES_COMPRESSION = 'OTEL_EXPORTER_OTLP_TRACES_COMPRESSION'; + public const OTEL_EXPORTER_OTLP_METRICS_COMPRESSION = 'OTEL_EXPORTER_OTLP_METRICS_COMPRESSION'; + public const OTEL_EXPORTER_OTLP_LOGS_COMPRESSION = 'OTEL_EXPORTER_OTLP_LOGS_COMPRESSION'; + // Timeout + public const OTEL_EXPORTER_OTLP_TIMEOUT = 'OTEL_EXPORTER_OTLP_TIMEOUT'; + public const OTEL_EXPORTER_OTLP_TRACES_TIMEOUT = 'OTEL_EXPORTER_OTLP_TRACES_TIMEOUT'; + public const OTEL_EXPORTER_OTLP_METRICS_TIMEOUT = 'OTEL_EXPORTER_OTLP_METRICS_TIMEOUT'; + public const OTEL_EXPORTER_OTLP_LOGS_TIMEOUT = 'OTEL_EXPORTER_OTLP_LOGS_TIMEOUT'; + // Protocol + public const OTEL_EXPORTER_OTLP_PROTOCOL = 'OTEL_EXPORTER_OTLP_PROTOCOL'; + public const OTEL_EXPORTER_OTLP_TRACES_PROTOCOL = 'OTEL_EXPORTER_OTLP_TRACES_PROTOCOL'; + public const OTEL_EXPORTER_OTLP_METRICS_PROTOCOL = 'OTEL_EXPORTER_OTLP_METRICS_PROTOCOL'; + public const OTEL_EXPORTER_OTLP_LOGS_PROTOCOL = 'OTEL_EXPORTER_OTLP_LOGS_PROTOCOL'; + /** + * Zipkin Exporter + * @see https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/configuration/sdk-environment-variables.md#zipkin-exporter + */ + public const OTEL_EXPORTER_ZIPKIN_ENDPOINT = 'OTEL_EXPORTER_ZIPKIN_ENDPOINT'; + public const OTEL_EXPORTER_ZIPKIN_TIMEOUT = 'OTEL_EXPORTER_ZIPKIN_TIMEOUT'; + public const OTEL_EXPORTER_ZIPKIN_PROTOCOL = 'OTEL_EXPORTER_ZIPKIN_PROTOCOL'; + /** + * Prometheus Exporter + * @see https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/configuration/sdk-environment-variables.md#prometheus-exporter + */ + public const OTEL_EXPORTER_PROMETHEUS_HOST = 'OTEL_EXPORTER_PROMETHEUS_HOST'; + public const OTEL_EXPORTER_PROMETHEUS_PORT = 'OTEL_EXPORTER_PROMETHEUS_PORT'; + /** + * Exporter Selection + * @see https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/configuration/sdk-environment-variables.md#exporter-selection + */ + public const OTEL_TRACES_EXPORTER = 'OTEL_TRACES_EXPORTER'; + public const OTEL_METRICS_EXPORTER = 'OTEL_METRICS_EXPORTER'; + public const OTEL_LOGS_EXPORTER = 'OTEL_LOGS_EXPORTER'; + /** + * Metrics SDK Configuration + * @see https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/configuration/sdk-environment-variables.md#metrics-sdk-configuration + * @see https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/configuration/sdk-environment-variables.md#periodic-exporting-metricreader + */ + public const OTEL_METRICS_EXEMPLAR_FILTER = 'OTEL_METRICS_EXEMPLAR_FILTER'; + public const OTEL_METRIC_EXPORT_INTERVAL = 'OTEL_METRIC_EXPORT_INTERVAL'; + public const OTEL_METRIC_EXPORT_TIMEOUT = 'OTEL_METRIC_EXPORT_TIMEOUT'; + public const OTEL_EXPORTER_OTLP_METRICS_TEMPORALITY_PREFERENCE = 'OTEL_EXPORTER_OTLP_METRICS_TEMPORALITY_PREFERENCE'; + public const OTEL_EXPORTER_OTLP_METRICS_DEFAULT_HISTOGRAM_AGGREGATION = 'OTEL_EXPORTER_OTLP_METRICS_DEFAULT_HISTOGRAM_AGGREGATION'; + /** + * Language Specific Environment Variables + * @see https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/configuration/sdk-environment-variables.md#language-specific-environment-variables + */ + public const OTEL_PHP_TRACES_PROCESSOR = 'OTEL_PHP_TRACES_PROCESSOR'; + public const OTEL_PHP_LOGS_PROCESSOR = 'OTEL_PHP_LOGS_PROCESSOR'; + public const OTEL_PHP_LOG_DESTINATION = 'OTEL_PHP_LOG_DESTINATION'; + public const OTEL_PHP_DETECTORS = 'OTEL_PHP_DETECTORS'; + public const OTEL_PHP_AUTOLOAD_ENABLED = 'OTEL_PHP_AUTOLOAD_ENABLED'; + public const OTEL_PHP_INTERNAL_METRICS_ENABLED = 'OTEL_PHP_INTERNAL_METRICS_ENABLED'; //whether the SDK should emit its own metrics + public const OTEL_PHP_DISABLED_INSTRUMENTATIONS = 'OTEL_PHP_DISABLED_INSTRUMENTATIONS'; +} diff --git a/vendor/open-telemetry/sdk/Common/Dev/Compatibility/README.md b/vendor/open-telemetry/sdk/Common/Dev/Compatibility/README.md new file mode 100644 index 000000000..661eed3b8 --- /dev/null +++ b/vendor/open-telemetry/sdk/Common/Dev/Compatibility/README.md @@ -0,0 +1,14 @@ +# Backwards Compatibility + +We aim to provide backward compatibility (without any guarantee) even for alpha releases, however the library will raise notices indicating breaking changes and what to do about them. \ +If you don't want these notices to appear or change the error message level, you can do so by calling: +```php +OpenTelemetry\SDK\Common\Dev\Compatibility\Util::setErrorLevel(0) +``` +to turn messages off completely, or (for example) +```php +OpenTelemetry\SDK\Common\Dev\Compatibility\Util::setErrorLevel(E_USER_DEPRECATED) +``` +to trigger only deprecation notices. Valid error levels are `0` (none), `E_USER_DEPRECATED`, `E_USER_NOTICE`, `E_USER_WARNING` and `E_USER_ERROR` \ +However (as long as in alpha) it is safer to pin a dependency on the library to a specific version and/or make the adjustments +mentioned in the provided messages, since doing otherwise may break things completely for you in the future! diff --git a/vendor/open-telemetry/sdk/Common/Dev/Compatibility/Util.php b/vendor/open-telemetry/sdk/Common/Dev/Compatibility/Util.php new file mode 100644 index 000000000..1a3debfdd --- /dev/null +++ b/vendor/open-telemetry/sdk/Common/Dev/Compatibility/Util.php @@ -0,0 +1,93 @@ +<?php + +declare(strict_types=1); + +namespace OpenTelemetry\SDK\Common\Dev\Compatibility; + +class Util +{ + public const E_NONE = 0; + public const DEFAULT_ERROR_LEVEL = E_USER_NOTICE; + public const ERROR_LEVELS = [ + self::E_NONE, + E_USER_DEPRECATED, + E_USER_NOTICE, + E_USER_WARNING, + E_USER_ERROR, + ]; + + private static int $errorLevel = E_USER_NOTICE; + + public static function setErrorLevel(int $errorLevel = E_USER_NOTICE): void + { + self::validateErrorLevel($errorLevel); + + self::$errorLevel = $errorLevel; + } + + public static function getErrorLevel(): int + { + return self::$errorLevel; + } + + /** + * @psalm-suppress ArgumentTypeCoercion + */ + public static function triggerClassDeprecationNotice(string $className, string $alternativeClassName = null): void + { + if (self::getErrorLevel() === self::E_NONE) { + return; + } + + $notice = sprintf( + 'Class "%s" is deprecated and will be removed in a future release. ', + $className + ); + + if ($alternativeClassName !== null) { + $notice .= sprintf('Please, use "%s" instead.', $alternativeClassName); + } + + trigger_error($notice, self::$errorLevel); + } + + /** + * @psalm-suppress ArgumentTypeCoercion + */ + public static function triggerMethodDeprecationNotice( + string $methodName, + string $alternativeMethodName = null, + string $alternativeClassName = null + ): void { + if (self::getErrorLevel() === self::E_NONE) { + return; + } + + $notice = sprintf( + 'Method "%s " is deprecated and will be removed in a future release. ', + $methodName + ); + + if ($alternativeMethodName !== null) { + $method = $alternativeClassName === null + ? $alternativeMethodName + : sprintf('%s::%s', $alternativeClassName, $alternativeMethodName); + + $notice .= sprintf('Please, use "%s" instead.', $method); + } + + trigger_error($notice, self::$errorLevel); + } + + private static function validateErrorLevel(int $errorLevel): void + { + if (!in_array($errorLevel, self::ERROR_LEVELS, true)) { + throw new \InvalidArgumentException( + sprintf( + 'Error level must be one of "%s"', + implode('", "', self::ERROR_LEVELS) + ), + ); + } + } +} diff --git a/vendor/open-telemetry/sdk/Common/Dev/Compatibility/_load.php b/vendor/open-telemetry/sdk/Common/Dev/Compatibility/_load.php new file mode 100644 index 000000000..99f86c574 --- /dev/null +++ b/vendor/open-telemetry/sdk/Common/Dev/Compatibility/_load.php @@ -0,0 +1,7 @@ +<?php + +declare(strict_types=1); +/** + * To add a BC compatibility: + * require_once __DIR__ . '/BC/SomeFile.php'; + */ diff --git a/vendor/open-telemetry/sdk/Common/Exception/StackTraceFormatter.php b/vendor/open-telemetry/sdk/Common/Exception/StackTraceFormatter.php new file mode 100644 index 000000000..675fc7626 --- /dev/null +++ b/vendor/open-telemetry/sdk/Common/Exception/StackTraceFormatter.php @@ -0,0 +1,155 @@ +<?php + +declare(strict_types=1); + +namespace OpenTelemetry\SDK\Common\Exception; + +use function basename; +use function count; +use function get_class; +use function sprintf; +use function str_repeat; + +use Throwable; + +/** + * @psalm-type Frame = array{ + * function: string, + * class: ?class-string, + * file: ?string, + * line: ?int, + * } + * @psalm-type Frames = non-empty-list<Frame> + */ +final class StackTraceFormatter +{ + private function __construct() + { + } + + /** + * Formats an exception in a java-like format. + * + * @param Throwable $e exception to format + * @return string formatted exception + * + * @see https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/Throwable.html#printStackTrace() + */ + public static function format(Throwable $e): string + { + $s = ''; + $seen = []; + + /** @var Frames|null $enclosing */ + $enclosing = null; + do { + if ($enclosing) { + self::writeNewline($s); + $s .= 'Caused by: '; + } + if (isset($seen[spl_object_id($e)])) { + $s .= '[CIRCULAR REFERENCE: '; + self::writeInlineHeader($s, $e); + $s .= ']'; + + break; + } + $seen[spl_object_id($e)] = $e; + + $frames = self::frames($e); + self::writeInlineHeader($s, $e); + self::writeFrames($s, $frames, $enclosing); + + $enclosing = $frames; + } while ($e = $e->getPrevious()); + + return $s; + } + + /** + * @phan-suppress-next-line PhanTypeMismatchDeclaredParam + * @param Frames $frames + * @phan-suppress-next-line PhanTypeMismatchDeclaredParam + * @param Frames|null $enclosing + */ + private static function writeFrames(string &$s, array $frames, ?array $enclosing): void + { + $n = count($frames); + if ($enclosing) { + for ($m = count($enclosing); + $n && $m && $frames[$n - 1] === $enclosing[$m - 1]; + $n--, $m--) { + } + } + for ($i = 0; $i < $n; $i++) { + $frame = $frames[$i]; + self::writeNewline($s, 1); + $s .= 'at '; + if ($frame['class'] !== null) { + $s .= self::formatName($frame['class']); + $s .= '.'; + } + $s .= self::formatName($frame['function']); + $s .= '('; + if ($frame['file'] !== null) { + $s .= basename($frame['file']); + if ($frame['line']) { + $s .= ':'; + $s .= $frame['line']; + } + } else { + $s .= 'Unknown Source'; + } + $s .= ')'; + } + if ($n !== count($frames)) { + self::writeNewline($s, 1); + $s .= sprintf('... %d more', count($frames) - $n); + } + } + + private static function writeInlineHeader(string &$s, Throwable $e): void + { + $s .= self::formatName(get_class($e)); + if ($e->getMessage() !== '') { + $s .= ': '; + $s .= $e->getMessage(); + } + } + + private static function writeNewline(string &$s, int $indent = 0): void + { + $s .= "\n"; + $s .= str_repeat("\t", $indent); + } + + /** + * @return Frames + * + * @psalm-suppress PossiblyUndefinedArrayOffset + */ + private static function frames(Throwable $e): array + { + $frames = []; + $trace = $e->getTrace(); + $traceCount = count($trace); + for ($i = 0; $i < $traceCount + 1; $i++) { + $frames[] = [ + 'function' => $trace[$i]['function'] ?? '{main}', + 'class' => $trace[$i]['class'] ?? null, + 'file' => $trace[$i - 1]['file'] ?? null, + 'line' => $trace[$i - 1]['line'] ?? null, + ]; + } + $frames[0]['file'] = $e->getFile(); + $frames[0]['line'] = $e->getLine(); + + /** @var Frames $frames */ + return $frames; + } + + private static function formatName(string $name): string + { + return strtr($name, ['\\' => '.']); + } +} diff --git a/vendor/open-telemetry/sdk/Common/Export/Http/PsrTransport.php b/vendor/open-telemetry/sdk/Common/Export/Http/PsrTransport.php new file mode 100644 index 000000000..a53e5b80a --- /dev/null +++ b/vendor/open-telemetry/sdk/Common/Export/Http/PsrTransport.php @@ -0,0 +1,168 @@ +<?php + +declare(strict_types=1); + +namespace OpenTelemetry\SDK\Common\Export\Http; + +use function assert; +use BadMethodCallException; +use function explode; +use function in_array; +use OpenTelemetry\SDK\Common\Export\TransportInterface; +use OpenTelemetry\SDK\Common\Future\CancellationInterface; +use OpenTelemetry\SDK\Common\Future\CompletedFuture; +use OpenTelemetry\SDK\Common\Future\ErrorFuture; +use OpenTelemetry\SDK\Common\Future\FutureInterface; +use Psr\Http\Client\ClientInterface; +use Psr\Http\Client\NetworkExceptionInterface; +use Psr\Http\Message\RequestFactoryInterface; +use Psr\Http\Message\ResponseInterface; +use Psr\Http\Message\StreamFactoryInterface; +use RuntimeException; +use function strtolower; +use Throwable; +use function time_nanosleep; +use function trim; + +/** + * @psalm-template CONTENT_TYPE of string + * @template-implements TransportInterface<CONTENT_TYPE> + */ +final class PsrTransport implements TransportInterface +{ + private ClientInterface $client; + private RequestFactoryInterface $requestFactory; + private StreamFactoryInterface $streamFactory; + + private string $endpoint; + private string $contentType; + private array $headers; + private array $compression; + private int $retryDelay; + private int $maxRetries; + + private bool $closed = false; + + /** + * @psalm-param CONTENT_TYPE $contentType + */ + public function __construct( + ClientInterface $client, + RequestFactoryInterface $requestFactory, + StreamFactoryInterface $streamFactory, + string $endpoint, + string $contentType, + array $headers, + array $compression, + int $retryDelay, + int $maxRetries + ) { + $this->client = $client; + $this->requestFactory = $requestFactory; + $this->streamFactory = $streamFactory; + $this->endpoint = $endpoint; + $this->contentType = $contentType; + $this->headers = $headers; + $this->compression = $compression; + $this->retryDelay = $retryDelay; + $this->maxRetries = $maxRetries; + } + + public function contentType(): string + { + return $this->contentType; + } + + public function send(string $payload, ?CancellationInterface $cancellation = null): FutureInterface + { + if ($this->closed) { + return new ErrorFuture(new BadMethodCallException('Transport closed')); + } + + $body = PsrUtils::encode($payload, $this->compression, $appliedEncodings); + $request = $this->requestFactory + ->createRequest('POST', $this->endpoint) + ->withBody($this->streamFactory->createStream($body)) + ->withHeader('Content-Type', $this->contentType) + ; + if ($appliedEncodings) { + $request = $request->withHeader('Content-Encoding', $appliedEncodings); + } + foreach ($this->headers as $header => $value) { + $request = $request->withAddedHeader($header, $value); + } + + for ($retries = 0;; $retries++) { + $response = null; + $e = null; + + try { + $response = $this->client->sendRequest($request); + if ($response->getStatusCode() >= 200 && $response->getStatusCode() < 300) { + break; + } + + if ($response->getStatusCode() >= 400 && $response->getStatusCode() < 500 && !in_array($response->getStatusCode(), [408, 429], true)) { + throw new RuntimeException($response->getReasonPhrase(), $response->getStatusCode()); + } + } catch (NetworkExceptionInterface $e) { + } catch (Throwable $e) { + return new ErrorFuture($e); + } + + if ($retries >= $this->maxRetries) { + return new ErrorFuture(new RuntimeException('Export retry limit exceeded', 0, $e)); + } + + $delay = PsrUtils::retryDelay($retries, $this->retryDelay, $response); + $sec = (int) $delay; + $nsec = (int) (($delay - $sec) * 1e9); + + /** @psalm-suppress ArgumentTypeCoercion */ + if (time_nanosleep($sec, $nsec) !== true) { + return new ErrorFuture(new RuntimeException('Export cancelled', 0, $e)); + } + } + + assert(isset($response)); + + try { + $body = PsrUtils::decode( + $response->getBody()->__toString(), + self::parseContentEncoding($response), + ); + } catch (Throwable $e) { + return new ErrorFuture($e); + } + + return new CompletedFuture($body); + } + + private static function parseContentEncoding(ResponseInterface $response): array + { + $encodings = []; + foreach (explode(',', $response->getHeaderLine('Content-Encoding')) as $encoding) { + if (($encoding = trim($encoding, " \t")) !== '') { + $encodings[] = strtolower($encoding); + } + } + + return $encodings; + } + + public function shutdown(?CancellationInterface $cancellation = null): bool + { + if ($this->closed) { + return false; + } + + $this->closed = true; + + return true; + } + + public function forceFlush(?CancellationInterface $cancellation = null): bool + { + return !$this->closed; + } +} diff --git a/vendor/open-telemetry/sdk/Common/Export/Http/PsrTransportFactory.php b/vendor/open-telemetry/sdk/Common/Export/Http/PsrTransportFactory.php new file mode 100644 index 000000000..5ef78d82c --- /dev/null +++ b/vendor/open-telemetry/sdk/Common/Export/Http/PsrTransportFactory.php @@ -0,0 +1,74 @@ +<?php + +declare(strict_types=1); + +namespace OpenTelemetry\SDK\Common\Export\Http; + +use const FILTER_VALIDATE_URL; +use function filter_var; +use Http\Discovery\Psr17FactoryDiscovery; +use Http\Discovery\Psr18ClientDiscovery; +use InvalidArgumentException; +use OpenTelemetry\SDK\Common\Export\TransportFactoryInterface; +use Psr\Http\Client\ClientInterface; +use Psr\Http\Message\RequestFactoryInterface; +use Psr\Http\Message\StreamFactoryInterface; + +final class PsrTransportFactory implements TransportFactoryInterface +{ + private ClientInterface $client; + private RequestFactoryInterface $requestFactory; + private StreamFactoryInterface $streamFactory; + + public function __construct( + ClientInterface $client, + RequestFactoryInterface $requestFactory, + StreamFactoryInterface $streamFactory + ) { + $this->client = $client; + $this->requestFactory = $requestFactory; + $this->streamFactory = $streamFactory; + } + + /** + * @phan-suppress PhanTypeMismatchArgumentNullable + */ + public function create( + string $endpoint, + string $contentType, + array $headers = [], + $compression = null, + float $timeout = 10., + int $retryDelay = 100, + int $maxRetries = 3, + ?string $cacert = null, + ?string $cert = null, + ?string $key = null + ): PsrTransport { + if (!filter_var($endpoint, FILTER_VALIDATE_URL)) { + throw new InvalidArgumentException(sprintf('Invalid endpoint url "%s"', $endpoint)); + } + assert(!empty($endpoint)); + + return new PsrTransport( + $this->client, + $this->requestFactory, + $this->streamFactory, + $endpoint, + $contentType, + $headers, + PsrUtils::compression($compression), + $retryDelay, + $maxRetries, + ); + } + + public static function discover(): self + { + return new self( + Psr18ClientDiscovery::find(), + Psr17FactoryDiscovery::findRequestFactory(), + Psr17FactoryDiscovery::findStreamFactory(), + ); + } +} diff --git a/vendor/open-telemetry/sdk/Common/Export/Http/PsrUtils.php b/vendor/open-telemetry/sdk/Common/Export/Http/PsrUtils.php new file mode 100644 index 000000000..eaf2f3b47 --- /dev/null +++ b/vendor/open-telemetry/sdk/Common/Export/Http/PsrUtils.php @@ -0,0 +1,175 @@ +<?php + +declare(strict_types=1); + +namespace OpenTelemetry\SDK\Common\Export\Http; + +use function array_filter; +use function array_map; +use function count; +use ErrorException; +use LogicException; +use function max; +use OpenTelemetry\SDK\Common\Export\TransportFactoryInterface; +use Psr\Http\Message\ResponseInterface; +use function rand; +use function restore_error_handler; +use function set_error_handler; +use function sprintf; +use function strcasecmp; +use function strtotime; +use Throwable; +use function time; +use function trim; +use UnexpectedValueException; + +/** + * @internal + */ +final class PsrUtils +{ + /** + * @param int $retry zero-indexed attempt number + * @param int $retryDelay initial delay in milliseconds + * @param ResponseInterface|null $response response of failed request + * @return float delay in seconds + */ + public static function retryDelay(int $retry, int $retryDelay, ?ResponseInterface $response = null): float + { + $delay = $retryDelay << $retry; + $delay = rand($delay >> 1, $delay) / 1000; + + return max($delay, self::parseRetryAfter($response)); + } + + private static function parseRetryAfter(?ResponseInterface $response): int + { + if (!$response || !$retryAfter = $response->getHeaderLine('Retry-After')) { + return 0; + } + + $retryAfter = trim($retryAfter, " \t"); + if ($retryAfter === (string) (int) $retryAfter) { + return (int) $retryAfter; + } + + if (($time = strtotime($retryAfter)) !== false) { + return $time - time(); + } + + return 0; + } + + /** + * @param list<string> $encodings + * @param array<int, string>|null $appliedEncodings + */ + public static function encode(string $value, array $encodings, ?array &$appliedEncodings = null): string + { + for ($i = 0, $n = count($encodings); $i < $n; $i++) { + if (!$encoder = self::encoder($encodings[$i])) { + unset($encodings[$i]); + + continue; + } + + try { + $value = $encoder($value); + } catch (Throwable $e) { + unset($encodings[$i]); + } + } + + $appliedEncodings = $encodings; + + return $value; + } + + /** + * @param list<string> $encodings + */ + public static function decode(string $value, array $encodings): string + { + for ($i = count($encodings); --$i >= 0;) { + if (strcasecmp($encodings[$i], 'identity') === 0) { + continue; + } + if (!$decoder = self::decoder($encodings[$i])) { + throw new UnexpectedValueException(sprintf('Not supported decompression encoding "%s"', $encodings[$i])); + } + + $value = $decoder($value); + } + + return $value; + } + + /** + * Resolve an array or CSV of compression types to a list + */ + public static function compression($compression): array + { + if (is_array($compression)) { + return $compression; + } + if (!$compression) { + return []; + } + if (strpos($compression, ',') === false) { + return [$compression]; + } + + return array_map('trim', explode(',', $compression)); + } + + private static function encoder(string $encoding): ?callable + { + static $encoders; + + /** @noinspection SpellCheckingInspection */ + $encoders ??= array_map(fn (callable $callable): callable => self::throwOnErrorOrFalse($callable), array_filter([ + TransportFactoryInterface::COMPRESSION_GZIP => 'gzencode', + TransportFactoryInterface::COMPRESSION_DEFLATE => 'gzcompress', + TransportFactoryInterface::COMPRESSION_BROTLI => 'brotli_compress', + ], 'function_exists')); + + return $encoders[$encoding] ?? null; + } + + private static function decoder(string $encoding): ?callable + { + static $decoders; + + /** @noinspection SpellCheckingInspection */ + $decoders ??= array_map(fn (callable $callable): callable => self::throwOnErrorOrFalse($callable), array_filter([ + TransportFactoryInterface::COMPRESSION_GZIP => 'gzdecode', + TransportFactoryInterface::COMPRESSION_DEFLATE => 'gzuncompress', + TransportFactoryInterface::COMPRESSION_BROTLI => 'brotli_uncompress', + ], 'function_exists')); + + return $decoders[$encoding] ?? null; + } + + private static function throwOnErrorOrFalse(callable $callable): callable + { + return static function (...$args) use ($callable) { + set_error_handler(static function (int $errno, string $errstr, string $errfile, int $errline): bool { + throw new ErrorException($errstr, 0, $errno, $errfile, $errline); + }); + + try { + $result = $callable(...$args); + } finally { + restore_error_handler(); + } + + /** @phan-suppress-next-line PhanPossiblyUndeclaredVariable */ + if ($result === false) { + throw new LogicException(); + } + + /** @phan-suppress-next-line PhanPossiblyUndeclaredVariable */ + return $result; + }; + } +} diff --git a/vendor/open-telemetry/sdk/Common/Export/Stream/StreamTransport.php b/vendor/open-telemetry/sdk/Common/Export/Stream/StreamTransport.php new file mode 100644 index 000000000..4b99cf756 --- /dev/null +++ b/vendor/open-telemetry/sdk/Common/Export/Stream/StreamTransport.php @@ -0,0 +1,97 @@ +<?php + +declare(strict_types=1); + +namespace OpenTelemetry\SDK\Common\Export\Stream; + +use BadMethodCallException; +use ErrorException; +use function fflush; +use function fwrite; +use OpenTelemetry\SDK\Common\Export\TransportInterface; +use OpenTelemetry\SDK\Common\Future\CancellationInterface; +use OpenTelemetry\SDK\Common\Future\CompletedFuture; +use OpenTelemetry\SDK\Common\Future\ErrorFuture; +use OpenTelemetry\SDK\Common\Future\FutureInterface; +use function restore_error_handler; +use RuntimeException; +use function set_error_handler; +use function strlen; +use Throwable; + +/** + * @internal + * + * @psalm-template CONTENT_TYPE of string + * @template-implements TransportInterface<CONTENT_TYPE> + */ +final class StreamTransport implements TransportInterface +{ + /** + * @var resource|null + */ + private $stream; + private string $contentType; + + /** + * @param resource $stream + * + * @psalm-param CONTENT_TYPE $contentType + */ + public function __construct($stream, string $contentType) + { + $this->stream = $stream; + $this->contentType = $contentType; + } + + public function contentType(): string + { + return $this->contentType; + } + + public function send(string $payload, ?CancellationInterface $cancellation = null): FutureInterface + { + if (!$this->stream) { + return new ErrorFuture(new BadMethodCallException('Transport closed')); + } + + set_error_handler(static function (int $errno, string $errstr, string $errfile, int $errline): bool { + throw new ErrorException($errstr, 0, $errno, $errfile, $errline); + }); + + try { + $bytesWritten = fwrite($this->stream, $payload); + } catch (Throwable $e) { + return new ErrorFuture($e); + } finally { + restore_error_handler(); + } + + if ($bytesWritten !== strlen($payload)) { + return new ErrorFuture(new RuntimeException(sprintf('Write failure, wrote %d of %d bytes', $bytesWritten, strlen($payload)))); + } + + return new CompletedFuture(null); + } + + public function shutdown(?CancellationInterface $cancellation = null): bool + { + if (!$this->stream) { + return false; + } + + $flush = @fflush($this->stream); + $this->stream = null; + + return $flush; + } + + public function forceFlush(?CancellationInterface $cancellation = null): bool + { + if (!$this->stream) { + return false; + } + + return @fflush($this->stream); + } +} diff --git a/vendor/open-telemetry/sdk/Common/Export/Stream/StreamTransportFactory.php b/vendor/open-telemetry/sdk/Common/Export/Stream/StreamTransportFactory.php new file mode 100644 index 000000000..59e411318 --- /dev/null +++ b/vendor/open-telemetry/sdk/Common/Export/Stream/StreamTransportFactory.php @@ -0,0 +1,118 @@ +<?php + +declare(strict_types=1); + +namespace OpenTelemetry\SDK\Common\Export\Stream; + +use ErrorException; +use function fopen; +use function implode; +use function is_resource; +use LogicException; +use OpenTelemetry\SDK\Common\Export\TransportFactoryInterface; +use OpenTelemetry\SDK\Common\Export\TransportInterface; +use function restore_error_handler; +use function set_error_handler; +use function sprintf; +use function stream_context_create; + +/** + * @psalm-internal \OpenTelemetry + */ +final class StreamTransportFactory implements TransportFactoryInterface +{ + /** + * @param string|resource $endpoint + * @param array<string, string|string[]> $headers + * @param string|string[]|null $compression + * + * @psalm-template CONTENT_TYPE of string + * @psalm-param CONTENT_TYPE $contentType + * @psalm-return TransportInterface<CONTENT_TYPE> + */ + public function create( + $endpoint, + string $contentType, + array $headers = [], + $compression = null, + float $timeout = 10., + int $retryDelay = 100, + int $maxRetries = 3, + ?string $cacert = null, + ?string $cert = null, + ?string $key = null + ): TransportInterface { + assert(!empty($endpoint)); + $stream = is_resource($endpoint) + ? $endpoint + : self::createStream( + $endpoint, + $contentType, + $headers, + $timeout, + $cacert, + $cert, + $key, + ); + + return new StreamTransport($stream, $contentType); + } + + /** + * @throws ErrorException + * @return resource + */ + private static function createStream( + string $endpoint, + string $contentType, + array $headers = [], + float $timeout = 10., + ?string $cacert = null, + ?string $cert = null, + ?string $key = null + ) { + $context = stream_context_create([ + 'http' => [ + 'method' => 'POST', + 'header' => self::createHeaderArray($contentType, $headers), + 'timeout' => $timeout, + ], + 'ssl' => [ + 'cafile' => $cacert, + 'local_cert' => $cert, + 'local_pk' => $key, + ], + ]); + + set_error_handler(static function (int $errno, string $errstr, string $errfile, int $errline): bool { + throw new ErrorException($errstr, 0, $errno, $errfile, $errline); + }); + + /** + * @psalm-suppress PossiblyNullArgument + */ + try { + $stream = fopen($endpoint, 'ab', false, $context); + } finally { + restore_error_handler(); + } + + /** @phan-suppress-next-line PhanPossiblyUndeclaredVariable */ + if (!$stream) { + throw new LogicException(sprintf('Failed opening stream "%s"', $endpoint)); + } + + return $stream; + } + + private static function createHeaderArray(string $contentType, array $headers): array + { + $header = []; + $header[] = sprintf('Content-Type: %s', $contentType); + foreach ($headers as $name => $value) { + $header[] = sprintf('%s: %s', $name, implode(', ', (array) $value)); + } + + return $header; + } +} diff --git a/vendor/open-telemetry/sdk/Common/Export/TransportFactoryInterface.php b/vendor/open-telemetry/sdk/Common/Export/TransportFactoryInterface.php new file mode 100644 index 000000000..48e538443 --- /dev/null +++ b/vendor/open-telemetry/sdk/Common/Export/TransportFactoryInterface.php @@ -0,0 +1,32 @@ +<?php + +declare(strict_types=1); + +namespace OpenTelemetry\SDK\Common\Export; + +interface TransportFactoryInterface +{ + public const COMPRESSION_GZIP = 'gzip'; + public const COMPRESSION_DEFLATE = 'deflate'; + public const COMPRESSION_BROTLI = 'br'; + + /** + * @psalm-template CONTENT_TYPE of string + * @psalm-param CONTENT_TYPE $contentType + * @psalm-param array<string, string|string[]> $headers + * @psalm-param string|string[]|null $compression + * @psalm-return TransportInterface<CONTENT_TYPE> + */ + public function create( + string $endpoint, + string $contentType, + array $headers = [], + $compression = null, + float $timeout = 10., + int $retryDelay = 100, + int $maxRetries = 3, + ?string $cacert = null, + ?string $cert = null, + ?string $key = null + ): TransportInterface; +} diff --git a/vendor/open-telemetry/sdk/Common/Export/TransportInterface.php b/vendor/open-telemetry/sdk/Common/Export/TransportInterface.php new file mode 100644 index 000000000..5fb26eff8 --- /dev/null +++ b/vendor/open-telemetry/sdk/Common/Export/TransportInterface.php @@ -0,0 +1,22 @@ +<?php + +declare(strict_types=1); + +namespace OpenTelemetry\SDK\Common\Export; + +use OpenTelemetry\SDK\Common\Future\CancellationInterface; +use OpenTelemetry\SDK\Common\Future\FutureInterface; + +/** + * @psalm-template-covariant CONTENT_TYPE of string + */ +interface TransportInterface +{ + public function contentType(): string; + + public function send(string $payload, ?CancellationInterface $cancellation = null): FutureInterface; + + public function shutdown(?CancellationInterface $cancellation = null): bool; + + public function forceFlush(?CancellationInterface $cancellation = null): bool; +} diff --git a/vendor/open-telemetry/sdk/Common/Future/CancellationInterface.php b/vendor/open-telemetry/sdk/Common/Future/CancellationInterface.php new file mode 100644 index 000000000..16909ec6d --- /dev/null +++ b/vendor/open-telemetry/sdk/Common/Future/CancellationInterface.php @@ -0,0 +1,18 @@ +<?php + +declare(strict_types=1); + +namespace OpenTelemetry\SDK\Common\Future; + +use Closure; +use Throwable; + +interface CancellationInterface +{ + /** + * @param Closure(Throwable): void $callback + */ + public function subscribe(Closure $callback): string; + + public function unsubscribe(string $id): void; +} diff --git a/vendor/open-telemetry/sdk/Common/Future/CompletedFuture.php b/vendor/open-telemetry/sdk/Common/Future/CompletedFuture.php new file mode 100644 index 000000000..7f0cd6536 --- /dev/null +++ b/vendor/open-telemetry/sdk/Common/Future/CompletedFuture.php @@ -0,0 +1,48 @@ +<?php + +declare(strict_types=1); + +namespace OpenTelemetry\SDK\Common\Future; + +use Closure; +use Throwable; + +/** + * @template T + * @template-implements FutureInterface<T> + */ +final class CompletedFuture implements FutureInterface +{ + /** @var T */ + private $value; + + /** + * @param T $value + */ + public function __construct($value) + { + $this->value = $value; + } + + public function await() + { + return $this->value; + } + + public function map(Closure $closure): FutureInterface + { + $c = $closure; + unset($closure); + + try { + return new CompletedFuture($c($this->value)); + } catch (Throwable $e) { + return new ErrorFuture($e); + } + } + + public function catch(Closure $closure): FutureInterface + { + return $this; + } +} diff --git a/vendor/open-telemetry/sdk/Common/Future/ErrorFuture.php b/vendor/open-telemetry/sdk/Common/Future/ErrorFuture.php new file mode 100644 index 000000000..32cf3d995 --- /dev/null +++ b/vendor/open-telemetry/sdk/Common/Future/ErrorFuture.php @@ -0,0 +1,40 @@ +<?php + +declare(strict_types=1); + +namespace OpenTelemetry\SDK\Common\Future; + +use Closure; +use Throwable; + +final class ErrorFuture implements FutureInterface +{ + private Throwable $throwable; + + public function __construct(Throwable $throwable) + { + $this->throwable = $throwable; + } + + public function await() + { + throw $this->throwable; + } + + public function map(Closure $closure): FutureInterface + { + return $this; + } + + public function catch(Closure $closure): FutureInterface + { + $c = $closure; + unset($closure); + + try { + return new CompletedFuture($c($this->throwable)); + } catch (Throwable $e) { + return new ErrorFuture($e); + } + } +} diff --git a/vendor/open-telemetry/sdk/Common/Future/FutureInterface.php b/vendor/open-telemetry/sdk/Common/Future/FutureInterface.php new file mode 100644 index 000000000..850699bf6 --- /dev/null +++ b/vendor/open-telemetry/sdk/Common/Future/FutureInterface.php @@ -0,0 +1,34 @@ +<?php + +declare(strict_types=1); + +namespace OpenTelemetry\SDK\Common\Future; + +use Closure; + +/** + * @template-covariant T + */ +interface FutureInterface +{ + /** + * @psalm-return T + */ + public function await(); + + /** + * @psalm-template U + * @psalm-param Closure(T): U $closure + * @psalm-return FutureInterface<U> + * + * @psalm-suppress InvalidTemplateParam + */ + public function map(Closure $closure): FutureInterface; + + /** + * @psalm-template U + * @psalm-param Closure(\Throwable): U $closure + * @psalm-return FutureInterface<T|U> + */ + public function catch(Closure $closure): FutureInterface; +} diff --git a/vendor/open-telemetry/sdk/Common/Future/NullCancellation.php b/vendor/open-telemetry/sdk/Common/Future/NullCancellation.php new file mode 100644 index 000000000..5e5b642f9 --- /dev/null +++ b/vendor/open-telemetry/sdk/Common/Future/NullCancellation.php @@ -0,0 +1,20 @@ +<?php + +declare(strict_types=1); + +namespace OpenTelemetry\SDK\Common\Future; + +use Closure; + +final class NullCancellation implements CancellationInterface +{ + public function subscribe(Closure $callback): string + { + return self::class; + } + + public function unsubscribe(string $id): void + { + // no-op + } +} diff --git a/vendor/open-telemetry/sdk/Common/Http/DependencyResolverInterface.php b/vendor/open-telemetry/sdk/Common/Http/DependencyResolverInterface.php new file mode 100644 index 000000000..824335213 --- /dev/null +++ b/vendor/open-telemetry/sdk/Common/Http/DependencyResolverInterface.php @@ -0,0 +1,13 @@ +<?php + +declare(strict_types=1); + +namespace OpenTelemetry\SDK\Common\Http; + +use OpenTelemetry\SDK\Common\Http\HttpPlug\Client\ResolverInterface as HttpPlugClientResolverInterface; +use OpenTelemetry\SDK\Common\Http\Psr\Client\ResolverInterface as PsrClientResolverInterface; +use OpenTelemetry\SDK\Common\Http\Psr\Message\FactoryResolverInterface; + +interface DependencyResolverInterface extends FactoryResolverInterface, PsrClientResolverInterface, HttpPlugClientResolverInterface +{ +} diff --git a/vendor/open-telemetry/sdk/Common/Http/HttpPlug/Client/ResolverInterface.php b/vendor/open-telemetry/sdk/Common/Http/HttpPlug/Client/ResolverInterface.php new file mode 100644 index 000000000..3b2f4d53e --- /dev/null +++ b/vendor/open-telemetry/sdk/Common/Http/HttpPlug/Client/ResolverInterface.php @@ -0,0 +1,12 @@ +<?php + +declare(strict_types=1); + +namespace OpenTelemetry\SDK\Common\Http\HttpPlug\Client; + +use Http\Client\HttpAsyncClient; + +interface ResolverInterface +{ + public function resolveHttpPlugAsyncClient(): HttpAsyncClient; +} diff --git a/vendor/open-telemetry/sdk/Common/Http/Psr/Client/ResolverInterface.php b/vendor/open-telemetry/sdk/Common/Http/Psr/Client/ResolverInterface.php new file mode 100644 index 000000000..ba028e38a --- /dev/null +++ b/vendor/open-telemetry/sdk/Common/Http/Psr/Client/ResolverInterface.php @@ -0,0 +1,12 @@ +<?php + +declare(strict_types=1); + +namespace OpenTelemetry\SDK\Common\Http\Psr\Client; + +use Psr\Http\Client\ClientInterface; + +interface ResolverInterface +{ + public function resolvePsrClient(): ClientInterface; +} diff --git a/vendor/open-telemetry/sdk/Common/Http/Psr/Message/FactoryResolverInterface.php b/vendor/open-telemetry/sdk/Common/Http/Psr/Message/FactoryResolverInterface.php new file mode 100644 index 000000000..4582e19ce --- /dev/null +++ b/vendor/open-telemetry/sdk/Common/Http/Psr/Message/FactoryResolverInterface.php @@ -0,0 +1,22 @@ +<?php + +declare(strict_types=1); + +namespace OpenTelemetry\SDK\Common\Http\Psr\Message; + +use Psr\Http\Message\RequestFactoryInterface; +use Psr\Http\Message\ResponseFactoryInterface; +use Psr\Http\Message\ServerRequestFactoryInterface; +use Psr\Http\Message\StreamFactoryInterface; +use Psr\Http\Message\UploadedFileFactoryInterface; +use Psr\Http\Message\UriFactoryInterface; + +interface FactoryResolverInterface +{ + public function resolveRequestFactory(): RequestFactoryInterface; + public function resolveResponseFactory(): ResponseFactoryInterface; + public function resolveServerRequestFactory(): ServerRequestFactoryInterface; + public function resolveStreamFactory(): StreamFactoryInterface; + public function resolveUploadedFileFactory(): UploadedFileFactoryInterface; + public function resolveUriFactory(): UriFactoryInterface; +} diff --git a/vendor/open-telemetry/sdk/Common/Http/Psr/Message/MessageFactory.php b/vendor/open-telemetry/sdk/Common/Http/Psr/Message/MessageFactory.php new file mode 100644 index 000000000..8e99d64c0 --- /dev/null +++ b/vendor/open-telemetry/sdk/Common/Http/Psr/Message/MessageFactory.php @@ -0,0 +1,52 @@ +<?php + +declare(strict_types=1); + +namespace OpenTelemetry\SDK\Common\Http\Psr\Message; + +use Psr\Http\Message\RequestFactoryInterface; +use Psr\Http\Message\RequestInterface; +use Psr\Http\Message\ResponseFactoryInterface; +use Psr\Http\Message\ResponseInterface; +use Psr\Http\Message\ServerRequestFactoryInterface; +use Psr\Http\Message\ServerRequestInterface; + +final class MessageFactory implements MessageFactoryInterface +{ + private RequestFactoryInterface $requestFactory; + private ResponseFactoryInterface $responseFactory; + private ServerRequestFactoryInterface $serverRequestFactory; + + public function __construct( + RequestFactoryInterface $requestFactory, + ResponseFactoryInterface $responseFactory, + ServerRequestFactoryInterface $serverRequestFactory + ) { + $this->requestFactory = $requestFactory; + $this->responseFactory = $responseFactory; + $this->serverRequestFactory = $serverRequestFactory; + } + + public static function create( + RequestFactoryInterface $requestFactory, + ResponseFactoryInterface $responseFactory, + ServerRequestFactoryInterface $serverRequestFactory + ): self { + return new self($requestFactory, $responseFactory, $serverRequestFactory); + } + + public function createRequest(string $method, $uri): RequestInterface + { + return $this->requestFactory->createRequest($method, $uri); + } + + public function createResponse(int $code = 200, string $reasonPhrase = ''): ResponseInterface + { + return $this->responseFactory->createResponse($code, $reasonPhrase); + } + + public function createServerRequest(string $method, $uri, array $serverParams = []): ServerRequestInterface + { + return $this->serverRequestFactory->createServerRequest($method, $uri, $serverParams); + } +} diff --git a/vendor/open-telemetry/sdk/Common/Http/Psr/Message/MessageFactoryInterface.php b/vendor/open-telemetry/sdk/Common/Http/Psr/Message/MessageFactoryInterface.php new file mode 100644 index 000000000..97258491f --- /dev/null +++ b/vendor/open-telemetry/sdk/Common/Http/Psr/Message/MessageFactoryInterface.php @@ -0,0 +1,13 @@ +<?php + +declare(strict_types=1); + +namespace OpenTelemetry\SDK\Common\Http\Psr\Message; + +use Psr\Http\Message\RequestFactoryInterface; +use Psr\Http\Message\ResponseFactoryInterface; +use Psr\Http\Message\ServerRequestFactoryInterface; + +interface MessageFactoryInterface extends RequestFactoryInterface, ServerRequestFactoryInterface, ResponseFactoryInterface +{ +} diff --git a/vendor/open-telemetry/sdk/Common/Instrumentation/InstrumentationScope.php b/vendor/open-telemetry/sdk/Common/Instrumentation/InstrumentationScope.php new file mode 100644 index 000000000..ec9b52fb0 --- /dev/null +++ b/vendor/open-telemetry/sdk/Common/Instrumentation/InstrumentationScope.php @@ -0,0 +1,46 @@ +<?php + +declare(strict_types=1); + +namespace OpenTelemetry\SDK\Common\Instrumentation; + +use OpenTelemetry\SDK\Common\Attribute\AttributesInterface; + +/** + * Represents the instrumentation scope information associated with the Tracer or Meter + */ +final class InstrumentationScope implements InstrumentationScopeInterface +{ + private string $name; + private ?string $version; + private ?string $schemaUrl; + private AttributesInterface $attributes; + + public function __construct(string $name, ?string $version, ?string $schemaUrl, AttributesInterface $attributes) + { + $this->name = $name; + $this->version = $version; + $this->schemaUrl = $schemaUrl; + $this->attributes = $attributes; + } + + public function getName(): string + { + return $this->name; + } + + public function getVersion(): ?string + { + return $this->version; + } + + public function getSchemaUrl(): ?string + { + return $this->schemaUrl; + } + + public function getAttributes(): AttributesInterface + { + return $this->attributes; + } +} diff --git a/vendor/open-telemetry/sdk/Common/Instrumentation/InstrumentationScopeFactory.php b/vendor/open-telemetry/sdk/Common/Instrumentation/InstrumentationScopeFactory.php new file mode 100644 index 000000000..f1ae7c072 --- /dev/null +++ b/vendor/open-telemetry/sdk/Common/Instrumentation/InstrumentationScopeFactory.php @@ -0,0 +1,31 @@ +<?php + +declare(strict_types=1); + +namespace OpenTelemetry\SDK\Common\Instrumentation; + +use OpenTelemetry\SDK\Common\Attribute\AttributesFactoryInterface; + +final class InstrumentationScopeFactory implements InstrumentationScopeFactoryInterface +{ + private AttributesFactoryInterface $attributesFactory; + + public function __construct(AttributesFactoryInterface $attributesFactory) + { + $this->attributesFactory = $attributesFactory; + } + + public function create( + string $name, + ?string $version = null, + ?string $schemaUrl = null, + iterable $attributes = [] + ): InstrumentationScopeInterface { + return new InstrumentationScope( + $name, + $version, + $schemaUrl, + $this->attributesFactory->builder($attributes)->build(), + ); + } +} diff --git a/vendor/open-telemetry/sdk/Common/Instrumentation/InstrumentationScopeFactoryInterface.php b/vendor/open-telemetry/sdk/Common/Instrumentation/InstrumentationScopeFactoryInterface.php new file mode 100644 index 000000000..78292de58 --- /dev/null +++ b/vendor/open-telemetry/sdk/Common/Instrumentation/InstrumentationScopeFactoryInterface.php @@ -0,0 +1,15 @@ +<?php + +declare(strict_types=1); + +namespace OpenTelemetry\SDK\Common\Instrumentation; + +interface InstrumentationScopeFactoryInterface +{ + public function create( + string $name, + ?string $version = null, + ?string $schemaUrl = null, + iterable $attributes = [] + ): InstrumentationScopeInterface; +} diff --git a/vendor/open-telemetry/sdk/Common/Instrumentation/InstrumentationScopeInterface.php b/vendor/open-telemetry/sdk/Common/Instrumentation/InstrumentationScopeInterface.php new file mode 100644 index 000000000..43ba71d89 --- /dev/null +++ b/vendor/open-telemetry/sdk/Common/Instrumentation/InstrumentationScopeInterface.php @@ -0,0 +1,18 @@ +<?php + +declare(strict_types=1); + +namespace OpenTelemetry\SDK\Common\Instrumentation; + +use OpenTelemetry\SDK\Common\Attribute\AttributesInterface; + +interface InstrumentationScopeInterface +{ + public function getName(): string; + + public function getVersion(): ?string; + + public function getSchemaUrl(): ?string; + + public function getAttributes(): AttributesInterface; +} diff --git a/vendor/open-telemetry/sdk/Common/Time/ClockFactory.php b/vendor/open-telemetry/sdk/Common/Time/ClockFactory.php new file mode 100644 index 000000000..33f4364f6 --- /dev/null +++ b/vendor/open-telemetry/sdk/Common/Time/ClockFactory.php @@ -0,0 +1,30 @@ +<?php + +declare(strict_types=1); + +namespace OpenTelemetry\SDK\Common\Time; + +final class ClockFactory implements ClockFactoryInterface +{ + private static ?ClockInterface $default = null; + + public static function create(): self + { + return new self(); + } + + public function build(): ClockInterface + { + return new SystemClock(); + } + + public static function getDefault(): ClockInterface + { + return self::$default ?? self::$default = self::create()->build(); + } + + public static function setDefault(?ClockInterface $clock): void + { + self::$default = $clock; + } +} diff --git a/vendor/open-telemetry/sdk/Common/Time/ClockFactoryInterface.php b/vendor/open-telemetry/sdk/Common/Time/ClockFactoryInterface.php new file mode 100644 index 000000000..6d9afde91 --- /dev/null +++ b/vendor/open-telemetry/sdk/Common/Time/ClockFactoryInterface.php @@ -0,0 +1,16 @@ +<?php + +declare(strict_types=1); + +namespace OpenTelemetry\SDK\Common\Time; + +interface ClockFactoryInterface +{ + public static function create(): self; + + public function build(): ClockInterface; + + public static function getDefault(): ClockInterface; + + public static function setDefault(?ClockInterface $clock): void; +} diff --git a/vendor/open-telemetry/sdk/Common/Time/ClockInterface.php b/vendor/open-telemetry/sdk/Common/Time/ClockInterface.php new file mode 100644 index 000000000..8f3170185 --- /dev/null +++ b/vendor/open-telemetry/sdk/Common/Time/ClockInterface.php @@ -0,0 +1,19 @@ +<?php + +declare(strict_types=1); + +namespace OpenTelemetry\SDK\Common\Time; + +interface ClockInterface +{ + public const MILLIS_PER_SECOND = 1_000; + public const MICROS_PER_SECOND = 1_000_000; + public const NANOS_PER_SECOND = 1_000_000_000; + public const NANOS_PER_MILLISECOND = 1_000_000; + public const NANOS_PER_MICROSECOND = 1_000; + + /** + * Returns the current epoch wall-clock timestamp in nanoseconds + */ + public function now(): int; +} diff --git a/vendor/open-telemetry/sdk/Common/Time/StopWatch.php b/vendor/open-telemetry/sdk/Common/Time/StopWatch.php new file mode 100644 index 000000000..b2abdabae --- /dev/null +++ b/vendor/open-telemetry/sdk/Common/Time/StopWatch.php @@ -0,0 +1,119 @@ +<?php + +declare(strict_types=1); + +namespace OpenTelemetry\SDK\Common\Time; + +final class StopWatch implements StopWatchInterface +{ + private const INITIAL_ELAPSED_TIME = 0; + + private ClockInterface $clock; + private bool $running = false; + private ?int $initialStartTime; + private ?int $startTime = null; + private ?int $stopTime = null; + + public function __construct(ClockInterface $clock, ?int $initialStartTime = null) + { + $this->clock = $clock; + $this->initialStartTime = $initialStartTime; + } + + public function isRunning(): bool + { + return $this->running; + } + + public function start(): void + { + // resolve start time as early as possible + $startTime = $this->time(); + + if ($this->isRunning()) { + return; + } + + $this->startTime = $startTime; + if (!$this->hasBeenStarted()) { + $this->initialStartTime = $startTime; + } + $this->running = true; + } + + public function stop(): void + { + if (!$this->isRunning()) { + return; + } + + $this->stopTime = $this->time(); + $this->running = false; + } + + public function reset(): void + { + $this->startTime = $this->initialStartTime = $this->isRunning() ? $this->time() : null; + } + + public function getElapsedTime(): int + { + if (!$this->hasBeenStarted()) { + return self::INITIAL_ELAPSED_TIME; + } + + return $this->calculateElapsedTime(); + } + + public function getLastElapsedTime(): int + { + if (!$this->hasBeenStarted()) { + return self::INITIAL_ELAPSED_TIME; + } + + return $this->calculateLastElapsedTime(); + } + + private function time(): int + { + return $this->clock->now(); + } + + private function hasBeenStarted(): bool + { + return $this->initialStartTime !== null; + } + + private function calculateElapsedTime(): int + { + $referenceTime = $this->isRunning() + ? $this->time() + : $this->getStopTime(); + + return $referenceTime - $this->getInitialStartTime(); + } + + private function calculateLastElapsedTime(): int + { + $referenceTime = $this->isRunning() + ? $this->time() + : $this->getStopTime(); + + return $referenceTime - $this->getStartTime(); + } + + private function getInitialStartTime(): ?int + { + return $this->initialStartTime; + } + + private function getStartTime(): ?int + { + return $this->startTime; + } + + private function getStopTime(): ?int + { + return $this->stopTime; + } +} diff --git a/vendor/open-telemetry/sdk/Common/Time/StopWatchFactory.php b/vendor/open-telemetry/sdk/Common/Time/StopWatchFactory.php new file mode 100644 index 000000000..f60c377fc --- /dev/null +++ b/vendor/open-telemetry/sdk/Common/Time/StopWatchFactory.php @@ -0,0 +1,44 @@ +<?php + +declare(strict_types=1); + +namespace OpenTelemetry\SDK\Common\Time; + +final class StopWatchFactory implements StopWatchFactoryInterface +{ + private static ?StopWatchInterface $default = null; + + private ClockInterface $clock; + private ?int $initialStartTime; + + public function __construct(?ClockInterface $clock = null, ?int $initialStartTime = null) + { + $this->clock = $clock ?? ClockFactory::getDefault(); + $this->initialStartTime = $initialStartTime; + } + + public static function create(?ClockInterface $clock = null, ?int $initialStartTime = null): self + { + return new self($clock, $initialStartTime); + } + + public static function fromClockFactory(ClockFactoryInterface $factory, ?int $initialStartTime = null): self + { + return self::create($factory->build(), $initialStartTime); + } + + public function build(): StopWatch + { + return new StopWatch($this->clock, $this->initialStartTime); + } + + public static function getDefault(): StopWatchInterface + { + return self::$default ?? self::$default = self::create()->build(); + } + + public static function setDefault(?StopWatchInterface $default): void + { + self::$default = $default; + } +} diff --git a/vendor/open-telemetry/sdk/Common/Time/StopWatchFactoryInterface.php b/vendor/open-telemetry/sdk/Common/Time/StopWatchFactoryInterface.php new file mode 100644 index 000000000..9750f5769 --- /dev/null +++ b/vendor/open-telemetry/sdk/Common/Time/StopWatchFactoryInterface.php @@ -0,0 +1,18 @@ +<?php + +declare(strict_types=1); + +namespace OpenTelemetry\SDK\Common\Time; + +interface StopWatchFactoryInterface +{ + public static function create(?ClockInterface $clock = null, ?int $initialStartTime = null): self; + + public static function fromClockFactory(ClockFactoryInterface $factory, ?int $initialStartTime = null): self; + + public function build(): StopWatchInterface; + + public static function getDefault(): StopWatchInterface; + + public static function setDefault(?StopWatchInterface $default): void; +} diff --git a/vendor/open-telemetry/sdk/Common/Time/StopWatchInterface.php b/vendor/open-telemetry/sdk/Common/Time/StopWatchInterface.php new file mode 100644 index 000000000..69a03b75e --- /dev/null +++ b/vendor/open-telemetry/sdk/Common/Time/StopWatchInterface.php @@ -0,0 +1,20 @@ +<?php + +declare(strict_types=1); + +namespace OpenTelemetry\SDK\Common\Time; + +interface StopWatchInterface +{ + public function isRunning(): bool; + + public function start(): void; + + public function stop(): void; + + public function reset(): void; + + public function getElapsedTime(): int; + + public function getLastElapsedTime(): int; +} diff --git a/vendor/open-telemetry/sdk/Common/Time/SystemClock.php b/vendor/open-telemetry/sdk/Common/Time/SystemClock.php new file mode 100644 index 000000000..f57e98490 --- /dev/null +++ b/vendor/open-telemetry/sdk/Common/Time/SystemClock.php @@ -0,0 +1,49 @@ +<?php + +declare(strict_types=1); + +namespace OpenTelemetry\SDK\Common\Time; + +use function hrtime; +use function microtime; + +final class SystemClock implements ClockInterface +{ + private static int $referenceTime = 0; + + public function __construct() + { + self::init(); + } + + public static function create(): self + { + return new self(); + } + + /** @inheritDoc */ + public function now(): int + { + return self::$referenceTime + hrtime(true); + } + + private static function init(): void + { + if (self::$referenceTime > 0) { + return; + } + + self::$referenceTime = self::calculateReferenceTime( + microtime(true), + hrtime(true) + ); + } + + /** + * Calculates the reference time which is later used to calculate the current wall clock time in nanoseconds by adding the current uptime. + */ + private static function calculateReferenceTime(float $wallClockMicroTime, int $upTime): int + { + return ((int) ($wallClockMicroTime * ClockInterface::NANOS_PER_SECOND)) - $upTime; + } +} diff --git a/vendor/open-telemetry/sdk/Common/Time/Util.php b/vendor/open-telemetry/sdk/Common/Time/Util.php new file mode 100644 index 000000000..e1be1f750 --- /dev/null +++ b/vendor/open-telemetry/sdk/Common/Time/Util.php @@ -0,0 +1,32 @@ +<?php + +declare(strict_types=1); + +namespace OpenTelemetry\SDK\Common\Time; + +class Util +{ + /** @psalm-pure */ + public static function nanosToMicros(int $nanoseconds): int + { + return intdiv($nanoseconds, ClockInterface::NANOS_PER_MICROSECOND); + } + + /** @psalm-pure */ + public static function nanosToMillis(int $nanoseconds): int + { + return intdiv($nanoseconds, ClockInterface::NANOS_PER_MILLISECOND); + } + + /** @psalm-pure */ + public static function secondsToNanos(int $seconds): int + { + return $seconds * ClockInterface::NANOS_PER_SECOND; + } + + /** @psalm-pure */ + public static function millisToNanos(int $milliSeconds): int + { + return $milliSeconds * ClockInterface::NANOS_PER_MILLISECOND; + } +} diff --git a/vendor/open-telemetry/sdk/Common/Util/ClassConstantAccessor.php b/vendor/open-telemetry/sdk/Common/Util/ClassConstantAccessor.php new file mode 100644 index 000000000..237e70ba5 --- /dev/null +++ b/vendor/open-telemetry/sdk/Common/Util/ClassConstantAccessor.php @@ -0,0 +1,35 @@ +<?php + +declare(strict_types=1); + +namespace OpenTelemetry\SDK\Common\Util; + +use LogicException; + +class ClassConstantAccessor +{ + public static function requireValue(string $className, string $constantName) + { + $constant = self::getFullName($className, $constantName); + + if (!defined($constant)) { + throw new LogicException( + sprintf('The class "%s" does not have a constant "%s"', $className, $constantName) + ); + } + + return constant($constant); + } + + public static function getValue(string $className, string $constantName) + { + $constant = self::getFullName($className, $constantName); + + return defined($constant) ? constant($constant) : null; + } + + private static function getFullName(string $className, string $constantName): string + { + return sprintf('%s::%s', $className, $constantName); + } +} diff --git a/vendor/open-telemetry/sdk/Common/Util/ShutdownHandler.php b/vendor/open-telemetry/sdk/Common/Util/ShutdownHandler.php new file mode 100644 index 000000000..2de6d47df --- /dev/null +++ b/vendor/open-telemetry/sdk/Common/Util/ShutdownHandler.php @@ -0,0 +1,82 @@ +<?php + +declare(strict_types=1); + +namespace OpenTelemetry\SDK\Common\Util; + +use function array_key_last; +use ArrayAccess; +use Closure; +use function register_shutdown_function; + +final class ShutdownHandler +{ + /** @var array<int, Closure>|null */ + private static ?array $handlers = null; + /** @var ArrayAccess<object, self>|null */ + private static ?ArrayAccess $weakMap = null; + + private array $ids = []; + + private function __construct() + { + } + + public function __destruct() + { + if (!self::$handlers) { + return; + } + foreach ($this->ids as $id) { + unset(self::$handlers[$id]); + } + } + + /** + * Registers a function that will be executed on shutdown. + * + * If the given function is bound to an object, then the function will only + * be executed if the bound object is still referenced on shutdown handler + * invocation. + * + * ```php + * ShutdownHandler::register([$tracerProvider, 'shutdown']); + * ``` + * + * @param callable $shutdownFunction function to register + * + * @see register_shutdown_function + */ + public static function register(callable $shutdownFunction): void + { + self::registerShutdownFunction(); + self::$handlers[] = weaken(closure($shutdownFunction), $target); + + if (!$object = $target) { + return; + } + + self::$weakMap ??= WeakMap::create(); + $handler = self::$weakMap[$object] ??= new self(); + $handler->ids[] = array_key_last(self::$handlers); + } + + private static function registerShutdownFunction(): void + { + if (self::$handlers === null) { + register_shutdown_function(static function (): void { + $handlers = self::$handlers; + self::$handlers = null; + self::$weakMap = null; + + // Push shutdown to end of queue + // @phan-suppress-next-line PhanTypeMismatchArgumentInternal + register_shutdown_function(static function (array $handlers): void { + foreach ($handlers as $handler) { + $handler(); + } + }, $handlers); + }); + } + } +} diff --git a/vendor/open-telemetry/sdk/Common/Util/WeakMap.php b/vendor/open-telemetry/sdk/Common/Util/WeakMap.php new file mode 100644 index 000000000..3b62d6d64 --- /dev/null +++ b/vendor/open-telemetry/sdk/Common/Util/WeakMap.php @@ -0,0 +1,175 @@ +<?php + +declare(strict_types=1); + +namespace OpenTelemetry\SDK\Common\Util; + +use ArrayAccess; +use function assert; +use function class_exists; +use function count; +use Countable; +use Error; +use function get_class; +use function is_object; +use IteratorAggregate; +use const PHP_VERSION_ID; +use function spl_object_id; +use function sprintf; +use Traversable; +use TypeError; +use WeakReference; + +/** + * @internal + */ +final class WeakMap implements ArrayAccess, Countable, IteratorAggregate +{ + private const KEY = '__otel_weak_map'; + + /** + * @var array<int, WeakReference> + */ + private array $objects = []; + + private function __construct() + { + } + + /** + * @return ArrayAccess&Countable&IteratorAggregate + */ + public static function create(): ArrayAccess + { + if (PHP_VERSION_ID >= 80000) { + /** @phan-suppress-next-line PhanUndeclaredClassReference */ + assert(class_exists(\WeakMap::class, false)); + /** @phan-suppress-next-line PhanUndeclaredClassMethod */ + $map = new \WeakMap(); + assert($map instanceof ArrayAccess); + assert($map instanceof Countable); + assert($map instanceof IteratorAggregate); + + return $map; + } + + return new self(); + } + + public function offsetExists($offset): bool + { + if (!is_object($offset)) { + throw new TypeError('WeakMap key must be an object'); + } + + return isset($offset->{self::KEY}[spl_object_id($this)]); + } + + /** + * @phan-suppress PhanUndeclaredClassAttribute + */ + #[\ReturnTypeWillChange] + public function offsetGet($offset) + { + if (!is_object($offset)) { + throw new TypeError('WeakMap key must be an object'); + } + if (!$this->contains($offset)) { + throw new Error(sprintf('Object %s#%d not contained in WeakMap', get_class($offset), spl_object_id($offset))); + } + + return $offset->{self::KEY}[spl_object_id($this)]; + } + + public function offsetSet($offset, $value): void + { + if ($offset === null) { + throw new Error('Cannot append to WeakMap'); + } + if (!is_object($offset)) { + throw new TypeError('WeakMap key must be an object'); + } + if (!$this->contains($offset)) { + $this->expunge(); + } + + $offset->{self::KEY}[spl_object_id($this)] = $value; + $this->objects[spl_object_id($offset)] = WeakReference::create($offset); + } + + public function offsetUnset($offset): void + { + if (!is_object($offset)) { + throw new TypeError('WeakMap key must be an object'); + } + if (!$this->contains($offset)) { + return; + } + + unset( + $offset->{self::KEY}[spl_object_id($this)], + $this->objects[spl_object_id($offset)], + ); + if (!$offset->{self::KEY}) { + unset($offset->{self::KEY}); + } + } + + public function count(): int + { + $this->expunge(); + + return count($this->objects); + } + + public function getIterator(): Traversable + { + $this->expunge(); + + foreach ($this->objects as $reference) { + if (($object = $reference->get()) && $this->contains($object)) { + yield $object => $this[$object]; + } + } + } + + public function __debugInfo(): array + { + $debugInfo = []; + foreach ($this as $key => $value) { + $debugInfo[] = ['key' => $key, 'value' => $value]; + } + + return $debugInfo; + } + + public function __destruct() + { + foreach ($this->objects as $reference) { + if ($object = $reference->get()) { + unset($this[$object]); + } + } + } + + private function contains(object $offset): bool + { + $reference = $this->objects[spl_object_id($offset)] ?? null; + if ($reference && $reference->get() === $offset) { + return true; + } + + unset($this->objects[spl_object_id($offset)]); + + return false; + } + + private function expunge(): void + { + foreach ($this->objects as $id => $reference) { + if (!$reference->get()) { + unset($this->objects[$id]); + } + } + } +} diff --git a/vendor/open-telemetry/sdk/Common/Util/functions.php b/vendor/open-telemetry/sdk/Common/Util/functions.php new file mode 100644 index 000000000..f4fb13b80 --- /dev/null +++ b/vendor/open-telemetry/sdk/Common/Util/functions.php @@ -0,0 +1,52 @@ +<?php + +declare(strict_types=1); + +namespace OpenTelemetry\SDK\Common\Util; + +use Closure; +use function get_class; +use ReflectionFunction; +use stdClass; +use WeakReference; + +/** + * @internal + */ +function closure(callable $callable): Closure +{ + return Closure::fromCallable($callable); +} + +/** + * @internal + * @see https://github.com/amphp/amp/blob/f682341c856b1f688026f787bef4f77eaa5c7970/src/functions.php#L140-L191 + */ +function weaken(Closure $closure, ?object &$target = null): Closure +{ + $reflection = new ReflectionFunction($closure); + if (!$target = $reflection->getClosureThis()) { + return $closure; + } + + $scope = $reflection->getClosureScopeClass(); + $name = $reflection->getShortName(); + if ($name !== '{closure}') { + /** @psalm-suppress InvalidScope @phpstan-ignore-next-line @phan-suppress-next-line PhanUndeclaredThis */ + $closure = fn (...$args) => $this->$name(...$args); + if ($scope !== null) { + $closure = $closure->bindTo(null, $scope->name); + } + } + + static $placeholder; + $placeholder ??= new stdClass(); + $closure = $closure->bindTo($placeholder); + + $ref = WeakReference::create($target); + + /** @psalm-suppress PossiblyInvalidFunctionCall */ + return $scope && get_class($target) === $scope->name && !$scope->isInternal() + ? static fn (...$args) => ($obj = $ref->get()) ? $closure->call($obj, ...$args) : null + : static fn (...$args) => ($obj = $ref->get()) ? $closure->bindTo($obj)(...$args) : null; +} |