Skip to content

Commit 3aafcfd

Browse files
committed
feat: Basic OTel Span Links Functionalities
1 parent e997b97 commit 3aafcfd

File tree

4 files changed

+72
-12
lines changed

4 files changed

+72
-12
lines changed

src/DDTrace/OpenTelemetry/Context.php

+15-2
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
use DDTrace\Tag;
99
use DDTrace\Util\ObjectKVStore;
1010
use OpenTelemetry\API\Trace as API;
11+
use OpenTelemetry\SDK\Common\Attribute\Attributes;
1112
use OpenTelemetry\SDK\Common\Attribute\AttributesFactory;
1213
use OpenTelemetry\SDK\Common\Instrumentation\InstrumentationScopeFactory;
1314
use OpenTelemetry\SDK\Common\Instrumentation\InstrumentationScopeInterface;
@@ -176,6 +177,18 @@ private static function activateParent(?SpanData $currentSpan): ContextInterface
176177
: null;
177178
$traceState = new API\TraceState($traceContext['tracestate'] ?? null);
178179

180+
// Check for span links
181+
$links = [];
182+
foreach ($currentSpan->links as $spanLink) {
183+
$linkSpanContext = API\SpanContext::create(
184+
$spanLink->traceId,
185+
$spanLink->spanId,
186+
API\TraceFlags::DEFAULT,
187+
new API\TraceState($spanLink->traceState ?? null),
188+
);
189+
$links[] = new SDK\Link($linkSpanContext, Attributes::create($spanLink->attributes));
190+
}
191+
179192
$OTelCurrentSpan = SDK\Span::startSpan(
180193
$currentSpan,
181194
API\SpanContext::create($currentTraceId, $currentSpanId, $traceFlags, $traceState), // $context
@@ -186,8 +199,8 @@ private static function activateParent(?SpanData $currentSpan): ContextInterface
186199
NoopSpanProcessor::getInstance(), // $spanProcessor
187200
ResourceInfoFactory::defaultResource(), // $resource
188201
(new AttributesFactory())->builder(), // $attributesBuilder
189-
[], // TODO: Handle Span Links
190-
0, // TODO: Handle Span Links
202+
$links, // $links
203+
count($links), // $totalRecordedLinks
191204
false // The span was created using the DD Api
192205
);
193206
ObjectKVStore::put($currentSpan, 'otel_span', $OTelCurrentSpan);

src/DDTrace/OpenTelemetry/Span.php

+38-2
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
namespace OpenTelemetry\SDK\Trace;
66

77
use DDTrace\SpanData;
8+
use DDTrace\SpanLink;
89
use DDTrace\Tag;
910
use DDTrace\Util\Convention;
1011
use DDTrace\Util\ObjectKVStore;
@@ -35,6 +36,16 @@ final class Span extends API\Span implements ReadWriteSpanInterface
3536
/** @readonly */
3637
private SpanProcessorInterface $spanProcessor;
3738

39+
/**
40+
* @readonly
41+
*
42+
* @var list<LinkInterface>
43+
*/
44+
private array $links;
45+
46+
/** @readonly */
47+
private int $totalRecordedLinks;
48+
3849
/** @readonly */
3950
private int $kind;
4051

@@ -56,6 +67,8 @@ private function __construct(
5667
API\SpanContextInterface $parentSpanContext,
5768
SpanProcessorInterface $spanProcessor,
5869
ResourceInfo $resource,
70+
array $links = [],
71+
int $totalRecordedLinks = 0,
5972
bool $isRemapped = true
6073
) {
6174
$this->span = $span;
@@ -65,6 +78,8 @@ private function __construct(
6578
$this->parentSpanContext = $parentSpanContext;
6679
$this->spanProcessor = $spanProcessor;
6780
$this->resource = $resource;
81+
$this->links = $links;
82+
$this->totalRecordedLinks = $totalRecordedLinks;
6883

6984
$this->status = StatusData::unset();
7085

@@ -75,6 +90,25 @@ private function __construct(
7590
// done in serializer.c:ddtrace_set_root_span_properties (as of v0.92.0)
7691
$span->name = $this->operationNameConvention = Convention::defaultOperationName($span);
7792
}
93+
94+
// Set the span links
95+
if ($isRemapped) {
96+
// At initialization time (now), only set the links if the span was created using the OTel API
97+
// Otherwise, the links were already set in DD's OpenTelemetry\Context\Context
98+
foreach ($links as $link) {
99+
/** @var LinkInterface $link */
100+
$linkContext = $link->getSpanContext();
101+
102+
$spanLink = new SpanLink();
103+
$spanLink->traceId = $linkContext->getTraceId();
104+
$spanLink->spanId = $linkContext->getSpanId();
105+
$spanLink->traceState = (string)$linkContext->getTraceState(); // __toString()
106+
$spanLink->attributes = $link->getAttributes()->toArray();
107+
$spanLink->droppedAttributesCount = 0; // Attributes limit aren't supported/meaningful in DD
108+
109+
$span->links[] = $spanLink;
110+
}
111+
}
78112
}
79113

80114
/**
@@ -116,6 +150,8 @@ public static function startSpan(
116150
$parentSpan->getContext(),
117151
$spanProcessor,
118152
$resource,
153+
$links,
154+
$totalRecordedLinks,
119155
$isRemapped
120156
);
121157

@@ -165,7 +201,7 @@ public function toSpanData(): SpanDataInterface
165201
return new ImmutableSpan(
166202
$this,
167203
$this->getName(),
168-
[], // TODO: Handle Span Links
204+
$this->links,
169205
[], // TODO: Handle Span Events
170206
Attributes::create(array_merge($this->span->meta, $this->span->metrics)),
171207
0,
@@ -206,7 +242,7 @@ public function getStartEpochNanos(): int
206242

207243
public function getTotalRecordedLinks(): int
208244
{
209-
return 0;
245+
return $this->totalRecordedLinks;
210246
}
211247

212248
public function getTotalRecordedEvents(): int

src/DDTrace/OpenTelemetry/SpanBuilder.php

+19-2
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,24 @@ public function setParent($context): API\SpanBuilderInterface
6969

7070
public function addLink(SpanContextInterface $context, iterable $attributes = []): SpanBuilderInterface
7171
{
72-
// TODO: Span Links are future works
72+
if (!$context->isValid()) {
73+
return $this;
74+
}
75+
76+
$this->totalNumberOfLinksAdded++;
77+
78+
if (count($this->links) === $this->tracerSharedState->getSpanLimits()->getLinkCountLimit()) {
79+
return $this;
80+
}
81+
82+
$this->links[] = new Link(
83+
$context,
84+
$this->tracerSharedState
85+
->getSpanLimits()
86+
->getLinkAttributesFactory()
87+
->builder($attributes)
88+
->build(),
89+
);
7390

7491
return $this;
7592
}
@@ -186,7 +203,7 @@ public function startSpan(): SpanInterface
186203
$this->tracerSharedState->getResource(),
187204
$attributesBuilder,
188205
$this->links,
189-
0,
206+
$this->totalNumberOfLinksAdded,
190207
);
191208
}
192209

tests/OpenTelemetry/Integration/SDK/SpanBuilderTest.php

-6
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,6 @@ public function test_set_parent_invalid_context(): void
9898
*/
9999
public function test_add_link(): void
100100
{
101-
$this->markTestSkipped("Span Links aren't yet supported");
102101
/** @var Span $span */
103102
$span = $this
104103
->tracer
@@ -112,7 +111,6 @@ public function test_add_link(): void
112111

113112
public function test_add_link_invalid(): void
114113
{
115-
$this->markTestIncomplete("Span Links aren't yet supported");
116114
/** @var Span $span */
117115
$span = $this
118116
->tracer
@@ -127,7 +125,6 @@ public function test_add_link_invalid(): void
127125

128126
public function test_add_link_dropping_links(): void
129127
{
130-
$this->markTestSkipped("Span Links aren't yet supported");
131128
$maxNumberOfLinks = 8;
132129
$tracerProvider = new TracerProvider([], null, null, (new SpanLimitsBuilder())->setLinkCountLimit($maxNumberOfLinks)->build());
133130
$spanBuilder = $tracerProvider
@@ -156,7 +153,6 @@ public function test_add_link_dropping_links(): void
156153

157154
public function test_add_link_truncate_link_attributes(): void
158155
{
159-
$this->markTestSkipped("Span Links aren't yet supported");
160156
$tracerProvider = new TracerProvider([], null, null, (new SpanLimitsBuilder())->setAttributePerLinkCountLimit(1)->build());
161157
/** @var Span $span */
162158
$span = $tracerProvider
@@ -178,7 +174,6 @@ public function test_add_link_truncate_link_attributes(): void
178174

179175
public function test_add_link_truncate_link_attribute_value(): void
180176
{
181-
$this->markTestSkipped("Spans Links aren't yet supported");
182177
$maxLength = 25;
183178

184179
$strVal = str_repeat('a', $maxLength);
@@ -218,7 +213,6 @@ public function test_add_link_truncate_link_attribute_value(): void
218213
*/
219214
public function test_add_link_no_effect_after_start_span(): void
220215
{
221-
$this->markTestSkipped("Span Links aren't yet supported");
222216
$spanBuilder = $this->tracer->spanBuilder(self::SPAN_NAME);
223217

224218
/** @var Span $span */

0 commit comments

Comments
 (0)