Skip to content

Commit 2e96621

Browse files
authored
allow 16 char b3 trace id (#869)
b3 spec allows trace id to be 16 or 32 char. other SIGs left-pad with zero to resolve this.
1 parent 80afb1d commit 2e96621

File tree

3 files changed

+72
-32
lines changed

3 files changed

+72
-32
lines changed

src/Extension/Propagator/B3/B3MultiPropagator.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,10 @@ private static function extractImpl($carrier, PropagationGetterInterface $getter
166166
return SpanContext::getInvalid();
167167
}
168168

169+
// B3 trace id may be 16 or 32 hex chars, but otel requires 32
170+
if (strlen($traceId) === 16) {
171+
$traceId = str_pad($traceId, 32, '0', STR_PAD_LEFT);
172+
}
169173
// Validates the traceId and spanId
170174
// Returns an invalid spanContext if any of the checks fail
171175
if (!SpanContextValidator::isValidTraceId($traceId) || !SpanContextValidator::isValidSpanId($spanId)) {

src/Extension/Propagator/B3/B3SinglePropagator.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,10 @@ private static function extractImpl($carrier, PropagationGetterInterface $getter
155155
return SpanContext::getInvalid();
156156
}
157157

158+
// B3 trace id may be 16 or 32 hex chars, but otel requires 32
159+
if (strlen($traceId) === 16) {
160+
$traceId = str_pad($traceId, 32, '0', STR_PAD_LEFT);
161+
}
158162
// Validates the traceId and spanId
159163
// Returns an invalid spanContext if any of the checks fail
160164
if (!SpanContextValidator::isValidTraceId($traceId) || !SpanContextValidator::isValidSpanId($spanId)) {

tests/Unit/Extension/Propagator/B3/B3PropagatorTest.php

Lines changed: 64 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -20,11 +20,10 @@
2020
*/
2121
class B3PropagatorTest extends TestCase
2222
{
23-
private const B3_SINGLE_TRACE_ID_BASE16 = 'ff0000000000051791e0000000000041';
24-
private const B3_SINGLE_SPAN_ID_BASE16 = 'ff00051791e00041';
25-
private const B3_SINGLE_HEADER_SAMPLED = self::B3_SINGLE_TRACE_ID_BASE16 . '-' . self::B3_SINGLE_SPAN_ID_BASE16 . '-1';
26-
private const B3_MULTI_TRACE_ID_BASE16 = 'ff000000000000301710000000000041';
27-
private const B3_MULTI_SPAN_ID_BASE16 = 'ff00003017100041';
23+
private const B3_TRACE_ID_16_CHAR = 'ff00051791e00041';
24+
private const B3_TRACE_ID = 'ff0000000000051791e0000000000041';
25+
private const B3_SPAN_ID = 'ff00051791e00041';
26+
private const B3_SINGLE_HEADER_SAMPLED = self::B3_TRACE_ID . '-' . self::B3_SPAN_ID . '-1';
2827
private const IS_SAMPLED = '1';
2928
private const IS_NOT_SAMPLED = '0';
3029

@@ -68,15 +67,15 @@ public function test_b3multi_inject(): void
6867
$carrier,
6968
null,
7069
$this->withSpanContext(
71-
SpanContext::create(self::B3_MULTI_TRACE_ID_BASE16, self::B3_MULTI_SPAN_ID_BASE16, SpanContextInterface::TRACE_FLAG_SAMPLED),
70+
SpanContext::create(self::B3_TRACE_ID, self::B3_SPAN_ID, SpanContextInterface::TRACE_FLAG_SAMPLED),
7271
Context::getCurrent()
7372
)
7473
);
7574

7675
$this->assertSame(
7776
[
78-
$this->TRACE_ID => self::B3_MULTI_TRACE_ID_BASE16,
79-
$this->SPAN_ID => self::B3_MULTI_SPAN_ID_BASE16,
77+
$this->TRACE_ID => self::B3_TRACE_ID,
78+
$this->SPAN_ID => self::B3_SPAN_ID,
8079
$this->SAMPLED => self::IS_SAMPLED,
8180
],
8281
$carrier
@@ -91,7 +90,7 @@ public function test_b3single_inject(): void
9190
$carrier,
9291
null,
9392
$this->withSpanContext(
94-
SpanContext::create(self::B3_SINGLE_TRACE_ID_BASE16, self::B3_SINGLE_SPAN_ID_BASE16, SpanContextInterface::TRACE_FLAG_SAMPLED),
93+
SpanContext::create(self::B3_TRACE_ID, self::B3_SPAN_ID, SpanContextInterface::TRACE_FLAG_SAMPLED),
9594
Context::getCurrent()
9695
)
9796
);
@@ -115,7 +114,7 @@ public function test_extract_only_b3single_sampled_context_with_b3single_instanc
115114
$this->assertNull($context->get(B3DebugFlagContextKey::instance()));
116115

117116
$this->assertEquals(
118-
SpanContext::createFromRemoteParent(self::B3_SINGLE_TRACE_ID_BASE16, self::B3_SINGLE_SPAN_ID_BASE16, SpanContextInterface::TRACE_FLAG_SAMPLED),
117+
SpanContext::createFromRemoteParent(self::B3_TRACE_ID, self::B3_SPAN_ID, SpanContextInterface::TRACE_FLAG_SAMPLED),
119118
$this->getSpanContext($context)
120119
);
121120
}
@@ -133,16 +132,16 @@ public function test_extract_only_b3single_sampled_context_with_b3multi_instance
133132
$this->assertNull($context->get(B3DebugFlagContextKey::instance()));
134133

135134
$this->assertEquals(
136-
SpanContext::createFromRemoteParent(self::B3_SINGLE_TRACE_ID_BASE16, self::B3_SINGLE_SPAN_ID_BASE16, SpanContextInterface::TRACE_FLAG_SAMPLED),
135+
SpanContext::createFromRemoteParent(self::B3_TRACE_ID, self::B3_SPAN_ID, SpanContextInterface::TRACE_FLAG_SAMPLED),
137136
$this->getSpanContext($context)
138137
);
139138
}
140139

141140
public function test_extract_only_b3multi_sampled_context_with_b3single_instance(): void
142141
{
143142
$carrier = [
144-
$this->TRACE_ID => self::B3_MULTI_TRACE_ID_BASE16,
145-
$this->SPAN_ID => self::B3_MULTI_SPAN_ID_BASE16,
143+
$this->TRACE_ID => self::B3_TRACE_ID,
144+
$this->SPAN_ID => self::B3_SPAN_ID,
146145
$this->SAMPLED => self::IS_SAMPLED,
147146
];
148147

@@ -151,16 +150,19 @@ public function test_extract_only_b3multi_sampled_context_with_b3single_instance
151150
$context = $propagator->extract($carrier);
152151

153152
$this->assertEquals(
154-
SpanContext::createFromRemoteParent(self::B3_MULTI_TRACE_ID_BASE16, self::B3_MULTI_SPAN_ID_BASE16, SpanContextInterface::TRACE_FLAG_SAMPLED),
153+
SpanContext::createFromRemoteParent(self::B3_TRACE_ID, self::B3_SPAN_ID, SpanContextInterface::TRACE_FLAG_SAMPLED),
155154
$this->getSpanContext($context)
156155
);
157156
}
158157

159-
public function test_extract_only_b3multi_sampled_context_with_b3multi_instance(): void
158+
/**
159+
* @dataProvider validTraceIdProvider
160+
*/
161+
public function test_extract_only_b3multi_sampled_context_with_b3multi_instance(string $traceId, string $expected): void
160162
{
161163
$carrier = [
162-
$this->TRACE_ID => self::B3_MULTI_TRACE_ID_BASE16,
163-
$this->SPAN_ID => self::B3_MULTI_SPAN_ID_BASE16,
164+
$this->TRACE_ID => $traceId,
165+
$this->SPAN_ID => self::B3_SPAN_ID,
164166
$this->SAMPLED => self::IS_SAMPLED,
165167
];
166168

@@ -169,16 +171,46 @@ public function test_extract_only_b3multi_sampled_context_with_b3multi_instance(
169171
$context = $propagator->extract($carrier);
170172

171173
$this->assertEquals(
172-
SpanContext::createFromRemoteParent(self::B3_MULTI_TRACE_ID_BASE16, self::B3_MULTI_SPAN_ID_BASE16, SpanContextInterface::TRACE_FLAG_SAMPLED),
174+
SpanContext::createFromRemoteParent($expected, self::B3_SPAN_ID, SpanContextInterface::TRACE_FLAG_SAMPLED),
175+
$this->getSpanContext($context)
176+
);
177+
}
178+
179+
/**
180+
* @dataProvider validTraceIdProvider
181+
*/
182+
public function test_extract_b3_single(string $traceId, string $expected): void
183+
{
184+
$carrier = [
185+
'b3' => $traceId . '-' . self::B3_SPAN_ID,
186+
];
187+
$context = B3Propagator::getB3SingleHeaderInstance()->extract($carrier);
188+
189+
$this->assertEquals(
190+
SpanContext::createFromRemoteParent($expected, self::B3_SPAN_ID, SpanContextInterface::TRACE_FLAG_DEFAULT),
173191
$this->getSpanContext($context)
174192
);
175193
}
176194

195+
public function validTraceIdProvider(): array
196+
{
197+
return [
198+
'16 char trace id' => [
199+
self::B3_TRACE_ID_16_CHAR,
200+
str_pad(self::B3_TRACE_ID_16_CHAR, 32, '0', STR_PAD_LEFT),
201+
],
202+
'32 char trace id' => [
203+
self::B3_TRACE_ID,
204+
self::B3_TRACE_ID,
205+
],
206+
];
207+
}
208+
177209
public function test_extract_both_sampled_context_with_b3single_instance(): void
178210
{
179211
$carrier = [
180-
$this->TRACE_ID => self::B3_MULTI_TRACE_ID_BASE16,
181-
$this->SPAN_ID => self::B3_MULTI_SPAN_ID_BASE16,
212+
$this->TRACE_ID => self::B3_TRACE_ID,
213+
$this->SPAN_ID => self::B3_SPAN_ID,
182214
$this->SAMPLED => self::IS_NOT_SAMPLED,
183215
$this->B3 => self::B3_SINGLE_HEADER_SAMPLED,
184216
];
@@ -188,16 +220,16 @@ public function test_extract_both_sampled_context_with_b3single_instance(): void
188220
$context = $propagator->extract($carrier);
189221

190222
$this->assertEquals(
191-
SpanContext::createFromRemoteParent(self::B3_SINGLE_TRACE_ID_BASE16, self::B3_SINGLE_SPAN_ID_BASE16, SpanContextInterface::TRACE_FLAG_SAMPLED),
223+
SpanContext::createFromRemoteParent(self::B3_TRACE_ID, self::B3_SPAN_ID, SpanContextInterface::TRACE_FLAG_SAMPLED),
192224
$this->getSpanContext($context)
193225
);
194226
}
195227

196228
public function test_extract_both_sampled_context_with_b3multi_instance(): void
197229
{
198230
$carrier = [
199-
$this->TRACE_ID => self::B3_MULTI_TRACE_ID_BASE16,
200-
$this->SPAN_ID => self::B3_MULTI_SPAN_ID_BASE16,
231+
$this->TRACE_ID => self::B3_TRACE_ID,
232+
$this->SPAN_ID => self::B3_SPAN_ID,
201233
$this->SAMPLED => self::IS_NOT_SAMPLED,
202234
$this->B3 => self::B3_SINGLE_HEADER_SAMPLED,
203235
];
@@ -207,7 +239,7 @@ public function test_extract_both_sampled_context_with_b3multi_instance(): void
207239
$context = $propagator->extract($carrier);
208240

209241
$this->assertEquals(
210-
SpanContext::createFromRemoteParent(self::B3_SINGLE_TRACE_ID_BASE16, self::B3_SINGLE_SPAN_ID_BASE16, SpanContextInterface::TRACE_FLAG_SAMPLED),
242+
SpanContext::createFromRemoteParent(self::B3_TRACE_ID, self::B3_SPAN_ID, SpanContextInterface::TRACE_FLAG_SAMPLED),
211243
$this->getSpanContext($context)
212244
);
213245
}
@@ -218,8 +250,8 @@ public function test_extract_both_sampled_context_with_b3multi_instance(): void
218250
public function test_extract_b3_single_invalid_and_b3_multi_valid_context_with_b3single_instance($headerValue): void
219251
{
220252
$carrier = [
221-
$this->TRACE_ID => self::B3_MULTI_TRACE_ID_BASE16,
222-
$this->SPAN_ID => self::B3_MULTI_SPAN_ID_BASE16,
253+
$this->TRACE_ID => self::B3_TRACE_ID,
254+
$this->SPAN_ID => self::B3_SPAN_ID,
223255
$this->SAMPLED => self::IS_NOT_SAMPLED,
224256
$this->B3 => $headerValue,
225257
];
@@ -229,7 +261,7 @@ public function test_extract_b3_single_invalid_and_b3_multi_valid_context_with_b
229261
$context = $propagator->extract($carrier);
230262

231263
$this->assertEquals(
232-
SpanContext::createFromRemoteParent(self::B3_MULTI_TRACE_ID_BASE16, self::B3_MULTI_SPAN_ID_BASE16, SpanContextInterface::TRACE_FLAG_DEFAULT),
264+
SpanContext::createFromRemoteParent(self::B3_TRACE_ID, self::B3_SPAN_ID, SpanContextInterface::TRACE_FLAG_DEFAULT),
233265
$this->getSpanContext($context)
234266
);
235267
}
@@ -240,8 +272,8 @@ public function test_extract_b3_single_invalid_and_b3_multi_valid_context_with_b
240272
public function test_extract_b3_single_invalid_and_b3_multi_valid_context_with_b3multi_instance($headerValue): void
241273
{
242274
$carrier = [
243-
$this->TRACE_ID => self::B3_MULTI_TRACE_ID_BASE16,
244-
$this->SPAN_ID => self::B3_MULTI_SPAN_ID_BASE16,
275+
$this->TRACE_ID => self::B3_TRACE_ID,
276+
$this->SPAN_ID => self::B3_SPAN_ID,
245277
$this->SAMPLED => self::IS_NOT_SAMPLED,
246278
$this->B3 => $headerValue,
247279
];
@@ -251,16 +283,16 @@ public function test_extract_b3_single_invalid_and_b3_multi_valid_context_with_b
251283
$context = $propagator->extract($carrier);
252284

253285
$this->assertEquals(
254-
SpanContext::createFromRemoteParent(self::B3_MULTI_TRACE_ID_BASE16, self::B3_MULTI_SPAN_ID_BASE16, SpanContextInterface::TRACE_FLAG_DEFAULT),
286+
SpanContext::createFromRemoteParent(self::B3_TRACE_ID, self::B3_SPAN_ID, SpanContextInterface::TRACE_FLAG_DEFAULT),
255287
$this->getSpanContext($context)
256288
);
257289
}
258290

259291
public function invalidB3SingleHeaderValueProvider(): array
260292
{
261293
return [
262-
'invalid traceid' => ['abcdefghijklmnopabcdefghijklmnop-' . self::B3_SINGLE_SPAN_ID_BASE16 . '-1'],
263-
'invalid spanid' => [self::B3_SINGLE_TRACE_ID_BASE16 . '-abcdefghijklmnop-1'],
294+
'invalid traceid' => ['abcdefghijklmnopabcdefghijklmnop-' . self::B3_SPAN_ID . '-1'],
295+
'invalid spanid' => [self::B3_TRACE_ID . '-abcdefghijklmnop-1'],
264296
];
265297
}
266298

0 commit comments

Comments
 (0)