diff options
Diffstat (limited to 'vendor/open-telemetry/context/Propagation')
7 files changed, 375 insertions, 0 deletions
diff --git a/vendor/open-telemetry/context/Propagation/ArrayAccessGetterSetter.php b/vendor/open-telemetry/context/Propagation/ArrayAccessGetterSetter.php new file mode 100644 index 000000000..51263044d --- /dev/null +++ b/vendor/open-telemetry/context/Propagation/ArrayAccessGetterSetter.php @@ -0,0 +1,129 @@ +<?php + +declare(strict_types=1); + +namespace OpenTelemetry\Context\Propagation; + +use function array_key_first; +use ArrayAccess; +use function get_class; +use function gettype; +use InvalidArgumentException; +use function is_array; +use function is_object; +use function is_string; +use function sprintf; +use function strcasecmp; +use Traversable; + +/** + * @see https://github.com/open-telemetry/opentelemetry-specification/blob/v1.6.1/specification/context/api-propagators.md#textmap-propagator Getter and Setter. + * + * Default implementation of {@see PropagationGetterInterface} and {@see PropagationSetterInterface}. + * This type is used if no custom getter/setter is provided to {@see TextMapPropagatorInterface::inject()} or {@see TextMapPropagatorInterface::extract()}. + */ +final class ArrayAccessGetterSetter implements PropagationGetterInterface, PropagationSetterInterface +{ + private static ?self $instance = null; + + /** + * Returns a singleton instance of `self` to avoid, multiple runtime allocations. + */ + public static function getInstance(): self + { + if (null === self::$instance) { + self::$instance = new self(); + } + + return self::$instance; + } + + /** {@inheritdoc} */ + public function keys($carrier): array + { + if ($this->isSupportedCarrier($carrier)) { + $keys = []; + foreach ($carrier as $key => $_) { + $keys[] = (string) $key; + } + + return $keys; + } + + throw new InvalidArgumentException( + sprintf( + 'Unsupported carrier type: %s.', + is_object($carrier) ? get_class($carrier) : gettype($carrier), + ) + ); + } + + /** {@inheritdoc} */ + public function get($carrier, string $key): ?string + { + if ($this->isSupportedCarrier($carrier)) { + $value = $carrier[$this->resolveKey($carrier, $key)] ?? null; + if (is_array($value) && $value) { + $value = $value[array_key_first($value)]; + } + + return is_string($value) + ? $value + : null; + } + + throw new InvalidArgumentException( + sprintf( + 'Unsupported carrier type: %s. Unable to get value associated with key:%s', + is_object($carrier) ? get_class($carrier) : gettype($carrier), + $key + ) + ); + } + + /** {@inheritdoc} */ + public function set(&$carrier, string $key, string $value): void + { + if ($key === '') { + throw new InvalidArgumentException('Unable to set value with an empty key'); + } + if ($this->isSupportedCarrier($carrier)) { + if (($r = $this->resolveKey($carrier, $key)) !== $key) { + unset($carrier[$r]); + } + + $carrier[$key] = $value; + + return; + } + + throw new InvalidArgumentException( + sprintf( + 'Unsupported carrier type: %s. Unable to set value associated with key:%s', + is_object($carrier) ? get_class($carrier) : gettype($carrier), + $key + ) + ); + } + + private function isSupportedCarrier($carrier): bool + { + return is_array($carrier) || $carrier instanceof ArrayAccess && $carrier instanceof Traversable; + } + + private function resolveKey($carrier, string $key): string + { + if (isset($carrier[$key])) { + return $key; + } + + foreach ($carrier as $k => $_) { + $k = (string) $k; + if (strcasecmp($k, $key) === 0) { + return $k; + } + } + + return $key; + } +} diff --git a/vendor/open-telemetry/context/Propagation/MultiTextMapPropagator.php b/vendor/open-telemetry/context/Propagation/MultiTextMapPropagator.php new file mode 100644 index 000000000..075fe98fe --- /dev/null +++ b/vendor/open-telemetry/context/Propagation/MultiTextMapPropagator.php @@ -0,0 +1,83 @@ +<?php + +declare(strict_types=1); + +namespace OpenTelemetry\Context\Propagation; + +use function array_map; +use function array_merge; +use function array_unique; +use function array_values; +use OpenTelemetry\Context\Context; +use OpenTelemetry\Context\ContextInterface; + +final class MultiTextMapPropagator implements TextMapPropagatorInterface +{ + /** + * @readonly + * + * @var list<TextMapPropagatorInterface> + */ + private array $propagators = []; + + /** + * @readonly + * + * @var list<string> + */ + private array $fields; + + /** + * @no-named-arguments + * + * @param list<TextMapPropagatorInterface> $propagators + */ + public function __construct(array $propagators) + { + $this->propagators = $propagators; + $this->fields = $this->extractFields($propagators); + } + + public function fields(): array + { + return $this->fields; + } + + public function inject(&$carrier, PropagationSetterInterface $setter = null, ContextInterface $context = null): void + { + foreach ($this->propagators as $propagator) { + $propagator->inject($carrier, $setter, $context); + } + } + + public function extract($carrier, PropagationGetterInterface $getter = null, ContextInterface $context = null): ContextInterface + { + $context ??= Context::getCurrent(); + + foreach ($this->propagators as $propagator) { + $context = $propagator->extract($carrier, $getter, $context); + } + + return $context; + } + + /** + * @param list<TextMapPropagatorInterface> $propagators + * @return list<string> + */ + private function extractFields(array $propagators): array + { + return array_values( + array_unique( + // Phan seems to struggle here with the variadic argument + // @phan-suppress-next-line PhanParamTooFewInternalUnpack + array_merge( + ...array_map( + static fn (TextMapPropagatorInterface $propagator) => $propagator->fields(), + $propagators + ) + ) + ) + ); + } +} diff --git a/vendor/open-telemetry/context/Propagation/NoopTextMapPropagator.php b/vendor/open-telemetry/context/Propagation/NoopTextMapPropagator.php new file mode 100644 index 000000000..c408cfc79 --- /dev/null +++ b/vendor/open-telemetry/context/Propagation/NoopTextMapPropagator.php @@ -0,0 +1,36 @@ +<?php + +declare(strict_types=1); + +namespace OpenTelemetry\Context\Propagation; + +use OpenTelemetry\Context\Context; +use OpenTelemetry\Context\ContextInterface; + +final class NoopTextMapPropagator implements TextMapPropagatorInterface +{ + private static ?self $instance = null; + + public static function getInstance(): self + { + if (null === self::$instance) { + self::$instance = new self(); + } + + return self::$instance; + } + + public function fields(): array + { + return []; + } + + public function extract($carrier, PropagationGetterInterface $getter = null, ContextInterface $context = null): ContextInterface + { + return $context ?? Context::getCurrent(); + } + + public function inject(&$carrier, PropagationSetterInterface $setter = null, ContextInterface $context = null): void + { + } +} diff --git a/vendor/open-telemetry/context/Propagation/PropagationGetterInterface.php b/vendor/open-telemetry/context/Propagation/PropagationGetterInterface.php new file mode 100644 index 000000000..d2976c63d --- /dev/null +++ b/vendor/open-telemetry/context/Propagation/PropagationGetterInterface.php @@ -0,0 +1,25 @@ +<?php + +declare(strict_types=1); + +namespace OpenTelemetry\Context\Propagation; + +/** + * @see https://github.com/open-telemetry/opentelemetry-specification/blob/v1.6.1/specification/context/api-propagators.md#getter-argument + */ +interface PropagationGetterInterface +{ + /** + * Returns the list of all the keys in the carrier. + * + * @see https://github.com/open-telemetry/opentelemetry-specification/blob/v1.6.1/specification/context/api-propagators.md#keys + * + * @return list<string> + */ + public function keys($carrier): array; + + /** + * Gets the value of a given key from a carrier. + */ + public function get($carrier, string $key) : ?string; +} diff --git a/vendor/open-telemetry/context/Propagation/PropagationSetterInterface.php b/vendor/open-telemetry/context/Propagation/PropagationSetterInterface.php new file mode 100644 index 000000000..75e205628 --- /dev/null +++ b/vendor/open-telemetry/context/Propagation/PropagationSetterInterface.php @@ -0,0 +1,16 @@ +<?php + +declare(strict_types=1); + +namespace OpenTelemetry\Context\Propagation; + +/** + * @see https://github.com/open-telemetry/opentelemetry-specification/blob/v1.6.1/specification/context/api-propagators.md#setter-argument + */ +interface PropagationSetterInterface +{ + /** + * Set the value for a given key on the associated carrier. + */ + public function set(&$carrier, string $key, string $value) : void; +} diff --git a/vendor/open-telemetry/context/Propagation/SanitizeCombinedHeadersPropagationGetter.php b/vendor/open-telemetry/context/Propagation/SanitizeCombinedHeadersPropagationGetter.php new file mode 100644 index 000000000..40652982e --- /dev/null +++ b/vendor/open-telemetry/context/Propagation/SanitizeCombinedHeadersPropagationGetter.php @@ -0,0 +1,46 @@ +<?php + +declare(strict_types=1); + +namespace OpenTelemetry\Context\Propagation; + +use function preg_replace; + +/** + * Some servers concatenate multiple headers with ';' -- we need to replace these with ',' + * This is still a workaround and doesn't get around the problem fully, specifically it doesn't + * handle edge cases where the header has a trailing ';' or an empty trace state. + * We also need to trim trailing separators from the header, found when a header is empty. + */ +final class SanitizeCombinedHeadersPropagationGetter implements PropagationGetterInterface +{ + private const LIST_MEMBERS_SEPARATOR = ','; + private const SERVER_CONCAT_HEADERS_REGEX = '/;(?=[^,=;]*=|$)/'; + private const TRAILING_LEADING_SEPARATOR_REGEX = '/^' . self::LIST_MEMBERS_SEPARATOR . '+|' . self::LIST_MEMBERS_SEPARATOR . '+$/'; + + private PropagationGetterInterface $getter; + + public function __construct(PropagationGetterInterface $getter) + { + $this->getter = $getter; + } + + public function keys($carrier): array + { + return $this->getter->keys($carrier); + } + + public function get($carrier, string $key): ?string + { + $value = $this->getter->get($carrier, $key); + if ($value === null) { + return null; + } + + return preg_replace( + [self::SERVER_CONCAT_HEADERS_REGEX, self::TRAILING_LEADING_SEPARATOR_REGEX], + [self::LIST_MEMBERS_SEPARATOR], + $value, + ); + } +} diff --git a/vendor/open-telemetry/context/Propagation/TextMapPropagatorInterface.php b/vendor/open-telemetry/context/Propagation/TextMapPropagatorInterface.php new file mode 100644 index 000000000..fdf2d5141 --- /dev/null +++ b/vendor/open-telemetry/context/Propagation/TextMapPropagatorInterface.php @@ -0,0 +1,40 @@ +<?php + +declare(strict_types=1); + +namespace OpenTelemetry\Context\Propagation; + +use OpenTelemetry\Context\ContextInterface; + +/** + * @see https://github.com/open-telemetry/opentelemetry-specification/blob/v1.6.1/specification/context/api-propagators.md#textmap-propagator + */ +interface TextMapPropagatorInterface +{ + /** + * Returns list of fields that will be used by this propagator. + * + * @see https://github.com/open-telemetry/opentelemetry-specification/blob/v1.6.1/specification/context/api-propagators.md#fields + * + * @return list<string> + */ + public function fields() : array; + + /** + * Injects specific values from the provided {@see ContextInterface} into the provided carrier + * via an {@see PropagationSetterInterface}. + * + * @see https://github.com/open-telemetry/opentelemetry-specification/blob/v1.6.1/specification/context/api-propagators.md#textmap-inject + * + * @param mixed $carrier + */ + public function inject(&$carrier, PropagationSetterInterface $setter = null, ContextInterface $context = null): void; + + /** + * Extracts specific values from the provided carrier into the provided {@see ContextInterface} + * via an {@see PropagationGetterInterface}. + * + * @see https://github.com/open-telemetry/opentelemetry-specification/blob/v1.6.1/specification/context/api-propagators.md#textmap-extract + */ + public function extract($carrier, PropagationGetterInterface $getter = null, ContextInterface $context = null): ContextInterface; +} |