-
Notifications
You must be signed in to change notification settings - Fork 92
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #77 from Nevay/feature/symfony-kernel-listener
Add basic symfony instrumentation bundle with kernel request listener
- Loading branch information
Showing
27 changed files
with
1,158 additions
and
65 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
29 changes: 29 additions & 0 deletions
29
src/Symfony/OtelBundle/DependencyInjection/Compiler/SetAliasIfNotDefinedCompilerPass.php
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
<?php | ||
|
||
declare(strict_types=1); | ||
|
||
namespace OpenTelemetry\Symfony\OtelBundle\DependencyInjection\Compiler; | ||
|
||
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; | ||
use Symfony\Component\DependencyInjection\ContainerBuilder; | ||
|
||
final class SetAliasIfNotDefinedCompilerPass implements CompilerPassInterface | ||
{ | ||
private string $service; | ||
private string $aliasService; | ||
|
||
public function __construct(string $service, string $aliasService) | ||
{ | ||
$this->service = $service; | ||
$this->aliasService = $aliasService; | ||
} | ||
|
||
public function process(ContainerBuilder $container): void | ||
{ | ||
if ($container->has($this->service)) { | ||
return; | ||
} | ||
|
||
$container->setAlias($this->service, $this->aliasService); | ||
} | ||
} |
79 changes: 79 additions & 0 deletions
79
src/Symfony/OtelBundle/DependencyInjection/Configuration.php
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,79 @@ | ||
<?php | ||
|
||
declare(strict_types=1); | ||
|
||
namespace OpenTelemetry\Symfony\OtelBundle\DependencyInjection; | ||
|
||
use function class_exists; | ||
use Symfony\Component\Config\Definition\Builder\ArrayNodeDefinition; | ||
use Symfony\Component\Config\Definition\Builder\NodeDefinition; | ||
use Symfony\Component\Config\Definition\Builder\TreeBuilder; | ||
use Symfony\Component\Config\Definition\ConfigurationInterface; | ||
use Symfony\Component\HttpKernel\HttpKernel; | ||
|
||
/** | ||
* @psalm-suppress PossiblyNullReference,PossiblyUndefinedMethod | ||
*/ | ||
final class Configuration implements ConfigurationInterface | ||
{ | ||
public function getConfigTreeBuilder(): TreeBuilder | ||
{ | ||
$builder = new TreeBuilder('otel'); | ||
|
||
$tracing = $builder->getRootNode() | ||
->addDefaultsIfNotSet() | ||
->children() | ||
->arrayNode('tracing') | ||
->addDefaultsIfNotSet(); | ||
|
||
$tracing->children()->append($this->httpTracingNode()); | ||
|
||
if (class_exists(HttpKernel::class)) { | ||
$tracing->children()->append($this->kernelTracingNode()); | ||
} | ||
|
||
return $builder; | ||
} | ||
|
||
private function httpTracingNode(): NodeDefinition | ||
{ | ||
return (new ArrayNodeDefinition('http')) | ||
->addDefaultsIfNotSet() | ||
->children() | ||
->arrayNode('server') | ||
->addDefaultsIfNotSet() | ||
->fixXmlConfig('requestHeader') | ||
->fixXmlConfig('responseHeader') | ||
->children() | ||
->arrayNode('requestHeaders') | ||
->info('Request headers to capture as span attributes.') | ||
->example(['Content-Type', 'X-Forwarded-For']) | ||
->beforeNormalization()->castToArray()->end() | ||
->scalarPrototype()->cannotBeEmpty()->end() | ||
->end() | ||
->arrayNode('responseHeaders') | ||
->info('Response headers to capture as span attributes.') | ||
->example(['Content-Type']) | ||
->beforeNormalization()->castToArray()->end() | ||
->scalarPrototype()->cannotBeEmpty()->end() | ||
->end() | ||
->end() | ||
->end() | ||
->end() | ||
; | ||
} | ||
|
||
private function kernelTracingNode(): NodeDefinition | ||
{ | ||
return (new ArrayNodeDefinition('kernel')) | ||
->addDefaultsIfNotSet() | ||
->canBeDisabled() | ||
->children() | ||
->booleanNode('extractRemoteContext') | ||
->info('Set to `false` if the kernel runs in a runtime that extracts the remote context before passing the request to the kernel.') | ||
->defaultTrue() | ||
->end() | ||
->end() | ||
; | ||
} | ||
} |
47 changes: 47 additions & 0 deletions
47
src/Symfony/OtelBundle/DependencyInjection/OtelExtension.php
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
<?php | ||
|
||
declare(strict_types=1); | ||
|
||
namespace OpenTelemetry\Symfony\OtelBundle\DependencyInjection; | ||
|
||
use OpenTelemetry\Context\Propagation\NoopTextMapPropagator; | ||
use OpenTelemetry\Symfony\OtelBundle\HttpKernel\RequestListener; | ||
use Symfony\Component\Config\Definition\ConfigurationInterface; | ||
use Symfony\Component\Config\FileLocator; | ||
use Symfony\Component\DependencyInjection\ContainerBuilder; | ||
use Symfony\Component\DependencyInjection\Extension\Extension; | ||
use Symfony\Component\DependencyInjection\Loader\PhpFileLoader; | ||
use Symfony\Component\DependencyInjection\Reference; | ||
|
||
final class OtelExtension extends Extension | ||
{ | ||
public function load(array $configs, ContainerBuilder $container) | ||
{ | ||
$config = $this->processConfiguration($this->getConfiguration($configs, $container), $configs); | ||
|
||
$loader = new PhpFileLoader($container, new FileLocator()); | ||
$loader->load(__DIR__ . '/../Resources/services.php'); | ||
|
||
$container->setParameter('otel.tracing.http.server.request_headers', $config['tracing']['http']['server']['requestHeaders']); | ||
$container->setParameter('otel.tracing.http.server.response_headers', $config['tracing']['http']['server']['responseHeaders']); | ||
|
||
if ($config['tracing']['kernel']['enabled'] ?? false) { | ||
$loader->load(__DIR__ . '/../Resources/services_kernel.php'); | ||
$this->loadKernelTracing($config['tracing']['kernel'], $container); | ||
} | ||
} | ||
|
||
private function loadKernelTracing(array $config, ContainerBuilder $container): void | ||
{ | ||
if (!$config['extractRemoteContext']) { | ||
$container->getDefinition(RequestListener::class) | ||
->setArgument('$propagator', new Reference(NoopTextMapPropagator::class)) | ||
; | ||
} | ||
} | ||
|
||
public function getConfiguration(array $config, ContainerBuilder $container): ConfigurationInterface | ||
{ | ||
return new Configuration(); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
<?php | ||
|
||
declare(strict_types=1); | ||
|
||
namespace OpenTelemetry\Symfony\OtelBundle\HttpKernel; | ||
|
||
use function count; | ||
use function implode; | ||
use OpenTelemetry\Context\Propagation\PropagationGetterInterface; | ||
use Symfony\Component\HttpFoundation\Request; | ||
|
||
/** | ||
* @internal | ||
*/ | ||
final class HeadersPropagator implements PropagationGetterInterface | ||
{ | ||
/** | ||
* @param Request $carrier | ||
* | ||
* @psalm-suppress LessSpecificImplementedReturnType | ||
*/ | ||
public function keys($carrier): array | ||
{ | ||
return $carrier->headers->keys(); | ||
} | ||
|
||
/** | ||
* @param Request $carrier | ||
*/ | ||
public function get($carrier, string $key): ?string | ||
{ | ||
/** @psalm-suppress InvalidArgument */ | ||
return count($carrier->headers->all($key)) > 1 | ||
/** @phpstan-ignore-next-line */ | ||
? implode(',', $carrier->headers->all($key)) | ||
: $carrier->headers->get($key); | ||
} | ||
} |
Oops, something went wrong.