auto root span creation (#1354)
* auto root span creation proof of concept for automatically creating a root span on startup. the obvious deficiencies are: - no idea of response values (status code etc) - does not capture exceptions * deptrac
This commit is contained in:
		
							parent
							
								
									69825d395a
								
							
						
					
					
						commit
						5276df3171
					
				| 
						 | 
				
			
			@ -380,6 +380,7 @@ return [
 | 
			
		|||
        'vendor/phpunit/phpunit/src',
 | 
			
		||||
        'vendor/google/protobuf/src',
 | 
			
		||||
        'vendor/ramsey/uuid/src',
 | 
			
		||||
        'vendor/nyholm/psr7-server/src',
 | 
			
		||||
    ],
 | 
			
		||||
 | 
			
		||||
    // A list of individual files to include in analysis
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -9,6 +9,7 @@
 | 
			
		|||
    "require": {
 | 
			
		||||
        "php": "^8.1",
 | 
			
		||||
        "google/protobuf": "^3.22 || ^4.0",
 | 
			
		||||
        "nyholm/psr7-server": "^1.1",
 | 
			
		||||
        "php-http/discovery": "^1.14",
 | 
			
		||||
        "psr/http-client": "^1.0",
 | 
			
		||||
        "psr/http-client-implementation": "^1.0",
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -105,6 +105,10 @@ deptrac:
 | 
			
		|||
          collectors:
 | 
			
		||||
              - type: className
 | 
			
		||||
                regex: ^Ramsey\\Uuid\\*
 | 
			
		||||
      -   name: NyholmPsr7Server
 | 
			
		||||
          collectors:
 | 
			
		||||
              - type: className
 | 
			
		||||
                regex: ^Nyholm\\Psr7Server\\*
 | 
			
		||||
 | 
			
		||||
    ruleset:
 | 
			
		||||
      Context:
 | 
			
		||||
| 
						 | 
				
			
			@ -134,6 +138,7 @@ deptrac:
 | 
			
		|||
          - HttpClients
 | 
			
		||||
          - SPI
 | 
			
		||||
          - RamseyUuid
 | 
			
		||||
          - NyholmPsr7Server
 | 
			
		||||
      Contrib:
 | 
			
		||||
          - +SDK
 | 
			
		||||
          - +OtelProto
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -0,0 +1,22 @@
 | 
			
		|||
<?php
 | 
			
		||||
 | 
			
		||||
declare(strict_types=1);
 | 
			
		||||
 | 
			
		||||
namespace OpenTelemetry\Example;
 | 
			
		||||
 | 
			
		||||
use OpenTelemetry\API\Globals;
 | 
			
		||||
use OpenTelemetry\API\Logs\LogRecord;
 | 
			
		||||
 | 
			
		||||
putenv('OTEL_PHP_AUTOLOAD_ENABLED=true');
 | 
			
		||||
putenv('OTEL_TRACES_EXPORTER=console');
 | 
			
		||||
putenv('OTEL_METRICS_EXPORTER=none');
 | 
			
		||||
putenv('OTEL_LOGS_EXPORTER=console');
 | 
			
		||||
putenv('OTEL_PROPAGATORS=tracecontext');
 | 
			
		||||
putenv('OTEL_PHP_EXPERIMENTAL_AUTO_ROOT_SPAN=true');
 | 
			
		||||
 | 
			
		||||
//Usage: php -S localhost:8080 examples/traces/features/auto_root_span.php
 | 
			
		||||
 | 
			
		||||
require dirname(__DIR__, 3) . '/vendor/autoload.php';
 | 
			
		||||
 | 
			
		||||
Globals::loggerProvider()->getLogger('test')->emit(new LogRecord('I processed a request'));
 | 
			
		||||
echo 'hello world!' . PHP_EOL;
 | 
			
		||||
| 
						 | 
				
			
			@ -119,5 +119,6 @@ interface Defaults
 | 
			
		|||
    public const OTEL_PHP_DISABLED_INSTRUMENTATIONS = [];
 | 
			
		||||
    public const OTEL_PHP_LOGS_PROCESSOR = 'batch';
 | 
			
		||||
    public const OTEL_PHP_LOG_DESTINATION = 'default';
 | 
			
		||||
    public const OTEL_PHP_EXPERIMENTAL_AUTO_ROOT_SPAN = 'false';
 | 
			
		||||
    public const OTEL_EXPERIMENTAL_CONFIG_FILE = 'sdk-config.yaml';
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -140,5 +140,6 @@ interface Variables
 | 
			
		|||
    public const OTEL_PHP_INTERNAL_METRICS_ENABLED = 'OTEL_PHP_INTERNAL_METRICS_ENABLED'; //whether the SDK should emit its own metrics
 | 
			
		||||
    public const OTEL_PHP_DISABLED_INSTRUMENTATIONS = 'OTEL_PHP_DISABLED_INSTRUMENTATIONS';
 | 
			
		||||
    public const OTEL_PHP_EXCLUDED_URLS = 'OTEL_PHP_EXCLUDED_URLS';
 | 
			
		||||
    public const OTEL_PHP_EXPERIMENTAL_AUTO_ROOT_SPAN = 'OTEL_PHP_EXPERIMENTAL_AUTO_ROOT_SPAN';
 | 
			
		||||
    public const OTEL_EXPERIMENTAL_CONFIG_FILE = 'OTEL_EXPERIMENTAL_CONFIG_FILE';
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -72,7 +72,7 @@ final class ShutdownHandler
 | 
			
		|||
                // Push shutdown to end of queue
 | 
			
		||||
                // @phan-suppress-next-line PhanTypeMismatchArgumentInternal
 | 
			
		||||
                register_shutdown_function(static function (array $handlers): void {
 | 
			
		||||
                    foreach ($handlers as $handler) {
 | 
			
		||||
                    foreach (array_reverse($handlers) as $handler) {
 | 
			
		||||
                        $handler();
 | 
			
		||||
                    }
 | 
			
		||||
                }, $handlers);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -30,6 +30,7 @@ use OpenTelemetry\SDK\Logs\LoggerProviderFactory;
 | 
			
		|||
use OpenTelemetry\SDK\Metrics\MeterProviderFactory;
 | 
			
		||||
use OpenTelemetry\SDK\Propagation\PropagatorFactory;
 | 
			
		||||
use OpenTelemetry\SDK\Resource\ResourceInfoFactory;
 | 
			
		||||
use OpenTelemetry\SDK\Trace\AutoRootSpan;
 | 
			
		||||
use OpenTelemetry\SDK\Trace\ExporterFactory;
 | 
			
		||||
use OpenTelemetry\SDK\Trace\SamplerFactory;
 | 
			
		||||
use OpenTelemetry\SDK\Trace\SpanProcessorFactory;
 | 
			
		||||
| 
						 | 
				
			
			@ -55,6 +56,14 @@ class SdkAutoloader
 | 
			
		|||
        }
 | 
			
		||||
        self::registerInstrumentations();
 | 
			
		||||
 | 
			
		||||
        if (AutoRootSpan::isEnabled()) {
 | 
			
		||||
            $request = AutoRootSpan::createRequest();
 | 
			
		||||
            if ($request) {
 | 
			
		||||
                AutoRootSpan::create($request);
 | 
			
		||||
                AutoRootSpan::registerShutdownHandler();
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return true;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -228,4 +237,5 @@ class SdkAutoloader
 | 
			
		|||
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -0,0 +1,108 @@
 | 
			
		|||
<?php
 | 
			
		||||
 | 
			
		||||
declare(strict_types=1);
 | 
			
		||||
 | 
			
		||||
namespace OpenTelemetry\SDK\Trace;
 | 
			
		||||
 | 
			
		||||
use Http\Discovery\Exception\NotFoundException;
 | 
			
		||||
use Http\Discovery\Psr17FactoryDiscovery;
 | 
			
		||||
use Nyholm\Psr7Server\ServerRequestCreator;
 | 
			
		||||
use OpenTelemetry\API\Behavior\LogsMessagesTrait;
 | 
			
		||||
use OpenTelemetry\API\Globals;
 | 
			
		||||
use OpenTelemetry\API\Trace\Span;
 | 
			
		||||
use OpenTelemetry\API\Trace\SpanKind;
 | 
			
		||||
use OpenTelemetry\Context\Context;
 | 
			
		||||
use OpenTelemetry\SDK\Common\Configuration\Configuration;
 | 
			
		||||
use OpenTelemetry\SDK\Common\Configuration\Variables;
 | 
			
		||||
use OpenTelemetry\SDK\Common\Util\ShutdownHandler;
 | 
			
		||||
use OpenTelemetry\SemConv\TraceAttributes;
 | 
			
		||||
use OpenTelemetry\SemConv\Version;
 | 
			
		||||
use Psr\Http\Message\ServerRequestInterface;
 | 
			
		||||
 | 
			
		||||
class AutoRootSpan
 | 
			
		||||
{
 | 
			
		||||
    use LogsMessagesTrait;
 | 
			
		||||
 | 
			
		||||
    public static function isEnabled(): bool
 | 
			
		||||
    {
 | 
			
		||||
        return
 | 
			
		||||
            !empty($_SERVER['REQUEST_METHOD'] ?? null)
 | 
			
		||||
            && Configuration::getBoolean(Variables::OTEL_PHP_EXPERIMENTAL_AUTO_ROOT_SPAN);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * @psalm-suppress ArgumentTypeCoercion
 | 
			
		||||
     * @internal
 | 
			
		||||
     */
 | 
			
		||||
    public static function create(ServerRequestInterface $request): void
 | 
			
		||||
    {
 | 
			
		||||
        $tracer = Globals::tracerProvider()->getTracer(
 | 
			
		||||
            'io.opentelemetry.php.auto-root-span',
 | 
			
		||||
            null,
 | 
			
		||||
            Version::VERSION_1_25_0->url(),
 | 
			
		||||
        );
 | 
			
		||||
        $parent = Globals::propagator()->extract($request->getHeaders());
 | 
			
		||||
        $startTime = array_key_exists('REQUEST_TIME_FLOAT', $request->getServerParams())
 | 
			
		||||
            ? $request->getServerParams()['REQUEST_TIME_FLOAT']
 | 
			
		||||
            : (int) microtime(true);
 | 
			
		||||
        $span = $tracer->spanBuilder($request->getMethod())
 | 
			
		||||
            ->setSpanKind(SpanKind::KIND_SERVER)
 | 
			
		||||
            ->setStartTimestamp((int) ($startTime*1_000_000))
 | 
			
		||||
            ->setParent($parent)
 | 
			
		||||
            ->setAttribute(TraceAttributes::URL_FULL, (string) $request->getUri())
 | 
			
		||||
            ->setAttribute(TraceAttributes::HTTP_REQUEST_METHOD, $request->getMethod())
 | 
			
		||||
            ->setAttribute(TraceAttributes::HTTP_REQUEST_BODY_SIZE, $request->getHeaderLine('Content-Length'))
 | 
			
		||||
            ->setAttribute(TraceAttributes::USER_AGENT_ORIGINAL, $request->getHeaderLine('User-Agent'))
 | 
			
		||||
            ->setAttribute(TraceAttributes::SERVER_ADDRESS, $request->getUri()->getHost())
 | 
			
		||||
            ->setAttribute(TraceAttributes::SERVER_PORT, $request->getUri()->getPort())
 | 
			
		||||
            ->setAttribute(TraceAttributes::URL_SCHEME, $request->getUri()->getScheme())
 | 
			
		||||
            ->setAttribute(TraceAttributes::URL_PATH, $request->getUri()->getPath())
 | 
			
		||||
            ->startSpan();
 | 
			
		||||
        Context::storage()->attach($span->storeInContext($parent));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * @internal
 | 
			
		||||
     */
 | 
			
		||||
    public static function createRequest(): ?ServerRequestInterface
 | 
			
		||||
    {
 | 
			
		||||
        assert(array_key_exists('REQUEST_METHOD', $_SERVER) && !empty($_SERVER['REQUEST_METHOD']));
 | 
			
		||||
 | 
			
		||||
        try {
 | 
			
		||||
            $creator = new ServerRequestCreator(
 | 
			
		||||
                Psr17FactoryDiscovery::findServerRequestFactory(),
 | 
			
		||||
                Psr17FactoryDiscovery::findUriFactory(),
 | 
			
		||||
                Psr17FactoryDiscovery::findUploadedFileFactory(),
 | 
			
		||||
                Psr17FactoryDiscovery::findStreamFactory(),
 | 
			
		||||
            );
 | 
			
		||||
 | 
			
		||||
            return $creator->fromGlobals();
 | 
			
		||||
        } catch (NotFoundException $e) {
 | 
			
		||||
            self::logError('Unable to initialize server request creator for auto root span creation', ['exception' => $e]);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return null;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * @internal
 | 
			
		||||
     */
 | 
			
		||||
    public static function registerShutdownHandler(): void
 | 
			
		||||
    {
 | 
			
		||||
        ShutdownHandler::register(self::shutdownHandler(...));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * @internal
 | 
			
		||||
     */
 | 
			
		||||
    public static function shutdownHandler(): void
 | 
			
		||||
    {
 | 
			
		||||
        $scope = Context::storage()->scope();
 | 
			
		||||
        if (!$scope) {
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
        $scope->detach();
 | 
			
		||||
        $span = Span::fromContext($scope->context());
 | 
			
		||||
        $span->end();
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -19,6 +19,7 @@
 | 
			
		|||
    "require": {
 | 
			
		||||
        "php": "^8.1",
 | 
			
		||||
        "ext-json": "*",
 | 
			
		||||
        "nyholm/psr7-server": "^1.1",
 | 
			
		||||
        "open-telemetry/api": "~1.0 || ~1.1",
 | 
			
		||||
        "open-telemetry/context": "^1.0",
 | 
			
		||||
        "open-telemetry/sem-conv": "^1.0",
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -0,0 +1,56 @@
 | 
			
		|||
--TEST--
 | 
			
		||||
Auto root span creation
 | 
			
		||||
--ENV--
 | 
			
		||||
OTEL_PHP_AUTOLOAD_ENABLED=true
 | 
			
		||||
OTEL_PHP_EXPERIMENTAL_AUTO_ROOT_SPAN=true
 | 
			
		||||
OTEL_TRACES_EXPORTER=console
 | 
			
		||||
OTEL_METRICS_EXPORTER=none
 | 
			
		||||
OTEL_LOGS_EXPORTER=console
 | 
			
		||||
REQUEST_METHOD=GET
 | 
			
		||||
REQUEST_URI=/foo?bar=baz
 | 
			
		||||
REQUEST_SCHEME=https
 | 
			
		||||
SERVER_NAME=example.com
 | 
			
		||||
SERVER_PORT=8080
 | 
			
		||||
HTTP_HOST=example.com:8080
 | 
			
		||||
HTTP_USER_AGENT=my-user-agent/1.0
 | 
			
		||||
REQUEST_TIME_FLOAT=1721706151.242976
 | 
			
		||||
HTTP_TRACEPARENT=00-ff000000000000000000000000000041-ff00000000000041-01
 | 
			
		||||
--FILE--
 | 
			
		||||
<?php
 | 
			
		||||
require_once 'vendor/autoload.php';
 | 
			
		||||
?>
 | 
			
		||||
--EXPECTF--
 | 
			
		||||
[
 | 
			
		||||
    {
 | 
			
		||||
        "name": "GET",
 | 
			
		||||
        "context": {
 | 
			
		||||
            "trace_id": "ff000000000000000000000000000041",
 | 
			
		||||
            "span_id": "%s",
 | 
			
		||||
            "trace_state": "",
 | 
			
		||||
            "trace_flags": 1
 | 
			
		||||
        },
 | 
			
		||||
        "resource": {%A
 | 
			
		||||
        },
 | 
			
		||||
        "parent_span_id": "ff00000000000041",
 | 
			
		||||
        "kind": "KIND_SERVER",
 | 
			
		||||
        "start": 1721706151242976,
 | 
			
		||||
        "end": %d,
 | 
			
		||||
        "attributes": {
 | 
			
		||||
            "url.full": "%s",
 | 
			
		||||
            "http.request.method": "GET",
 | 
			
		||||
            "http.request.body.size": "",
 | 
			
		||||
            "user_agent.original": "my-user-agent\/1.0",
 | 
			
		||||
            "server.address": "%S",
 | 
			
		||||
            "server.port": %d,
 | 
			
		||||
            "url.scheme": "https",
 | 
			
		||||
            "url.path": "\/foo"
 | 
			
		||||
        },
 | 
			
		||||
        "status": {
 | 
			
		||||
            "code": "Unset",
 | 
			
		||||
            "description": ""
 | 
			
		||||
        },
 | 
			
		||||
        "events": [],
 | 
			
		||||
        "links": [],
 | 
			
		||||
        "schema_url": "%s"
 | 
			
		||||
    }
 | 
			
		||||
]
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,145 @@
 | 
			
		|||
<?php
 | 
			
		||||
 | 
			
		||||
declare(strict_types=1);
 | 
			
		||||
 | 
			
		||||
namespace OpenTelemetry\Tests\SDK\Trace;
 | 
			
		||||
 | 
			
		||||
use Nyholm\Psr7\ServerRequest;
 | 
			
		||||
use OpenTelemetry\API\Instrumentation\Configurator;
 | 
			
		||||
use OpenTelemetry\API\Trace\Propagation\TraceContextPropagator;
 | 
			
		||||
use OpenTelemetry\API\Trace\Span;
 | 
			
		||||
use OpenTelemetry\API\Trace\SpanBuilderInterface;
 | 
			
		||||
use OpenTelemetry\API\Trace\SpanInterface;
 | 
			
		||||
use OpenTelemetry\API\Trace\SpanKind;
 | 
			
		||||
use OpenTelemetry\API\Trace\TracerInterface;
 | 
			
		||||
use OpenTelemetry\API\Trace\TracerProviderInterface;
 | 
			
		||||
use OpenTelemetry\Context\Context;
 | 
			
		||||
use OpenTelemetry\Context\ContextInterface;
 | 
			
		||||
use OpenTelemetry\Context\ContextKeys;
 | 
			
		||||
use OpenTelemetry\Context\ScopeInterface;
 | 
			
		||||
use OpenTelemetry\SDK\Common\Configuration\Variables;
 | 
			
		||||
use OpenTelemetry\SDK\Trace\AutoRootSpan;
 | 
			
		||||
use OpenTelemetry\Tests\TestState;
 | 
			
		||||
use PHPUnit\Framework\Attributes\BackupGlobals;
 | 
			
		||||
use PHPUnit\Framework\Attributes\CoversClass;
 | 
			
		||||
use PHPUnit\Framework\Attributes\DataProvider;
 | 
			
		||||
use PHPUnit\Framework\MockObject\MockObject;
 | 
			
		||||
use PHPUnit\Framework\TestCase;
 | 
			
		||||
 | 
			
		||||
#[CoversClass(AutoRootSpan::class)]
 | 
			
		||||
class AutoRootSpanTest extends TestCase
 | 
			
		||||
{
 | 
			
		||||
    use TestState;
 | 
			
		||||
 | 
			
		||||
    /** @var (TracerInterface&MockObject) */
 | 
			
		||||
    private TracerInterface $tracer;
 | 
			
		||||
    private ScopeInterface $scope;
 | 
			
		||||
 | 
			
		||||
    public function setUp(): void
 | 
			
		||||
    {
 | 
			
		||||
        $tracerProvider = $this->createMock(TracerProviderInterface::class);
 | 
			
		||||
        $this->tracer = $this->createMock(TracerInterface::class);
 | 
			
		||||
        $tracerProvider->method('getTracer')->willReturn($this->tracer);
 | 
			
		||||
 | 
			
		||||
        $this->scope = Configurator::create()
 | 
			
		||||
            ->withTracerProvider($tracerProvider)
 | 
			
		||||
            ->withPropagator(new TraceContextPropagator())
 | 
			
		||||
            ->activate();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function tearDown(): void
 | 
			
		||||
    {
 | 
			
		||||
        $this->scope->detach();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    #[BackupGlobals(true)]
 | 
			
		||||
    #[DataProvider('enabledProvider')]
 | 
			
		||||
    public function test_is_enabled(string $enabled, ?string $method, bool $expected): void
 | 
			
		||||
    {
 | 
			
		||||
        $this->setEnvironmentVariable(Variables::OTEL_PHP_EXPERIMENTAL_AUTO_ROOT_SPAN, $enabled);
 | 
			
		||||
        $_SERVER['REQUEST_METHOD'] = $method;
 | 
			
		||||
 | 
			
		||||
        $this->assertSame($expected, AutoRootSpan::isEnabled());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static function enabledProvider(): array
 | 
			
		||||
    {
 | 
			
		||||
        return [
 | 
			
		||||
            ['true', 'GET', true],
 | 
			
		||||
            ['true', null, false],
 | 
			
		||||
            ['true', '', false],
 | 
			
		||||
            ['false', 'GET', false],
 | 
			
		||||
        ];
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    #[BackupGlobals(true)]
 | 
			
		||||
    public function test_create_request(): void
 | 
			
		||||
    {
 | 
			
		||||
        $_SERVER['REQUEST_METHOD'] = 'GET';
 | 
			
		||||
        $_SERVER['REQUEST_URI'] = '/foo';
 | 
			
		||||
 | 
			
		||||
        $request = AutoRootSpan::createRequest();
 | 
			
		||||
        $this->assertNotNull($request);
 | 
			
		||||
        $this->assertSame('GET', $request->getMethod());
 | 
			
		||||
        $this->assertSame('/foo', $request->getUri()->getPath());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function test_create(): void
 | 
			
		||||
    {
 | 
			
		||||
        $body = 'hello otel';
 | 
			
		||||
        $traceId = 'ff000000000000000000000000000041';
 | 
			
		||||
        $spanId = 'ff00000000000041';
 | 
			
		||||
        $traceParent = '00-' . $traceId . '-' . $spanId . '-01';
 | 
			
		||||
        $request = new ServerRequest('POST', 'https://example.com/foo?bar=baz', ['traceparent' => $traceParent], $body);
 | 
			
		||||
 | 
			
		||||
        $spanBuilder = $this->createMock(SpanBuilderInterface::class);
 | 
			
		||||
        $spanBuilder
 | 
			
		||||
            ->expects($this->once())
 | 
			
		||||
            ->method('setSpanKind')
 | 
			
		||||
            ->with($this->equalTo(SpanKind::KIND_SERVER))
 | 
			
		||||
            ->willReturnSelf();
 | 
			
		||||
        $spanBuilder
 | 
			
		||||
            ->expects($this->once())
 | 
			
		||||
            ->method('setStartTimestamp')
 | 
			
		||||
            ->willReturnSelf();
 | 
			
		||||
        $spanBuilder
 | 
			
		||||
            ->expects($this->once())
 | 
			
		||||
            ->method('setParent')
 | 
			
		||||
            ->with($this->callback(function (ContextInterface $parent) use ($traceId, $spanId) {
 | 
			
		||||
                $span = Span::fromContext($parent);
 | 
			
		||||
                $this->assertSame($traceId, $span->getContext()->getTraceId());
 | 
			
		||||
                $this->assertSame($spanId, $span->getContext()->getSpanId());
 | 
			
		||||
 | 
			
		||||
                return true;
 | 
			
		||||
            }))
 | 
			
		||||
            ->willReturnSelf();
 | 
			
		||||
        $spanBuilder
 | 
			
		||||
            ->expects($this->atLeast(8))
 | 
			
		||||
            ->method('setAttribute')
 | 
			
		||||
            ->willReturnSelf();
 | 
			
		||||
 | 
			
		||||
        $this->tracer
 | 
			
		||||
            ->expects($this->once())
 | 
			
		||||
            ->method('spanBuilder')
 | 
			
		||||
            ->with($this->equalTo('POST'))
 | 
			
		||||
            ->willReturn($spanBuilder);
 | 
			
		||||
 | 
			
		||||
        AutoRootSpan::create($request);
 | 
			
		||||
 | 
			
		||||
        $scope = Context::storage()->scope();
 | 
			
		||||
        $this->assertNotNull($scope);
 | 
			
		||||
        $scope->detach();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function test_shutdown_handler(): void
 | 
			
		||||
    {
 | 
			
		||||
        $this->setEnvironmentVariable('OTEL_PHP_DEBUG_SCOPES_DISABLED', 'true');
 | 
			
		||||
        $span = $this->createMock(SpanInterface::class);
 | 
			
		||||
        $span
 | 
			
		||||
            ->expects($this->once())
 | 
			
		||||
            ->method('end');
 | 
			
		||||
        Context::getCurrent()->with(ContextKeys::span(), $span)->activate();
 | 
			
		||||
 | 
			
		||||
        AutoRootSpan::shutdownHandler();
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
		Loading…
	
		Reference in New Issue