diff options
Diffstat (limited to 'vendor/open-telemetry/sdk/Trace/Span.php')
-rw-r--r-- | vendor/open-telemetry/sdk/Trace/Span.php | 359 |
1 files changed, 359 insertions, 0 deletions
diff --git a/vendor/open-telemetry/sdk/Trace/Span.php b/vendor/open-telemetry/sdk/Trace/Span.php new file mode 100644 index 000000000..f72ec1bd7 --- /dev/null +++ b/vendor/open-telemetry/sdk/Trace/Span.php @@ -0,0 +1,359 @@ +<?php + +declare(strict_types=1); + +namespace OpenTelemetry\SDK\Trace; + +use function get_class; +use OpenTelemetry\API\Trace as API; +use OpenTelemetry\Context\ContextInterface; +use OpenTelemetry\SDK\Common\Attribute\AttributesBuilderInterface; +use OpenTelemetry\SDK\Common\Dev\Compatibility\Util as BcUtil; +use OpenTelemetry\SDK\Common\Exception\StackTraceFormatter; +use OpenTelemetry\SDK\Common\Instrumentation\InstrumentationScopeInterface; +use OpenTelemetry\SDK\Common\Time\ClockFactory; +use OpenTelemetry\SDK\Resource\ResourceInfo; +use Throwable; + +final class Span extends API\Span implements ReadWriteSpanInterface +{ + + /** @readonly */ + private API\SpanContextInterface $context; + + /** @readonly */ + private API\SpanContextInterface $parentSpanContext; + + /** @readonly */ + private SpanLimits $spanLimits; + + /** @readonly */ + private SpanProcessorInterface $spanProcessor; + + /** + * @readonly + * + * @var list<LinkInterface> + */ + private array $links; + + /** @readonly */ + private int $totalRecordedLinks; + + /** @readonly */ + private int $kind; + + /** @readonly */ + private ResourceInfo $resource; + + /** @readonly */ + private InstrumentationScopeInterface $instrumentationScope; + + /** @readonly */ + private int $startEpochNanos; + + /** @var non-empty-string */ + private string $name; + + /** @var list<EventInterface> */ + private array $events = []; + + private AttributesBuilderInterface $attributesBuilder; + private int $totalRecordedEvents = 0; + private StatusDataInterface $status; + private int $endEpochNanos = 0; + private bool $hasEnded = false; + + /** + * @param non-empty-string $name + * @param list<LinkInterface> $links + */ + private function __construct( + string $name, + API\SpanContextInterface $context, + InstrumentationScopeInterface $instrumentationScope, + int $kind, + API\SpanContextInterface $parentSpanContext, + SpanLimits $spanLimits, + SpanProcessorInterface $spanProcessor, + ResourceInfo $resource, + AttributesBuilderInterface $attributesBuilder, + array $links, + int $totalRecordedLinks, + int $startEpochNanos + ) { + $this->context = $context; + $this->instrumentationScope = $instrumentationScope; + $this->parentSpanContext = $parentSpanContext; + $this->links = $links; + $this->totalRecordedLinks = $totalRecordedLinks; + $this->name = $name; + $this->kind = $kind; + $this->spanProcessor = $spanProcessor; + $this->resource = $resource; + $this->startEpochNanos = $startEpochNanos; + $this->attributesBuilder = $attributesBuilder; + $this->status = StatusData::unset(); + $this->spanLimits = $spanLimits; + } + + /** + * This method _MUST_ not be used directly. + * End users should use a {@see API\TracerInterface} in order to create spans. + * + * @param non-empty-string $name + * @psalm-param API\SpanKind::KIND_* $kind + * @param list<LinkInterface> $links + * + * @internal + * @psalm-internal OpenTelemetry + */ + public static function startSpan( + string $name, + API\SpanContextInterface $context, + InstrumentationScopeInterface $instrumentationScope, + int $kind, + API\SpanInterface $parentSpan, + ContextInterface $parentContext, + SpanLimits $spanLimits, + SpanProcessorInterface $spanProcessor, + ResourceInfo $resource, + AttributesBuilderInterface $attributesBuilder, + array $links, + int $totalRecordedLinks, + int $startEpochNanos + ): self { + $span = new self( + $name, + $context, + $instrumentationScope, + $kind, + $parentSpan->getContext(), + $spanLimits, + $spanProcessor, + $resource, + $attributesBuilder, + $links, + $totalRecordedLinks, + $startEpochNanos !== 0 ? $startEpochNanos : ClockFactory::getDefault()->now() + ); + + // Call onStart here to ensure the span is fully initialized. + $spanProcessor->onStart($span, $parentContext); + + return $span; + } + + /** + * Backward compatibility methods + * + * @codeCoverageIgnore + */ + public static function formatStackTrace(Throwable $e, array &$seen = null): string + { + BcUtil::triggerMethodDeprecationNotice( + __METHOD__, + 'format', + StackTraceFormatter::class + ); + + return StackTraceFormatter::format($e); + } + + /** @inheritDoc */ + public function getContext(): API\SpanContextInterface + { + return $this->context; + } + + /** @inheritDoc */ + public function isRecording(): bool + { + return !$this->hasEnded; + } + + /** @inheritDoc */ + public function setAttribute(string $key, $value): self + { + if ($this->hasEnded) { + return $this; + } + + $this->attributesBuilder[$key] = $value; + + return $this; + } + + /** @inheritDoc */ + public function setAttributes(iterable $attributes): self + { + foreach ($attributes as $key => $value) { + $this->attributesBuilder[$key] = $value; + } + + return $this; + } + + /** @inheritDoc */ + public function addEvent(string $name, iterable $attributes = [], ?int $timestamp = null): self + { + if ($this->hasEnded) { + return $this; + } + if (++$this->totalRecordedEvents > $this->spanLimits->getEventCountLimit()) { + return $this; + } + + $timestamp ??= ClockFactory::getDefault()->now(); + $eventAttributesBuilder = $this->spanLimits->getEventAttributesFactory()->builder($attributes); + + $this->events[] = new Event($name, $timestamp, $eventAttributesBuilder->build()); + + return $this; + } + + /** @inheritDoc */ + public function recordException(Throwable $exception, iterable $attributes = [], ?int $timestamp = null): self + { + if ($this->hasEnded) { + return $this; + } + if (++$this->totalRecordedEvents > $this->spanLimits->getEventCountLimit()) { + return $this; + } + + $timestamp ??= ClockFactory::getDefault()->now(); + $eventAttributesBuilder = $this->spanLimits->getEventAttributesFactory()->builder([ + 'exception.type' => get_class($exception), + 'exception.message' => $exception->getMessage(), + 'exception.stacktrace' => StackTraceFormatter::format($exception), + ]); + + foreach ($attributes as $key => $value) { + $eventAttributesBuilder[$key] = $value; + } + + $this->events[] = new Event('exception', $timestamp, $eventAttributesBuilder->build()); + + return $this; + } + + /** @inheritDoc */ + public function updateName(string $name): self + { + if ($this->hasEnded) { + return $this; + } + $this->name = $name; + + return $this; + } + + /** @inheritDoc */ + public function setStatus(string $code, string $description = null): self + { + if ($this->hasEnded) { + return $this; + } + + // An attempt to set value Unset SHOULD be ignored. + if ($code === API\StatusCode::STATUS_UNSET) { + return $this; + } + + // When span status is set to Ok it SHOULD be considered final and any further attempts to change it SHOULD be ignored. + if ($this->status->getCode() === API\StatusCode::STATUS_OK) { + return $this; + } + $this->status = StatusData::create($code, $description); + + return $this; + } + + /** @inheritDoc */ + public function end(int $endEpochNanos = null): void + { + if ($this->hasEnded) { + return; + } + + $this->endEpochNanos = $endEpochNanos ?? ClockFactory::getDefault()->now(); + $this->hasEnded = true; + + $this->spanProcessor->onEnd($this); + } + + /** @inheritDoc */ + public function getName(): string + { + return $this->name; + } + + public function getParentContext(): API\SpanContextInterface + { + return $this->parentSpanContext; + } + + public function getInstrumentationScope(): InstrumentationScopeInterface + { + return $this->instrumentationScope; + } + + public function hasEnded(): bool + { + return $this->hasEnded; + } + + public function toSpanData(): SpanDataInterface + { + return new ImmutableSpan( + $this, + $this->name, + $this->links, + $this->events, + $this->attributesBuilder->build(), + $this->totalRecordedEvents, + $this->status, + $this->endEpochNanos, + $this->hasEnded + ); + } + + /** @inheritDoc */ + public function getDuration(): int + { + return ($this->hasEnded ? $this->endEpochNanos : ClockFactory::getDefault()->now()) - $this->startEpochNanos; + } + + /** @inheritDoc */ + public function getKind(): int + { + return $this->kind; + } + + /** @inheritDoc */ + public function getAttribute(string $key) + { + return $this->attributesBuilder[$key]; + } + + public function getStartEpochNanos(): int + { + return $this->startEpochNanos; + } + + public function getTotalRecordedLinks(): int + { + return $this->totalRecordedLinks; + } + + public function getTotalRecordedEvents(): int + { + return $this->totalRecordedEvents; + } + + public function getResource(): ResourceInfo + { + return $this->resource; + } +} |