vendor/open-telemetry/sdk/Trace/Span.php line 18

Open in your IDE?
  1. <?php
  2. declare(strict_types=1);
  3. namespace OpenTelemetry\SDK\Trace;
  4. use function get_class;
  5. use OpenTelemetry\API\Trace as API;
  6. use OpenTelemetry\Context\ContextInterface;
  7. use OpenTelemetry\SDK\Common\Attribute\AttributesBuilderInterface;
  8. use OpenTelemetry\SDK\Common\Dev\Compatibility\Util as BcUtil;
  9. use OpenTelemetry\SDK\Common\Exception\StackTraceFormatter;
  10. use OpenTelemetry\SDK\Common\Instrumentation\InstrumentationScopeInterface;
  11. use OpenTelemetry\SDK\Common\Time\ClockFactory;
  12. use OpenTelemetry\SDK\Resource\ResourceInfo;
  13. use Throwable;
  14. final class Span extends API\Span implements ReadWriteSpanInterface
  15. {
  16.     /** @readonly */
  17.     private API\SpanContextInterface $context;
  18.     /** @readonly */
  19.     private API\SpanContextInterface $parentSpanContext;
  20.     /** @readonly */
  21.     private SpanLimits $spanLimits;
  22.     /** @readonly */
  23.     private SpanProcessorInterface $spanProcessor;
  24.     /**
  25.      * @readonly
  26.      *
  27.      * @var list<LinkInterface>
  28.      */
  29.     private array $links;
  30.     /** @readonly */
  31.     private int $totalRecordedLinks;
  32.     /** @readonly */
  33.     private int $kind;
  34.     /** @readonly */
  35.     private ResourceInfo $resource;
  36.     /** @readonly */
  37.     private InstrumentationScopeInterface $instrumentationScope;
  38.     /** @readonly */
  39.     private int $startEpochNanos;
  40.     /** @var non-empty-string */
  41.     private string $name;
  42.     /** @var list<EventInterface> */
  43.     private array $events = [];
  44.     private AttributesBuilderInterface $attributesBuilder;
  45.     private int $totalRecordedEvents 0;
  46.     private StatusDataInterface $status;
  47.     private int $endEpochNanos 0;
  48.     private bool $hasEnded false;
  49.     /**
  50.      * @param non-empty-string $name
  51.      * @param list<LinkInterface> $links
  52.      */
  53.     private function __construct(
  54.         string $name,
  55.         API\SpanContextInterface $context,
  56.         InstrumentationScopeInterface $instrumentationScope,
  57.         int $kind,
  58.         API\SpanContextInterface $parentSpanContext,
  59.         SpanLimits $spanLimits,
  60.         SpanProcessorInterface $spanProcessor,
  61.         ResourceInfo $resource,
  62.         AttributesBuilderInterface $attributesBuilder,
  63.         array $links,
  64.         int $totalRecordedLinks,
  65.         int $startEpochNanos
  66.     ) {
  67.         $this->context $context;
  68.         $this->instrumentationScope $instrumentationScope;
  69.         $this->parentSpanContext $parentSpanContext;
  70.         $this->links $links;
  71.         $this->totalRecordedLinks $totalRecordedLinks;
  72.         $this->name $name;
  73.         $this->kind $kind;
  74.         $this->spanProcessor $spanProcessor;
  75.         $this->resource $resource;
  76.         $this->startEpochNanos $startEpochNanos;
  77.         $this->attributesBuilder $attributesBuilder;
  78.         $this->status StatusData::unset();
  79.         $this->spanLimits $spanLimits;
  80.     }
  81.     /**
  82.      * This method _MUST_ not be used directly.
  83.      * End users should use a {@see API\TracerInterface} in order to create spans.
  84.      *
  85.      * @param non-empty-string $name
  86.      * @psalm-param API\SpanKind::KIND_* $kind
  87.      * @param list<LinkInterface> $links
  88.      *
  89.      * @internal
  90.      * @psalm-internal OpenTelemetry
  91.      */
  92.     public static function startSpan(
  93.         string $name,
  94.         API\SpanContextInterface $context,
  95.         InstrumentationScopeInterface $instrumentationScope,
  96.         int $kind,
  97.         API\SpanInterface $parentSpan,
  98.         ContextInterface $parentContext,
  99.         SpanLimits $spanLimits,
  100.         SpanProcessorInterface $spanProcessor,
  101.         ResourceInfo $resource,
  102.         AttributesBuilderInterface $attributesBuilder,
  103.         array $links,
  104.         int $totalRecordedLinks,
  105.         int $startEpochNanos
  106.     ): self {
  107.         $span = new self(
  108.             $name,
  109.             $context,
  110.             $instrumentationScope,
  111.             $kind,
  112.             $parentSpan->getContext(),
  113.             $spanLimits,
  114.             $spanProcessor,
  115.             $resource,
  116.             $attributesBuilder,
  117.             $links,
  118.             $totalRecordedLinks,
  119.             $startEpochNanos !== $startEpochNanos ClockFactory::getDefault()->now()
  120.         );
  121.         // Call onStart here to ensure the span is fully initialized.
  122.         $spanProcessor->onStart($span$parentContext);
  123.         return $span;
  124.     }
  125.     /**
  126.      * Backward compatibility methods
  127.      *
  128.      * @codeCoverageIgnore
  129.      */
  130.     public static function formatStackTrace(Throwable $e, array &$seen null): string
  131.     {
  132.         BcUtil::triggerMethodDeprecationNotice(
  133.             __METHOD__,
  134.             'format',
  135.             StackTraceFormatter::class
  136.         );
  137.         return StackTraceFormatter::format($e);
  138.     }
  139.     /** @inheritDoc */
  140.     public function getContext(): API\SpanContextInterface
  141.     {
  142.         return $this->context;
  143.     }
  144.     /** @inheritDoc */
  145.     public function isRecording(): bool
  146.     {
  147.         return !$this->hasEnded;
  148.     }
  149.     /** @inheritDoc */
  150.     public function setAttribute(string $key$value): self
  151.     {
  152.         if ($this->hasEnded) {
  153.             return $this;
  154.         }
  155.         $this->attributesBuilder[$key] = $value;
  156.         return $this;
  157.     }
  158.     /** @inheritDoc */
  159.     public function setAttributes(iterable $attributes): self
  160.     {
  161.         foreach ($attributes as $key => $value) {
  162.             $this->attributesBuilder[$key] = $value;
  163.         }
  164.         return $this;
  165.     }
  166.     /** @inheritDoc */
  167.     public function addEvent(string $nameiterable $attributes = [], ?int $timestamp null): self
  168.     {
  169.         if ($this->hasEnded) {
  170.             return $this;
  171.         }
  172.         if (++$this->totalRecordedEvents $this->spanLimits->getEventCountLimit()) {
  173.             return $this;
  174.         }
  175.         $timestamp ??= ClockFactory::getDefault()->now();
  176.         $eventAttributesBuilder $this->spanLimits->getEventAttributesFactory()->builder($attributes);
  177.         $this->events[] = new Event($name$timestamp$eventAttributesBuilder->build());
  178.         return $this;
  179.     }
  180.     /** @inheritDoc */
  181.     public function recordException(Throwable $exceptioniterable $attributes = [], ?int $timestamp null): self
  182.     {
  183.         if ($this->hasEnded) {
  184.             return $this;
  185.         }
  186.         if (++$this->totalRecordedEvents $this->spanLimits->getEventCountLimit()) {
  187.             return $this;
  188.         }
  189.         $timestamp ??= ClockFactory::getDefault()->now();
  190.         $eventAttributesBuilder $this->spanLimits->getEventAttributesFactory()->builder([
  191.             'exception.type' => get_class($exception),
  192.             'exception.message' => $exception->getMessage(),
  193.             'exception.stacktrace' => StackTraceFormatter::format($exception),
  194.         ]);
  195.         foreach ($attributes as $key => $value) {
  196.             $eventAttributesBuilder[$key] = $value;
  197.         }
  198.         $this->events[] = new Event('exception'$timestamp$eventAttributesBuilder->build());
  199.         return $this;
  200.     }
  201.     /** @inheritDoc */
  202.     public function updateName(string $name): self
  203.     {
  204.         if ($this->hasEnded) {
  205.             return $this;
  206.         }
  207.         $this->name $name;
  208.         return $this;
  209.     }
  210.     /** @inheritDoc */
  211.     public function setStatus(string $codestring $description null): self
  212.     {
  213.         if ($this->hasEnded) {
  214.             return $this;
  215.         }
  216.         // An attempt to set value Unset SHOULD be ignored.
  217.         if ($code === API\StatusCode::STATUS_UNSET) {
  218.             return $this;
  219.         }
  220.         // When span status is set to Ok it SHOULD be considered final and any further attempts to change it SHOULD be ignored.
  221.         if ($this->status->getCode() === API\StatusCode::STATUS_OK) {
  222.             return $this;
  223.         }
  224.         $this->status StatusData::create($code$description);
  225.         return $this;
  226.     }
  227.     /** @inheritDoc */
  228.     public function end(int $endEpochNanos null): void
  229.     {
  230.         if ($this->hasEnded) {
  231.             return;
  232.         }
  233.         $this->endEpochNanos $endEpochNanos ?? ClockFactory::getDefault()->now();
  234.         $this->hasEnded true;
  235.         $this->spanProcessor->onEnd($this);
  236.     }
  237.     /** @inheritDoc */
  238.     public function getName(): string
  239.     {
  240.         return $this->name;
  241.     }
  242.     public function getParentContext(): API\SpanContextInterface
  243.     {
  244.         return $this->parentSpanContext;
  245.     }
  246.     public function getInstrumentationScope(): InstrumentationScopeInterface
  247.     {
  248.         return $this->instrumentationScope;
  249.     }
  250.     public function hasEnded(): bool
  251.     {
  252.         return $this->hasEnded;
  253.     }
  254.     public function toSpanData(): SpanDataInterface
  255.     {
  256.         return new ImmutableSpan(
  257.             $this,
  258.             $this->name,
  259.             $this->links,
  260.             $this->events,
  261.             $this->attributesBuilder->build(),
  262.             $this->totalRecordedEvents,
  263.             $this->status,
  264.             $this->endEpochNanos,
  265.             $this->hasEnded
  266.         );
  267.     }
  268.     /** @inheritDoc */
  269.     public function getDuration(): int
  270.     {
  271.         return ($this->hasEnded $this->endEpochNanos ClockFactory::getDefault()->now()) - $this->startEpochNanos;
  272.     }
  273.     /** @inheritDoc */
  274.     public function getKind(): int
  275.     {
  276.         return $this->kind;
  277.     }
  278.     /** @inheritDoc */
  279.     public function getAttribute(string $key)
  280.     {
  281.         return $this->attributesBuilder[$key];
  282.     }
  283.     public function getStartEpochNanos(): int
  284.     {
  285.         return $this->startEpochNanos;
  286.     }
  287.     public function getTotalRecordedLinks(): int
  288.     {
  289.         return $this->totalRecordedLinks;
  290.     }
  291.     public function getTotalRecordedEvents(): int
  292.     {
  293.         return $this->totalRecordedEvents;
  294.     }
  295.     public function getResource(): ResourceInfo
  296.     {
  297.         return $this->resource;
  298.     }
  299. }