Skip to content

Commit

Permalink
wip
Browse files Browse the repository at this point in the history
  • Loading branch information
gaelreyrol committed Jan 30, 2024
1 parent 4c5f695 commit fd929be
Show file tree
Hide file tree
Showing 25 changed files with 242 additions and 332 deletions.
7 changes: 2 additions & 5 deletions src/DependencyInjection/OpenTelemetryLogsExtension.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,6 @@
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Reference;

use function Symfony\Component\DependencyInjection\Loader\Configurator\service;

/**
* @phpstan-import-type ExporterOptions from ExporterOptionsInterface
*/
Expand Down Expand Up @@ -94,9 +92,8 @@ private function loadLogProcessor(string $name, array $processor): void
sprintf('open_telemetry.logs.processors.%s', $name),
new ChildDefinition('open_telemetry.logs.processor_interface')
)
->setFactory([service(sprintf('open_telemetry.logs.processor_factory.%s', $processor['type'])), 'createProcessor'])
->setFactory([new Reference(sprintf('open_telemetry.logs.processor_factory.%s', $processor['type'])), 'createProcessor'])
->setArguments([
$processor['type'],
array_map(fn (string $processor) => new Reference($processor), $processor['processors']),
new Reference($processor['exporter']),
]);
Expand All @@ -115,7 +112,7 @@ private function loadLogProvider(string $name, array $provider): void
sprintf('open_telemetry.logs.providers.%s', $name),
new ChildDefinition('open_telemetry.logs.provider_interface')
)
->setFactory([service(sprintf('open_telemetry.logs.provider_factory.%s', $provider['type'])), 'createProvider'])
->setFactory([new Reference(sprintf('open_telemetry.logs.provider_factory.%s', $provider['type'])), 'createProvider'])
->setArguments([
new Reference($provider['processor']),
]);
Expand Down
4 changes: 1 addition & 3 deletions src/DependencyInjection/OpenTelemetryMetricsExtension.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,6 @@
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Reference;

use function Symfony\Component\DependencyInjection\Loader\Configurator\service;

/**
* @phpstan-import-type ExporterOptions from ExporterOptionsInterface
*/
Expand Down Expand Up @@ -91,7 +89,7 @@ private function loadMetricProvider(string $name, array $provider): void
sprintf('open_telemetry.metrics.providers.%s', $name),
new ChildDefinition('open_telemetry.metrics.provider_interface'),
)
->setFactory([service(sprintf('open_telemetry.metrics.provider_factory.%s', $provider['type'])), 'createProvider'])
->setFactory([new Reference(sprintf('open_telemetry.metrics.provider_factory.%s', $provider['type'])), 'createProvider'])
->setArguments([
new Reference($provider['exporter']),
new Reference($provider['filter']),
Expand Down
194 changes: 26 additions & 168 deletions src/DependencyInjection/OpenTelemetryTracesExtension.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,9 @@

use FriendsOfOpenTelemetry\OpenTelemetryBundle\OpenTelemetry\Exporter\ExporterDsn;
use FriendsOfOpenTelemetry\OpenTelemetryBundle\OpenTelemetry\Exporter\ExporterOptionsInterface;
use FriendsOfOpenTelemetry\OpenTelemetryBundle\OpenTelemetry\Trace\SpanExporter\TraceExporterEnum;
use FriendsOfOpenTelemetry\OpenTelemetryBundle\OpenTelemetry\Trace\SpanProcessor\SpanProcessorEnum;
use FriendsOfOpenTelemetry\OpenTelemetryBundle\OpenTelemetry\Trace\SpanProcessor\SpanProcessorFactoryInterface;
use FriendsOfOpenTelemetry\OpenTelemetryBundle\OpenTelemetry\Trace\TracerProvider\TraceProviderEnum;
use FriendsOfOpenTelemetry\OpenTelemetryBundle\OpenTelemetry\Trace\TracerProvider\TracerProviderFactoryInterface;
use FriendsOfOpenTelemetry\OpenTelemetryBundle\OpenTelemetry\Trace\TracerProvider\TraceSamplerEnum;
use OpenTelemetry\SDK\Trace\SpanProcessorInterface;
use OpenTelemetry\SDK\Trace\TracerProviderInterface;
use FriendsOfOpenTelemetry\OpenTelemetryBundle\OpenTelemetry\Exporter\OtlpExporterOptions;
use Symfony\Component\DependencyInjection\ChildDefinition;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Definition;
use Symfony\Component\DependencyInjection\Reference;

/**
Expand Down Expand Up @@ -76,19 +68,14 @@ public function __invoke(array $config, ContainerBuilder $container): void
*/
private function loadTraceExporter(string $name, array $options): void
{
$exporterId = sprintf('open_telemetry.traces.exporters.%s', $name);
$dsn = ExporterDsn::fromString($options['dsn']);
$exporter = TraceExporterEnum::from($dsn->getExporter());

$exporterDefinitionsFactory = new ExporterDefinitionsFactory($this->container);

$this->container
->setDefinition($exporterId, new ChildDefinition('open_telemetry.traces.exporter'))
->setClass($exporter->getClass())
->setFactory([$exporter->getFactoryClass(), 'createExporter'])
->setDefinition(
sprintf('open_telemetry.traces.exporters.%s', $name),
new ChildDefinition('open_telemetry.traces.exporter')
)
->setArguments([
'$dsn' => $exporterDefinitionsFactory->createExporterDsnDefinition($options['dsn']),
'$options' => $exporterDefinitionsFactory->createExporterOptionsDefinition($options['options'] ?? []),
ExporterDsn::fromString($options['dsn']),
OtlpExporterOptions::fromConfiguration($options['options']),
]);
}

Expand All @@ -101,73 +88,18 @@ private function loadTraceExporter(string $name, array $options): void
*/
private function loadTraceProcessor(string $name, array $processor): void
{
$processorId = sprintf('open_telemetry.traces.processors.%s', $name);
$options = $this->getTraceProcessorOptions($processor);

$this->container
->setDefinition($processorId, new ChildDefinition('open_telemetry.traces.processor'))
->setClass($options['class'])
->setFactory([$options['factory'], 'createProcessor'])
->setDefinition(
sprintf('open_telemetry.traces.processors.%s', $name),
new ChildDefinition('open_telemetry.traces.processor'),
)
->setFactory([new Reference(sprintf('open_telemetry.traces.processor_factory.%s', $processor['type'])), 'createProcessor'])
->setArguments([
'$processors' => $options['processors'],
'$exporter' => $options['exporter'],
array_map(fn (string $processor) => new Reference($processor), $processor['processors']),
new Reference($processor['exporter']),
]);
}

/**
* @param array{
* type: string,
* processors?: string[],
* exporter?: string
* } $processor
*
* @return array{
* factory: class-string<SpanProcessorFactoryInterface>,
* class: class-string<SpanProcessorInterface>,
* processors: ?Reference[],
* exporter: ?Reference,
* }
*/
private function getTraceProcessorOptions(array $processor): array
{
$processorEnum = SpanProcessorEnum::from($processor['type']);
$options = [
'factory' => $processorEnum->getFactoryClass(),
'class' => $processorEnum->getClass(),
'processors' => [],
'exporter' => null,
];

// if (SpanProcessorEnum::Batch === $options['type']) {
// // TODO: Check batch options
// clock: OpenTelemetry\SDK\Common\Time\SystemClock
// max_queue_size: 2048
// schedule_delay: 5000
// export_timeout: 30000
// max_export_batch_size: 512
// auto_flush: true
// }

if (SpanProcessorEnum::Multi === $processorEnum) {
if (!isset($processor['processors']) || 0 === count($processor['processors'])) {
throw new \InvalidArgumentException('Processors are not set or empty');
}
$options['processors'] = array_map(
fn (string $processor) => new Reference(sprintf('open_telemetry.traces.processors.%s', $processor)),
$processor['processors'],
);
}

if (SpanProcessorEnum::Simple === $processorEnum) {
if (!isset($processor['exporter'])) {
throw new \InvalidArgumentException('Exporter is not set');
}
$options['exporter'] = new Reference(sprintf('open_telemetry.traces.exporters.%s', $processor['exporter']));
}

return $options;
}

/**
* @param array{
* type: string,
Expand All @@ -177,90 +109,18 @@ private function getTraceProcessorOptions(array $processor): array
*/
private function loadTraceProvider(string $name, array $provider): void
{
$providerId = sprintf('open_telemetry.traces.providers.%s', $name);
$options = $this->getTraceProviderOptions($provider);

$sampler = isset($provider['sampler']) ? $this->getTraceSamplerDefinition($provider['sampler']) : $this->container->getDefinition('open_telemetry.traces.samplers.always_on');

$this->container
->setDefinition($providerId, new ChildDefinition('open_telemetry.traces.provider'))
->setClass($options['class'])
->setFactory([$options['factory'], 'createProvider'])
->setDefinition(
sprintf('open_telemetry.traces.providers.%s', $name),
new ChildDefinition('open_telemetry.traces.provider'),
)
->setFactory([new Reference(sprintf('open_telemetry.traces.provider_factory.%s', $provider['type'])), 'createProvider'])
->setArguments([
'$sampler' => $sampler,
'$processors' => $options['processors'],
new Reference($provider['sampler']),
array_map(fn (string $processor) => new Reference($processor), $provider['processors']),
]);
}

/**
* @param array{type: string, ratio?: float, parent?: string} $sampler
*/
private function getTraceSamplerDefinition(array $sampler): Definition
{
$type = TraceSamplerEnum::from($sampler['type']);

if (TraceSamplerEnum::TraceIdRatio === $type && !isset($sampler['ratio'])) {
throw new \InvalidArgumentException(sprintf("Sampler of type '%s' requires a ratio parameter.", $type->value));
}

if (TraceSamplerEnum::ParentBased === $type) {
if (!isset($sampler['parent'])) {
throw new \InvalidArgumentException(sprintf("Sampler of type '%s' requires a parent parameter.", $type->value));
}
$parentSampler = TraceSamplerEnum::tryFrom($sampler['parent']);
if (!in_array($parentSampler, [TraceSamplerEnum::AlwaysOn, TraceSamplerEnum::AlwaysOff], true)) {
throw new \InvalidArgumentException(sprintf("Unsupported '%s' parent sampler", $parentSampler->value));
}
}

return match ($type) {
TraceSamplerEnum::AlwaysOn => $this->container->getDefinition('open_telemetry.traces.samplers.always_on'),
TraceSamplerEnum::AlwaysOff => $this->container->getDefinition('open_telemetry.traces.samplers.always_off'),
TraceSamplerEnum::TraceIdRatio => $this->container
->getDefinition('open_telemetry.traces.samplers.trace_id_ratio_based')
->setArgument('$probability', $sampler['ratio']),
TraceSamplerEnum::ParentBased => $this->container
->getDefinition('open_telemetry.traces.samplers.parent_based')
->setArgument('$root', $this->getTraceSamplerDefinition([
'type' => $sampler['parent'],
])),
};
}

/**
* @param array{
* type: string,
* processors?: string[]
* } $provider
*
* @return array{
* factory: class-string<TracerProviderFactoryInterface>,
* class: class-string<TracerProviderInterface>,
* processors: ?Reference[],
* }
*/
private function getTraceProviderOptions(array $provider): array
{
$providerEnum = TraceProviderEnum::from($provider['type']);
$options = [
'factory' => $providerEnum->getFactoryClass(),
'class' => $providerEnum->getClass(),
'processors' => [],
];

if (TraceProviderEnum::Default === $providerEnum) {
if (!isset($provider['processors']) || 0 === count($provider['processors'])) {
throw new \InvalidArgumentException('Processors are not set or empty');
}
$options['processors'] = array_map(
fn (string $processor) => new Reference(sprintf('open_telemetry.traces.processors.%s', $processor)),
$provider['processors']
);
}

return $options;
}

/**
* @param array{
* name?: string,
Expand All @@ -270,15 +130,13 @@ private function getTraceProviderOptions(array $provider): array
*/
private function loadTraceTracer(string $name, array $tracer): void
{
$tracerId = sprintf('open_telemetry.traces.tracers.%s', $name);

$this->container
->setDefinition($tracerId, new ChildDefinition('open_telemetry.traces.tracer'))
->setDefinition(
sprintf('open_telemetry.traces.tracers.%s', $name),
new ChildDefinition('open_telemetry.traces.tracer'),
)
->setPublic(true)
->setFactory([
new Reference(sprintf('open_telemetry.traces.providers.%s', $tracer['provider'])),
'getTracer',
])
->setFactory([new Reference($tracer['provider']), 'getTracer'])
->setArguments([
$tracer['name'] ?? $this->container->getParameter('open_telemetry.bundle.name'),
$tracer['version'] ?? $this->container->getParameter('open_telemetry.bundle.version'),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,10 @@

namespace FriendsOfOpenTelemetry\OpenTelemetryBundle\OpenTelemetry\Metric\MetricExporter;

use FriendsOfOpenTelemetry\OpenTelemetryBundle\OpenTelemetry\Log\LogExporter\LogExporterFactoryInterface;
use FriendsOfOpenTelemetry\OpenTelemetryBundle\OpenTelemetry\Transport\TransportFactoryInterface;
use Psr\Log\LoggerInterface;

abstract class AbstractMetricExporterFactory implements LogExporterFactoryInterface
abstract class AbstractMetricExporterFactory implements MetricExporterFactoryInterface
{
public function __construct(
protected TransportFactoryInterface $transportFactory,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
use FriendsOfOpenTelemetry\OpenTelemetryBundle\OpenTelemetry\Metric\MetricExporterEndpoint;
use FriendsOfOpenTelemetry\OpenTelemetryBundle\OpenTelemetry\Metric\MetricExporterOptions;
use OpenTelemetry\Contrib\Otlp\MetricExporter;
use OpenTelemetry\SDK\Metrics\MetricExporterInterface;

final class OtlpMetricExporterFactory extends AbstractMetricExporterFactory
{
Expand All @@ -15,7 +16,7 @@ public function supports(#[\SensitiveParameter] ExporterDsn $dsn, ExporterOption
return MetricExporterEnum::Otlp === MetricExporterEnum::tryFrom($dsn->getExporter());
}

public function createExporter(#[\SensitiveParameter] ExporterDsn $dsn, ExporterOptionsInterface $options): MetricExporter
public function createExporter(#[\SensitiveParameter] ExporterDsn $dsn, ExporterOptionsInterface $options): MetricExporterInterface
{
assert($options instanceof MetricExporterOptions);

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<?php

namespace FriendsOfOpenTelemetry\OpenTelemetryBundle\OpenTelemetry\Trace\SpanExporter;

use FriendsOfOpenTelemetry\OpenTelemetryBundle\OpenTelemetry\Transport\TransportFactoryInterface;
use Psr\Log\LoggerInterface;

abstract readonly class AbstractSpanExporterFactory implements SpanExporterFactoryInterface
{
public function __construct(
protected TransportFactoryInterface $transportFactory,
protected ?LoggerInterface $logger = null
) {
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,17 @@
use FriendsOfOpenTelemetry\OpenTelemetryBundle\OpenTelemetry\Exporter\ExporterDsn;
use FriendsOfOpenTelemetry\OpenTelemetryBundle\OpenTelemetry\Exporter\ExporterOptionsInterface;
use FriendsOfOpenTelemetry\OpenTelemetryBundle\OpenTelemetry\Trace\TraceExporterEndpoint;
use FriendsOfOpenTelemetry\OpenTelemetryBundle\OpenTelemetry\Transport\StreamTransportFactory;
use OpenTelemetry\SDK\Trace\SpanExporter\ConsoleSpanExporter;

final readonly class ConsoleSpanExporterFactory implements SpanExporterFactoryInterface
final readonly class ConsoleSpanExporterFactory extends AbstractSpanExporterFactory
{
public static function createExporter(ExporterDsn $dsn, ExporterOptionsInterface $options): ConsoleSpanExporter
public function supports(#[\SensitiveParameter] ExporterDsn $dsn, ExporterOptionsInterface $options): bool
{
$transport = StreamTransportFactory::fromExporter(TraceExporterEndpoint::fromDsn($dsn), $options)->createTransport();
return TraceExporterEnum::Console === TraceExporterEnum::tryFrom($dsn->getExporter());
}

return new ConsoleSpanExporter($transport);
public function createExporter(#[\SensitiveParameter] ExporterDsn $dsn, ExporterOptionsInterface $options): ConsoleSpanExporter
{
return new ConsoleSpanExporter($this->transportFactory->createTransport(TraceExporterEndpoint::fromDsn($dsn), $options));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,14 @@
use FriendsOfOpenTelemetry\OpenTelemetryBundle\OpenTelemetry\Exporter\ExporterOptionsInterface;
use OpenTelemetry\SDK\Trace\SpanExporter\InMemoryExporter;

final readonly class InMemorySpanExporterFactory implements SpanExporterFactoryInterface
final readonly class InMemorySpanExporterFactory extends AbstractSpanExporterFactory
{
public static function createExporter(ExporterDsn $dsn = null, ExporterOptionsInterface $options = null): InMemoryExporter
public function supports(#[\SensitiveParameter] ExporterDsn $dsn, ExporterOptionsInterface $options): bool
{
return TraceExporterEnum::InMemory === TraceExporterEnum::tryFrom($dsn->getExporter());
}

public function createExporter(#[\SensitiveParameter] ExporterDsn $dsn, ExporterOptionsInterface $options): InMemoryExporter
{
return new InMemoryExporter();
}
Expand Down
Loading

0 comments on commit fd929be

Please sign in to comment.