diff --git a/src/Propagation/Instana/README.md b/src/Propagation/Instana/README.md
index c3acb6ea6..1ba3ade4b 100644
--- a/src/Propagation/Instana/README.md
+++ b/src/Propagation/Instana/README.md
@@ -1,6 +1,15 @@
-OpenTelemetry Instana Propagator
+[](https://github.com/opentelemetry-php/contrib-propagator-instana/releases)
+[](https://github.com/open-telemetry/opentelemetry-php/issues)
+[](https://github.com/open-telemetry/opentelemetry-php-contrib/tree/main/src/Propagation/Instana)
+[](https://github.com/opentelemetry-php/contrib-propagator-instana)
+[](https://packagist.org/packages/open-telemetry/opentelemetry-propagation-instana/)
+[](https://packagist.org/packages/open-telemetry/opentelemetry-propagation-instana/)
-The OpenTelemetry Propagator for Instana provides HTTP header propagation for systems that are using IBM Observability by Instana.
+This is a read-only subtree split of https://github.com/open-telemetry/opentelemetry-php-contrib.
+
+# OpenTelemetry Instana Propagator
+
+The OpenTelemetry Propagator for Instana provides HTTP header propagation and Baggage propagation for systems that are using IBM Observability by Instana.
This propagator translates the Instana trace correlation headers (`X-INSTANA-T/X-INSTANA-S/X-INSTANA-L`) into the OpenTelemetry `SpanContext`, and vice versa.
It does not handle `TraceState`.
@@ -14,11 +23,17 @@ composer require open-telemetry/opentelemetry-propagation-instana
## Usage
```
-$propagator = InstanaMultiPropagator::getInstance();
+$propagator = InstanaPropagator::getInstance();
```
Both of the above have extract and inject methods available to extract and inject respectively into the header.
+For Baggage propagation, use opentelemetry's MultiTextMapPropagator, and pass the array list of propagators i.e Instana and Baggage propagator as below.
+
+```
+$propagator = new MultiTextMapPropagator(InstantPropagator::getInstance(), BaggagePropagator::getInstance());
+```
+
## Propagator Details
There are three headers that the propagator handles: `X-INSTANA-T` (the trace ID), `X-INSTANA-S` (the parent span ID), and `X-INSTANA-L` (the sampling level).
diff --git a/src/Propagation/Instana/_register.php b/src/Propagation/Instana/_register.php
index 15b0f1425..4add57cc9 100644
--- a/src/Propagation/Instana/_register.php
+++ b/src/Propagation/Instana/_register.php
@@ -1,13 +1,15 @@
tests/Unit
+
+ tests/Integration
+
diff --git a/src/Propagation/Instana/src/InstanaMultiPropagator.php b/src/Propagation/Instana/src/InstanaPropagator.php
similarity index 97%
rename from src/Propagation/Instana/src/InstanaMultiPropagator.php
rename to src/Propagation/Instana/src/InstanaPropagator.php
index ddae29c40..a3755c4c0 100644
--- a/src/Propagation/Instana/src/InstanaMultiPropagator.php
+++ b/src/Propagation/Instana/src/InstanaPropagator.php
@@ -21,7 +21,7 @@
* "instana" http headers used for trace context propagation across service
* boundaries.
*/
-final class InstanaMultiPropagator implements TextMapPropagatorInterface
+final class InstanaPropagator implements TextMapPropagatorInterface
{
/**
* The X-INSTANA-T header is required and is encoded as 32 lower-hex characters.
@@ -115,7 +115,6 @@ public function extract($carrier, ?PropagationGetterInterface $getter = null, ?C
if (($traceId === '' && $spanId === '') && $level !== null) {
return (new NonRecordingSpan($spanContext))
->storeInContext($context);
-
} elseif (!$spanContext->isValid()) {
return $context;
}
@@ -161,7 +160,7 @@ private static function extractImpl($carrier, PropagationGetterInterface $getter
}
if ($spanId && strlen($spanId) < 16) {
- $spanId = str_pad($spanId, 16, '0', STR_PAD_LEFT);
+ $spanId = str_pad($spanId, 16, '0', STR_PAD_LEFT);
}
return SpanContext::createFromRemoteParent(
diff --git a/src/Propagation/Instana/tests/Integration/InstanaMultiPropagatorTest.php b/src/Propagation/Instana/tests/Integration/InstanaMultiPropagatorTest.php
new file mode 100644
index 000000000..5df1cf685
--- /dev/null
+++ b/src/Propagation/Instana/tests/Integration/InstanaMultiPropagatorTest.php
@@ -0,0 +1,143 @@
+InstanaPropagator = InstanaPropagator::getInstance();
+ $instanaMultiFields = $this->InstanaPropagator->fields();
+ $this->TRACE_ID = $instanaMultiFields[0];
+ $this->SPAN_ID = $instanaMultiFields[1];
+ $this->SAMPLED = $instanaMultiFields[2];
+ }
+
+ /**
+ * @dataProvider sampledValueProvider
+ */
+ public function test_extract_sampled_context_with_baggage($sampledValue): void
+ {
+ $carrier = [
+ $this->TRACE_ID => self::X_INSTANA_T,
+ $this->SPAN_ID => self::X_INSTANA_S,
+ $this->SAMPLED => $sampledValue,
+ 'baggage' => 'user_id=12345,request_id=abcde',
+ ];
+ $propagator = new MultiTextMapPropagator([InstanaPropagator::getInstance(), BaggagePropagator::getInstance()]);
+ $context = $propagator->extract($carrier);
+
+ $this->assertEquals(
+ SpanContext::createFromRemoteParent(self::X_INSTANA_T, self::X_INSTANA_S, TraceFlags::SAMPLED),
+ $this->getSpanContext($this->InstanaPropagator->extract($carrier))
+ );
+
+ // Verify baggage
+ $baggage = Baggage::fromContext($context);
+ $this->assertEquals('12345', $baggage->getValue('user_id'));
+ $this->assertEquals('abcde', $baggage->getValue('request_id'));
+
+ $arr = [];
+
+ foreach ($baggage->getAll() as $key => $value) {
+ $arr[$key] = $value->getValue();
+ }
+
+ $this->assertEquals(
+ ['user_id' => '12345', 'request_id' => 'abcde'],
+ $arr
+ );
+ }
+
+ /**
+ * @dataProvider sampledValueProvider
+ */
+ public function test_extract_sampled_context_with_baggage_but_instana_propagator($sampledValue): void
+ {
+ $carrier = [
+ $this->TRACE_ID => self::X_INSTANA_T,
+ $this->SPAN_ID => self::X_INSTANA_S,
+ $this->SAMPLED => $sampledValue,
+ 'baggage' => 'user_id=12345,request_id=abcde',
+ ];
+ $context = $this->InstanaPropagator->extract($carrier);
+
+ $this->assertEquals(
+ SpanContext::createFromRemoteParent(self::X_INSTANA_T, self::X_INSTANA_S, TraceFlags::SAMPLED),
+ $this->getSpanContext($this->InstanaPropagator->extract($carrier))
+ );
+
+ // Verify baggage is not propagated
+ $baggage = Baggage::fromContext($context);
+ $this->assertNull($baggage->getValue('user_id'));
+ $this->assertNull($baggage->getValue('request_id'));
+
+ }
+
+ public function test_baggage_inject(): void
+ {
+ $carrier = [];
+
+ $propagator = new MultiTextMapPropagator([InstanaPropagator::getInstance(), BaggagePropagator::getInstance()]);
+
+ $propagator->inject(
+ $carrier,
+ null,
+ Context::getRoot()->withContextValue(
+ Baggage::getBuilder()
+ ->set('nometa', 'nometa-value')
+ ->set('meta', 'meta-value', new Metadata('somemetadata; someother=foo'))
+ ->build()
+ )
+ );
+
+ $this->assertSame(
+ ['baggage' => 'nometa=nometa-value,meta=meta-value;somemetadata; someother=foo'],
+ $carrier
+ );
+ }
+
+ public static function sampledValueProvider(): array
+ {
+ return [
+ 'String sampled value' => ['1'],
+ 'Boolean(lower string) sampled value' => ['true'],
+ 'Boolean(upper string) sampled value' => ['TRUE'],
+ 'Boolean(camel string) sampled value' => ['True'],
+ ];
+ }
+
+ private function getSpanContext(ContextInterface $context): SpanContextInterface
+ {
+ return Span::fromContext($context)->getContext();
+ }
+
+}
diff --git a/src/Propagation/Instana/tests/Unit/InstanaMultiPropagatorTest.php b/src/Propagation/Instana/tests/Unit/InstanaPropagatorTest.php
similarity index 87%
rename from src/Propagation/Instana/tests/Unit/InstanaMultiPropagatorTest.php
rename to src/Propagation/Instana/tests/Unit/InstanaPropagatorTest.php
index a7324cef8..4d46d6128 100644
--- a/src/Propagation/Instana/tests/Unit/InstanaMultiPropagatorTest.php
+++ b/src/Propagation/Instana/tests/Unit/InstanaPropagatorTest.php
@@ -8,15 +8,16 @@
use OpenTelemetry\API\Trace\SpanContextInterface;
use OpenTelemetry\API\Trace\SpanContextValidator;
use OpenTelemetry\API\Trace\TraceFlags;
-use OpenTelemetry\Context\Context;
+use OpenTelemetry\Context\Context;
use OpenTelemetry\Context\ContextInterface;
-use OpenTelemetry\Contrib\Propagation\Instana\InstanaMultiPropagator as InstanaMultiPropagator;
+use OpenTelemetry\Contrib\Propagation\Instana\InstanaPropagator;
+
use OpenTelemetry\SDK\Trace\Span;
use Override;
use PHPUnit\Framework\TestCase;
-final class InstanaMultiPropagatorTest extends TestCase
+final class InstanaPropagatorTest extends TestCase
{
private const X_INSTANA_T = 'ff000000000000000000000000000041';
private const X_INSTANA_S = 'ff00000000000041';
@@ -27,13 +28,13 @@ final class InstanaMultiPropagatorTest extends TestCase
private $SPAN_ID;
private $SAMPLED;
- private InstanaMultiPropagator $instanaMultiPropagator;
+ private InstanaPropagator $InstanaPropagator;
#[Override]
protected function setUp(): void
{
- $this->instanaMultiPropagator = InstanaMultiPropagator::getInstance();
- $instanaMultiFields = $this->instanaMultiPropagator->fields();
+ $this->InstanaPropagator = InstanaPropagator::getInstance();
+ $instanaMultiFields = $this->InstanaPropagator->fields();
$this->TRACE_ID = $instanaMultiFields[0];
$this->SPAN_ID = $instanaMultiFields[1];
$this->SAMPLED = $instanaMultiFields[2];
@@ -43,14 +44,14 @@ public function test_fields(): void
{
$this->assertSame(
['X-INSTANA-T', 'X-INSTANA-S', 'X-INSTANA-L'],
- $this->instanaMultiPropagator->fields()
+ $this->InstanaPropagator->fields()
);
}
public function test_inject_empty(): void
{
$carrier = [];
- $this->instanaMultiPropagator->inject($carrier);
+ $this->InstanaPropagator->inject($carrier);
$this->assertEmpty($carrier);
}
@@ -58,7 +59,7 @@ public function test_inject_invalid_context(): void
{
$carrier = [];
$this
- ->instanaMultiPropagator
+ ->InstanaPropagator
->inject(
$carrier,
null,
@@ -78,7 +79,7 @@ public function test_inject_sampled_context(): void
{
$carrier = [];
$this
- ->instanaMultiPropagator
+ ->InstanaPropagator
->inject(
$carrier,
null,
@@ -102,7 +103,7 @@ public function test_inject_non_sampled_context(): void
{
$carrier = [];
$this
- ->instanaMultiPropagator
+ ->InstanaPropagator
->inject(
$carrier,
null,
@@ -126,7 +127,7 @@ public function test_inject_sampled_context_when_other_traceflags_set(): void
{
$carrier = [];
$this
- ->instanaMultiPropagator
+ ->InstanaPropagator
->inject(
$carrier,
null,
@@ -156,7 +157,7 @@ public function test_extract_context_with_lowercase_headers(): void
$this->assertEquals(
SpanContext::createFromRemoteParent(self::X_INSTANA_T, self::X_INSTANA_S, TraceFlags::SAMPLED),
- $this->getSpanContext($this->instanaMultiPropagator->extract($carrier))
+ $this->getSpanContext($this->InstanaPropagator->extract($carrier))
);
}
@@ -183,7 +184,7 @@ public function test_extract_sampled_context($sampledValue): void
$this->assertEquals(
SpanContext::createFromRemoteParent(self::X_INSTANA_T, self::X_INSTANA_S, TraceFlags::SAMPLED),
- $this->getSpanContext($this->instanaMultiPropagator->extract($carrier))
+ $this->getSpanContext($this->InstanaPropagator->extract($carrier))
);
}
@@ -210,7 +211,7 @@ public function test_extract_non_sampled_context($sampledValue): void
$this->assertEquals(
SpanContext::createFromRemoteParent(self::X_INSTANA_T, self::X_INSTANA_S),
- $this->getSpanContext($this->instanaMultiPropagator->extract($carrier))
+ $this->getSpanContext($this->InstanaPropagator->extract($carrier))
);
}
@@ -237,7 +238,7 @@ public function test_extract_default_sampled_context($sampledValue): void
$this->assertEquals(
SpanContext::createFromRemoteParent(self::X_INSTANA_T, self::X_INSTANA_S, TraceFlags::DEFAULT),
- $this->getSpanContext($this->instanaMultiPropagator->extract($carrier))
+ $this->getSpanContext($this->InstanaPropagator->extract($carrier))
);
}
@@ -262,7 +263,7 @@ public function test_extract_invalid_sampled_context($sampledValue): void
$this->assertEquals(
SpanContext::createFromRemoteParent(self::X_INSTANA_T, self::X_INSTANA_S),
- $this->getSpanContext($this->instanaMultiPropagator->extract($carrier))
+ $this->getSpanContext($this->InstanaPropagator->extract($carrier))
);
}
@@ -286,7 +287,7 @@ public function test_extract_context_with_sampled_no_trace_and_span_headers(): v
'0000000000000000',
TraceFlags::SAMPLED
),
- $this->getSpanContext($this->instanaMultiPropagator->extract($carrier))
+ $this->getSpanContext($this->InstanaPropagator->extract($carrier))
);
}
@@ -302,7 +303,7 @@ public function test_extract_context_with_no_trace_and_span_headers(): void
'0000000000000000',
TraceFlags::DEFAULT
),
- $this->getSpanContext($this->instanaMultiPropagator->extract($carrier))
+ $this->getSpanContext($this->InstanaPropagator->extract($carrier))
);
}
@@ -313,9 +314,9 @@ public function test_extract_and_inject(): void
$this->SPAN_ID => self::X_INSTANA_S,
$this->SAMPLED => self::IS_SAMPLED,
];
- $context = $this->instanaMultiPropagator->extract($extractCarrier);
+ $context = $this->InstanaPropagator->extract($extractCarrier);
$injectCarrier = [];
- $this->instanaMultiPropagator->inject($injectCarrier, null, $context);
+ $this->InstanaPropagator->inject($injectCarrier, null, $context);
$this->assertSame($injectCarrier, $extractCarrier);
}
@@ -340,7 +341,7 @@ public function test_extract_leftpad_spand_id(): void
$this->assertEquals(
SpanContext::createFromRemoteParent('00000000000000004aaba1a52cf8ee09', '0007b5a2e4d86bd1', TraceFlags::SAMPLED),
- $this->getSpanContext($this->instanaMultiPropagator->extract($carrier))
+ $this->getSpanContext($this->InstanaPropagator->extract($carrier))
);
}
@@ -403,7 +404,7 @@ private function assertInvalid(array $carrier): void
{
$this->assertSame(
Context::getCurrent(),
- $this->instanaMultiPropagator->extract($carrier),
+ $this->InstanaPropagator->extract($carrier),
);
}