diff options
Diffstat (limited to 'vendor/open-telemetry/sdk/Logs')
28 files changed, 1377 insertions, 0 deletions
diff --git a/vendor/open-telemetry/sdk/Logs/Exporter/ConsoleExporter.php b/vendor/open-telemetry/sdk/Logs/Exporter/ConsoleExporter.php new file mode 100644 index 000000000..e34fa308c --- /dev/null +++ b/vendor/open-telemetry/sdk/Logs/Exporter/ConsoleExporter.php @@ -0,0 +1,106 @@ +<?php + +declare(strict_types=1); + +namespace OpenTelemetry\SDK\Logs\Exporter; + +use OpenTelemetry\SDK\Common\Export\TransportInterface; +use OpenTelemetry\SDK\Common\Future\CancellationInterface; +use OpenTelemetry\SDK\Common\Future\CompletedFuture; +use OpenTelemetry\SDK\Common\Future\FutureInterface; +use OpenTelemetry\SDK\Common\Instrumentation\InstrumentationScopeInterface; +use OpenTelemetry\SDK\Logs\LogRecordExporterInterface; +use OpenTelemetry\SDK\Logs\ReadableLogRecord; +use OpenTelemetry\SDK\Resource\ResourceInfo; + +/** + * A JSON console exporter for LogRecords. This is only useful for testing; the + * output is human-readable, and is not compatible with the OTLP format. + */ +class ConsoleExporter implements LogRecordExporterInterface +{ + private TransportInterface $transport; + + public function __construct(TransportInterface $transport) + { + $this->transport = $transport; + } + + /** + * @param iterable<mixed, ReadableLogRecord> $batch + */ + public function export(iterable $batch, ?CancellationInterface $cancellation = null): FutureInterface + { + $resource = null; + $scopes = []; + foreach ($batch as $record) { + if (!$resource) { + $resource = $this->convertResource($record->getResource()); + } + $key = $this->scopeKey($record->getInstrumentationScope()); + if (!array_key_exists($key, $scopes)) { + $scopes[$key] = $this->convertInstrumentationScope($record->getInstrumentationScope()); + } + $scopes[$key]['logs'][] = $this->convertLogRecord($record); + } + $output = [ + 'resource' => $resource, + 'scopes' => array_values($scopes), + ]; + $this->transport->send(json_encode($output, JSON_PRETTY_PRINT)); + + return new CompletedFuture(true); + } + + public function forceFlush(?CancellationInterface $cancellation = null): bool + { + return true; + } + + public function shutdown(?CancellationInterface $cancellation = null): bool + { + return true; + } + private function convertLogRecord(ReadableLogRecord $record): array + { + $spanContext = $record->getSpanContext(); + + return [ + 'timestamp' => $record->getTimestamp(), + 'observed_timestamp' => $record->getObservedTimestamp(), + 'severity_number' => $record->getSeverityNumber(), + 'severity_text' => $record->getSeverityText(), + 'body' => $record->getBody(), + 'trace_id' => $spanContext !== null ? $spanContext->getTraceId() : '', + 'span_id' => $spanContext !== null ? $spanContext->getSpanId() : '', + 'trace_flags' => $spanContext !== null ? $spanContext->getTraceFlags() : null, + 'attributes' => $record->getAttributes()->toArray(), + 'dropped_attributes_count' => $record->getAttributes()->getDroppedAttributesCount(), + ]; + } + + private function convertResource(ResourceInfo $resource): array + { + return [ + 'attributes' => $resource->getAttributes()->toArray(), + 'dropped_attributes_count' => $resource->getAttributes()->getDroppedAttributesCount(), + ]; + } + + private function scopeKey(InstrumentationScopeInterface $scope): string + { + return serialize([$scope->getName(), $scope->getVersion(), $scope->getSchemaUrl(), $scope->getAttributes()]); + } + + private function convertInstrumentationScope(InstrumentationScopeInterface $scope): array + { + return [ + 'name' => $scope->getName(), + 'version' => $scope->getVersion(), + 'attributes' => $scope->getAttributes()->toArray(), + 'dropped_attributes_count' => $scope->getAttributes()->getDroppedAttributesCount(), + 'schema_url' => $scope->getSchemaUrl(), + 'logs' => [], + ]; + } +} diff --git a/vendor/open-telemetry/sdk/Logs/Exporter/ConsoleExporterFactory.php b/vendor/open-telemetry/sdk/Logs/Exporter/ConsoleExporterFactory.php new file mode 100644 index 000000000..a959540a0 --- /dev/null +++ b/vendor/open-telemetry/sdk/Logs/Exporter/ConsoleExporterFactory.php @@ -0,0 +1,19 @@ +<?php + +declare(strict_types=1); + +namespace OpenTelemetry\SDK\Logs\Exporter; + +use OpenTelemetry\SDK\Logs\LogRecordExporterFactoryInterface; +use OpenTelemetry\SDK\Logs\LogRecordExporterInterface; +use OpenTelemetry\SDK\Registry; + +class ConsoleExporterFactory implements LogRecordExporterFactoryInterface +{ + public function create(): LogRecordExporterInterface + { + $transport = Registry::transportFactory('stream')->create('php://stdout', 'application/json'); + + return new ConsoleExporter($transport); + } +} diff --git a/vendor/open-telemetry/sdk/Logs/Exporter/InMemoryExporter.php b/vendor/open-telemetry/sdk/Logs/Exporter/InMemoryExporter.php new file mode 100644 index 000000000..dca0531f3 --- /dev/null +++ b/vendor/open-telemetry/sdk/Logs/Exporter/InMemoryExporter.php @@ -0,0 +1,48 @@ +<?php + +declare(strict_types=1); + +namespace OpenTelemetry\SDK\Logs\Exporter; + +use ArrayObject; +use OpenTelemetry\SDK\Common\Future\CancellationInterface; +use OpenTelemetry\SDK\Common\Future\CompletedFuture; +use OpenTelemetry\SDK\Common\Future\FutureInterface; +use OpenTelemetry\SDK\Logs\LogRecordExporterInterface; + +class InMemoryExporter implements LogRecordExporterInterface +{ + private ArrayObject $storage; + + public function __construct(?ArrayObject $storage = null) + { + $this->storage = $storage ?? new ArrayObject(); + } + + /** + * @inheritDoc + */ + public function export(iterable $batch, ?CancellationInterface $cancellation = null): FutureInterface + { + foreach ($batch as $record) { + $this->storage[] = $record; + } + + return new CompletedFuture(true); + } + + public function forceFlush(?CancellationInterface $cancellation = null): bool + { + return true; + } + + public function shutdown(?CancellationInterface $cancellation = null): bool + { + return true; + } + + public function getStorage(): ArrayObject + { + return $this->storage; + } +} diff --git a/vendor/open-telemetry/sdk/Logs/Exporter/InMemoryExporterFactory.php b/vendor/open-telemetry/sdk/Logs/Exporter/InMemoryExporterFactory.php new file mode 100644 index 000000000..6f24defe0 --- /dev/null +++ b/vendor/open-telemetry/sdk/Logs/Exporter/InMemoryExporterFactory.php @@ -0,0 +1,16 @@ +<?php + +declare(strict_types=1); + +namespace OpenTelemetry\SDK\Logs\Exporter; + +use OpenTelemetry\SDK\Logs\LogRecordExporterFactoryInterface; +use OpenTelemetry\SDK\Logs\LogRecordExporterInterface; + +class InMemoryExporterFactory implements LogRecordExporterFactoryInterface +{ + public function create(): LogRecordExporterInterface + { + return new InMemoryExporter(); + } +} diff --git a/vendor/open-telemetry/sdk/Logs/Exporter/NoopExporter.php b/vendor/open-telemetry/sdk/Logs/Exporter/NoopExporter.php new file mode 100644 index 000000000..8eeff62bd --- /dev/null +++ b/vendor/open-telemetry/sdk/Logs/Exporter/NoopExporter.php @@ -0,0 +1,28 @@ +<?php + +declare(strict_types=1); + +namespace OpenTelemetry\SDK\Logs\Exporter; + +use OpenTelemetry\SDK\Common\Future\CancellationInterface; +use OpenTelemetry\SDK\Common\Future\CompletedFuture; +use OpenTelemetry\SDK\Common\Future\FutureInterface; +use OpenTelemetry\SDK\Logs\LogRecordExporterInterface; + +class NoopExporter implements LogRecordExporterInterface +{ + public function export(iterable $batch, ?CancellationInterface $cancellation = null): FutureInterface + { + return new CompletedFuture(true); + } + + public function forceFlush(?CancellationInterface $cancellation = null): bool + { + return true; + } + + public function shutdown(?CancellationInterface $cancellation = null): bool + { + return true; + } +} diff --git a/vendor/open-telemetry/sdk/Logs/Exporter/_register.php b/vendor/open-telemetry/sdk/Logs/Exporter/_register.php new file mode 100644 index 000000000..96958baa8 --- /dev/null +++ b/vendor/open-telemetry/sdk/Logs/Exporter/_register.php @@ -0,0 +1,6 @@ +<?php + +declare(strict_types=1); + +\OpenTelemetry\SDK\Registry::registerLogRecordExporterFactory('console', \OpenTelemetry\SDK\Logs\Exporter\ConsoleExporterFactory::class); +\OpenTelemetry\SDK\Registry::registerLogRecordExporterFactory('memory', \OpenTelemetry\SDK\Logs\Exporter\InMemoryExporterFactory::class); diff --git a/vendor/open-telemetry/sdk/Logs/ExporterFactory.php b/vendor/open-telemetry/sdk/Logs/ExporterFactory.php new file mode 100644 index 000000000..2a560ae95 --- /dev/null +++ b/vendor/open-telemetry/sdk/Logs/ExporterFactory.php @@ -0,0 +1,29 @@ +<?php + +declare(strict_types=1); + +namespace OpenTelemetry\SDK\Logs; + +use InvalidArgumentException; +use OpenTelemetry\SDK\Common\Configuration\Configuration; +use OpenTelemetry\SDK\Common\Configuration\Variables; +use OpenTelemetry\SDK\Logs\Exporter\NoopExporter; +use OpenTelemetry\SDK\Registry; + +class ExporterFactory +{ + public function create(): LogRecordExporterInterface + { + $exporters = Configuration::getList(Variables::OTEL_LOGS_EXPORTER); + if (1 !== count($exporters)) { + throw new InvalidArgumentException(sprintf('Configuration %s requires exactly 1 exporter', Variables::OTEL_TRACES_EXPORTER)); + } + $exporter = $exporters[0]; + if ($exporter === 'none') { + return new NoopExporter(); + } + $factory = Registry::logRecordExporterFactory($exporter); + + return $factory->create(); + } +} diff --git a/vendor/open-telemetry/sdk/Logs/LogRecordExporterFactoryInterface.php b/vendor/open-telemetry/sdk/Logs/LogRecordExporterFactoryInterface.php new file mode 100644 index 000000000..523bec1ba --- /dev/null +++ b/vendor/open-telemetry/sdk/Logs/LogRecordExporterFactoryInterface.php @@ -0,0 +1,10 @@ +<?php + +declare(strict_types=1); + +namespace OpenTelemetry\SDK\Logs; + +interface LogRecordExporterFactoryInterface +{ + public function create(): LogRecordExporterInterface; +} diff --git a/vendor/open-telemetry/sdk/Logs/LogRecordExporterInterface.php b/vendor/open-telemetry/sdk/Logs/LogRecordExporterInterface.php new file mode 100644 index 000000000..cf9e1aca8 --- /dev/null +++ b/vendor/open-telemetry/sdk/Logs/LogRecordExporterInterface.php @@ -0,0 +1,18 @@ +<?php + +declare(strict_types=1); + +namespace OpenTelemetry\SDK\Logs; + +use OpenTelemetry\SDK\Common\Future\CancellationInterface; +use OpenTelemetry\SDK\Common\Future\FutureInterface; + +interface LogRecordExporterInterface +{ + /** + * @param iterable<ReadableLogRecord> $batch + */ + public function export(iterable $batch, ?CancellationInterface $cancellation = null): FutureInterface; + public function forceFlush(?CancellationInterface $cancellation = null): bool; + public function shutdown(?CancellationInterface $cancellation = null): bool; +} diff --git a/vendor/open-telemetry/sdk/Logs/LogRecordLimits.php b/vendor/open-telemetry/sdk/Logs/LogRecordLimits.php new file mode 100644 index 000000000..9f71e62ee --- /dev/null +++ b/vendor/open-telemetry/sdk/Logs/LogRecordLimits.php @@ -0,0 +1,29 @@ +<?php + +declare(strict_types=1); + +namespace OpenTelemetry\SDK\Logs; + +use OpenTelemetry\SDK\Common\Attribute\AttributesFactoryInterface; + +/** + * @see https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/logs/sdk.md#logrecord-limits + */ +class LogRecordLimits +{ + private AttributesFactoryInterface $attributesFactory; + + /** + * @internal Use {@see SpanLimitsBuilder} to create {@see SpanLimits} instance. + */ + public function __construct( + AttributesFactoryInterface $attributesFactory + ) { + $this->attributesFactory = $attributesFactory; + } + + public function getAttributeFactory(): AttributesFactoryInterface + { + return $this->attributesFactory; + } +} diff --git a/vendor/open-telemetry/sdk/Logs/LogRecordLimitsBuilder.php b/vendor/open-telemetry/sdk/Logs/LogRecordLimitsBuilder.php new file mode 100644 index 000000000..3aa5217ef --- /dev/null +++ b/vendor/open-telemetry/sdk/Logs/LogRecordLimitsBuilder.php @@ -0,0 +1,58 @@ +<?php + +declare(strict_types=1); + +namespace OpenTelemetry\SDK\Logs; + +use OpenTelemetry\SDK\Common\Attribute\Attributes; +use OpenTelemetry\SDK\Common\Configuration\Configuration; +use OpenTelemetry\SDK\Common\Configuration\Variables; +use const PHP_INT_MAX; + +class LogRecordLimitsBuilder +{ + /** @var ?int Maximum allowed attribute count per record */ + private ?int $attributeCountLimit = null; + + /** @var ?int Maximum allowed attribute value length */ + private ?int $attributeValueLengthLimit = null; + + /** + * @param int $attributeCountLimit Maximum allowed attribute count per record + */ + public function setAttributeCountLimit(int $attributeCountLimit): LogRecordLimitsBuilder + { + $this->attributeCountLimit = $attributeCountLimit; + + return $this; + } + + /** + * @param int $attributeValueLengthLimit Maximum allowed attribute value length + */ + public function setAttributeValueLengthLimit(int $attributeValueLengthLimit): LogRecordLimitsBuilder + { + $this->attributeValueLengthLimit = $attributeValueLengthLimit; + + return $this; + } + + /** + * @see https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/configuration/sdk-environment-variables.md#attribute-limits + */ + public function build(): LogRecordLimits + { + $attributeCountLimit = $this->attributeCountLimit + ?: Configuration::getInt(Variables::OTEL_LOGRECORD_ATTRIBUTE_COUNT_LIMIT); + $attributeValueLengthLimit = $this->attributeValueLengthLimit + ?: Configuration::getInt(Variables::OTEL_LOGRECORD_ATTRIBUTE_VALUE_LENGTH_LIMIT); + + if ($attributeValueLengthLimit === PHP_INT_MAX) { + $attributeValueLengthLimit = null; + } + + $attributesFactory = Attributes::factory($attributeCountLimit, $attributeValueLengthLimit); + + return new LogRecordLimits($attributesFactory); + } +} diff --git a/vendor/open-telemetry/sdk/Logs/LogRecordProcessorFactory.php b/vendor/open-telemetry/sdk/Logs/LogRecordProcessorFactory.php new file mode 100644 index 000000000..dec463735 --- /dev/null +++ b/vendor/open-telemetry/sdk/Logs/LogRecordProcessorFactory.php @@ -0,0 +1,62 @@ +<?php + +declare(strict_types=1); + +namespace OpenTelemetry\SDK\Logs; + +use InvalidArgumentException; +use OpenTelemetry\API\Metrics\MeterProviderInterface; +use OpenTelemetry\SDK\Common\Configuration\Configuration; +use OpenTelemetry\SDK\Common\Configuration\KnownValues; +use OpenTelemetry\SDK\Common\Configuration\KnownValues as Values; +use OpenTelemetry\SDK\Common\Configuration\Variables; +use OpenTelemetry\SDK\Common\Time\ClockFactory; +use OpenTelemetry\SDK\Logs\Processor\BatchLogRecordProcessor; +use OpenTelemetry\SDK\Logs\Processor\MultiLogRecordProcessor; +use OpenTelemetry\SDK\Logs\Processor\NoopLogRecordProcessor; +use OpenTelemetry\SDK\Logs\Processor\SimpleLogRecordProcessor; + +class LogRecordProcessorFactory +{ + public function create(LogRecordExporterInterface $exporter, ?MeterProviderInterface $meterProvider = null): LogRecordProcessorInterface + { + $processors = []; + $list = Configuration::getList(Variables::OTEL_PHP_LOGS_PROCESSOR); + foreach ($list as $name) { + $processors[] = $this->createProcessor($name, $exporter, $meterProvider); + } + + switch (count($processors)) { + case 0: + return NoopLogRecordProcessor::getInstance(); + case 1: + return $processors[0]; + default: + return new MultiLogRecordProcessor($processors); + } + } + + private function createProcessor(string $name, LogRecordExporterInterface $exporter, ?MeterProviderInterface $meterProvider = null): LogRecordProcessorInterface + { + switch ($name) { + case KnownValues::VALUE_BATCH: + return new BatchLogRecordProcessor( + $exporter, + ClockFactory::getDefault(), + Configuration::getInt(Variables::OTEL_BLRP_MAX_QUEUE_SIZE), + Configuration::getInt(Variables::OTEL_BLRP_SCHEDULE_DELAY), + Configuration::getInt(Variables::OTEL_BLRP_EXPORT_TIMEOUT), + Configuration::getInt(Variables::OTEL_BLRP_MAX_EXPORT_BATCH_SIZE), + true, + $meterProvider, + ); + case KnownValues::VALUE_SIMPLE: + return new SimpleLogRecordProcessor($exporter); + case Values::VALUE_NOOP: + case Values::VALUE_NONE: + return NoopLogRecordProcessor::getInstance(); + default: + throw new InvalidArgumentException('Unknown processor: ' . $name); + } + } +} diff --git a/vendor/open-telemetry/sdk/Logs/LogRecordProcessorInterface.php b/vendor/open-telemetry/sdk/Logs/LogRecordProcessorInterface.php new file mode 100644 index 000000000..1977d48fd --- /dev/null +++ b/vendor/open-telemetry/sdk/Logs/LogRecordProcessorInterface.php @@ -0,0 +1,15 @@ +<?php + +declare(strict_types=1); + +namespace OpenTelemetry\SDK\Logs; + +use OpenTelemetry\Context\ContextInterface; +use OpenTelemetry\SDK\Common\Future\CancellationInterface; + +interface LogRecordProcessorInterface +{ + public function onEmit(ReadWriteLogRecord $record, ?ContextInterface $context = null): void; + public function shutdown(?CancellationInterface $cancellation = null): bool; + public function forceFlush(?CancellationInterface $cancellation = null): bool; +} diff --git a/vendor/open-telemetry/sdk/Logs/Logger.php b/vendor/open-telemetry/sdk/Logs/Logger.php new file mode 100644 index 000000000..0b8db152d --- /dev/null +++ b/vendor/open-telemetry/sdk/Logs/Logger.php @@ -0,0 +1,37 @@ +<?php + +declare(strict_types=1); + +namespace OpenTelemetry\SDK\Logs; + +use OpenTelemetry\API\Logs\LoggerInterface; +use OpenTelemetry\API\Logs\LogRecord; +use OpenTelemetry\SDK\Common\Instrumentation\InstrumentationScopeInterface; + +/** + * Note that this logger class is deliberately NOT psr-3 compatible, per spec: "Note: this document defines a log + * backend API. The API is not intended to be called by application developers directly." + * + * @see https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/logs/bridge-api.md + */ +class Logger implements LoggerInterface +{ + private InstrumentationScopeInterface $scope; + private LoggerSharedState $loggerSharedState; + + public function __construct(LoggerSharedState $loggerSharedState, InstrumentationScopeInterface $scope) + { + $this->loggerSharedState = $loggerSharedState; + $this->scope = $scope; + } + + public function emit(LogRecord $logRecord): void + { + $readWriteLogRecord = new ReadWriteLogRecord($this->scope, $this->loggerSharedState, $logRecord); + // @see https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/logs/sdk.md#onemit + $this->loggerSharedState->getProcessor()->onEmit( + $readWriteLogRecord, + $readWriteLogRecord->getContext(), + ); + } +} diff --git a/vendor/open-telemetry/sdk/Logs/LoggerProvider.php b/vendor/open-telemetry/sdk/Logs/LoggerProvider.php new file mode 100644 index 000000000..f0a8266c1 --- /dev/null +++ b/vendor/open-telemetry/sdk/Logs/LoggerProvider.php @@ -0,0 +1,56 @@ +<?php + +declare(strict_types=1); + +namespace OpenTelemetry\SDK\Logs; + +use OpenTelemetry\API\Logs\LoggerInterface; +use OpenTelemetry\API\Logs\NoopLogger; +use OpenTelemetry\SDK\Common\Future\CancellationInterface; +use OpenTelemetry\SDK\Common\Instrumentation\InstrumentationScopeFactoryInterface; +use OpenTelemetry\SDK\Resource\ResourceInfo; +use OpenTelemetry\SDK\Resource\ResourceInfoFactory; + +class LoggerProvider implements LoggerProviderInterface +{ + private LoggerSharedState $loggerSharedState; + private InstrumentationScopeFactoryInterface $instrumentationScopeFactory; + + public function __construct(LogRecordProcessorInterface $processor, InstrumentationScopeFactoryInterface $instrumentationScopeFactory, ?ResourceInfo $resource = null) + { + $this->loggerSharedState = new LoggerSharedState( + $resource ?? ResourceInfoFactory::defaultResource(), + (new LogRecordLimitsBuilder())->build(), + $processor + ); + $this->instrumentationScopeFactory = $instrumentationScopeFactory; + } + + /** + * @see https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/logs/sdk.md#logger-creation + */ + public function getLogger(string $name, ?string $version = null, ?string $schemaUrl = null, iterable $attributes = []): LoggerInterface + { + if ($this->loggerSharedState->hasShutdown()) { + return NoopLogger::getInstance(); + } + $scope = $this->instrumentationScopeFactory->create($name, $version, $schemaUrl, $attributes); + + return new Logger($this->loggerSharedState, $scope); + } + + public function shutdown(CancellationInterface $cancellation = null): bool + { + return $this->loggerSharedState->shutdown($cancellation); + } + + public function forceFlush(CancellationInterface $cancellation = null): bool + { + return $this->loggerSharedState->forceFlush($cancellation); + } + + public static function builder(): LoggerProviderBuilder + { + return new LoggerProviderBuilder(); + } +} diff --git a/vendor/open-telemetry/sdk/Logs/LoggerProviderBuilder.php b/vendor/open-telemetry/sdk/Logs/LoggerProviderBuilder.php new file mode 100644 index 000000000..37c56245c --- /dev/null +++ b/vendor/open-telemetry/sdk/Logs/LoggerProviderBuilder.php @@ -0,0 +1,55 @@ +<?php + +declare(strict_types=1); + +namespace OpenTelemetry\SDK\Logs; + +use OpenTelemetry\SDK\Common\Attribute\Attributes; +use OpenTelemetry\SDK\Common\Instrumentation\InstrumentationScopeFactory; +use OpenTelemetry\SDK\Logs\Processor\MultiLogRecordProcessor; +use OpenTelemetry\SDK\Logs\Processor\NoopLogRecordProcessor; +use OpenTelemetry\SDK\Resource\ResourceInfo; + +class LoggerProviderBuilder +{ + /** + * @var array<LogRecordProcessorInterface> + */ + private array $processors = []; + private ?ResourceInfo $resource = null; + + public function addLogRecordProcessor(LogRecordProcessorInterface $processor): self + { + $this->processors[] = $processor; + + return $this; + } + + public function setResource(ResourceInfo $resource): self + { + $this->resource = $resource; + + return $this; + } + + public function build(): LoggerProviderInterface + { + return new LoggerProvider( + $this->buildProcessor(), + new InstrumentationScopeFactory(Attributes::factory()), + $this->resource + ); + } + + private function buildProcessor(): LogRecordProcessorInterface + { + switch (count($this->processors)) { + case 0: + return NoopLogRecordProcessor::getInstance(); + case 1: + return $this->processors[0]; + default: + return new MultiLogRecordProcessor($this->processors); + } + } +} diff --git a/vendor/open-telemetry/sdk/Logs/LoggerProviderFactory.php b/vendor/open-telemetry/sdk/Logs/LoggerProviderFactory.php new file mode 100644 index 000000000..3d0e965fd --- /dev/null +++ b/vendor/open-telemetry/sdk/Logs/LoggerProviderFactory.php @@ -0,0 +1,24 @@ +<?php + +declare(strict_types=1); + +namespace OpenTelemetry\SDK\Logs; + +use OpenTelemetry\SDK\Common\Instrumentation\InstrumentationScopeFactory; +use OpenTelemetry\SDK\Metrics\MeterProviderInterface; +use OpenTelemetry\SDK\Sdk; + +class LoggerProviderFactory +{ + public function create(?MeterProviderInterface $meterProvider = null): LoggerProviderInterface + { + if (Sdk::isDisabled()) { + return NoopLoggerProvider::getInstance(); + } + $exporter = (new ExporterFactory())->create(); + $processor = (new LogRecordProcessorFactory())->create($exporter, $meterProvider); + $instrumentationScopeFactory = new InstrumentationScopeFactory((new LogRecordLimitsBuilder())->build()->getAttributeFactory()); + + return new LoggerProvider($processor, $instrumentationScopeFactory); + } +} diff --git a/vendor/open-telemetry/sdk/Logs/LoggerProviderInterface.php b/vendor/open-telemetry/sdk/Logs/LoggerProviderInterface.php new file mode 100644 index 000000000..5debb13cc --- /dev/null +++ b/vendor/open-telemetry/sdk/Logs/LoggerProviderInterface.php @@ -0,0 +1,13 @@ +<?php + +declare(strict_types=1); + +namespace OpenTelemetry\SDK\Logs; + +use OpenTelemetry\API\Logs as API; + +interface LoggerProviderInterface extends API\LoggerProviderInterface +{ + public function shutdown(): bool; + public function forceFlush(): bool; +} diff --git a/vendor/open-telemetry/sdk/Logs/LoggerSharedState.php b/vendor/open-telemetry/sdk/Logs/LoggerSharedState.php new file mode 100644 index 000000000..aeeb45518 --- /dev/null +++ b/vendor/open-telemetry/sdk/Logs/LoggerSharedState.php @@ -0,0 +1,60 @@ +<?php + +declare(strict_types=1); + +namespace OpenTelemetry\SDK\Logs; + +use OpenTelemetry\SDK\Common\Future\CancellationInterface; +use OpenTelemetry\SDK\Resource\ResourceInfo; + +class LoggerSharedState +{ + private ResourceInfo $resource; + private LogRecordProcessorInterface $processor; + private LogRecordLimits $limits; + private ?bool $shutdownResult = null; + + public function __construct( + ResourceInfo $resource, + LogRecordLimits $limits, + LogRecordProcessorInterface $processor + ) { + $this->resource = $resource; + $this->limits = $limits; + $this->processor = $processor; + } + public function hasShutdown(): bool + { + return null !== $this->shutdownResult; + } + + public function getResource(): ResourceInfo + { + return $this->resource; + } + + public function getProcessor(): LogRecordProcessorInterface + { + return $this->processor; + } + + public function getLogRecordLimits(): LogRecordLimits + { + return $this->limits; + } + + public function shutdown(?CancellationInterface $cancellation = null): bool + { + if ($this->shutdownResult !== null) { + return $this->shutdownResult; + } + $this->shutdownResult = $this->processor->shutdown($cancellation); + + return $this->shutdownResult; + } + + public function forceFlush(?CancellationInterface $cancellation = null): bool + { + return $this->processor->forceFlush($cancellation); + } +} diff --git a/vendor/open-telemetry/sdk/Logs/NoopLoggerProvider.php b/vendor/open-telemetry/sdk/Logs/NoopLoggerProvider.php new file mode 100644 index 000000000..819e02ee5 --- /dev/null +++ b/vendor/open-telemetry/sdk/Logs/NoopLoggerProvider.php @@ -0,0 +1,33 @@ +<?php + +declare(strict_types=1); + +namespace OpenTelemetry\SDK\Logs; + +use OpenTelemetry\API\Logs\LoggerInterface; +use OpenTelemetry\API\Logs\NoopLogger; + +class NoopLoggerProvider implements LoggerProviderInterface +{ + public static function getInstance(): self + { + static $instance; + + return $instance ??= new self(); + } + + public function getLogger(string $name, ?string $version = null, ?string $schemaUrl = null, iterable $attributes = []): LoggerInterface + { + return NoopLogger::getInstance(); + } + + public function shutdown(): bool + { + return true; + } + + public function forceFlush(): bool + { + return true; + } +} diff --git a/vendor/open-telemetry/sdk/Logs/Processor/BatchLogRecordProcessor.php b/vendor/open-telemetry/sdk/Logs/Processor/BatchLogRecordProcessor.php new file mode 100644 index 000000000..fc6faca54 --- /dev/null +++ b/vendor/open-telemetry/sdk/Logs/Processor/BatchLogRecordProcessor.php @@ -0,0 +1,273 @@ +<?php + +declare(strict_types=1); + +namespace OpenTelemetry\SDK\Logs\Processor; + +use InvalidArgumentException; +use OpenTelemetry\API\Behavior\LogsMessagesTrait; +use OpenTelemetry\API\Metrics\MeterProviderInterface; +use OpenTelemetry\API\Metrics\ObserverInterface; +use OpenTelemetry\Context\Context; +use OpenTelemetry\Context\ContextInterface; +use OpenTelemetry\SDK\Common\Future\CancellationInterface; +use OpenTelemetry\SDK\Common\Time\ClockInterface; +use OpenTelemetry\SDK\Logs\LogRecordExporterInterface; +use OpenTelemetry\SDK\Logs\LogRecordProcessorInterface; +use OpenTelemetry\SDK\Logs\ReadWriteLogRecord; +use SplQueue; +use Throwable; + +class BatchLogRecordProcessor implements LogRecordProcessorInterface +{ + use LogsMessagesTrait; + + public const DEFAULT_SCHEDULE_DELAY = 1000; + public const DEFAULT_EXPORT_TIMEOUT = 30000; + public const DEFAULT_MAX_QUEUE_SIZE = 2048; + public const DEFAULT_MAX_EXPORT_BATCH_SIZE = 512; + + private const ATTRIBUTES_PROCESSOR = ['processor' => 'batching']; + private const ATTRIBUTES_QUEUED = self::ATTRIBUTES_PROCESSOR + ['state' => 'queued']; + private const ATTRIBUTES_PENDING = self::ATTRIBUTES_PROCESSOR + ['state' => 'pending']; + private const ATTRIBUTES_PROCESSED = self::ATTRIBUTES_PROCESSOR + ['state' => 'processed']; + private const ATTRIBUTES_DROPPED = self::ATTRIBUTES_PROCESSOR + ['state' => 'dropped']; + private const ATTRIBUTES_FREE = self::ATTRIBUTES_PROCESSOR + ['state' => 'free']; + + private LogRecordExporterInterface $exporter; + private ClockInterface $clock; + private int $maxQueueSize; + private int $scheduledDelayNanos; + private int $maxExportBatchSize; + private bool $autoFlush; + private ContextInterface $exportContext; + + private ?int $nextScheduledRun = null; + private bool $running = false; + private int $dropped = 0; + private int $processed = 0; + private int $batchId = 0; + private int $queueSize = 0; + /** @var list<ReadWriteLogRecord> */ + private array $batch = []; + /** @var SplQueue<list<ReadWriteLogRecord>> */ + private SplQueue $queue; + /** @var SplQueue<array{int, string, ?CancellationInterface, bool, ContextInterface}> */ + private SplQueue $flush; + + private bool $closed = false; + + public function __construct( + LogRecordExporterInterface $exporter, + ClockInterface $clock, + int $maxQueueSize = self::DEFAULT_MAX_QUEUE_SIZE, + int $scheduledDelayMillis = self::DEFAULT_SCHEDULE_DELAY, + int $exportTimeoutMillis = self::DEFAULT_EXPORT_TIMEOUT, + int $maxExportBatchSize = self::DEFAULT_MAX_EXPORT_BATCH_SIZE, + bool $autoFlush = true, + ?MeterProviderInterface $meterProvider = null + ) { + if ($maxQueueSize <= 0) { + throw new InvalidArgumentException(sprintf('Maximum queue size (%d) must be greater than zero', $maxQueueSize)); + } + if ($scheduledDelayMillis <= 0) { + throw new InvalidArgumentException(sprintf('Scheduled delay (%d) must be greater than zero', $scheduledDelayMillis)); + } + if ($exportTimeoutMillis <= 0) { + throw new InvalidArgumentException(sprintf('Export timeout (%d) must be greater than zero', $exportTimeoutMillis)); + } + if ($maxExportBatchSize <= 0) { + throw new InvalidArgumentException(sprintf('Maximum export batch size (%d) must be greater than zero', $maxExportBatchSize)); + } + if ($maxExportBatchSize > $maxQueueSize) { + throw new InvalidArgumentException(sprintf('Maximum export batch size (%d) must be less than or equal to maximum queue size (%d)', $maxExportBatchSize, $maxQueueSize)); + } + + $this->exporter = $exporter; + $this->clock = $clock; + $this->maxQueueSize = $maxQueueSize; + $this->scheduledDelayNanos = $scheduledDelayMillis * 1_000_000; + $this->maxExportBatchSize = $maxExportBatchSize; + $this->autoFlush = $autoFlush; + + $this->exportContext = Context::getCurrent(); + $this->queue = new SplQueue(); + $this->flush = new SplQueue(); + + if ($meterProvider === null) { + return; + } + + $meter = $meterProvider->getMeter('io.opentelemetry.sdk'); + $meter + ->createObservableUpDownCounter( + 'otel.logs.log_processor.logs', + '{logs}', + 'The number of log records received by the processor', + ) + ->observe(function (ObserverInterface $observer): void { + $queued = $this->queue->count() * $this->maxExportBatchSize + count($this->batch); + $pending = $this->queueSize - $queued; + $processed = $this->processed; + $dropped = $this->dropped; + + $observer->observe($queued, self::ATTRIBUTES_QUEUED); + $observer->observe($pending, self::ATTRIBUTES_PENDING); + $observer->observe($processed, self::ATTRIBUTES_PROCESSED); + $observer->observe($dropped, self::ATTRIBUTES_DROPPED); + }); + $meter + ->createObservableUpDownCounter( + 'otel.logs.log_processor.queue.limit', + '{logs}', + 'The queue size limit', + ) + ->observe(function (ObserverInterface $observer): void { + $observer->observe($this->maxQueueSize, self::ATTRIBUTES_PROCESSOR); + }); + $meter + ->createObservableUpDownCounter( + 'otel.logs.log_processor.queue.usage', + '{logs}', + 'The current queue usage', + ) + ->observe(function (ObserverInterface $observer): void { + $queued = $this->queue->count() * $this->maxExportBatchSize + count($this->batch); + $pending = $this->queueSize - $queued; + $free = $this->maxQueueSize - $this->queueSize; + + $observer->observe($queued, self::ATTRIBUTES_QUEUED); + $observer->observe($pending, self::ATTRIBUTES_PENDING); + $observer->observe($free, self::ATTRIBUTES_FREE); + }); + } + + public function onEmit(ReadWriteLogRecord $record, ?ContextInterface $context = null): void + { + if ($this->closed) { + return; + } + + if ($this->queueSize === $this->maxQueueSize) { + $this->dropped++; + + return; + } + + $this->queueSize++; + $this->batch[] = $record; + $this->nextScheduledRun ??= $this->clock->now() + $this->scheduledDelayNanos; + + if (count($this->batch) === $this->maxExportBatchSize) { + $this->enqueueBatch(); + } + if ($this->autoFlush) { + $this->flush(); + } + } + + public function forceFlush(?CancellationInterface $cancellation = null): bool + { + if ($this->closed) { + return false; + } + + return $this->flush(__FUNCTION__, $cancellation); + } + + public function shutdown(?CancellationInterface $cancellation = null): bool + { + if ($this->closed) { + return false; + } + + $this->closed = true; + + return $this->flush(__FUNCTION__, $cancellation); + } + + private function flush(?string $flushMethod = null, ?CancellationInterface $cancellation = null): bool + { + if ($flushMethod !== null) { + $flushId = $this->batchId + $this->queue->count() + (int) (bool) $this->batch; + $this->flush->enqueue([$flushId, $flushMethod, $cancellation, !$this->running, Context::getCurrent()]); + } + + if ($this->running) { + return false; + } + + $success = true; + $exception = null; + $this->running = true; + + try { + for (;;) { + while (!$this->flush->isEmpty() && $this->flush->bottom()[0] <= $this->batchId) { + [, $flushMethod, $cancellation, $propagateResult, $context] = $this->flush->dequeue(); + $scope = $context->activate(); + + try { + $result = $this->exporter->$flushMethod($cancellation); + if ($propagateResult) { + $success = $result; + } + } catch (Throwable $e) { + if ($propagateResult) { + $exception = $e; + } else { + self::logError(sprintf('Unhandled %s error', $flushMethod), ['exception' => $e]); + } + } finally { + $scope->detach(); + } + } + + if (!$this->shouldFlush()) { + break; + } + + if ($this->queue->isEmpty()) { + $this->enqueueBatch(); + } + $batchSize = count($this->queue->bottom()); + $this->batchId++; + $scope = $this->exportContext->activate(); + + try { + $this->exporter->export($this->queue->dequeue())->await(); + } catch (Throwable $e) { + self::logError('Unhandled export error', ['exception' => $e]); + } finally { + $this->processed += $batchSize; + $this->queueSize -= $batchSize; + $scope->detach(); + } + } + } finally { + $this->running = false; + } + + if ($exception !== null) { + throw $exception; + } + + return $success; + } + + private function shouldFlush(): bool + { + return !$this->flush->isEmpty() + || $this->autoFlush && !$this->queue->isEmpty() + || $this->autoFlush && $this->nextScheduledRun !== null && $this->clock->now() > $this->nextScheduledRun; + } + + private function enqueueBatch(): void + { + assert($this->batch !== []); + + $this->queue->enqueue($this->batch); + $this->batch = []; + $this->nextScheduledRun = null; + } +} diff --git a/vendor/open-telemetry/sdk/Logs/Processor/MultiLogRecordProcessor.php b/vendor/open-telemetry/sdk/Logs/Processor/MultiLogRecordProcessor.php new file mode 100644 index 000000000..753a75df8 --- /dev/null +++ b/vendor/open-telemetry/sdk/Logs/Processor/MultiLogRecordProcessor.php @@ -0,0 +1,62 @@ +<?php + +declare(strict_types=1); + +namespace OpenTelemetry\SDK\Logs\Processor; + +use OpenTelemetry\Context\ContextInterface; +use OpenTelemetry\SDK\Common\Future\CancellationInterface; +use OpenTelemetry\SDK\Logs\LogRecordProcessorInterface; +use OpenTelemetry\SDK\Logs\ReadWriteLogRecord; + +class MultiLogRecordProcessor implements LogRecordProcessorInterface +{ + // @var LogRecordProcessorInterface[] + private array $processors = []; + + public function __construct(array $processors) + { + foreach ($processors as $processor) { + assert($processor instanceof LogRecordProcessorInterface); + $this->processors[] = $processor; + } + } + + public function onEmit(ReadWriteLogRecord $record, ?ContextInterface $context = null): void + { + foreach ($this->processors as $processor) { + $processor->onEmit($record, $context); + } + } + + /** + * Returns `true` if all processors shut down successfully, else `false` + * Subsequent calls to `shutdown` are a no-op. + */ + public function shutdown(?CancellationInterface $cancellation = null): bool + { + $result = true; + foreach ($this->processors as $processor) { + if (!$processor->shutdown($cancellation)) { + $result = false; + } + } + + return $result; + } + + /** + * Returns `true` if all processors flush successfully, else `false`. + */ + public function forceFlush(?CancellationInterface $cancellation = null): bool + { + $result = true; + foreach ($this->processors as $processor) { + if (!$processor->forceFlush($cancellation)) { + $result = false; + } + } + + return $result; + } +} diff --git a/vendor/open-telemetry/sdk/Logs/Processor/NoopLogRecordProcessor.php b/vendor/open-telemetry/sdk/Logs/Processor/NoopLogRecordProcessor.php new file mode 100644 index 000000000..7028052e1 --- /dev/null +++ b/vendor/open-telemetry/sdk/Logs/Processor/NoopLogRecordProcessor.php @@ -0,0 +1,37 @@ +<?php + +declare(strict_types=1); + +namespace OpenTelemetry\SDK\Logs\Processor; + +use OpenTelemetry\Context\ContextInterface; +use OpenTelemetry\SDK\Common\Future\CancellationInterface; +use OpenTelemetry\SDK\Logs\LogRecordProcessorInterface; +use OpenTelemetry\SDK\Logs\ReadWriteLogRecord; + +class NoopLogRecordProcessor implements LogRecordProcessorInterface +{ + public static function getInstance(): self + { + static $instance; + + return $instance ??= new self(); + } + + /** + * @codeCoverageIgnore + */ + public function onEmit(ReadWriteLogRecord $record, ?ContextInterface $context = null): void + { + } + + public function shutdown(?CancellationInterface $cancellation = null): bool + { + return true; + } + + public function forceFlush(?CancellationInterface $cancellation = null): bool + { + return true; + } +} diff --git a/vendor/open-telemetry/sdk/Logs/Processor/SimpleLogRecordProcessor.php b/vendor/open-telemetry/sdk/Logs/Processor/SimpleLogRecordProcessor.php new file mode 100644 index 000000000..f26f6607c --- /dev/null +++ b/vendor/open-telemetry/sdk/Logs/Processor/SimpleLogRecordProcessor.php @@ -0,0 +1,38 @@ +<?php + +declare(strict_types=1); + +namespace OpenTelemetry\SDK\Logs\Processor; + +use OpenTelemetry\Context\ContextInterface; +use OpenTelemetry\SDK\Common\Future\CancellationInterface; +use OpenTelemetry\SDK\Logs\LogRecordExporterInterface; +use OpenTelemetry\SDK\Logs\LogRecordProcessorInterface; +use OpenTelemetry\SDK\Logs\ReadWriteLogRecord; + +class SimpleLogRecordProcessor implements LogRecordProcessorInterface +{ + private LogRecordExporterInterface $exporter; + public function __construct(LogRecordExporterInterface $exporter) + { + $this->exporter = $exporter; + } + + /** + * @see https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/logs/sdk.md#onemit + */ + public function onEmit(ReadWriteLogRecord $record, ?ContextInterface $context = null): void + { + $this->exporter->export([$record]); + } + + public function shutdown(?CancellationInterface $cancellation = null): bool + { + return $this->exporter->shutdown($cancellation); + } + + public function forceFlush(?CancellationInterface $cancellation = null): bool + { + return $this->exporter->forceFlush($cancellation); + } +} diff --git a/vendor/open-telemetry/sdk/Logs/PsrSeverityMapperInterface.php b/vendor/open-telemetry/sdk/Logs/PsrSeverityMapperInterface.php new file mode 100644 index 000000000..3bb288c56 --- /dev/null +++ b/vendor/open-telemetry/sdk/Logs/PsrSeverityMapperInterface.php @@ -0,0 +1,50 @@ +<?php + +declare(strict_types=1); + +namespace OpenTelemetry\SDK\Logs; + +use Psr\Log\LogLevel as PsrLogLevel; + +interface PsrSeverityMapperInterface +{ + /** + * Severity code according to rfc5424 (Syslog Protocol) + * @see : https://datatracker.ietf.org/doc/html/rfc5424#page-10 + */ + public const RFC_CODE = [ + // Detailed debug information. + PsrLogLevel::DEBUG => 7, + // Interesting events. Examples: User logs in, SQL logs. + PsrLogLevel::INFO => 6, + // Normal but significant events. + PsrLogLevel::NOTICE => 5, + // Exceptional occurrences that are not errors. Examples: Use of deprecated APIs, poor use of an API, + // undesirable things that are not necessarily wrong. + PsrLogLevel::WARNING => 4, + // Runtime errors that do not require immediate action but should typically be logged and monitored. + PsrLogLevel::ERROR => 3, + // Critical conditions. Example: Application component unavailable, unexpected exception. + PsrLogLevel::CRITICAL => 2, + // Action must be taken immediately. Example: Entire website down, database unavailable, etc. + // This should trigger the alerts and wake you up. + PsrLogLevel::ALERT => 1, + // Emergency: system is unusable. + PsrLogLevel::EMERGENCY => 0, + ]; + + /** + * Mappig of OpenTelemetry SeverityNumber to PsrLogLevel. + * @see: https://github.com/open-telemetry/opentelemetry-specification/blob/v1.7.0/specification/logs/data-model.md#field-severitynumber + */ + public const SEVERITY_NUMBER = [ + PsrLogLevel::DEBUG => 5, + PsrLogLevel::INFO => 9, + PsrLogLevel::NOTICE => 10, + PsrLogLevel::WARNING => 13, + PsrLogLevel::ERROR => 17, + PsrLogLevel::CRITICAL => 18, + PsrLogLevel::ALERT => 21, + PsrLogLevel::EMERGENCY => 22, + ]; +} diff --git a/vendor/open-telemetry/sdk/Logs/ReadWriteLogRecord.php b/vendor/open-telemetry/sdk/Logs/ReadWriteLogRecord.php new file mode 100644 index 000000000..9bb4b1564 --- /dev/null +++ b/vendor/open-telemetry/sdk/Logs/ReadWriteLogRecord.php @@ -0,0 +1,9 @@ +<?php + +declare(strict_types=1); + +namespace OpenTelemetry\SDK\Logs; + +class ReadWriteLogRecord extends ReadableLogRecord +{ +} diff --git a/vendor/open-telemetry/sdk/Logs/ReadableLogRecord.php b/vendor/open-telemetry/sdk/Logs/ReadableLogRecord.php new file mode 100644 index 000000000..5c6531477 --- /dev/null +++ b/vendor/open-telemetry/sdk/Logs/ReadableLogRecord.php @@ -0,0 +1,103 @@ +<?php + +declare(strict_types=1); + +namespace OpenTelemetry\SDK\Logs; + +use OpenTelemetry\API\Logs\LogRecord; +use OpenTelemetry\API\Trace\Span; +use OpenTelemetry\API\Trace\SpanContextInterface; +use OpenTelemetry\Context\Context; +use OpenTelemetry\Context\ContextInterface; +use OpenTelemetry\SDK\Common\Attribute\AttributesInterface; +use OpenTelemetry\SDK\Common\Attribute\LogRecordAttributeValidator; +use OpenTelemetry\SDK\Common\Instrumentation\InstrumentationScopeInterface; +use OpenTelemetry\SDK\Resource\ResourceInfo; + +/** + * @see https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/logs/data-model.md#log-and-event-record-definition + * "Note: Typically this will be implemented with a new interface or (immutable) value type." + */ +class ReadableLogRecord extends LogRecord +{ + private InstrumentationScopeInterface $scope; + private LoggerSharedState $loggerSharedState; + protected AttributesInterface $convertedAttributes; + protected SpanContextInterface $spanContext; + + public function __construct(InstrumentationScopeInterface $scope, LoggerSharedState $loggerSharedState, LogRecord $logRecord) + { + $this->scope = $scope; + $this->loggerSharedState = $loggerSharedState; + + parent::__construct($logRecord->body); + $this->timestamp = $logRecord->timestamp; + $this->observedTimestamp = $logRecord->observedTimestamp + ?? (int) (microtime(true) * LogRecord::NANOS_PER_SECOND); + $this->context = $logRecord->context; + $context = $this->context ?? Context::getCurrent(); + $this->spanContext = Span::fromContext($context)->getContext(); + $this->severityNumber = $logRecord->severityNumber; + $this->severityText = $logRecord->severityText; + + //convert attributes now so that excess data is not sent to processors + $this->convertedAttributes = $this->loggerSharedState + ->getLogRecordLimits() + ->getAttributeFactory() + ->builder($logRecord->attributes, new LogRecordAttributeValidator()) + ->build(); + } + + public function getInstrumentationScope(): InstrumentationScopeInterface + { + return $this->scope; + } + + public function getResource(): ResourceInfo + { + return $this->loggerSharedState->getResource(); + } + + public function getTimestamp(): ?int + { + return $this->timestamp; + } + + public function getObservedTimestamp(): ?int + { + return $this->observedTimestamp; + } + + public function getContext(): ?ContextInterface + { + return $this->context; + } + + public function getSpanContext(): ?SpanContextInterface + { + return $this->spanContext; + } + + public function getSeverityNumber(): ?int + { + return $this->severityNumber; + } + + public function getSeverityText(): ?string + { + return $this->severityText; + } + + /** + * @return mixed|null + */ + public function getBody() + { + return $this->body; + } + + public function getAttributes(): AttributesInterface + { + return $this->convertedAttributes; + } +} diff --git a/vendor/open-telemetry/sdk/Logs/SimplePsrFileLogger.php b/vendor/open-telemetry/sdk/Logs/SimplePsrFileLogger.php new file mode 100644 index 000000000..9d9d55de6 --- /dev/null +++ b/vendor/open-telemetry/sdk/Logs/SimplePsrFileLogger.php @@ -0,0 +1,83 @@ +<?php + +declare(strict_types=1); + +namespace OpenTelemetry\SDK\Logs; + +use Psr\Log\InvalidArgumentException; +use Psr\Log\LoggerInterface; +use Psr\Log\LoggerTrait; +use Psr\Log\LogLevel; +use ReflectionClass; +use Throwable; + +class SimplePsrFileLogger implements LoggerInterface +{ + use LoggerTrait; + + private const DEFAULT_LOGGER_NAME = 'otel'; + + private static ?array $logLevels = null; + + private string $filename; + + private string $loggerName ; + + /** + * @param string $filename + */ + public function __construct(string $filename, string $loggerName = self::DEFAULT_LOGGER_NAME) + { + $this->filename = $filename; + $this->loggerName = $loggerName; + } + + /** + * @psalm-suppress MoreSpecificImplementedParamType + */ + public function log($level, $message, array $context = []): void + { + $level = strtolower($level); + + if (!in_array($level, self::getLogLevels(), true)) { + throw new InvalidArgumentException( + sprintf('Invalid Log level: "%s"', $level) + ); + } + + file_put_contents($this->filename, $this->formatLog((string) $level, (string) $message, $context), FILE_APPEND); + } + + /** + * @param string $level + * @param string $message + * @param array $context + * @return string + */ + private function formatLog(string $level, string $message, array $context = []): string + { + try { + $encodedContext = json_encode($context, JSON_THROW_ON_ERROR); + } catch (Throwable $t) { + $encodedContext = sprintf('(Could not encode context: %s)', $t->getMessage()); + } + + return sprintf( + '[%s] %s %s: %s %s%s', + date(DATE_RFC3339_EXTENDED), + $this->loggerName, + $level, + $message, + $encodedContext, + PHP_EOL + ); + } + + /** + * @return array + */ + private static function getLogLevels(): array + { + return self::$logLevels ?? self::$logLevels = (new ReflectionClass(LogLevel::class))->getConstants(); + } +} |