scopeManager = $this->createMock(ScopeManager::class); $this->sampler = $this->createMock(SamplerInterface::class); $this->reporter = $this->createMock(ReporterInterface::class); $this->logger = new NullLogger(); $this->tracer = new Tracer($this->serviceName, $this->reporter, $this->sampler, true, $this->logger, $this->scopeManager); } public function testStartSpan(): void { $span = $this->tracer->startSpan($this->operationName); $this->assertEquals($this->operationName, $span->getOperationName()); } public function testStartActiveSpan(): void { $tracer = new Tracer($this->serviceName, $this->reporter, $this->sampler); $tracer->startActiveSpan('test-operation1'); $this->assertEquals('test-operation1', $tracer->getActiveSpan()->getOperationName()); $scope = $tracer->startActiveSpan('test-operation2'); $this->assertEquals('test-operation2', $tracer->getActiveSpan()->getOperationName()); $scope->close(); $this->assertEquals('test-operation1', $tracer->getActiveSpan()->getOperationName()); } /** @test */ public function shouldAddConfiguredTagsToStartedSpanWhenSampled(): void { $this->sampler->expects($this->any()) ->method('isSampled') ->willReturn([true, []]); $tags = [ 'bar' => 'a-value', 'other.tag' => 'foo', ]; $tracer = new Tracer( $this->serviceName, $this->reporter, $this->sampler, true, $this->logger, $this->scopeManager, TRACE_ID_HEADER, BAGGAGE_HEADER_PREFIX, DEBUG_ID_HEADER_KEY, $tags ); $span = $tracer->startSpan('test-span'); $spanTags = $span->getTags(); foreach ($tags as $name => $value) { $this->assertArrayHasKey($name, $spanTags, "Tag '$name' should be set on span"); $this->assertEquals($value, $spanTags[$name]->value, "Tag '$name' should have configured value"); } } /** @test */ public function shouldAddNoConfiguredTagsToStartedSpanWhenNotSampled(): void { $this->sampler->expects($this->any()) ->method('isSampled') ->willReturn([false, []]); $tags = [ 'bar' => 'a-value', 'other.tag' => 'foo', ]; $tracer = new Tracer( $this->serviceName, $this->reporter, $this->sampler, true, $this->logger, $this->scopeManager, TRACE_ID_HEADER, BAGGAGE_HEADER_PREFIX, DEBUG_ID_HEADER_KEY, $tags ); $span = $tracer->startSpan('test-span'); $this->assertEquals([], $span->getTags(), 'No tags should be set when not sampled'); } /** @test */ public function shouldThrowExceptionOnInvalidFormat(): void { $spanContext = new SpanContext(0, 0, 0, 0); $carrier = []; $this->expectException(UnsupportedFormatException::class); $this->expectExceptionMessage('The format "bad-format" is not supported.'); $this->tracer->inject($spanContext, 'bad-format', $carrier); $this->assertSame([], $carrier); } /** @test */ public function shouldNotThrowExceptionOnInvalidContext(): void { $spanContext = new NoopSpanContext(); $carrier = []; $this->tracer->inject($spanContext, ZIPKIN_SPAN_FORMAT, $carrier); $this->assertSame([], $carrier); } /** @test */ public function shouldInjectSpanContextToCarrier(): void { $spanContext = new SpanContext(0, 0, 0, 0); $carrier = []; $this->tracer->inject($spanContext, TEXT_MAP, $carrier); $this->assertCount(1, $carrier); $this->assertEquals('0:0:0:0', $carrier[TRACE_ID_HEADER]); } /** @test */ public function shouldThrowExceptionOnExtractInvalidFormat(): void { $this->expectException(UnsupportedFormatException::class); $this->expectExceptionMessage('The format "bad-format" is not supported.'); $this->tracer->extract('bad-format', []); } /** @test */ public function shouldNotThrowExceptionOnExtractFromMalformedState(): void { $this->assertNull($this->tracer->extract(TEXT_MAP, ['uber-trace-id' => ''])); } /** @test */ public function shouldExtractSpanContextFromCarrier(): void { $carrier = ['uber-trace-id' => '32834e4115071776:f7802330248418d:f123456789012345:1']; $this->assertInstanceOf(SpanContext::class, $this->tracer->extract(TEXT_MAP, $carrier)); } public function testGetScopeManager() { $this->assertEquals($this->scopeManager, $this->tracer->getScopeManager()); } public function testGetActiveSpan(): void { $span = $this->createMock(Span::class); $scope = $this->createMock(Scope::class); $scope->expects($this->once())->method('getSpan')->willReturn($span); $this->scopeManager->expects($this->once())->method('getActive')->willReturn($scope); $this->assertEquals($span, $this->tracer->getActiveSpan()); } public function testGetActiveSpanNull(): void { $this->scopeManager->expects($this->once())->method('getActive')->willReturn(null); $this->assertEquals(null, $this->tracer->getActiveSpan()); } public function testFlush(): void { $this->reporter->expects($this->once())->method('close'); $this->tracer->flush(); } /** @test */ public function shouldHandleEmptyHostName(): void { $tracer = new \ReflectionClass(Tracer::class); $getHostByName = $tracer->getMethod('getHostByName'); $getHostByName->setAccessible(true); $stub = $this->getMockBuilder(Tracer::class) ->disableOriginalConstructor() ->getMockForAbstractClass(); $logger = $tracer->getProperty('logger'); $logger->setAccessible(true); $logger->setValue($stub, $this->logger); $this->assertEquals('127.0.0.1', $getHostByName->invokeArgs($stub, [null])); } }