*/ private array $links = []; private AttributesBuilderInterface $attributesBuilder; private int $totalNumberOfLinksAdded = 0; private int $startEpochNanos = 0; /** @param non-empty-string $spanName */ public function __construct( string $spanName, InstrumentationScopeInterface $instrumentationScope, TracerSharedState $tracerSharedState ) { $this->spanName = $spanName; $this->instrumentationScope = $instrumentationScope; $this->tracerSharedState = $tracerSharedState; $this->attributesBuilder = $tracerSharedState->getSpanLimits()->getAttributesFactory()->builder(); } /** @inheritDoc */ public function setParent($context): API\SpanBuilderInterface { $this->parentContext = $context; return $this; } /** @inheritDoc */ public function addLink(API\SpanContextInterface $context, iterable $attributes = []): API\SpanBuilderInterface { if (!$context->isValid()) { return $this; } $this->totalNumberOfLinksAdded++; if (count($this->links) === $this->tracerSharedState->getSpanLimits()->getLinkCountLimit()) { return $this; } $this->links[] = new Link( $context, $this->tracerSharedState ->getSpanLimits() ->getLinkAttributesFactory() ->builder($attributes) ->build(), ); return $this; } /** @inheritDoc */ public function setAttribute(string $key, $value): API\SpanBuilderInterface { $this->attributesBuilder[$key] = $value; return $this; } /** @inheritDoc */ public function setAttributes(iterable $attributes): API\SpanBuilderInterface { foreach ($attributes as $key => $value) { $this->attributesBuilder[$key] = $value; } return $this; } /** * @inheritDoc * * @psalm-param API\SpanKind::KIND_* $spanKind */ public function setSpanKind(int $spanKind): API\SpanBuilderInterface { $this->spanKind = $spanKind; return $this; } /** @inheritDoc */ public function setStartTimestamp(int $timestampNanos): API\SpanBuilderInterface { if (0 > $timestampNanos) { return $this; } $this->startEpochNanos = $timestampNanos; return $this; } /** @inheritDoc */ public function startSpan(): API\SpanInterface { $parentContext = Context::resolve($this->parentContext); $parentSpan = Span::fromContext($parentContext); $parentSpanContext = $parentSpan->getContext(); $spanId = $this->tracerSharedState->getIdGenerator()->generateSpanId(); if (!$parentSpanContext->isValid()) { $traceId = $this->tracerSharedState->getIdGenerator()->generateTraceId(); } else { $traceId = $parentSpanContext->getTraceId(); } $samplingResult = $this ->tracerSharedState ->getSampler() ->shouldSample( $parentContext, $traceId, $this->spanName, $this->spanKind, $this->attributesBuilder->build(), $this->links, ); $samplingDecision = $samplingResult->getDecision(); $samplingResultTraceState = $samplingResult->getTraceState(); $spanContext = API\SpanContext::create( $traceId, $spanId, SamplingResult::RECORD_AND_SAMPLE === $samplingDecision ? API\TraceFlags::SAMPLED : API\TraceFlags::DEFAULT, $samplingResultTraceState, ); if (!in_array($samplingDecision, [SamplingResult::RECORD_AND_SAMPLE, SamplingResult::RECORD_ONLY], true)) { return Span::wrap($spanContext); } $attributesBuilder = clone $this->attributesBuilder; foreach ($samplingResult->getAttributes() as $key => $value) { $attributesBuilder[$key] = $value; } return Span::startSpan( $this->spanName, $spanContext, $this->instrumentationScope, $this->spanKind, $parentSpan, $parentContext, $this->tracerSharedState->getSpanLimits(), $this->tracerSharedState->getSpanProcessor(), $this->tracerSharedState->getResource(), $attributesBuilder, $this->links, $this->totalNumberOfLinksAdded, $this->startEpochNanos ); } }