Add `TextMapPropagator` to instrumentation context (#1401)

This commit is contained in:
Tobias Bachert 2024-10-16 00:42:37 +02:00 committed by GitHub
parent c632d960a5
commit 2c1da9aaec
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 96 additions and 5 deletions

View File

@ -8,8 +8,6 @@ use Nevay\SPI\ServiceLoader;
use OpenTelemetry\API\Globals; use OpenTelemetry\API\Globals;
use OpenTelemetry\API\Instrumentation\AutoInstrumentation\ExtensionHookManager; use OpenTelemetry\API\Instrumentation\AutoInstrumentation\ExtensionHookManager;
use OpenTelemetry\API\Instrumentation\AutoInstrumentation\Instrumentation; use OpenTelemetry\API\Instrumentation\AutoInstrumentation\Instrumentation;
use OpenTelemetry\API\Logs\NoopLoggerProvider;
use OpenTelemetry\API\Metrics\Noop\NoopMeterProvider;
use OpenTelemetry\Config\SDK\Configuration; use OpenTelemetry\Config\SDK\Configuration;
use OpenTelemetry\Config\SDK\Configuration\Context; use OpenTelemetry\Config\SDK\Configuration\Context;
use OpenTelemetry\Example\Example; use OpenTelemetry\Example\Example;
@ -25,7 +23,7 @@ require __DIR__ . '/../../vendor/autoload.php';
Configuration::parseFile(__DIR__ . '/otel-sdk.yaml')->create(new Context())->setAutoShutdown(true)->buildAndRegisterGlobal(); Configuration::parseFile(__DIR__ . '/otel-sdk.yaml')->create(new Context())->setAutoShutdown(true)->buildAndRegisterGlobal();
$configuration = \OpenTelemetry\Config\SDK\Instrumentation::parseFile(__DIR__ . '/otel-sdk.yaml')->create(); $configuration = \OpenTelemetry\Config\SDK\Instrumentation::parseFile(__DIR__ . '/otel-sdk.yaml')->create();
$hookManager = new ExtensionHookManager(); $hookManager = new ExtensionHookManager();
$context = new \OpenTelemetry\API\Instrumentation\AutoInstrumentation\Context(Globals::tracerProvider(), new NoopMeterProvider(), new NoopLoggerProvider()); $context = new \OpenTelemetry\API\Instrumentation\AutoInstrumentation\Context(Globals::tracerProvider(), Globals::meterProvider(), Globals::loggerProvider(), Globals::propagator());
foreach (ServiceLoader::load(Instrumentation::class) as $instrumentation) { foreach (ServiceLoader::load(Instrumentation::class) as $instrumentation) {
$instrumentation->register($hookManager, $configuration, $context); $instrumentation->register($hookManager, $configuration, $context);

View File

@ -10,6 +10,8 @@ use OpenTelemetry\API\Metrics\MeterProviderInterface;
use OpenTelemetry\API\Metrics\Noop\NoopMeterProvider; use OpenTelemetry\API\Metrics\Noop\NoopMeterProvider;
use OpenTelemetry\API\Trace\NoopTracerProvider; use OpenTelemetry\API\Trace\NoopTracerProvider;
use OpenTelemetry\API\Trace\TracerProviderInterface; use OpenTelemetry\API\Trace\TracerProviderInterface;
use OpenTelemetry\Context\Propagation\NoopTextMapPropagator;
use OpenTelemetry\Context\Propagation\TextMapPropagatorInterface;
/** /**
* Context used for component creation. * Context used for component creation.
@ -20,6 +22,7 @@ final class Context
public readonly TracerProviderInterface $tracerProvider = new NoopTracerProvider(), public readonly TracerProviderInterface $tracerProvider = new NoopTracerProvider(),
public readonly MeterProviderInterface $meterProvider = new NoopMeterProvider(), public readonly MeterProviderInterface $meterProvider = new NoopMeterProvider(),
public readonly LoggerProviderInterface $loggerProvider = new NoopLoggerProvider(), public readonly LoggerProviderInterface $loggerProvider = new NoopLoggerProvider(),
public readonly TextMapPropagatorInterface $propagator = new NoopTextMapPropagator(),
) { ) {
} }
} }

View File

@ -0,0 +1,53 @@
<?php
declare(strict_types=1);
namespace OpenTelemetry\SDK\Propagation;
use Closure;
use OpenTelemetry\Context\ContextInterface;
use OpenTelemetry\Context\Propagation\PropagationGetterInterface;
use OpenTelemetry\Context\Propagation\PropagationSetterInterface;
use OpenTelemetry\Context\Propagation\TextMapPropagatorInterface;
/**
* @internal
*/
final class LateBindingTextMapPropagator implements TextMapPropagatorInterface
{
/**
* @param TextMapPropagatorInterface|Closure(): TextMapPropagatorInterface $propagator
*/
public function __construct(
private TextMapPropagatorInterface|Closure $propagator,
) {
}
public function fields(): array
{
if (!$this->propagator instanceof TextMapPropagatorInterface) {
$this->propagator = ($this->propagator)();
}
return $this->propagator->fields();
}
public function inject(mixed &$carrier, ?PropagationSetterInterface $setter = null, ?ContextInterface $context = null): void
{
if (!$this->propagator instanceof TextMapPropagatorInterface) {
$this->propagator = ($this->propagator)();
}
$this->propagator->inject($carrier, $setter, $context);
}
public function extract($carrier, ?PropagationGetterInterface $getter = null, ?ContextInterface $context = null): ContextInterface
{
if (!$this->propagator instanceof TextMapPropagatorInterface) {
$this->propagator = ($this->propagator)();
}
return $this->propagator->extract($carrier, $getter, $context);
}
}

View File

@ -23,12 +23,14 @@ use OpenTelemetry\API\Trace\TracerProviderInterface;
use OpenTelemetry\Config\SDK\Configuration as SdkConfiguration; use OpenTelemetry\Config\SDK\Configuration as SdkConfiguration;
use OpenTelemetry\Config\SDK\Instrumentation as SdkInstrumentation; use OpenTelemetry\Config\SDK\Instrumentation as SdkInstrumentation;
use OpenTelemetry\Context\Context; use OpenTelemetry\Context\Context;
use OpenTelemetry\Context\Propagation\TextMapPropagatorInterface;
use OpenTelemetry\SDK\Common\Configuration\Configuration; use OpenTelemetry\SDK\Common\Configuration\Configuration;
use OpenTelemetry\SDK\Common\Configuration\Variables; use OpenTelemetry\SDK\Common\Configuration\Variables;
use OpenTelemetry\SDK\Common\Util\ShutdownHandler; use OpenTelemetry\SDK\Common\Util\ShutdownHandler;
use OpenTelemetry\SDK\Logs\EventLoggerProviderFactory; use OpenTelemetry\SDK\Logs\EventLoggerProviderFactory;
use OpenTelemetry\SDK\Logs\LoggerProviderFactory; use OpenTelemetry\SDK\Logs\LoggerProviderFactory;
use OpenTelemetry\SDK\Metrics\MeterProviderFactory; use OpenTelemetry\SDK\Metrics\MeterProviderFactory;
use OpenTelemetry\SDK\Propagation\LateBindingTextMapPropagator;
use OpenTelemetry\SDK\Propagation\PropagatorFactory; use OpenTelemetry\SDK\Propagation\PropagatorFactory;
use OpenTelemetry\SDK\Resource\ResourceInfoFactory; use OpenTelemetry\SDK\Resource\ResourceInfoFactory;
use OpenTelemetry\SDK\Trace\AutoRootSpan; use OpenTelemetry\SDK\Trace\AutoRootSpan;
@ -154,7 +156,8 @@ class SdkAutoloader
$tracerProvider = self::createLateBindingTracerProvider(); $tracerProvider = self::createLateBindingTracerProvider();
$meterProvider = self::createLateBindingMeterProvider(); $meterProvider = self::createLateBindingMeterProvider();
$loggerProvider = self::createLateBindingLoggerProvider(); $loggerProvider = self::createLateBindingLoggerProvider();
$context = new InstrumentationContext($tracerProvider, $meterProvider, $loggerProvider); $propagator = self::createLateBindingTextMapPropagator();
$context = new InstrumentationContext($tracerProvider, $meterProvider, $loggerProvider, $propagator);
foreach (ServiceLoader::load(Instrumentation::class) as $instrumentation) { foreach (ServiceLoader::load(Instrumentation::class) as $instrumentation) {
/** @var Instrumentation $instrumentation */ /** @var Instrumentation $instrumentation */
@ -204,6 +207,19 @@ class SdkAutoloader
}); });
} }
private static function createLateBindingTextMapPropagator(): TextMapPropagatorInterface
{
return new LateBindingTextMapPropagator(static function (): TextMapPropagatorInterface {
$scope = Context::getRoot()->activate();
try {
return Globals::propagator();
} finally {
$scope->detach();
}
});
}
private static function getHookManager(): HookManagerInterface private static function getHookManager(): HookManagerInterface
{ {
/** @var HookManagerInterface $hookManager */ /** @var HookManagerInterface $hookManager */

View File

@ -8,6 +8,7 @@ use OpenTelemetry\API\Instrumentation\AutoInstrumentation\Context;
use OpenTelemetry\API\Logs\NoopLoggerProvider; use OpenTelemetry\API\Logs\NoopLoggerProvider;
use OpenTelemetry\API\Metrics\Noop\NoopMeterProvider; use OpenTelemetry\API\Metrics\Noop\NoopMeterProvider;
use OpenTelemetry\API\Trace\NoopTracerProvider; use OpenTelemetry\API\Trace\NoopTracerProvider;
use OpenTelemetry\Context\Propagation\NoopTextMapPropagator;
use PHPUnit\Framework\Attributes\CoversClass; use PHPUnit\Framework\Attributes\CoversClass;
use PHPUnit\Framework\TestCase; use PHPUnit\Framework\TestCase;
@ -20,5 +21,6 @@ class ContextTest extends TestCase
$this->assertInstanceOf(NoopTracerProvider::class, $context->tracerProvider); $this->assertInstanceOf(NoopTracerProvider::class, $context->tracerProvider);
$this->assertInstanceOf(NoopMeterProvider::class, $context->meterProvider); $this->assertInstanceOf(NoopMeterProvider::class, $context->meterProvider);
$this->assertInstanceOf(NoopLoggerProvider::class, $context->loggerProvider); $this->assertInstanceOf(NoopLoggerProvider::class, $context->loggerProvider);
$this->assertInstanceOf(NoopTextMapPropagator::class, $context->propagator);
} }
} }

View File

@ -4,6 +4,7 @@ declare(strict_types=1);
namespace OpenTelemetry\Tests\Unit\API\Instrumentation\AutoInstrumentation; namespace OpenTelemetry\Tests\Unit\API\Instrumentation\AutoInstrumentation;
use function assert;
use Nevay\SPI\ServiceLoader; use Nevay\SPI\ServiceLoader;
use OpenTelemetry\API\Behavior\Internal\Logging; use OpenTelemetry\API\Behavior\Internal\Logging;
use OpenTelemetry\API\Configuration\ConfigProperties; use OpenTelemetry\API\Configuration\ConfigProperties;
@ -25,11 +26,13 @@ use OpenTelemetry\API\Trace\LateBindingTracer;
use OpenTelemetry\API\Trace\LateBindingTracerProvider; use OpenTelemetry\API\Trace\LateBindingTracerProvider;
use OpenTelemetry\API\Trace\TracerInterface; use OpenTelemetry\API\Trace\TracerInterface;
use OpenTelemetry\API\Trace\TracerProviderInterface; use OpenTelemetry\API\Trace\TracerProviderInterface;
use OpenTelemetry\Context\Propagation\TextMapPropagatorInterface;
use OpenTelemetry\SDK\Common\Configuration\Variables; use OpenTelemetry\SDK\Common\Configuration\Variables;
use OpenTelemetry\SDK\SdkAutoloader; use OpenTelemetry\SDK\SdkAutoloader;
use OpenTelemetry\Tests\TestState; use OpenTelemetry\Tests\TestState;
use PHPUnit\Framework\Attributes\CoversClass; use PHPUnit\Framework\Attributes\CoversClass;
use PHPUnit\Framework\TestCase; use PHPUnit\Framework\TestCase;
use Prophecy\PhpUnit\ProphecyTrait;
#[CoversClass(LateBindingLoggerProvider::class)] #[CoversClass(LateBindingLoggerProvider::class)]
#[CoversClass(LateBindingLogger::class)] #[CoversClass(LateBindingLogger::class)]
@ -45,6 +48,7 @@ use PHPUnit\Framework\TestCase;
class LateBindingProviderTest extends TestCase class LateBindingProviderTest extends TestCase
{ {
use TestState; use TestState;
use ProphecyTrait;
public function setUp(): void public function setUp(): void
{ {
@ -77,6 +81,12 @@ class LateBindingProviderTest extends TestCase
return self::$context->loggerProvider->getLogger('test'); return self::$context->loggerProvider->getLogger('test');
} }
public function getPropagator(): TextMapPropagatorInterface
{
assert(self::$context !== null);
return self::$context->propagator;
}
}; };
$this->setEnvironmentVariable(Variables::OTEL_PHP_AUTOLOAD_ENABLED, 'true'); $this->setEnvironmentVariable(Variables::OTEL_PHP_AUTOLOAD_ENABLED, 'true');
$tracer_accessed = false; $tracer_accessed = false;
@ -101,14 +111,17 @@ class LateBindingProviderTest extends TestCase
return $this->createMock(LoggerInterface::class); return $this->createMock(LoggerInterface::class);
}); });
$propagator = $this->prophesize(TextMapPropagatorInterface::class);
ServiceLoader::register(Instrumentation::class, $instrumentation::class); ServiceLoader::register(Instrumentation::class, $instrumentation::class);
$this->assertTrue(SdkAutoloader::autoload()); $this->assertTrue(SdkAutoloader::autoload());
//initializer added _after_ autoloader has run and instrumentation registered //initializer added _after_ autoloader has run and instrumentation registered
Globals::registerInitializer(function (Configurator $configurator) use ($tracerProvider, $loggerProvider, $meterProvider): Configurator { Globals::registerInitializer(function (Configurator $configurator) use ($tracerProvider, $loggerProvider, $meterProvider, $propagator): Configurator {
return $configurator return $configurator
->withTracerProvider($tracerProvider) ->withTracerProvider($tracerProvider)
->withMeterProvider($meterProvider) ->withMeterProvider($meterProvider)
->withLoggerProvider($loggerProvider) ->withLoggerProvider($loggerProvider)
->withPropagator($propagator->reveal())
; ;
}); });
@ -129,5 +142,11 @@ class LateBindingProviderTest extends TestCase
$this->assertFalse($logger_accessed); $this->assertFalse($logger_accessed);
$logger->emit(new LogRecord()); /** @phpstan-ignore-next-line */ $logger->emit(new LogRecord()); /** @phpstan-ignore-next-line */
$this->assertTrue($logger_accessed); $this->assertTrue($logger_accessed);
/** @phpstan-ignore-next-line */
$propagator->fields()->shouldNotHaveBeenCalled();
$instrumentation->getPropagator()->fields();
/** @phpstan-ignore-next-line */
$propagator->fields()->shouldHaveBeenCalledOnce();
} }
} }