From 973816b44ca163ae55874afca69943bf83791d7e Mon Sep 17 00:00:00 2001 From: Amber Sistla Date: Sat, 14 Nov 2020 05:54:18 -0800 Subject: [PATCH] Associating Spans with their TracerProvider (#215) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Added functionality to associate a resource with a span. Added a `defaultResource` method to `ResourceInfo`. Added test cases to ‘ResourceTest.php`, `TracerProviderTest.php`, `TracingTest.php`. * Some `psalm` fixes. * Psalm. --- sdk/Resource/ResourceInfo.php | 21 +- sdk/Trace/Span.php | 13 + sdk/Trace/SpanOptions.php | 2 +- sdk/Trace/Tracer.php | 16 +- sdk/Trace/TracerProvider.php | 14 +- tests/Sdk/Unit/Resource/ResourceTest.php | 53 ++- tests/Sdk/Unit/Trace/TracerProviderTest.php | 105 ++++++ tests/Sdk/Unit/Trace/TracingTest.php | 339 ++++++++++++++++++++ 8 files changed, 547 insertions(+), 16 deletions(-) diff --git a/sdk/Resource/ResourceInfo.php b/sdk/Resource/ResourceInfo.php index 75566046..b640c13e 100644 --- a/sdk/Resource/ResourceInfo.php +++ b/sdk/Resource/ResourceInfo.php @@ -24,7 +24,15 @@ class ResourceInfo public static function create(Attributes $attributes): self { - return new ResourceInfo(clone $attributes); + $resource = self::merge(self::defaultResource(), new ResourceInfo(clone $attributes)); + /* + * The SDK MUST extract information from the OTEL_RESOURCE_ATTRIBUTES environment + * variable and merge this. + * todo: after resource detection is implemented, merge it here. + * return $resource.merge(....); + * + */ + return $resource; } /** @@ -53,6 +61,17 @@ class ResourceInfo return new ResourceInfo($mergedAttributes); } + public static function defaultResource(): self + { + return new ResourceInfo(new Attributes( + [ + ResourceConstants::TELEMETRY_SDK_NAME => 'opentelemetry', + ResourceConstants::TELEMETRY_SDK_LANGUAGE => 'php', + ResourceConstants::TELEMETRY_SDK_VERSION => 'dev', + ] + )); + } + public static function emptyResource(): self { return new ResourceInfo(new Attributes()); diff --git a/sdk/Trace/Span.php b/sdk/Trace/Span.php index ad87dfeb..a5a0fbbe 100644 --- a/sdk/Trace/Span.php +++ b/sdk/Trace/Span.php @@ -4,6 +4,7 @@ declare(strict_types=1); namespace OpenTelemetry\Sdk\Trace; +use OpenTelemetry\Sdk\Resource\ResourceInfo; use OpenTelemetry\Trace as API; class Span implements API\Span @@ -20,6 +21,11 @@ class Span implements API\Span private $statusCode; private $statusDescription; + /** + * @var ResourceInfo + */ + private $resource; // An immutable representation of the entity producing telemetry. + private $attributes; private $events; private $links = null; @@ -44,6 +50,7 @@ class Span implements API\Span API\SpanContext $spanContext, ?API\SpanContext $parentSpanContext = null, ?Sampler $sampler = null, + ?ResourceInfo $resource = null, int $spanKind = API\SpanKind::KIND_INTERNAL ) { $this->name = $name; @@ -51,6 +58,7 @@ class Span implements API\Span $this->parentSpanContext = $parentSpanContext; $this->spanKind = $spanKind; $this->sampler = $sampler; + $this->resource = $resource ?? ResourceInfo::emptyResource(); $moment = Clock::get()->moment(); $this->startEpochTimestamp = $moment[0]; $this->start = $moment[1]; @@ -62,6 +70,11 @@ class Span implements API\Span $this->events = new Events(); } + public function getResource(): ResourceInfo + { + return clone $this->resource; + } + public function getContext(): API\SpanContext { return clone $this->spanContext; diff --git a/sdk/Trace/SpanOptions.php b/sdk/Trace/SpanOptions.php index dfcbe496..00b2c65f 100644 --- a/sdk/Trace/SpanOptions.php +++ b/sdk/Trace/SpanOptions.php @@ -96,7 +96,7 @@ final class SpanOptions implements API\SpanOptions ? SpanContext::fork($span->getContext()->getTraceId()) : SpanContext::generate(); - $span = new Span($this->name, $context, $this->parent, null, $this->kind); + $span = new Span($this->name, $context, $this->parent, null, $this->tracer->getResource(), $this->kind); if ($this->startEpochTimestamp !== null) { $span->setStartEpochTimestamp($this->startEpochTimestamp); diff --git a/sdk/Trace/Tracer.php b/sdk/Trace/Tracer.php index c18323a3..40a260df 100644 --- a/sdk/Trace/Tracer.php +++ b/sdk/Trace/Tracer.php @@ -22,11 +22,11 @@ class Tracer implements API\Tracer public function __construct( TracerProvider $provider, - ResourceInfo $resource, + ResourceInfo $resource = null, API\SpanContext $context = null ) { $this->provider = $provider; - $this->resource = $resource; + $this->resource = $resource ?? ResourceInfo::emptyResource(); $this->importedContext = $context; } @@ -50,6 +50,7 @@ class Tracer implements API\Tracer * @param string $name * @param API\SpanContext $parentContext * @param bool $isRemote + * @param int $spanKind * @return Span */ @@ -81,7 +82,7 @@ class Tracer implements API\Tracer if (SamplingResult::NOT_RECORD == $samplingResult->getDecision()) { $span = $this->generateSpanInstance('', $context); } else { - $span = $this->generateSpanInstance($name, $context, $sampler); + $span = $this->generateSpanInstance($name, $context, $sampler, $this->resource); if ($span->isRecording()) { $this->provider->getSpanProcessor()->onStart($span); @@ -167,7 +168,10 @@ class Tracer implements API\Tracer { return $this->spans; } - + public function getResource(): ResourceInfo + { + return clone $this->resource; + } public function endActiveSpan(?int $timestamp = null) { /** @@ -182,7 +186,7 @@ class Tracer implements API\Tracer } } - private function generateSpanInstance(string $name, API\SpanContext $context, Sampler $sampler = null): API\Span + private function generateSpanInstance(string $name, API\SpanContext $context, Sampler $sampler = null, ResourceInfo $resource = null): API\Span { $parent = null; @@ -193,7 +197,7 @@ class Tracer implements API\Tracer $parent = $this->getActiveSpan()->getContext(); } - $span = new Span($name, $context, $parent, $sampler); + $span = new Span($name, $context, $parent, $sampler, $resource); } $this->spans[] = $span; diff --git a/sdk/Trace/TracerProvider.php b/sdk/Trace/TracerProvider.php index e66436d6..895575da 100644 --- a/sdk/Trace/TracerProvider.php +++ b/sdk/Trace/TracerProvider.php @@ -54,13 +54,15 @@ final class TracerProvider implements API\TracerProvider } $spanContext = SpanContext::generateSampled(); - + /* + * A resource can be associated with the TracerProvider when the TracerProvider is created. + * That association cannot be changed later. When associated with a TracerProvider, all + * Spans produced by any Tracer from the provider MUST be associated with this Resource. + */ + $primary = $this->getResource(); $resource = ResourceInfo::create( new Attributes( [ - ResourceConstants::TELEMETRY_SDK_NAME => 'opentelemetry', - ResourceConstants::TELEMETRY_SDK_LANGUAGE => 'php', - ResourceConstants::TELEMETRY_SDK_VERSION => 'dev', ResourceConstants::SERVICE_NAME => $name, ResourceConstants::SERVICE_VERSION => $version, ResourceConstants::SERVICE_INSTANCE_ID => uniqid($name . $version), @@ -70,7 +72,7 @@ final class TracerProvider implements API\TracerProvider return $this->tracers[$name] = new Tracer( $this, - ResourceInfo::merge($this->getResource(), $resource), + ResourceInfo::merge($primary, $resource), $spanContext ); } @@ -94,6 +96,6 @@ final class TracerProvider implements API\TracerProvider public function getResource(): ResourceInfo { - return $this->resource; + return clone $this->resource; } } diff --git a/tests/Sdk/Unit/Resource/ResourceTest.php b/tests/Sdk/Unit/Resource/ResourceTest.php index 314e2e3c..69a5755e 100644 --- a/tests/Sdk/Unit/Resource/ResourceTest.php +++ b/tests/Sdk/Unit/Resource/ResourceTest.php @@ -4,6 +4,7 @@ declare(strict_types=1); namespace OpenTelemetry\Tests\Sdk\Unit\Resource; +use OpenTelemetry\Sdk\Resource\ResourceConstants; use OpenTelemetry\Sdk\Resource\ResourceInfo; use OpenTelemetry\Sdk\Trace\Attribute; use OpenTelemetry\Sdk\Trace\Attributes; @@ -19,7 +20,9 @@ class ResourceTest extends TestCase $resource = ResourceInfo::emptyResource(); $this->assertEmpty($resource->getAttributes()); } - + /** + * @test + */ public function testGetAttributes() { $attributes = new Attributes(); @@ -28,11 +31,54 @@ class ResourceTest extends TestCase /** @var Attribute $name */ $name = $resource->getAttributes()->getAttribute('name'); + /** @var Attribute $sdkname */ + $sdkname = $resource->getAttributes()->getAttribute(ResourceConstants::TELEMETRY_SDK_NAME); + /** @var Attribute $sdklanguage */ + $sdklanguage = $resource->getAttributes()->getAttribute(ResourceConstants::TELEMETRY_SDK_LANGUAGE); + /** @var Attribute $sdkversion */ + $sdkversion = $resource->getAttributes()->getAttribute(ResourceConstants::TELEMETRY_SDK_VERSION); + $attributes->setAttribute(ResourceConstants::TELEMETRY_SDK_NAME, 'opentelemetry'); + $attributes->setAttribute(ResourceConstants::TELEMETRY_SDK_LANGUAGE, 'php'); + $attributes->setAttribute(ResourceConstants::TELEMETRY_SDK_VERSION, 'dev'); + + $this->assertEquals($attributes, $resource->getAttributes()); + $this->assertEquals('opentelemetry', $sdkname->getValue()); + $this->assertEquals('php', $sdklanguage->getValue()); + $this->assertEquals('dev', $sdkversion->getValue()); $this->assertEquals($attributes, $resource->getAttributes()); $this->assertEquals('test', $name->getValue()); } + /** + * @test + */ + public function testDefaultResource() + { + $attributes = new Attributes( + [ + ResourceConstants::TELEMETRY_SDK_NAME => 'opentelemetry', + ResourceConstants::TELEMETRY_SDK_LANGUAGE => 'php', + ResourceConstants::TELEMETRY_SDK_VERSION => 'dev', + ] + ); + $resource = ResourceInfo::create(new Attributes()); + /** @var Attribute $sdkname */ + $sdkname = $resource->getAttributes()->getAttribute(ResourceConstants::TELEMETRY_SDK_NAME); + /** @var Attribute $sdklanguage */ + $sdklanguage = $resource->getAttributes()->getAttribute(ResourceConstants::TELEMETRY_SDK_LANGUAGE); + /** @var Attribute $sdkversion */ + $sdkversion = $resource->getAttributes()->getAttribute(ResourceConstants::TELEMETRY_SDK_VERSION); + + $this->assertEquals($attributes, $resource->getAttributes()); + $this->assertEquals('opentelemetry', $sdkname->getValue()); + $this->assertEquals('php', $sdklanguage->getValue()); + $this->assertEquals('dev', $sdkversion->getValue()); + } + + /** + * @test + */ public function testMerge() { $primary = ResourceInfo::create(new Attributes(['name' => 'primary', 'empty' => ''])); @@ -46,12 +92,15 @@ class ResourceTest extends TestCase /** @var Attribute $empty */ $empty = $result->getAttributes()->getAttribute('empty'); - $this->assertCount(3, $result->getAttributes()); + $this->assertCount(6, $result->getAttributes()); $this->assertEquals('primary', $name->getValue()); $this->assertEquals('1.0.0', $version->getValue()); $this->assertEquals('value', $empty->getValue()); } + /** + * @test + */ public function testImmutableCreate() { $attributes = new Attributes(); diff --git a/tests/Sdk/Unit/Trace/TracerProviderTest.php b/tests/Sdk/Unit/Trace/TracerProviderTest.php index 6bd93a4d..25a222b0 100644 --- a/tests/Sdk/Unit/Trace/TracerProviderTest.php +++ b/tests/Sdk/Unit/Trace/TracerProviderTest.php @@ -4,10 +4,15 @@ declare(strict_types=1); namespace OpenTelemetry\Tests\Sdk\Unit\Trace; +use OpenTelemetry\Sdk\Resource\ResourceConstants; +use OpenTelemetry\Sdk\Resource\ResourceInfo; +use OpenTelemetry\Sdk\Trace\Attribute; +use OpenTelemetry\Sdk\Trace\Attributes; use OpenTelemetry\Sdk\Trace\Sampler\AlwaysOffSampler; use OpenTelemetry\Sdk\Trace\Sampler\AlwaysOnSampler; use OpenTelemetry\Sdk\Trace\Sampler\ParentBased; use OpenTelemetry\Sdk\Trace\Sampler\TraceIdRatioBasedSampler; +use OpenTelemetry\Sdk\Trace\Tracer; use OpenTelemetry\Sdk\Trace\TracerProvider; use PHPUnit\Framework\TestCase; @@ -62,4 +67,104 @@ class TracerProviderTest extends TestCase self::assertSame($description, 'TraceIdRatioBasedSampler{0.500000}'); } + /** + * @test + */ + public function newTraceProvidersProvidesEmptyResource() + { + $traceProvider = new TracerProvider(); + $resource = $traceProvider->getResource(); + $attributes = $resource->getAttributes(); + + $this->assertCount(0, $attributes); + } + /** + * @test + */ + public function newTraceProviderWithTracerProvidesNonEmptyResource() + { + $traceProvider = new TracerProvider(); + /** @var Tracer $tracer */ + $tracer = $traceProvider->getTracer('name', 'version'); + $resource = $tracer->getResource(); + $attributes = $resource->getAttributes(); + + /** @var Attribute $sdkname */ + $sdkname = $resource->getAttributes()->getAttribute(ResourceConstants::TELEMETRY_SDK_NAME); + /** @var Attribute $sdklanguage */ + $sdklanguage = $resource->getAttributes()->getAttribute(ResourceConstants::TELEMETRY_SDK_LANGUAGE); + /** @var Attribute $sdkversion */ + $sdkversion = $resource->getAttributes()->getAttribute(ResourceConstants::TELEMETRY_SDK_VERSION); + /** @var Attribute $servicename */ + $servicename = $attributes->getAttribute(ResourceConstants::SERVICE_NAME); + /** @var Attribute $serviceversion */ + $serviceversion = $attributes->getAttribute(ResourceConstants::SERVICE_VERSION); + $this->assertEquals($attributes, $resource->getAttributes()); + + $this->assertEquals('opentelemetry', $sdkname->getValue()); + $this->assertEquals('php', $sdklanguage->getValue()); + $this->assertEquals('dev', $sdkversion->getValue()); + $this->assertEquals('name', $servicename->getValue()); + $this->assertEquals('version', $serviceversion->getValue()); + + $this->assertCount(6, $attributes); + } + /** + * @test + */ + public function tracerFromTraceProviderAssociatesWithTraceProviderResource() + { + /* + * A resource can be associated with the TracerProvider when the TracerProvider is created. + * That association cannot be changed later. When associated with a TracerProvider, all + * Spans produced by any Tracer from the provider MUST be associated with this Resource. + */ + + // Create a new provider with a resource containing 2 attributes. + $providerResource = ResourceInfo::create(new Attributes(['provider' => 'primary', 'empty' => ''])); + $traceProvider = new TracerProvider($providerResource); + $tpAttributes = $traceProvider->getResource()->getAttributes(); + + // Verify the resource associated with the trace provider. + $this->assertCount(5, $tpAttributes); + /** @var Attribute $primary */ + $primary = $tpAttributes->getAttribute('provider'); + /** @var Attribute $empty */ + $empty = $tpAttributes->getAttribute('empty'); + $this->assertEquals('primary', $primary->getValue()); + $this->assertEquals('', $empty->getValue()); + + // Add a Tracer. The trace provider should add its resource to the new Tracer. + /** @var Tracer $tracer */ + $tracer = $traceProvider->getTracer('name', 'version'); + $resource = $tracer->getResource(); + $attributes = $resource->getAttributes(); + + // Verify the resource associated with the tracer. + /** @var Attribute $sdkname */ + $sdkname = $resource->getAttributes()->getAttribute(ResourceConstants::TELEMETRY_SDK_NAME); + /** @var Attribute $sdklanguage */ + $sdklanguage = $resource->getAttributes()->getAttribute(ResourceConstants::TELEMETRY_SDK_LANGUAGE); + /** @var Attribute $sdkversion */ + $sdkversion = $resource->getAttributes()->getAttribute(ResourceConstants::TELEMETRY_SDK_VERSION); + /** @var Attribute $servicename */ + $servicename = $attributes->getAttribute(ResourceConstants::SERVICE_NAME); + /** @var Attribute $serviceversion */ + $serviceversion = $attributes->getAttribute(ResourceConstants::SERVICE_VERSION); + + /** @var Attribute $primary */ + $primary = $attributes->getAttribute('provider'); + /** @var Attribute $empty */ + $empty = $attributes->getAttribute('empty'); + $this->assertEquals('primary', $primary->getValue()); + $this->assertEquals('', $empty->getValue()); + + $this->assertEquals('opentelemetry', $sdkname->getValue()); + $this->assertEquals('php', $sdklanguage->getValue()); + $this->assertEquals('dev', $sdkversion->getValue()); + $this->assertEquals('name', $servicename->getValue()); + $this->assertEquals('version', $serviceversion->getValue()); + + $this->assertCount(8, $attributes); + } } diff --git a/tests/Sdk/Unit/Trace/TracingTest.php b/tests/Sdk/Unit/Trace/TracingTest.php index f34f9eaf..e896482c 100644 --- a/tests/Sdk/Unit/Trace/TracingTest.php +++ b/tests/Sdk/Unit/Trace/TracingTest.php @@ -5,14 +5,17 @@ declare(strict_types=1); namespace OpenTelemetry\Tests\Sdk\Unit\Trace; use function iterator_to_array; +use OpenTelemetry\Sdk\Resource\ResourceConstants; use OpenTelemetry\Sdk\Resource\ResourceInfo; use OpenTelemetry\Sdk\Trace as SDK; use OpenTelemetry\Sdk\Trace\Attribute; use OpenTelemetry\Sdk\Trace\Attributes; use OpenTelemetry\Sdk\Trace\Clock; +use OpenTelemetry\Sdk\Trace\Span; use OpenTelemetry\Sdk\Trace\SpanContext; use OpenTelemetry\Sdk\Trace\SpanStatus; use OpenTelemetry\Sdk\Trace\Tracer; +use OpenTelemetry\Sdk\Trace\TracerProvider; use PHPUnit\Framework\TestCase; class TracingTest extends TestCase @@ -336,4 +339,340 @@ class TracingTest extends TestCase $tracer->getActiveSpan() ); } + + public function testCreateSpanResourceNonDefaultTraceProviderNonDefaultTrace() + { + /* + * A resource can be associated with the TracerProvider when the TracerProvider is created. + * That association cannot be changed later. When associated with a TracerProvider, all + * Spans produced by any Tracer from the provider MUST be associated with this Resource. + */ + + // Create a new provider with a resource containing 2 attributes. + $providerResource = ResourceInfo::create(new Attributes(['provider' => 'primary', 'empty' => ''])); + $traceProvider = new TracerProvider($providerResource); + $tpAttributes = $traceProvider->getResource()->getAttributes(); + + // Verify the resource associated with the trace provider. + $this->assertCount(5, $tpAttributes); + /** @var Attribute $primary */ + $primary = $tpAttributes->getAttribute('provider'); + /** @var Attribute $empty */ + $empty = $tpAttributes->getAttribute('empty'); + $this->assertEquals('primary', $primary->getValue()); + $this->assertEquals('', $empty->getValue()); + + // Add a Tracer. The trace provider should add its resource to the new Tracer. + /** @var Tracer $tracer */ + $tracer = $traceProvider->getTracer('name', 'version'); + $resource = $tracer->getResource(); + $attributes = $resource->getAttributes(); + + // Verify the resource associated with the tracer. + /** @var Attribute $name */ + $name = $resource->getAttributes()->getAttribute('name'); + /** @var Attribute $sdkname */ + $sdkname = $resource->getAttributes()->getAttribute(ResourceConstants::TELEMETRY_SDK_NAME); + /** @var Attribute $sdklanguage */ + $sdklanguage = $resource->getAttributes()->getAttribute(ResourceConstants::TELEMETRY_SDK_LANGUAGE); + /** @var Attribute $sdkversion */ + $sdkversion = $resource->getAttributes()->getAttribute(ResourceConstants::TELEMETRY_SDK_VERSION); + /** @var Attribute $servicename */ + $servicename = $attributes->getAttribute(ResourceConstants::SERVICE_NAME); + /** @var Attribute $serviceversion */ + $serviceversion = $attributes->getAttribute(ResourceConstants::SERVICE_VERSION); + + /** @var Attribute $primary */ + $primary = $attributes->getAttribute('provider'); + /** @var Attribute $empty */ + $empty = $attributes->getAttribute('empty'); + $this->assertEquals('primary', $primary->getValue()); + $this->assertEquals('', $empty->getValue()); + + $this->assertEquals('opentelemetry', $sdkname->getValue()); + $this->assertEquals('php', $sdklanguage->getValue()); + $this->assertEquals('dev', $sdkversion->getValue()); + $this->assertEquals('name', $servicename->getValue()); + $this->assertEquals('version', $serviceversion->getValue()); + + $this->assertCount(8, $attributes); + + // Start a span with the tracer. + $tracer->startAndActivateSpan('firstSpan'); + + /** @var Span $global */ + $global = $tracer->getActiveSpan(); + $this->assertSame($tracer->getActiveSpan(), $global); + + // Verify the resource associated with the span. + /** @var Attributes $attributes */ + $attributes = $global->getResource()->getAttributes(); + + /** @var Attribute $name */ + $name = $resource->getAttributes()->getAttribute('name'); + /** @var Attribute $sdkname */ + $sdkname = $resource->getAttributes()->getAttribute(ResourceConstants::TELEMETRY_SDK_NAME); + /** @var Attribute $sdklanguage */ + $sdklanguage = $resource->getAttributes()->getAttribute(ResourceConstants::TELEMETRY_SDK_LANGUAGE); + /** @var Attribute $sdkversion */ + $sdkversion = $resource->getAttributes()->getAttribute(ResourceConstants::TELEMETRY_SDK_VERSION); + /** @var Attribute $servicename */ + $servicename = $attributes->getAttribute(ResourceConstants::SERVICE_NAME); + /** @var Attribute $serviceversion */ + $serviceversion = $attributes->getAttribute(ResourceConstants::SERVICE_VERSION); + + /** @var Attribute $primary */ + $primary = $attributes->getAttribute('provider'); + /** @var Attribute $empty */ + $empty = $attributes->getAttribute('empty'); + $this->assertEquals('primary', $primary->getValue()); + $this->assertEquals('', $empty->getValue()); + + $this->assertEquals('opentelemetry', $sdkname->getValue()); + $this->assertEquals('php', $sdklanguage->getValue()); + $this->assertEquals('dev', $sdkversion->getValue()); + $this->assertEquals('name', $servicename->getValue()); + $this->assertEquals('version', $serviceversion->getValue()); + + $this->assertCount(8, $attributes); + } + + public function testCreateSpanGetsResourceFromDefaultTraceProviderDefaultTrace() + { + /* + * A resource can be associated with the TracerProvider when the TracerProvider is created. + * That association cannot be changed later. When associated with a TracerProvider, all + * Spans produced by any Tracer from the provider MUST be associated with this Resource. + */ + + // Create a new provider. + $traceProvider = new TracerProvider(); + $tpAttributes = $traceProvider->getResource()->getAttributes(); + + // Verify the resource associated with the trace provider. + $this->assertCount(0, $tpAttributes); + + // Add a Tracer. The trace provider should merge its resource one inherited from the traceprovider. + /** @var Tracer $tracer */ + $tracer = $traceProvider->getTracer('name'); + $resource = $tracer->getResource(); + $attributes = $resource->getAttributes(); + + // Verify the resource associated with the tracer. + /** @var Attribute $sdkname */ + $sdkname = $resource->getAttributes()->getAttribute(ResourceConstants::TELEMETRY_SDK_NAME); + /** @var Attribute $sdklanguage */ + $sdklanguage = $resource->getAttributes()->getAttribute(ResourceConstants::TELEMETRY_SDK_LANGUAGE); + /** @var Attribute $sdkversion */ + $sdkversion = $resource->getAttributes()->getAttribute(ResourceConstants::TELEMETRY_SDK_VERSION); + /** @var Attribute $servicename */ + $servicename = $attributes->getAttribute(ResourceConstants::SERVICE_NAME); + /** @var Attribute $serviceversion */ + $serviceversion = $attributes->getAttribute(ResourceConstants::SERVICE_VERSION); + + $this->assertEquals('opentelemetry', $sdkname->getValue()); + $this->assertEquals('php', $sdklanguage->getValue()); + $this->assertEquals('dev', $sdkversion->getValue()); + $this->assertEquals('name', $servicename->getValue()); + $this->assertEquals('', $serviceversion->getValue()); + + $this->assertCount(6, $attributes); + + // Start a span with the tracer. + $tracer->startAndActivateSpan('firstSpan'); + /** @var Span $global */ + $global = $tracer->getActiveSpan(); + $this->assertSame($tracer->getActiveSpan(), $global); + + // Verify the resource associated with the span. + + $attributes = $global->getResource()->getAttributes(); + + /** @var Attribute $sdkname */ + $sdkname = $resource->getAttributes()->getAttribute(ResourceConstants::TELEMETRY_SDK_NAME); + /** @var Attribute $sdklanguage */ + $sdklanguage = $resource->getAttributes()->getAttribute(ResourceConstants::TELEMETRY_SDK_LANGUAGE); + /** @var Attribute $sdkversion */ + $sdkversion = $resource->getAttributes()->getAttribute(ResourceConstants::TELEMETRY_SDK_VERSION); + /** @var Attribute $servicename */ + $servicename = $attributes->getAttribute(ResourceConstants::SERVICE_NAME); + /** @var Attribute $serviceversion */ + $serviceversion = $attributes->getAttribute(ResourceConstants::SERVICE_VERSION); + + $this->assertEquals('opentelemetry', $sdkname->getValue()); + $this->assertEquals('php', $sdklanguage->getValue()); + $this->assertEquals('dev', $sdkversion->getValue()); + $this->assertEquals('name', $servicename->getValue()); + $this->assertEquals('', $serviceversion->getValue()); + + $this->assertCount(6, $attributes); + } + + public function testCreateSpanGetsResourceFromNonDefaultTraceProviderDefaultTrace() + { + /* + * A resource can be associated with the TracerProvider when the TracerProvider is created. + * That association cannot be changed later. When associated with a TracerProvider, all + * Spans produced by any Tracer from the provider MUST be associated with this Resource. + */ + + // Create a new provider with a resource containing 2 attributes. + $providerResource = ResourceInfo::create(new Attributes(['provider' => 'primary', 'empty' => ''])); + $traceProvider = new TracerProvider($providerResource); + $tpAttributes = $traceProvider->getResource()->getAttributes(); + + // Verify the resource associated with the trace provider. + $this->assertCount(5, $tpAttributes); + + /** @var Attribute $primary */ + $primary = $tpAttributes->getAttribute('provider'); + /** @var Attribute $empty */ + $empty = $tpAttributes->getAttribute('empty'); + $this->assertEquals('primary', $primary->getValue()); + $this->assertEquals('', $empty->getValue()); + + // Add a Tracer. The trace provider should add its resource to the new Tracer. + /** @var Tracer $tracer */ + $tracer = $traceProvider->getTracer('name'); + $resource = $tracer->getResource(); + $attributes = $resource->getAttributes(); + + // Verify the resource associated with the tracer. + /** @var Attribute $name */ + $name = $resource->getAttributes()->getAttribute('name'); + /** @var Attribute $sdkname */ + $sdkname = $resource->getAttributes()->getAttribute(ResourceConstants::TELEMETRY_SDK_NAME); + /** @var Attribute $sdklanguage */ + $sdklanguage = $resource->getAttributes()->getAttribute(ResourceConstants::TELEMETRY_SDK_LANGUAGE); + /** @var Attribute $sdkversion */ + $sdkversion = $resource->getAttributes()->getAttribute(ResourceConstants::TELEMETRY_SDK_VERSION); + /** @var Attribute $servicename */ + $servicename = $attributes->getAttribute(ResourceConstants::SERVICE_NAME); + /** @var Attribute $serviceversion */ + $serviceversion = $attributes->getAttribute(ResourceConstants::SERVICE_VERSION); + + /** @var Attribute $primary */ + $primary = $attributes->getAttribute('provider'); + /** @var Attribute $empty */ + $empty = $attributes->getAttribute('empty'); + $this->assertEquals('primary', $primary->getValue()); + $this->assertEquals('', $empty->getValue()); + + $this->assertEquals('opentelemetry', $sdkname->getValue()); + $this->assertEquals('php', $sdklanguage->getValue()); + $this->assertEquals('dev', $sdkversion->getValue()); + $this->assertEquals('name', $servicename->getValue()); + $this->assertEquals('', $serviceversion->getValue()); + + $this->assertCount(8, $attributes); + + // Start a span with the tracer. + $tracer->startAndActivateSpan('firstSpan'); + + /** @var Span $global */ + $global = $tracer->getActiveSpan(); + $this->assertSame($tracer->getActiveSpan(), $global); + + // Verify the resource associated with the span. + + $attributes = $global->getResource()->getAttributes(); + + /** @var Attribute $sdkname */ + $sdkname = $resource->getAttributes()->getAttribute(ResourceConstants::TELEMETRY_SDK_NAME); + /** @var Attribute $sdklanguage */ + $sdklanguage = $resource->getAttributes()->getAttribute(ResourceConstants::TELEMETRY_SDK_LANGUAGE); + /** @var Attribute $sdkversion */ + $sdkversion = $resource->getAttributes()->getAttribute(ResourceConstants::TELEMETRY_SDK_VERSION); + /** @var Attribute $servicename */ + $servicename = $attributes->getAttribute(ResourceConstants::SERVICE_NAME); + /** @var Attribute $serviceversion */ + $serviceversion = $attributes->getAttribute(ResourceConstants::SERVICE_VERSION); + + /** @var Attribute $primary */ + $primary = $attributes->getAttribute('provider'); + /** @var Attribute $empty */ + $empty = $attributes->getAttribute('empty'); + $this->assertEquals('primary', $primary->getValue()); + $this->assertEquals('', $empty->getValue()); + + $this->assertEquals('opentelemetry', $sdkname->getValue()); + $this->assertEquals('php', $sdklanguage->getValue()); + $this->assertEquals('dev', $sdkversion->getValue()); + $this->assertEquals('name', $servicename->getValue()); + $this->assertEquals('', $serviceversion->getValue()); + + $this->assertCount(8, $attributes); + } + + public function testCreateSpanGetsResourceFromDefaultTraceProviderNonDefaultTrace() + { + /* + * A resource can be associated with the TracerProvider when the TracerProvider is created. + * That association cannot be changed later. When associated with a TracerProvider, all + * Spans produced by any Tracer from the provider MUST be associated with this Resource. + */ + + // Create a new provider. + $traceProvider = new TracerProvider(); + $tpAttributes = $traceProvider->getResource()->getAttributes(); + + // Verify the resource associated with the trace provider. + $this->assertCount(0, $tpAttributes); + + // Add a Tracer. The trace provider should merge its resource one inherited from the traceprovider. + /** @var Tracer $tracer */ + $tracer = $traceProvider->getTracer('name', 'version'); + $resource = $tracer->getResource(); + $attributes = $resource->getAttributes(); + + // Verify the resource associated with the tracer. + /** @var Attribute $sdkname */ + $sdkname = $resource->getAttributes()->getAttribute(ResourceConstants::TELEMETRY_SDK_NAME); + /** @var Attribute $sdklanguage */ + $sdklanguage = $resource->getAttributes()->getAttribute(ResourceConstants::TELEMETRY_SDK_LANGUAGE); + /** @var Attribute $sdkversion */ + $sdkversion = $resource->getAttributes()->getAttribute(ResourceConstants::TELEMETRY_SDK_VERSION); + /** @var Attribute $servicename */ + $servicename = $attributes->getAttribute(ResourceConstants::SERVICE_NAME); + /** @var Attribute $serviceversion */ + $serviceversion = $attributes->getAttribute(ResourceConstants::SERVICE_VERSION); + + $this->assertEquals('opentelemetry', $sdkname->getValue()); + $this->assertEquals('php', $sdklanguage->getValue()); + $this->assertEquals('dev', $sdkversion->getValue()); + $this->assertEquals('name', $servicename->getValue()); + $this->assertEquals('version', $serviceversion->getValue()); + + $this->assertCount(6, $attributes); + + // Start a span with the tracer. + $tracer->startAndActivateSpan('firstSpan'); + + /** @var Span $global */ + $global = $tracer->getActiveSpan(); + $this->assertSame($tracer->getActiveSpan(), $global); + + // Verify the resource associated with the span. + + $attributes = $global->getResource()->getAttributes(); + + /** @var Attribute $sdkname */ + $sdkname = $resource->getAttributes()->getAttribute(ResourceConstants::TELEMETRY_SDK_NAME); + /** @var Attribute $sdklanguage */ + $sdklanguage = $resource->getAttributes()->getAttribute(ResourceConstants::TELEMETRY_SDK_LANGUAGE); + /** @var Attribute $sdkversion */ + $sdkversion = $resource->getAttributes()->getAttribute(ResourceConstants::TELEMETRY_SDK_VERSION); + /** @var Attribute $servicename */ + $servicename = $attributes->getAttribute(ResourceConstants::SERVICE_NAME); + /** @var Attribute $serviceversion */ + $serviceversion = $attributes->getAttribute(ResourceConstants::SERVICE_VERSION); + + $this->assertEquals('opentelemetry', $sdkname->getValue()); + $this->assertEquals('php', $sdklanguage->getValue()); + $this->assertEquals('dev', $sdkversion->getValue()); + $this->assertEquals('name', $servicename->getValue()); + $this->assertEquals('version', $serviceversion->getValue()); + + $this->assertCount(6, $attributes); + } }