summaryrefslogtreecommitdiff
path: root/vendor/open-telemetry/exporter-otlp
diff options
context:
space:
mode:
authorAndrew Dolgov <[email protected]>2023-10-20 17:12:29 +0300
committerAndrew Dolgov <[email protected]>2023-10-20 21:13:39 +0300
commitcdd7ad020e165fe680703b6d3319b908b682fb7a (patch)
treeb51eb09b7b4587e8fbc5624ac8d88d28cfcd0b04 /vendor/open-telemetry/exporter-otlp
parent45a9ff0c88cbd33892ff16ab837e9059937d656e (diff)
jaeger-client -> opentelemetry
Diffstat (limited to 'vendor/open-telemetry/exporter-otlp')
-rw-r--r--vendor/open-telemetry/exporter-otlp/AttributesConverter.php62
-rw-r--r--vendor/open-telemetry/exporter-otlp/ContentTypes.php12
-rw-r--r--vendor/open-telemetry/exporter-otlp/HttpEndpointResolver.php145
-rw-r--r--vendor/open-telemetry/exporter-otlp/HttpEndpointResolverInterface.php28
-rw-r--r--vendor/open-telemetry/exporter-otlp/LogsConverter.php142
-rw-r--r--vendor/open-telemetry/exporter-otlp/LogsExporter.php85
-rw-r--r--vendor/open-telemetry/exporter-otlp/LogsExporterFactory.php85
-rw-r--r--vendor/open-telemetry/exporter-otlp/MetricConverter.php265
-rw-r--r--vendor/open-telemetry/exporter-otlp/MetricExporter.php97
-rw-r--r--vendor/open-telemetry/exporter-otlp/MetricExporterFactory.php110
-rw-r--r--vendor/open-telemetry/exporter-otlp/OtlpHttpTransportFactory.php33
-rw-r--r--vendor/open-telemetry/exporter-otlp/OtlpUtil.php45
-rw-r--r--vendor/open-telemetry/exporter-otlp/ProtobufSerializer.php115
-rw-r--r--vendor/open-telemetry/exporter-otlp/Protocols.php36
-rw-r--r--vendor/open-telemetry/exporter-otlp/README.md45
-rw-r--r--vendor/open-telemetry/exporter-otlp/SpanConverter.php187
-rw-r--r--vendor/open-telemetry/exporter-otlp/SpanExporter.php81
-rw-r--r--vendor/open-telemetry/exporter-otlp/SpanExporterFactory.php96
-rw-r--r--vendor/open-telemetry/exporter-otlp/_register.php9
-rw-r--r--vendor/open-telemetry/exporter-otlp/composer.json41
20 files changed, 1719 insertions, 0 deletions
diff --git a/vendor/open-telemetry/exporter-otlp/AttributesConverter.php b/vendor/open-telemetry/exporter-otlp/AttributesConverter.php
new file mode 100644
index 000000000..4a349ab67
--- /dev/null
+++ b/vendor/open-telemetry/exporter-otlp/AttributesConverter.php
@@ -0,0 +1,62 @@
+<?php
+
+declare(strict_types=1);
+
+namespace OpenTelemetry\Contrib\Otlp;
+
+use function is_array;
+use function is_bool;
+use function is_float;
+use function is_int;
+use function is_string;
+use Opentelemetry\Proto\Common\V1\AnyValue;
+use Opentelemetry\Proto\Common\V1\ArrayValue;
+use Opentelemetry\Proto\Common\V1\KeyValue;
+use Opentelemetry\Proto\Common\V1\KeyValueList;
+
+final class AttributesConverter
+{
+ public static function convertAnyValue($value): AnyValue
+ {
+ $result = new AnyValue();
+ if (is_array($value)) {
+ if (self::isSimpleArray($value)) {
+ $values = new ArrayValue();
+ foreach ($value as $element) {
+ /** @psalm-suppress InvalidArgument */
+ $values->getValues()[] = self::convertAnyValue($element);
+ }
+ $result->setArrayValue($values);
+ } else {
+ $values = new KeyValueList();
+ foreach ($value as $key => $element) {
+ /** @psalm-suppress InvalidArgument */
+ $values->getValues()[] = new KeyValue(['key' => $key, 'value' => self::convertAnyValue($element)]);
+ }
+ $result->setKvlistValue($values);
+ }
+ }
+ if (is_int($value)) {
+ $result->setIntValue($value);
+ }
+ if (is_bool($value)) {
+ $result->setBoolValue($value);
+ }
+ if (is_float($value)) {
+ $result->setDoubleValue($value);
+ }
+ if (is_string($value)) {
+ $result->setStringValue($value);
+ }
+
+ return $result;
+ }
+
+ /**
+ * Test whether an array is simple (non-KeyValue)
+ */
+ public static function isSimpleArray(array $value): bool
+ {
+ return $value === [] || array_key_first($value) === 0;
+ }
+}
diff --git a/vendor/open-telemetry/exporter-otlp/ContentTypes.php b/vendor/open-telemetry/exporter-otlp/ContentTypes.php
new file mode 100644
index 000000000..8ac70d54a
--- /dev/null
+++ b/vendor/open-telemetry/exporter-otlp/ContentTypes.php
@@ -0,0 +1,12 @@
+<?php
+
+declare(strict_types=1);
+
+namespace OpenTelemetry\Contrib\Otlp;
+
+interface ContentTypes
+{
+ public const PROTOBUF = 'application/x-protobuf';
+ public const JSON = 'application/json';
+ public const NDJSON = 'application/x-ndjson';
+}
diff --git a/vendor/open-telemetry/exporter-otlp/HttpEndpointResolver.php b/vendor/open-telemetry/exporter-otlp/HttpEndpointResolver.php
new file mode 100644
index 000000000..b50346427
--- /dev/null
+++ b/vendor/open-telemetry/exporter-otlp/HttpEndpointResolver.php
@@ -0,0 +1,145 @@
+<?php
+
+declare(strict_types=1);
+
+namespace OpenTelemetry\Contrib\Otlp;
+
+use InvalidArgumentException;
+use OpenTelemetry\API\Signals;
+use OpenTelemetry\SDK\Common\Adapter\HttpDiscovery\MessageFactoryResolver;
+use OpenTelemetry\SDK\Common\Http\Psr\Message\FactoryResolverInterface;
+use Psr\Http\Message\UriInterface;
+
+/**
+ * Resolves non-signal-specific OTLP HTTP endpoints to signal-specific ones according to the specification.
+ * @see https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/protocol/exporter.md#endpoint-urls-for-otlphttp
+ */
+class HttpEndpointResolver implements HttpEndpointResolverInterface
+{
+ private const SCHEME_ATTRIBUTE = 'scheme';
+ private const HOST_ATTRIBUTE = 'host';
+ private const PORT_ATTRIBUTE = 'port';
+ private const USER_ATTRIBUTE = 'user';
+ private const PASS_ATTRIBUTE = 'pass';
+ private const PATH_ATTRIBUTE = 'path';
+ private const DEFAULT_SCHEME = 'https';
+ private const ROOT_PATH = '/';
+
+ private FactoryResolverInterface $httpFactoryResolver;
+
+ public function __construct(?FactoryResolverInterface $httpFactoryResolver = null)
+ {
+ $this->httpFactoryResolver = $httpFactoryResolver ?? MessageFactoryResolver::create();
+ }
+
+ public static function create(?FactoryResolverInterface $httpFactoryResolver = null): self
+ {
+ return new self($httpFactoryResolver);
+ }
+
+ public function resolve(string $endpoint, string $signal): UriInterface
+ {
+ $components = self::parseEndpoint($endpoint);
+
+ return self::addPort(
+ self::addUserInfo(
+ $this->createDefaultUri($components, $signal),
+ $components
+ ),
+ $components
+ );
+ }
+
+ public function resolveToString(string $endpoint, string $signal): string
+ {
+ return (string) $this->resolve($endpoint, $signal);
+ }
+
+ private function createUri(): UriInterface
+ {
+ return $this->httpFactoryResolver->resolveUriFactory()
+ ->createUri();
+ }
+
+ private function createDefaultUri(array $components, string $signal): UriInterface
+ {
+ if (isset($components[self::SCHEME_ATTRIBUTE])) {
+ self::validateScheme($components[self::SCHEME_ATTRIBUTE]);
+ }
+
+ return $this->createUri()
+ ->withScheme($components[self::SCHEME_ATTRIBUTE] ?? self::DEFAULT_SCHEME)
+ ->withPath(self::resolvePath($components[self::PATH_ATTRIBUTE] ?? self::ROOT_PATH, $signal))
+ ->withHost($components[self::HOST_ATTRIBUTE]);
+ }
+
+ private static function validateScheme(string $protocol): void
+ {
+ if (!in_array($protocol, HttpEndpointResolverInterface::VALID_SCHEMES, true)) {
+ throw new InvalidArgumentException(sprintf(
+ 'Expected protocol to be http or https, given: "%s"',
+ $protocol
+ ));
+ }
+ }
+
+ private static function validateSignal(string $signal): void
+ {
+ if (!in_array($signal, Signals::SIGNALS)) {
+ throw new InvalidArgumentException(sprintf(
+ 'Signal must be one of "%s". Given "%s"',
+ implode(', ', Signals::SIGNALS),
+ $signal
+ ));
+ }
+ }
+
+ private static function parseEndpoint(string $endpoint): array
+ {
+ $result = parse_url($endpoint);
+
+ if (!is_array($result) || !isset($result[self::HOST_ATTRIBUTE])) {
+ throw new InvalidArgumentException(sprintf(
+ 'Failed to parse endpoint "%s"',
+ $endpoint
+ ));
+ }
+
+ return $result;
+ }
+
+ private static function addUserInfo(UriInterface $uri, array $components): UriInterface
+ {
+ if (isset($components[self::USER_ATTRIBUTE])) {
+ $uri = $uri->withUserInfo(
+ $components[self::USER_ATTRIBUTE],
+ $components[self::PASS_ATTRIBUTE] ?? null
+ );
+ }
+
+ return $uri;
+ }
+
+ private static function addPort(UriInterface $uri, array $components): UriInterface
+ {
+ if (isset($components[self::PORT_ATTRIBUTE])) {
+ $uri = $uri->withPort(
+ $components[self::PORT_ATTRIBUTE]
+ );
+ }
+
+ return $uri;
+ }
+
+ private static function resolvePath(string $path, string $signal): string
+ {
+ self::validateSignal($signal);
+
+ return str_replace('//', '/', sprintf('%s/%s', $path, self::getDefaultPath($signal)));
+ }
+
+ private static function getDefaultPath(string $signal): string
+ {
+ return HttpEndpointResolverInterface::DEFAULT_PATHS[$signal];
+ }
+}
diff --git a/vendor/open-telemetry/exporter-otlp/HttpEndpointResolverInterface.php b/vendor/open-telemetry/exporter-otlp/HttpEndpointResolverInterface.php
new file mode 100644
index 000000000..fe165bd8a
--- /dev/null
+++ b/vendor/open-telemetry/exporter-otlp/HttpEndpointResolverInterface.php
@@ -0,0 +1,28 @@
+<?php
+
+declare(strict_types=1);
+
+namespace OpenTelemetry\Contrib\Otlp;
+
+use OpenTelemetry\API\Signals;
+use Psr\Http\Message\UriInterface;
+
+interface HttpEndpointResolverInterface
+{
+ public const TRACE_DEFAULT_PATH = 'v1/traces';
+ public const METRICS_DEFAULT_PATH = 'v1/metrics';
+ public const LOGS_DEFAULT_PATH = 'v1/logs';
+ public const DEFAULT_PATHS = [
+ Signals::TRACE => self::TRACE_DEFAULT_PATH,
+ Signals::METRICS => self::METRICS_DEFAULT_PATH,
+ Signals::LOGS => self::LOGS_DEFAULT_PATH,
+ ];
+ public const VALID_SCHEMES = [
+ 'http',
+ 'https',
+ ];
+
+ public function resolve(string $endpoint, string $signal): UriInterface;
+
+ public function resolveToString(string $endpoint, string $signal): string;
+}
diff --git a/vendor/open-telemetry/exporter-otlp/LogsConverter.php b/vendor/open-telemetry/exporter-otlp/LogsConverter.php
new file mode 100644
index 000000000..1da53ad1f
--- /dev/null
+++ b/vendor/open-telemetry/exporter-otlp/LogsConverter.php
@@ -0,0 +1,142 @@
+<?php
+
+declare(strict_types=1);
+
+namespace OpenTelemetry\Contrib\Otlp;
+
+use Opentelemetry\Proto\Collector\Logs\V1\ExportLogsServiceRequest;
+use Opentelemetry\Proto\Common\V1\InstrumentationScope;
+use Opentelemetry\Proto\Common\V1\KeyValue;
+use Opentelemetry\Proto\Logs\V1\LogRecord;
+use Opentelemetry\Proto\Logs\V1\ResourceLogs;
+use Opentelemetry\Proto\Logs\V1\ScopeLogs;
+use Opentelemetry\Proto\Resource\V1\Resource as Resource_;
+use OpenTelemetry\SDK\Common\Attribute\AttributesInterface;
+use OpenTelemetry\SDK\Common\Instrumentation\InstrumentationScopeInterface;
+use OpenTelemetry\SDK\Logs\ReadableLogRecord;
+use OpenTelemetry\SDK\Resource\ResourceInfo;
+
+class LogsConverter
+{
+ private ProtobufSerializer $serializer;
+
+ public function __construct(?ProtobufSerializer $serializer = null)
+ {
+ $this->serializer = $serializer ?? ProtobufSerializer::getDefault();
+ }
+
+ /**
+ * @param iterable<ReadableLogRecord> $logs
+ * @psalm-suppress InvalidArgument
+ */
+ public function convert(iterable $logs): ExportLogsServiceRequest
+ {
+ $pExportLogsServiceRequest = new ExportLogsServiceRequest();
+ $scopeLogs = [];
+ $resourceLogs = [];
+ $resourceCache = [];
+ $scopeCache = [];
+
+ foreach ($logs as $log) {
+ $resource = $log->getResource();
+ $instrumentationScope = $log->getInstrumentationScope();
+
+ $resourceId = $resourceCache[spl_object_id($resource)] ??= serialize([
+ $resource->getSchemaUrl(),
+ $resource->getAttributes()->toArray(),
+ $resource->getAttributes()->getDroppedAttributesCount(),
+ ]);
+ $instrumentationScopeId = $scopeCache[spl_object_id($instrumentationScope)] ??= serialize([
+ $instrumentationScope->getName(),
+ $instrumentationScope->getVersion(),
+ $instrumentationScope->getSchemaUrl(),
+ $instrumentationScope->getAttributes()->toArray(),
+ $instrumentationScope->getAttributes()->getDroppedAttributesCount(),
+ ]);
+
+ if (($pResourceLogs = $resourceLogs[$resourceId] ?? null) === null) {
+ /** @psalm-suppress InvalidArgument */
+ $pExportLogsServiceRequest->getResourceLogs()[]
+ = $resourceLogs[$resourceId]
+ = $pResourceLogs
+ = $this->convertResourceLogs($resource);
+ }
+
+ if (($pScopeLogs = $scopeLogs[$resourceId][$instrumentationScopeId] ?? null) === null) {
+ $pResourceLogs->getScopeLogs()[]
+ = $scopeLogs[$resourceId][$instrumentationScopeId]
+ = $pScopeLogs
+ = $this->convertInstrumentationScope($instrumentationScope);
+ }
+
+ $pScopeLogs->getLogRecords()[] = $this->convertLogRecord($log);
+ }
+
+ return $pExportLogsServiceRequest;
+ }
+
+ private function convertLogRecord(ReadableLogRecord $record): LogRecord
+ {
+ $pLogRecord = new LogRecord();
+ $pLogRecord->setBody(AttributesConverter::convertAnyValue($record->getBody()));
+ $pLogRecord->setTimeUnixNano($record->getTimestamp() ?? 0);
+ $pLogRecord->setObservedTimeUnixNano($record->getObservedTimestamp() ?? 0);
+ $spanContext = $record->getSpanContext();
+ if ($spanContext !== null && $spanContext->isValid()) {
+ $pLogRecord->setTraceId($this->serializer->serializeTraceId($spanContext->getTraceIdBinary()));
+ $pLogRecord->setSpanId($this->serializer->serializeSpanId($spanContext->getSpanIdBinary()));
+ $pLogRecord->setFlags($spanContext->getTraceFlags());
+ }
+ $severityNumber = $record->getSeverityNumber();
+ if ($severityNumber !== null) {
+ $pLogRecord->setSeverityNumber($severityNumber);
+ }
+ $severityText = $record->getSeverityText();
+ if ($severityText !== null) {
+ $pLogRecord->setSeverityText($severityText);
+ }
+ $this->setAttributes($pLogRecord, $record->getAttributes());
+ $pLogRecord->setDroppedAttributesCount($record->getAttributes()->getDroppedAttributesCount());
+
+ return $pLogRecord;
+ }
+
+ private function convertInstrumentationScope(InstrumentationScopeInterface $instrumentationScope): ScopeLogs
+ {
+ $pScopeLogs = new ScopeLogs();
+ $pInstrumentationScope = new InstrumentationScope();
+ $pInstrumentationScope->setName($instrumentationScope->getName());
+ $pInstrumentationScope->setVersion((string) $instrumentationScope->getVersion());
+ $this->setAttributes($pInstrumentationScope, $instrumentationScope->getAttributes());
+ $pInstrumentationScope->setDroppedAttributesCount($instrumentationScope->getAttributes()->getDroppedAttributesCount());
+ $pScopeLogs->setScope($pInstrumentationScope);
+ $pScopeLogs->setSchemaUrl((string) $instrumentationScope->getSchemaUrl());
+
+ return $pScopeLogs;
+ }
+
+ private function convertResourceLogs(ResourceInfo $resource): ResourceLogs
+ {
+ $pResourceLogs = new ResourceLogs();
+ $pResource = new Resource_();
+ $this->setAttributes($pResource, $resource->getAttributes());
+ $pResource->setDroppedAttributesCount($resource->getAttributes()->getDroppedAttributesCount());
+ $pResourceLogs->setResource($pResource);
+
+ return $pResourceLogs;
+ }
+
+ /**
+ * @param Resource_|LogRecord|InstrumentationScope $pElement
+ */
+ private function setAttributes($pElement, AttributesInterface $attributes): void
+ {
+ foreach ($attributes as $key => $value) {
+ /** @psalm-suppress InvalidArgument */
+ $pElement->getAttributes()[] = (new KeyValue())
+ ->setKey($key)
+ ->setValue(AttributesConverter::convertAnyValue($value));
+ }
+ $pElement->setDroppedAttributesCount($attributes->getDroppedAttributesCount());
+ }
+}
diff --git a/vendor/open-telemetry/exporter-otlp/LogsExporter.php b/vendor/open-telemetry/exporter-otlp/LogsExporter.php
new file mode 100644
index 000000000..fb100391f
--- /dev/null
+++ b/vendor/open-telemetry/exporter-otlp/LogsExporter.php
@@ -0,0 +1,85 @@
+<?php
+
+declare(strict_types=1);
+
+namespace OpenTelemetry\Contrib\Otlp;
+
+use OpenTelemetry\API\Behavior\LogsMessagesTrait;
+use Opentelemetry\Proto\Collector\Logs\V1\ExportLogsServiceResponse;
+use OpenTelemetry\SDK\Common\Export\TransportInterface;
+use OpenTelemetry\SDK\Common\Future\CancellationInterface;
+use OpenTelemetry\SDK\Common\Future\FutureInterface;
+use OpenTelemetry\SDK\Logs\LogRecordExporterInterface;
+use OpenTelemetry\SDK\Logs\ReadableLogRecord;
+use RuntimeException;
+use Throwable;
+
+/**
+ * @psalm-import-type SUPPORTED_CONTENT_TYPES from ProtobufSerializer
+ */
+class LogsExporter implements LogRecordExporterInterface
+{
+ use LogsMessagesTrait;
+
+ private TransportInterface $transport;
+ private ProtobufSerializer $serializer;
+
+ /**
+ * @psalm-param TransportInterface<SUPPORTED_CONTENT_TYPES> $transport
+ */
+ public function __construct(TransportInterface $transport)
+ {
+ if (!class_exists('\Google\Protobuf\Api')) {
+ throw new RuntimeException('No protobuf implementation found (ext-protobuf or google/protobuf)');
+ }
+ $this->transport = $transport;
+ $this->serializer = ProtobufSerializer::forTransport($transport);
+ }
+
+ /**
+ * @param iterable<ReadableLogRecord> $batch
+ */
+ public function export(iterable $batch, ?CancellationInterface $cancellation = null): FutureInterface
+ {
+ return $this->transport
+ ->send($this->serializer->serialize((new LogsConverter($this->serializer))->convert($batch)), $cancellation)
+ ->map(function (?string $payload): bool {
+ if ($payload === null) {
+ return true;
+ }
+
+ $serviceResponse = new ExportLogsServiceResponse();
+ $this->serializer->hydrate($serviceResponse, $payload);
+
+ $partialSuccess = $serviceResponse->getPartialSuccess();
+ if ($partialSuccess !== null && $partialSuccess->getRejectedLogRecords()) {
+ self::logError('Export partial success', [
+ 'rejected_logs' => $partialSuccess->getRejectedLogRecords(),
+ 'error_message' => $partialSuccess->getErrorMessage(),
+ ]);
+
+ return false;
+ }
+ if ($partialSuccess !== null && $partialSuccess->getErrorMessage()) {
+ self::logWarning('Export success with warnings/suggestions', ['error_message' => $partialSuccess->getErrorMessage()]);
+ }
+
+ return true;
+ })
+ ->catch(static function (Throwable $throwable): bool {
+ self::logError('Export failure', ['exception' => $throwable]);
+
+ return false;
+ });
+ }
+
+ public function forceFlush(?CancellationInterface $cancellation = null): bool
+ {
+ return $this->transport->forceFlush($cancellation);
+ }
+
+ public function shutdown(?CancellationInterface $cancellation = null): bool
+ {
+ return $this->transport->shutdown($cancellation);
+ }
+}
diff --git a/vendor/open-telemetry/exporter-otlp/LogsExporterFactory.php b/vendor/open-telemetry/exporter-otlp/LogsExporterFactory.php
new file mode 100644
index 000000000..17fd68887
--- /dev/null
+++ b/vendor/open-telemetry/exporter-otlp/LogsExporterFactory.php
@@ -0,0 +1,85 @@
+<?php
+
+declare(strict_types=1);
+
+namespace OpenTelemetry\Contrib\Otlp;
+
+use OpenTelemetry\API\Signals;
+use OpenTelemetry\SDK\Common\Configuration\Configuration;
+use OpenTelemetry\SDK\Common\Configuration\Defaults;
+use OpenTelemetry\SDK\Common\Configuration\Variables;
+use OpenTelemetry\SDK\Common\Export\TransportFactoryInterface;
+use OpenTelemetry\SDK\Common\Export\TransportInterface;
+use OpenTelemetry\SDK\Logs\LogRecordExporterFactoryInterface;
+use OpenTelemetry\SDK\Logs\LogRecordExporterInterface;
+use OpenTelemetry\SDK\Registry;
+
+class LogsExporterFactory implements LogRecordExporterFactoryInterface
+{
+ private const DEFAULT_COMPRESSION = 'none';
+
+ private ?TransportFactoryInterface $transportFactory;
+
+ public function __construct(?TransportFactoryInterface $transportFactory = null)
+ {
+ $this->transportFactory = $transportFactory;
+ }
+
+ /**
+ * @psalm-suppress ArgumentTypeCoercion
+ */
+ public function create(): LogRecordExporterInterface
+ {
+ $protocol = Configuration::has(Variables::OTEL_EXPORTER_OTLP_LOGS_PROTOCOL)
+ ? Configuration::getEnum(Variables::OTEL_EXPORTER_OTLP_LOGS_PROTOCOL)
+ : Configuration::getEnum(Variables::OTEL_EXPORTER_OTLP_PROTOCOL);
+
+ return new LogsExporter($this->buildTransport($protocol));
+ }
+
+ /**
+ * @psalm-suppress UndefinedClass
+ */
+ private function buildTransport(string $protocol): TransportInterface
+ {
+ $endpoint = $this->getEndpoint($protocol);
+
+ $headers = Configuration::has(Variables::OTEL_EXPORTER_OTLP_LOGS_HEADERS)
+ ? Configuration::getMap(Variables::OTEL_EXPORTER_OTLP_LOGS_HEADERS)
+ : Configuration::getMap(Variables::OTEL_EXPORTER_OTLP_HEADERS);
+ $headers += OtlpUtil::getUserAgentHeader();
+ $compression = $this->getCompression();
+
+ $factoryClass = Registry::transportFactory($protocol);
+ $factory = $this->transportFactory ?: new $factoryClass();
+
+ return $factory->create(
+ $endpoint,
+ Protocols::contentType($protocol),
+ $headers,
+ $compression,
+ );
+ }
+
+ private function getCompression(): string
+ {
+ return Configuration::has(Variables::OTEL_EXPORTER_OTLP_LOGS_COMPRESSION) ?
+ Configuration::getEnum(Variables::OTEL_EXPORTER_OTLP_LOGS_COMPRESSION) :
+ Configuration::getEnum(Variables::OTEL_EXPORTER_OTLP_COMPRESSION, self::DEFAULT_COMPRESSION);
+ }
+
+ private function getEndpoint(string $protocol): string
+ {
+ if (Configuration::has(Variables::OTEL_EXPORTER_OTLP_LOGS_ENDPOINT)) {
+ return Configuration::getString(Variables::OTEL_EXPORTER_OTLP_LOGS_ENDPOINT);
+ }
+ $endpoint = Configuration::has(Variables::OTEL_EXPORTER_OTLP_ENDPOINT)
+ ? Configuration::getString(Variables::OTEL_EXPORTER_OTLP_ENDPOINT)
+ : Defaults::OTEL_EXPORTER_OTLP_ENDPOINT;
+ if ($protocol === Protocols::GRPC) {
+ return $endpoint . OtlpUtil::method(Signals::LOGS);
+ }
+
+ return HttpEndpointResolver::create()->resolveToString($endpoint, Signals::LOGS);
+ }
+}
diff --git a/vendor/open-telemetry/exporter-otlp/MetricConverter.php b/vendor/open-telemetry/exporter-otlp/MetricConverter.php
new file mode 100644
index 000000000..584c41365
--- /dev/null
+++ b/vendor/open-telemetry/exporter-otlp/MetricConverter.php
@@ -0,0 +1,265 @@
+<?php
+
+declare(strict_types=1);
+
+namespace OpenTelemetry\Contrib\Otlp;
+
+use function hex2bin;
+use function is_float;
+use function is_int;
+use function method_exists;
+use Opentelemetry\Proto\Collector\Metrics\V1\ExportMetricsServiceRequest;
+use Opentelemetry\Proto\Common\V1\InstrumentationScope;
+use Opentelemetry\Proto\Common\V1\KeyValue;
+use Opentelemetry\Proto\Metrics\V1\AggregationTemporality;
+use Opentelemetry\Proto\Metrics\V1\Exemplar;
+use Opentelemetry\Proto\Metrics\V1\Gauge;
+use Opentelemetry\Proto\Metrics\V1\Histogram;
+use Opentelemetry\Proto\Metrics\V1\HistogramDataPoint;
+use Opentelemetry\Proto\Metrics\V1\Metric;
+use Opentelemetry\Proto\Metrics\V1\NumberDataPoint;
+use Opentelemetry\Proto\Metrics\V1\ResourceMetrics;
+use Opentelemetry\Proto\Metrics\V1\ScopeMetrics;
+use Opentelemetry\Proto\Metrics\V1\Sum;
+use Opentelemetry\Proto\Resource\V1\Resource as Resource_;
+use OpenTelemetry\SDK;
+use function serialize;
+
+final class MetricConverter
+{
+ private ProtobufSerializer $serializer;
+
+ public function __construct(?ProtobufSerializer $serializer = null)
+ {
+ $this->serializer = $serializer ?? ProtobufSerializer::getDefault();
+ }
+
+ /**
+ * @param iterable<SDK\Metrics\Data\Metric> $batch
+ */
+ public function convert(iterable $batch): ExportMetricsServiceRequest
+ {
+ $pExportMetricsServiceRequest = new ExportMetricsServiceRequest();
+
+ $resourceMetrics = [];
+ $resourceCache = [];
+ $scopeMetrics = [];
+ $scopeCache = [];
+ foreach ($batch as $metric) {
+ $resource = $metric->resource;
+ $instrumentationScope = $metric->instrumentationScope;
+
+ $resourceId = $resourceCache[spl_object_id($resource)] ??= serialize([
+ $resource->getSchemaUrl(),
+ $resource->getAttributes()->toArray(),
+ $resource->getAttributes()->getDroppedAttributesCount(),
+ ]);
+ $instrumentationScopeId = $scopeCache[spl_object_id($instrumentationScope)] ??= serialize([
+ $instrumentationScope->getName(),
+ $instrumentationScope->getVersion(),
+ $instrumentationScope->getSchemaUrl(),
+ $instrumentationScope->getAttributes()->toArray(),
+ $instrumentationScope->getAttributes()->getDroppedAttributesCount(),
+ ]);
+
+ if (($pResourceMetrics = $resourceMetrics[$resourceId] ?? null) === null) {
+ /** @psalm-suppress InvalidArgument */
+ $pExportMetricsServiceRequest->getResourceMetrics()[]
+ = $resourceMetrics[$resourceId]
+ = $pResourceMetrics
+ = $this->convertResourceMetrics($resource);
+ }
+
+ if (($pScopeMetrics = $scopeMetrics[$resourceId][$instrumentationScopeId] ?? null) === null) {
+ /** @psalm-suppress InvalidArgument */
+ $pResourceMetrics->getScopeMetrics()[]
+ = $scopeMetrics[$resourceId][$instrumentationScopeId]
+ = $pScopeMetrics
+ = $this->convertScopeMetrics($instrumentationScope);
+ }
+
+ /** @psalm-suppress InvalidArgument */
+ $pScopeMetrics->getMetrics()[] = $this->convertMetric($metric);
+ }
+
+ return $pExportMetricsServiceRequest;
+ }
+
+ private function convertResourceMetrics(SDK\Resource\ResourceInfo $resource): ResourceMetrics
+ {
+ $pResourceMetrics = new ResourceMetrics();
+ $pResource = new Resource_();
+ $this->setAttributes($pResource, $resource->getAttributes());
+ $pResourceMetrics->setResource($pResource);
+ $pResourceMetrics->setSchemaUrl((string) $resource->getSchemaUrl());
+
+ return $pResourceMetrics;
+ }
+
+ private function convertScopeMetrics(SDK\Common\Instrumentation\InstrumentationScopeInterface $instrumentationScope): ScopeMetrics
+ {
+ $pScopeMetrics = new ScopeMetrics();
+ $pInstrumentationScope = new InstrumentationScope();
+ $pInstrumentationScope->setName($instrumentationScope->getName());
+ $pInstrumentationScope->setVersion((string) $instrumentationScope->getVersion());
+ $this->setAttributes($pInstrumentationScope, $instrumentationScope->getAttributes());
+ $pScopeMetrics->setScope($pInstrumentationScope);
+ $pScopeMetrics->setSchemaUrl((string) $instrumentationScope->getSchemaUrl());
+
+ return $pScopeMetrics;
+ }
+
+ private function convertMetric(SDK\Metrics\Data\Metric $metric): Metric
+ {
+ $pMetric = new Metric();
+ $pMetric->setName($metric->name);
+ $pMetric->setDescription((string) $metric->description);
+ $pMetric->setUnit((string) $metric->unit);
+
+ $data = $metric->data;
+ if ($data instanceof SDK\Metrics\Data\Gauge) {
+ $pMetric->setGauge($this->convertGauge($data));
+ }
+ if ($data instanceof SDK\Metrics\Data\Histogram) {
+ $pMetric->setHistogram($this->convertHistogram($data));
+ }
+ if ($data instanceof SDK\Metrics\Data\Sum) {
+ $pMetric->setSum($this->convertSum($data));
+ }
+
+ return $pMetric;
+ }
+
+ private function convertTemporality($temporality): int
+ {
+ switch ($temporality) {
+ case SDK\Metrics\Data\Temporality::DELTA:
+ return AggregationTemporality::AGGREGATION_TEMPORALITY_DELTA;
+ case SDK\Metrics\Data\Temporality::CUMULATIVE:
+ return AggregationTemporality::AGGREGATION_TEMPORALITY_CUMULATIVE;
+ }
+
+ // @codeCoverageIgnoreStart
+ return AggregationTemporality::AGGREGATION_TEMPORALITY_UNSPECIFIED;
+ // @codeCoverageIgnoreEnd
+ }
+
+ private function convertGauge(SDK\Metrics\Data\Gauge $gauge): Gauge
+ {
+ $pGauge = new Gauge();
+ foreach ($gauge->dataPoints as $dataPoint) {
+ /** @psalm-suppress InvalidArgument */
+ $pGauge->getDataPoints()[] = $this->convertNumberDataPoint($dataPoint);
+ }
+
+ return $pGauge;
+ }
+
+ private function convertHistogram(SDK\Metrics\Data\Histogram $histogram): Histogram
+ {
+ $pHistogram = new Histogram();
+ foreach ($histogram->dataPoints as $dataPoint) {
+ /** @psalm-suppress InvalidArgument */
+ $pHistogram->getDataPoints()[] = $this->convertHistogramDataPoint($dataPoint);
+ }
+ $pHistogram->setAggregationTemporality($this->convertTemporality($histogram->temporality));
+
+ return $pHistogram;
+ }
+
+ private function convertSum(SDK\Metrics\Data\Sum $sum): Sum
+ {
+ $pSum = new Sum();
+ foreach ($sum->dataPoints as $dataPoint) {
+ /** @psalm-suppress InvalidArgument */
+ $pSum->getDataPoints()[] = $this->convertNumberDataPoint($dataPoint);
+ }
+ $pSum->setAggregationTemporality($this->convertTemporality($sum->temporality));
+ $pSum->setIsMonotonic($sum->monotonic);
+
+ return $pSum;
+ }
+
+ private function convertNumberDataPoint(SDK\Metrics\Data\NumberDataPoint $dataPoint): NumberDataPoint
+ {
+ $pNumberDataPoint = new NumberDataPoint();
+ $this->setAttributes($pNumberDataPoint, $dataPoint->attributes);
+ $pNumberDataPoint->setStartTimeUnixNano($dataPoint->startTimestamp);
+ $pNumberDataPoint->setTimeUnixNano($dataPoint->timestamp);
+ if (is_int($dataPoint->value)) {
+ $pNumberDataPoint->setAsInt($dataPoint->value);
+ }
+ if (is_float($dataPoint->value)) {
+ $pNumberDataPoint->setAsDouble($dataPoint->value);
+ }
+ foreach ($dataPoint->exemplars as $exemplar) {
+ /** @psalm-suppress InvalidArgument */
+ $pNumberDataPoint->getExemplars()[] = $this->convertExemplar($exemplar);
+ }
+
+ return $pNumberDataPoint;
+ }
+
+ private function convertHistogramDataPoint(SDK\Metrics\Data\HistogramDataPoint $dataPoint): HistogramDataPoint
+ {
+ $pHistogramDataPoint = new HistogramDataPoint();
+ $this->setAttributes($pHistogramDataPoint, $dataPoint->attributes);
+ $pHistogramDataPoint->setStartTimeUnixNano($dataPoint->startTimestamp);
+ $pHistogramDataPoint->setTimeUnixNano($dataPoint->timestamp);
+ $pHistogramDataPoint->setCount($dataPoint->count);
+ $pHistogramDataPoint->setSum($dataPoint->sum);
+ /** @phpstan-ignore-next-line */
+ $pHistogramDataPoint->setBucketCounts($dataPoint->bucketCounts);
+ /** @phpstan-ignore-next-line */
+ $pHistogramDataPoint->setExplicitBounds($dataPoint->explicitBounds);
+ foreach ($dataPoint->exemplars as $exemplar) {
+ /** @psalm-suppress InvalidArgument */
+ $pHistogramDataPoint->getExemplars()[] = $this->convertExemplar($exemplar);
+ }
+
+ return $pHistogramDataPoint;
+ }
+
+ private function convertExemplar(SDK\Metrics\Data\Exemplar $exemplar): Exemplar
+ {
+ $pExemplar = new Exemplar();
+ $this->setFilteredAttributes($pExemplar, $exemplar->attributes);
+ $pExemplar->setTimeUnixNano($exemplar->timestamp);
+ $pExemplar->setSpanId($this->serializer->serializeSpanId(hex2bin((string) $exemplar->spanId)));
+ $pExemplar->setTraceId($this->serializer->serializeTraceId(hex2bin((string) $exemplar->traceId)));
+ if (is_int($exemplar->value)) {
+ $pExemplar->setAsInt($exemplar->value);
+ }
+ if (is_float($exemplar->value)) {
+ $pExemplar->setAsDouble($exemplar->value);
+ }
+
+ return $pExemplar;
+ }
+
+ /**
+ * @param Resource_|NumberDataPoint|HistogramDataPoint|InstrumentationScope $pElement
+ */
+ private function setAttributes($pElement, SDK\Common\Attribute\AttributesInterface $attributes): void
+ {
+ foreach ($attributes as $key => $value) {
+ /** @psalm-suppress InvalidArgument */
+ $pElement->getAttributes()[] = $pAttribute = new KeyValue();
+ $pAttribute->setKey($key);
+ $pAttribute->setValue(AttributesConverter::convertAnyValue($value));
+ }
+ if (method_exists($pElement, 'setDroppedAttributesCount')) {
+ $pElement->setDroppedAttributesCount($attributes->getDroppedAttributesCount());
+ }
+ }
+
+ private function setFilteredAttributes(Exemplar $pElement, SDK\Common\Attribute\AttributesInterface $attributes): void
+ {
+ foreach ($attributes as $key => $value) {
+ /** @psalm-suppress InvalidArgument */
+ $pElement->getFilteredAttributes()[] = $pAttribute = new KeyValue();
+ $pAttribute->setKey($key);
+ $pAttribute->setValue(AttributesConverter::convertAnyValue($value));
+ }
+ }
+}
diff --git a/vendor/open-telemetry/exporter-otlp/MetricExporter.php b/vendor/open-telemetry/exporter-otlp/MetricExporter.php
new file mode 100644
index 000000000..efd149c7f
--- /dev/null
+++ b/vendor/open-telemetry/exporter-otlp/MetricExporter.php
@@ -0,0 +1,97 @@
+<?php
+
+declare(strict_types=1);
+
+namespace OpenTelemetry\Contrib\Otlp;
+
+use OpenTelemetry\API\Behavior\LogsMessagesTrait;
+use Opentelemetry\Proto\Collector\Metrics\V1\ExportMetricsServiceResponse;
+use OpenTelemetry\SDK\Common\Export\TransportInterface;
+use OpenTelemetry\SDK\Metrics\AggregationTemporalitySelectorInterface;
+use OpenTelemetry\SDK\Metrics\Data\Temporality;
+use OpenTelemetry\SDK\Metrics\MetricMetadataInterface;
+use OpenTelemetry\SDK\Metrics\PushMetricExporterInterface;
+use RuntimeException;
+use Throwable;
+
+/**
+ * @see https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/metrics/sdk_exporters/stdout.md#opentelemetry-metrics-exporter---standard-output
+ * @see https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/protocol/file-exporter.md#json-file-serialization
+ * @psalm-import-type SUPPORTED_CONTENT_TYPES from ProtobufSerializer
+ */
+final class MetricExporter implements PushMetricExporterInterface, AggregationTemporalitySelectorInterface
+{
+ use LogsMessagesTrait;
+
+ private TransportInterface $transport;
+ private ProtobufSerializer $serializer;
+ /**
+ * @var string|Temporality|null
+ */
+ private $temporality;
+
+ /**
+ * @param string|Temporality|null $temporality
+ *
+ * @psalm-param TransportInterface<SUPPORTED_CONTENT_TYPES> $transport
+ */
+ public function __construct(TransportInterface $transport, $temporality = null)
+ {
+ if (!class_exists('\Google\Protobuf\Api')) {
+ throw new RuntimeException('No protobuf implementation found (ext-protobuf or google/protobuf)');
+ }
+ $this->transport = $transport;
+ $this->serializer = ProtobufSerializer::forTransport($transport);
+ $this->temporality = $temporality;
+ }
+
+ public function temporality(MetricMetadataInterface $metric)
+ {
+ return $this->temporality ?? $metric->temporality();
+ }
+
+ public function export(iterable $batch): bool
+ {
+ return $this->transport
+ ->send($this->serializer->serialize((new MetricConverter($this->serializer))->convert($batch)))
+ ->map(function (?string $payload): bool {
+ if ($payload === null) {
+ return true;
+ }
+
+ $serviceResponse = new ExportMetricsServiceResponse();
+ $this->serializer->hydrate($serviceResponse, $payload);
+
+ $partialSuccess = $serviceResponse->getPartialSuccess();
+ if ($partialSuccess !== null && $partialSuccess->getRejectedDataPoints()) {
+ self::logError('Export partial success', [
+ 'rejected_data_points' => $partialSuccess->getRejectedDataPoints(),
+ 'error_message' => $partialSuccess->getErrorMessage(),
+ ]);
+
+ return false;
+ }
+ if ($partialSuccess !== null && $partialSuccess->getErrorMessage()) {
+ self::logWarning('Export success with warnings/suggestions', ['error_message' => $partialSuccess->getErrorMessage()]);
+ }
+
+ return true;
+ })
+ ->catch(static function (Throwable $throwable): bool {
+ self::logError('Export failure', ['exception' => $throwable]);
+
+ return false;
+ })
+ ->await();
+ }
+
+ public function shutdown(): bool
+ {
+ return $this->transport->shutdown();
+ }
+
+ public function forceFlush(): bool
+ {
+ return $this->transport->forceFlush();
+ }
+}
diff --git a/vendor/open-telemetry/exporter-otlp/MetricExporterFactory.php b/vendor/open-telemetry/exporter-otlp/MetricExporterFactory.php
new file mode 100644
index 000000000..284428b73
--- /dev/null
+++ b/vendor/open-telemetry/exporter-otlp/MetricExporterFactory.php
@@ -0,0 +1,110 @@
+<?php
+
+declare(strict_types=1);
+
+namespace OpenTelemetry\Contrib\Otlp;
+
+use OpenTelemetry\API\Signals;
+use OpenTelemetry\SDK\Common\Configuration\Configuration;
+use OpenTelemetry\SDK\Common\Configuration\Defaults;
+use OpenTelemetry\SDK\Common\Configuration\Variables;
+use OpenTelemetry\SDK\Common\Export\TransportFactoryInterface;
+use OpenTelemetry\SDK\Common\Export\TransportInterface;
+use OpenTelemetry\SDK\Metrics\Data\Temporality;
+use OpenTelemetry\SDK\Metrics\MetricExporterFactoryInterface;
+use OpenTelemetry\SDK\Metrics\MetricExporterInterface;
+use OpenTelemetry\SDK\Registry;
+
+class MetricExporterFactory implements MetricExporterFactoryInterface
+{
+ private const DEFAULT_COMPRESSION = 'none';
+
+ private ?TransportFactoryInterface $transportFactory;
+
+ public function __construct(?TransportFactoryInterface $transportFactory = null)
+ {
+ $this->transportFactory = $transportFactory;
+ }
+
+ /**
+ * @psalm-suppress ArgumentTypeCoercion
+ */
+ public function create(): MetricExporterInterface
+ {
+ $protocol = Configuration::has(Variables::OTEL_EXPORTER_OTLP_METRICS_PROTOCOL)
+ ? Configuration::getEnum(Variables::OTEL_EXPORTER_OTLP_METRICS_PROTOCOL)
+ : Configuration::getEnum(Variables::OTEL_EXPORTER_OTLP_PROTOCOL);
+ $temporality = $this->getTemporality();
+
+ return new MetricExporter($this->buildTransport($protocol), $temporality);
+ }
+
+ /**
+ * @psalm-suppress UndefinedClass
+ */
+ private function buildTransport(string $protocol): TransportInterface
+ {
+ /**
+ * @todo (https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/metrics/sdk.md#periodic-exporting-metricreader)
+ * - OTEL_METRIC_EXPORT_INTERVAL
+ * - OTEL_METRIC_EXPORT_TIMEOUT
+ */
+ $endpoint = $this->getEndpoint($protocol);
+
+ $headers = Configuration::has(Variables::OTEL_EXPORTER_OTLP_METRICS_HEADERS)
+ ? Configuration::getMap(Variables::OTEL_EXPORTER_OTLP_METRICS_HEADERS)
+ : Configuration::getMap(Variables::OTEL_EXPORTER_OTLP_HEADERS);
+ $headers += OtlpUtil::getUserAgentHeader();
+ $compression = $this->getCompression();
+
+ $factoryClass = Registry::transportFactory($protocol);
+ $factory = $this->transportFactory ?: new $factoryClass();
+
+ return $factory->create(
+ $endpoint,
+ Protocols::contentType($protocol),
+ $headers,
+ $compression,
+ );
+ }
+
+ /**
+ * @todo return string|Temporality|null (php >= 8.0)
+ */
+ private function getTemporality()
+ {
+ $value = Configuration::getEnum(Variables::OTEL_EXPORTER_OTLP_METRICS_TEMPORALITY_PREFERENCE);
+ switch (strtolower($value)) {
+ case 'cumulative':
+ return Temporality::CUMULATIVE;
+ case 'delta':
+ return Temporality::DELTA;
+ case 'lowmemory':
+ return null;
+ default:
+ throw new \UnexpectedValueException('Unknown temporality: ' . $value);
+ }
+ }
+
+ private function getCompression(): string
+ {
+ return Configuration::has(Variables::OTEL_EXPORTER_OTLP_METRICS_COMPRESSION) ?
+ Configuration::getEnum(Variables::OTEL_EXPORTER_OTLP_METRICS_COMPRESSION) :
+ Configuration::getEnum(Variables::OTEL_EXPORTER_OTLP_COMPRESSION, self::DEFAULT_COMPRESSION);
+ }
+
+ private function getEndpoint(string $protocol): string
+ {
+ if (Configuration::has(Variables::OTEL_EXPORTER_OTLP_METRICS_ENDPOINT)) {
+ return Configuration::getString(Variables::OTEL_EXPORTER_OTLP_METRICS_ENDPOINT);
+ }
+ $endpoint = Configuration::has(Variables::OTEL_EXPORTER_OTLP_ENDPOINT)
+ ? Configuration::getString(Variables::OTEL_EXPORTER_OTLP_ENDPOINT)
+ : Defaults::OTEL_EXPORTER_OTLP_ENDPOINT;
+ if ($protocol === Protocols::GRPC) {
+ return $endpoint . OtlpUtil::method(Signals::METRICS);
+ }
+
+ return HttpEndpointResolver::create()->resolveToString($endpoint, Signals::METRICS);
+ }
+}
diff --git a/vendor/open-telemetry/exporter-otlp/OtlpHttpTransportFactory.php b/vendor/open-telemetry/exporter-otlp/OtlpHttpTransportFactory.php
new file mode 100644
index 000000000..5cf3ff9e4
--- /dev/null
+++ b/vendor/open-telemetry/exporter-otlp/OtlpHttpTransportFactory.php
@@ -0,0 +1,33 @@
+<?php
+
+declare(strict_types=1);
+
+namespace OpenTelemetry\Contrib\Otlp;
+
+use OpenTelemetry\SDK\Common\Export\Http\PsrTransport;
+use OpenTelemetry\SDK\Common\Export\Http\PsrTransportFactory;
+use OpenTelemetry\SDK\Common\Export\TransportFactoryInterface;
+
+class OtlpHttpTransportFactory implements TransportFactoryInterface
+{
+ private const DEFAULT_COMPRESSION = 'none';
+
+ 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 ($compression === self::DEFAULT_COMPRESSION) {
+ $compression = null;
+ }
+
+ return PsrTransportFactory::discover()->create($endpoint, $contentType, $headers, $compression, $timeout, $retryDelay, $maxRetries, $cacert, $cert, $key);
+ }
+}
diff --git a/vendor/open-telemetry/exporter-otlp/OtlpUtil.php b/vendor/open-telemetry/exporter-otlp/OtlpUtil.php
new file mode 100644
index 000000000..6901c1324
--- /dev/null
+++ b/vendor/open-telemetry/exporter-otlp/OtlpUtil.php
@@ -0,0 +1,45 @@
+<?php
+
+declare(strict_types=1);
+
+namespace OpenTelemetry\Contrib\Otlp;
+
+use OpenTelemetry\API\Signals;
+use OpenTelemetry\SDK\Resource\Detectors\Sdk;
+use OpenTelemetry\SemConv\ResourceAttributes;
+use UnexpectedValueException;
+
+class OtlpUtil
+{
+ /**
+ * gRPC per-signal methods
+ * @see protobuf *ServiceClient
+ */
+ private const METHODS = [
+ Signals::TRACE => '/opentelemetry.proto.collector.trace.v1.TraceService/Export',
+ Signals::METRICS => '/opentelemetry.proto.collector.metrics.v1.MetricsService/Export',
+ Signals::LOGS => '/opentelemetry.proto.collector.logs.v1.LogsService/Export',
+ ];
+
+ public static function method(string $signal): string
+ {
+ if (!array_key_exists($signal, self::METHODS)) {
+ throw new UnexpectedValueException('gRPC method not defined for signal: ' . $signal);
+ }
+
+ return self::METHODS[$signal];
+ }
+
+ /**
+ * @link https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/protocol/exporter.md#user-agent
+ */
+ public static function getUserAgentHeader(): array
+ {
+ $resource = (new Sdk())->getResource();
+
+ return ['User-Agent' => sprintf(
+ 'OTel OTLP Exporter PHP/%s',
+ $resource->getAttributes()->get(ResourceAttributes::TELEMETRY_SDK_VERSION) ?: 'unknown'
+ )];
+ }
+}
diff --git a/vendor/open-telemetry/exporter-otlp/ProtobufSerializer.php b/vendor/open-telemetry/exporter-otlp/ProtobufSerializer.php
new file mode 100644
index 000000000..c244d0066
--- /dev/null
+++ b/vendor/open-telemetry/exporter-otlp/ProtobufSerializer.php
@@ -0,0 +1,115 @@
+<?php
+
+declare(strict_types=1);
+
+namespace OpenTelemetry\Contrib\Otlp;
+
+use AssertionError;
+use function base64_decode;
+use function bin2hex;
+use Exception;
+use Google\Protobuf\Internal\Message;
+use InvalidArgumentException;
+use OpenTelemetry\SDK\Common\Export\TransportInterface;
+use function sprintf;
+
+/**
+ * @internal
+ *
+ * @psalm-type SUPPORTED_CONTENT_TYPES = self::PROTOBUF|self::JSON|self::NDJSON
+ */
+final class ProtobufSerializer
+{
+ private const PROTOBUF = 'application/x-protobuf';
+ private const JSON = 'application/json';
+ private const NDJSON = 'application/x-ndjson';
+
+ private string $contentType;
+
+ private function __construct(string $contentType)
+ {
+ $this->contentType = $contentType;
+ }
+
+ public static function getDefault(): ProtobufSerializer
+ {
+ return new self(self::PROTOBUF);
+ }
+
+ /**
+ * @psalm-param TransportInterface<SUPPORTED_CONTENT_TYPES> $transport
+ */
+ public static function forTransport(TransportInterface $transport): ProtobufSerializer
+ {
+ switch ($contentType = $transport->contentType()) {
+ case self::PROTOBUF:
+ case self::JSON:
+ case self::NDJSON:
+ return new self($contentType);
+ default:
+ throw new InvalidArgumentException(sprintf('Not supported content type "%s"', $contentType));
+ }
+ }
+
+ public function serializeTraceId(string $traceId): string
+ {
+ switch ($this->contentType) {
+ case self::PROTOBUF:
+ return $traceId;
+ case self::JSON:
+ case self::NDJSON:
+ return base64_decode(bin2hex($traceId));
+ default:
+ throw new AssertionError();
+ }
+ }
+
+ public function serializeSpanId(string $spanId): string
+ {
+ switch ($this->contentType) {
+ case self::PROTOBUF:
+ return $spanId;
+ case self::JSON:
+ case self::NDJSON:
+ return base64_decode(bin2hex($spanId));
+ default:
+ throw new AssertionError();
+ }
+ }
+
+ public function serialize(Message $message): string
+ {
+ switch ($this->contentType) {
+ case self::PROTOBUF:
+ return $message->serializeToString();
+ case self::JSON:
+ //@todo https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/protocol/otlp.md#json-protobuf-encoding
+ return $message->serializeToJsonString();
+ case self::NDJSON:
+ return $message->serializeToJsonString() . "\n";
+ default:
+ throw new AssertionError();
+ }
+ }
+
+ /**
+ * @throws Exception
+ */
+ public function hydrate(Message $message, string $payload): void
+ {
+ switch ($this->contentType) {
+ case self::PROTOBUF:
+ $message->mergeFromString($payload);
+
+ break;
+ case self::JSON:
+ case self::NDJSON:
+ // @phan-suppress-next-line PhanParamTooManyInternal
+ $message->mergeFromJsonString($payload, true);
+
+ break;
+ default:
+ throw new AssertionError();
+ }
+ }
+}
diff --git a/vendor/open-telemetry/exporter-otlp/Protocols.php b/vendor/open-telemetry/exporter-otlp/Protocols.php
new file mode 100644
index 000000000..96b04d8bf
--- /dev/null
+++ b/vendor/open-telemetry/exporter-otlp/Protocols.php
@@ -0,0 +1,36 @@
+<?php
+
+declare(strict_types=1);
+
+namespace OpenTelemetry\Contrib\Otlp;
+
+use OpenTelemetry\SDK\Common\Configuration\KnownValues;
+use UnexpectedValueException;
+
+class Protocols
+{
+ public const GRPC = KnownValues::VALUE_GRPC;
+ public const HTTP_PROTOBUF = KnownValues::VALUE_HTTP_PROTOBUF;
+ public const HTTP_JSON = KnownValues::VALUE_HTTP_JSON;
+ public const HTTP_NDJSON = KnownValues::VALUE_HTTP_NDJSON;
+ private const PROTOCOLS = [
+ self::GRPC => ContentTypes::PROTOBUF,
+ self::HTTP_PROTOBUF => ContentTypes::PROTOBUF,
+ self::HTTP_JSON => ContentTypes::JSON,
+ self::HTTP_NDJSON => ContentTypes::NDJSON,
+ ];
+
+ public static function validate(string $protocol): void
+ {
+ if (!array_key_exists($protocol, self::PROTOCOLS)) {
+ throw new UnexpectedValueException('Unknown protocol: ' . $protocol);
+ }
+ }
+
+ public static function contentType(string $protocol): string
+ {
+ self::validate($protocol);
+
+ return self::PROTOCOLS[$protocol];
+ }
+}
diff --git a/vendor/open-telemetry/exporter-otlp/README.md b/vendor/open-telemetry/exporter-otlp/README.md
new file mode 100644
index 000000000..a41349da0
--- /dev/null
+++ b/vendor/open-telemetry/exporter-otlp/README.md
@@ -0,0 +1,45 @@
+[![Releases](https://img.shields.io/badge/releases-purple)](https://github.com/opentelemetry-php/exporter-otlp/releases)
+[![Source](https://img.shields.io/badge/source-exporter--otlp-green)](https://github.com/open-telemetry/opentelemetry-php/tree/main/src/Contrib/Otlp)
+[![Mirror](https://img.shields.io/badge/mirror-opentelemetry--php:exporter--otlp-blue)](https://github.com/opentelemetry-php/exporter-otlp)
+[![Latest Version](http://poser.pugx.org/open-telemetry/exporter-otlp/v/unstable)](https://packagist.org/packages/open-telemetry/exporter-otlp/)
+[![Stable](http://poser.pugx.org/open-telemetry/exporter-otlp/v/stable)](https://packagist.org/packages/open-telemetry/exporter-otlp/)
+
+# OpenTelemetry OTLP exporter
+
+## Documentation
+
+https://opentelemetry.io/docs/instrumentation/php/exporters/#otlp
+
+## Usage
+
+See https://github.com/open-telemetry/opentelemetry-php/blob/main/examples/traces/exporters/otlp_http.php
+
+## Http transport
+
+```php
+$transport = (new \OpenTelemetry\Contrib\Otlp\OtlpHttpTransportFactory())->create('http://collector:4318');
+$exporter = new \OpenTelemetry\Contrib\Otlp\SpanExporter($transport);
+```
+
+## gRPC transport
+
+To export over gRPC, you will need to additionally install the `open-telemetry/transport-grpc` package.
+
+## Protobuf Runtime library
+
+OTLP exporting requires a [protobuf implementation](https://github.com/protocolbuffers/protobuf/tree/main/php).
+
+The `open-telemetry/gen-otlp-protobuf` requires the `google/protobuf` native implementation. It's fine for development, but
+not recommended for production usage.
+
+The recommended option for production is to install the Protobuf C extension for PHP. The extension
+makes exporting _significantly_ more performant. This can be easily installed with the following command:
+
+```shell
+pecl install protobuf
+```
+
+## Contributing
+
+This repository is a read-only git subtree split.
+To contribute, please see the main [OpenTelemetry PHP monorepo](https://github.com/open-telemetry/opentelemetry-php).
diff --git a/vendor/open-telemetry/exporter-otlp/SpanConverter.php b/vendor/open-telemetry/exporter-otlp/SpanConverter.php
new file mode 100644
index 000000000..1a8b4369e
--- /dev/null
+++ b/vendor/open-telemetry/exporter-otlp/SpanConverter.php
@@ -0,0 +1,187 @@
+<?php
+
+declare(strict_types=1);
+
+namespace OpenTelemetry\Contrib\Otlp;
+
+use OpenTelemetry\API\Trace as API;
+use Opentelemetry\Proto\Collector\Trace\V1\ExportTraceServiceRequest;
+use Opentelemetry\Proto\Common\V1\InstrumentationScope;
+use Opentelemetry\Proto\Common\V1\KeyValue;
+use Opentelemetry\Proto\Resource\V1\Resource as Resource_;
+use Opentelemetry\Proto\Trace\V1\ResourceSpans;
+use Opentelemetry\Proto\Trace\V1\ScopeSpans;
+use Opentelemetry\Proto\Trace\V1\Span;
+use Opentelemetry\Proto\Trace\V1\Span\Event;
+use Opentelemetry\Proto\Trace\V1\Span\Link;
+use Opentelemetry\Proto\Trace\V1\Span\SpanKind;
+use Opentelemetry\Proto\Trace\V1\Status;
+use Opentelemetry\Proto\Trace\V1\Status\StatusCode;
+use OpenTelemetry\SDK\Common\Attribute\AttributesInterface;
+use OpenTelemetry\SDK\Common\Instrumentation\InstrumentationScopeInterface;
+use OpenTelemetry\SDK\Resource\ResourceInfo;
+use OpenTelemetry\SDK\Trace\SpanDataInterface;
+use function serialize;
+use function spl_object_id;
+
+final class SpanConverter
+{
+ private ProtobufSerializer $serializer;
+
+ public function __construct(?ProtobufSerializer $serializer = null)
+ {
+ $this->serializer = $serializer ?? ProtobufSerializer::getDefault();
+ }
+
+ public function convert(iterable $spans): ExportTraceServiceRequest
+ {
+ $pExportTraceServiceRequest = new ExportTraceServiceRequest();
+
+ $resourceSpans = [];
+ $resourceCache = [];
+ $scopeSpans = [];
+ $scopeCache = [];
+ foreach ($spans as $span) {
+ $resource = $span->getResource();
+ $instrumentationScope = $span->getInstrumentationScope();
+
+ $resourceId = $resourceCache[spl_object_id($resource)] ??= serialize([
+ $resource->getSchemaUrl(),
+ $resource->getAttributes()->toArray(),
+ $resource->getAttributes()->getDroppedAttributesCount(),
+ ]);
+ $instrumentationScopeId = $scopeCache[spl_object_id($instrumentationScope)] ??= serialize([
+ $instrumentationScope->getName(),
+ $instrumentationScope->getVersion(),
+ $instrumentationScope->getSchemaUrl(),
+ $instrumentationScope->getAttributes()->toArray(),
+ $instrumentationScope->getAttributes()->getDroppedAttributesCount(),
+ ]);
+
+ if (($pResourceSpans = $resourceSpans[$resourceId] ?? null) === null) {
+ /** @psalm-suppress InvalidArgument */
+ $pExportTraceServiceRequest->getResourceSpans()[]
+ = $resourceSpans[$resourceId]
+ = $pResourceSpans
+ = $this->convertResourceSpans($resource);
+ }
+
+ if (($pScopeSpans = $scopeSpans[$resourceId][$instrumentationScopeId] ?? null) === null) {
+ /** @psalm-suppress InvalidArgument */
+ $pResourceSpans->getScopeSpans()[]
+ = $scopeSpans[$resourceId][$instrumentationScopeId]
+ = $pScopeSpans
+ = $this->convertScopeSpans($instrumentationScope);
+ }
+
+ /** @psalm-suppress InvalidArgument */
+ $pScopeSpans->getSpans()[] = $this->convertSpan($span);
+ }
+
+ return $pExportTraceServiceRequest;
+ }
+
+ private function convertResourceSpans(ResourceInfo $resource): ResourceSpans
+ {
+ $pResourceSpans = new ResourceSpans();
+ $pResource = new Resource_();
+ $this->setAttributes($pResource, $resource->getAttributes());
+ $pResourceSpans->setResource($pResource);
+ $pResourceSpans->setSchemaUrl((string) $resource->getSchemaUrl());
+
+ return $pResourceSpans;
+ }
+
+ private function convertScopeSpans(InstrumentationScopeInterface $instrumentationScope): ScopeSpans
+ {
+ $pScopeSpans = new ScopeSpans();
+ $pInstrumentationScope = new InstrumentationScope();
+ $pInstrumentationScope->setName($instrumentationScope->getName());
+ $pInstrumentationScope->setVersion((string) $instrumentationScope->getVersion());
+ $this->setAttributes($pInstrumentationScope, $instrumentationScope->getAttributes());
+ $pScopeSpans->setScope($pInstrumentationScope);
+ $pScopeSpans->setSchemaUrl((string) $instrumentationScope->getSchemaUrl());
+
+ return $pScopeSpans;
+ }
+
+ /**
+ * @param Resource_|Span|Event|Link|InstrumentationScope $pElement
+ */
+ private function setAttributes($pElement, AttributesInterface $attributes): void
+ {
+ foreach ($attributes as $key => $value) {
+ /** @psalm-suppress InvalidArgument */
+ $pElement->getAttributes()[] = (new KeyValue())
+ ->setKey($key)
+ ->setValue(AttributesConverter::convertAnyValue($value));
+ }
+ $pElement->setDroppedAttributesCount($attributes->getDroppedAttributesCount());
+ }
+
+ private function convertSpanKind(int $kind): int
+ {
+ switch ($kind) {
+ case API\SpanKind::KIND_INTERNAL: return SpanKind::SPAN_KIND_INTERNAL;
+ case API\SpanKind::KIND_CLIENT: return SpanKind::SPAN_KIND_CLIENT;
+ case API\SpanKind::KIND_SERVER: return SpanKind::SPAN_KIND_SERVER;
+ case API\SpanKind::KIND_PRODUCER: return SpanKind::SPAN_KIND_PRODUCER;
+ case API\SpanKind::KIND_CONSUMER: return SpanKind::SPAN_KIND_CONSUMER;
+ }
+
+ return SpanKind::SPAN_KIND_UNSPECIFIED;
+ }
+
+ private function convertStatusCode(string $status): int
+ {
+ switch ($status) {
+ case API\StatusCode::STATUS_UNSET: return StatusCode::STATUS_CODE_UNSET;
+ case API\StatusCode::STATUS_OK: return StatusCode::STATUS_CODE_OK;
+ case API\StatusCode::STATUS_ERROR: return StatusCode::STATUS_CODE_ERROR;
+ }
+
+ return StatusCode::STATUS_CODE_UNSET;
+ }
+
+ private function convertSpan(SpanDataInterface $span): Span
+ {
+ $pSpan = new Span();
+ $pSpan->setTraceId($this->serializer->serializeTraceId($span->getContext()->getTraceIdBinary()));
+ $pSpan->setSpanId($this->serializer->serializeSpanId($span->getContext()->getSpanIdBinary()));
+ $pSpan->setTraceState((string) $span->getContext()->getTraceState());
+ if ($span->getParentContext()->isValid()) {
+ $pSpan->setParentSpanId($this->serializer->serializeSpanId($span->getParentContext()->getSpanIdBinary()));
+ }
+ $pSpan->setName($span->getName());
+ $pSpan->setKind($this->convertSpanKind($span->getKind()));
+ $pSpan->setStartTimeUnixNano($span->getStartEpochNanos());
+ $pSpan->setEndTimeUnixNano($span->getEndEpochNanos());
+ $this->setAttributes($pSpan, $span->getAttributes());
+
+ foreach ($span->getEvents() as $event) {
+ /** @psalm-suppress InvalidArgument */
+ $pSpan->getEvents()[] = $pEvent = new Event();
+ $pEvent->setTimeUnixNano($event->getEpochNanos());
+ $pEvent->setName($event->getName());
+ $this->setAttributes($pEvent, $event->getAttributes());
+ }
+ $pSpan->setDroppedEventsCount($span->getTotalDroppedEvents());
+
+ foreach ($span->getLinks() as $link) {
+ /** @psalm-suppress InvalidArgument */
+ $pSpan->getLinks()[] = $pLink = new Link();
+ $pLink->setTraceId($this->serializer->serializeTraceId($link->getSpanContext()->getTraceIdBinary()));
+ $pLink->setSpanId($this->serializer->serializeSpanId($link->getSpanContext()->getSpanIdBinary()));
+ $pLink->setTraceState((string) $link->getSpanContext()->getTraceState());
+ $this->setAttributes($pLink, $link->getAttributes());
+ }
+ $pSpan->setDroppedLinksCount($span->getTotalDroppedLinks());
+
+ $pStatus = new Status();
+ $pStatus->setMessage($span->getStatus()->getDescription());
+ $pStatus->setCode($this->convertStatusCode($span->getStatus()->getCode()));
+ $pSpan->setStatus($pStatus);
+
+ return $pSpan;
+ }
+}
diff --git a/vendor/open-telemetry/exporter-otlp/SpanExporter.php b/vendor/open-telemetry/exporter-otlp/SpanExporter.php
new file mode 100644
index 000000000..a496206f4
--- /dev/null
+++ b/vendor/open-telemetry/exporter-otlp/SpanExporter.php
@@ -0,0 +1,81 @@
+<?php
+
+declare(strict_types=1);
+
+namespace OpenTelemetry\Contrib\Otlp;
+
+use OpenTelemetry\API\Behavior\LogsMessagesTrait;
+use Opentelemetry\Proto\Collector\Trace\V1\ExportTraceServiceResponse;
+use OpenTelemetry\SDK\Common\Export\TransportInterface;
+use OpenTelemetry\SDK\Common\Future\CancellationInterface;
+use OpenTelemetry\SDK\Common\Future\FutureInterface;
+use OpenTelemetry\SDK\Trace\SpanExporterInterface;
+use RuntimeException;
+use Throwable;
+
+/**
+ * @psalm-import-type SUPPORTED_CONTENT_TYPES from ProtobufSerializer
+ */
+final class SpanExporter implements SpanExporterInterface
+{
+ use LogsMessagesTrait;
+
+ private TransportInterface $transport;
+ private ProtobufSerializer $serializer;
+
+ /**
+ * @psalm-param TransportInterface<SUPPORTED_CONTENT_TYPES> $transport
+ */
+ public function __construct(TransportInterface $transport)
+ {
+ if (!class_exists('\Google\Protobuf\Api')) {
+ throw new RuntimeException('No protobuf implementation found (ext-protobuf or google/protobuf)');
+ }
+ $this->transport = $transport;
+ $this->serializer = ProtobufSerializer::forTransport($transport);
+ }
+
+ public function export(iterable $batch, ?CancellationInterface $cancellation = null): FutureInterface
+ {
+ return $this->transport
+ ->send($this->serializer->serialize((new SpanConverter($this->serializer))->convert($batch)), $cancellation)
+ ->map(function (?string $payload): bool {
+ if ($payload === null) {
+ return true;
+ }
+
+ $serviceResponse = new ExportTraceServiceResponse();
+ $this->serializer->hydrate($serviceResponse, $payload);
+
+ $partialSuccess = $serviceResponse->getPartialSuccess();
+ if ($partialSuccess !== null && $partialSuccess->getRejectedSpans()) {
+ self::logError('Export partial success', [
+ 'rejected_spans' => $partialSuccess->getRejectedSpans(),
+ 'error_message' => $partialSuccess->getErrorMessage(),
+ ]);
+
+ return false;
+ }
+ if ($partialSuccess !== null && $partialSuccess->getErrorMessage()) {
+ self::logWarning('Export success with warnings/suggestions', ['error_message' => $partialSuccess->getErrorMessage()]);
+ }
+
+ return true;
+ })
+ ->catch(static function (Throwable $throwable): bool {
+ self::logError('Export failure', ['exception' => $throwable]);
+
+ return false;
+ });
+ }
+
+ public function shutdown(?CancellationInterface $cancellation = null): bool
+ {
+ return $this->transport->shutdown($cancellation);
+ }
+
+ public function forceFlush(?CancellationInterface $cancellation = null): bool
+ {
+ return $this->transport->forceFlush($cancellation);
+ }
+}
diff --git a/vendor/open-telemetry/exporter-otlp/SpanExporterFactory.php b/vendor/open-telemetry/exporter-otlp/SpanExporterFactory.php
new file mode 100644
index 000000000..ce0550735
--- /dev/null
+++ b/vendor/open-telemetry/exporter-otlp/SpanExporterFactory.php
@@ -0,0 +1,96 @@
+<?php
+
+declare(strict_types=1);
+
+namespace OpenTelemetry\Contrib\Otlp;
+
+use OpenTelemetry\API\Behavior\LogsMessagesTrait;
+use OpenTelemetry\API\Signals;
+use OpenTelemetry\SDK\Common\Configuration\Configuration;
+use OpenTelemetry\SDK\Common\Configuration\Defaults;
+use OpenTelemetry\SDK\Common\Configuration\Variables;
+use OpenTelemetry\SDK\Common\Export\TransportFactoryInterface;
+use OpenTelemetry\SDK\Common\Export\TransportInterface;
+use OpenTelemetry\SDK\Registry;
+use OpenTelemetry\SDK\Trace\SpanExporter\SpanExporterFactoryInterface;
+use OpenTelemetry\SDK\Trace\SpanExporterInterface;
+
+class SpanExporterFactory implements SpanExporterFactoryInterface
+{
+ use LogsMessagesTrait;
+
+ private ?TransportFactoryInterface $transportFactory;
+
+ private const DEFAULT_COMPRESSION = 'none';
+
+ public function __construct(?TransportFactoryInterface $transportFactory = null)
+ {
+ $this->transportFactory = $transportFactory;
+ }
+
+ /**
+ * @psalm-suppress ArgumentTypeCoercion
+ */
+ public function create(): SpanExporterInterface
+ {
+ $transport = $this->buildTransport();
+
+ return new SpanExporter($transport);
+ }
+
+ /**
+ * @psalm-suppress ArgumentTypeCoercion
+ * @psalm-suppress UndefinedClass
+ */
+ private function buildTransport(): TransportInterface
+ {
+ $protocol = $this->getProtocol();
+ $contentType = Protocols::contentType($protocol);
+ $endpoint = $this->getEndpoint($protocol);
+ $headers = $this->getHeaders();
+ $compression = $this->getCompression();
+
+ $factoryClass = Registry::transportFactory($protocol);
+ $factory = $this->transportFactory ?: new $factoryClass();
+
+ return $factory->create($endpoint, $contentType, $headers, $compression);
+ }
+
+ private function getProtocol(): string
+ {
+ return Configuration::has(Variables::OTEL_EXPORTER_OTLP_TRACES_PROTOCOL) ?
+ Configuration::getEnum(Variables::OTEL_EXPORTER_OTLP_TRACES_PROTOCOL) :
+ Configuration::getEnum(Variables::OTEL_EXPORTER_OTLP_PROTOCOL);
+ }
+
+ private function getEndpoint(string $protocol): string
+ {
+ if (Configuration::has(Variables::OTEL_EXPORTER_OTLP_TRACES_ENDPOINT)) {
+ return Configuration::getString(Variables::OTEL_EXPORTER_OTLP_TRACES_ENDPOINT);
+ }
+ $endpoint = Configuration::has(Variables::OTEL_EXPORTER_OTLP_ENDPOINT)
+ ? Configuration::getString(Variables::OTEL_EXPORTER_OTLP_ENDPOINT)
+ : Defaults::OTEL_EXPORTER_OTLP_ENDPOINT;
+ if ($protocol === Protocols::GRPC) {
+ return $endpoint . OtlpUtil::method(Signals::TRACE);
+ }
+
+ return HttpEndpointResolver::create()->resolveToString($endpoint, Signals::TRACE);
+ }
+
+ private function getHeaders(): array
+ {
+ $headers = Configuration::has(Variables::OTEL_EXPORTER_OTLP_TRACES_HEADERS) ?
+ Configuration::getMap(Variables::OTEL_EXPORTER_OTLP_TRACES_HEADERS) :
+ Configuration::getMap(Variables::OTEL_EXPORTER_OTLP_HEADERS);
+
+ return $headers + OtlpUtil::getUserAgentHeader();
+ }
+
+ private function getCompression(): string
+ {
+ return Configuration::has(Variables::OTEL_EXPORTER_OTLP_TRACES_COMPRESSION) ?
+ Configuration::getEnum(Variables::OTEL_EXPORTER_OTLP_TRACES_COMPRESSION) :
+ Configuration::getEnum(Variables::OTEL_EXPORTER_OTLP_COMPRESSION, self::DEFAULT_COMPRESSION);
+ }
+}
diff --git a/vendor/open-telemetry/exporter-otlp/_register.php b/vendor/open-telemetry/exporter-otlp/_register.php
new file mode 100644
index 000000000..b3acdc3af
--- /dev/null
+++ b/vendor/open-telemetry/exporter-otlp/_register.php
@@ -0,0 +1,9 @@
+<?php
+
+declare(strict_types=1);
+\OpenTelemetry\SDK\Registry::registerSpanExporterFactory('otlp', \OpenTelemetry\Contrib\Otlp\SpanExporterFactory::class);
+\OpenTelemetry\SDK\Registry::registerMetricExporterFactory('otlp', \OpenTelemetry\Contrib\Otlp\MetricExporterFactory::class);
+
+\OpenTelemetry\SDK\Registry::registerTransportFactory('http', \OpenTelemetry\Contrib\Otlp\OtlpHttpTransportFactory::class);
+
+\OpenTelemetry\SDK\Registry::registerLogRecordExporterFactory('otlp', \OpenTelemetry\Contrib\Otlp\LogsExporterFactory::class);
diff --git a/vendor/open-telemetry/exporter-otlp/composer.json b/vendor/open-telemetry/exporter-otlp/composer.json
new file mode 100644
index 000000000..fdb13362d
--- /dev/null
+++ b/vendor/open-telemetry/exporter-otlp/composer.json
@@ -0,0 +1,41 @@
+{
+ "name": "open-telemetry/exporter-otlp",
+ "description": "OTLP exporter for OpenTelemetry.",
+ "keywords": ["opentelemetry", "otel", "tracing", "metrics", "exporter", "otlp", "grpc", "http"],
+ "type": "library",
+ "support": {
+ "issues": "https://github.com/open-telemetry/opentelemetry-php/issues",
+ "source": "https://github.com/open-telemetry/opentelemetry-php",
+ "docs": "https://opentelemetry.io/docs/php",
+ "chat": "https://app.slack.com/client/T08PSQ7BQ/C01NFPCV44V"
+ },
+ "license": "Apache-2.0",
+ "authors": [
+ {
+ "name": "opentelemetry-php contributors",
+ "homepage": "https://github.com/open-telemetry/opentelemetry-php/graphs/contributors"
+ }
+ ],
+ "require": {
+ "php": "^7.4 || ^8.0",
+ "php-http/discovery": "^1.14",
+ "open-telemetry/gen-otlp-protobuf": "^1.0",
+ "open-telemetry/api": "^1.0",
+ "open-telemetry/sdk": "^1.0"
+ },
+ "suggest": {
+ },
+ "autoload": {
+ "psr-4": {
+ "OpenTelemetry\\Contrib\\Otlp\\": "."
+ },
+ "files": [
+ "_register.php"
+ ]
+ },
+ "extra": {
+ "branch-alias": {
+ "dev-main": "1.0.x-dev"
+ }
+ }
+}