• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

FriendsOfOpenTelemetry / opentelemetry-bundle / 24235891213

10 Apr 2026 09:18AM UTC coverage: 91.764% (+0.08%) from 91.68%
24235891213

Pull #209

github

web-flow
Merge 4640c7f75 into c221a1e0c
Pull Request #209: feat(OpenTelemetry/Transport): replace Guzzle with Symfony HTTP Client and Nyholm PSR-7/17

37 of 37 new or added lines in 9 files covered. (100.0%)

8 existing lines in 1 file now uncovered.

2284 of 2489 relevant lines covered (91.76%)

59.92 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

93.85
/src/DependencyInjection/OpenTelemetryExtension.php
1
<?php
2

3
namespace FriendsOfOpenTelemetry\OpenTelemetryBundle\DependencyInjection;
4

5
use Doctrine\Bundle\DoctrineBundle\DoctrineBundle;
6
use FriendsOfOpenTelemetry\OpenTelemetryBundle\Instrumentation\InstrumentationTypeEnum;
7
use Symfony\Bundle\TwigBundle\TwigBundle;
8
use Symfony\Component\Cache\CacheItem;
9
use Symfony\Component\Config\FileLocator;
10
use Symfony\Component\Console\Command\Command;
11
use Symfony\Component\DependencyInjection\ContainerBuilder;
12
use Symfony\Component\DependencyInjection\Loader\PhpFileLoader;
13
use Symfony\Component\HttpClient\HttpClient;
14
use Symfony\Component\HttpKernel\DependencyInjection\ConfigurableExtension;
15
use Symfony\Component\Mailer\MailerInterface;
16
use Symfony\Component\Messenger\Envelope;
17

18
/**
19
 * @phpstan-type InstrumentationConfig array{
20
 *     type?: string,
21
 *     tracing: TracingInstrumentationConfig,
22
 *     metering: MeteringInstrumentationConfig,
23
 * }
24
 * @phpstan-type TracingInstrumentationConfig array{
25
 *     enabled: bool,
26
 *     tracer: ?string,
27
 *     exclude_paths?: string[],
28
 *     exclude_commands?: string[]
29
 * }
30
 * @phpstan-type MeteringInstrumentationConfig array{
31
 *     enabled: bool,
32
 *     meter: ?string,
33
 * }
34
 */
35
final class OpenTelemetryExtension extends ConfigurableExtension
36
{
37
    protected function loadInternal(array $mergedConfig, ContainerBuilder $container): void
38
    {
39
        $loader = new PhpFileLoader($container, new FileLocator(dirname(__DIR__).'/Resources/config'));
100✔
40
        $loader->load('services.php');
100✔
41

42
        $channels = $container->hasParameter('monolog.additional_channels')
100✔
43
            ? $container->getParameter('monolog.additional_channels')
28✔
44
            : [];
72✔
45
        $channels[] = 'open_telemetry';
100✔
46
        $container->setParameter('monolog.additional_channels', array_unique($channels));
100✔
47

48
        $loader->load('services_transports.php');
100✔
49
        $loader->load('services_logs.php');
100✔
50
        $loader->load('services_metrics.php');
100✔
51
        $loader->load('services_traces.php');
100✔
52
        $loader->load('services_tracing_instrumentation.php');
100✔
53
        $loader->load('services_metering_instrumentation.php');
100✔
54

55
        $this->registerTransportHttpClient($mergedConfig['transport_http_client'], $container);
100✔
56
        $this->registerService($mergedConfig['service'], $container);
100✔
57
        $this->registerInstrumentation($mergedConfig['instrumentation'], $container);
100✔
58

59
        (new OpenTelemetryTracesExtension())($mergedConfig['traces'], $container);
100✔
60
        (new OpenTelemetryMetricsExtension())($mergedConfig['metrics'], $container);
96✔
61
        (new OpenTelemetryLogsExtension())($mergedConfig['logs'], $container);
92✔
62
    }
63

64
    /**
65
     * @param array{
66
     *     namespace: string,
67
     *     name: string,
68
     *     version: string,
69
     *     environment: string
70
     * } $config
71
     */
72
    private function registerService(array $config, ContainerBuilder $container): void
73
    {
74
        $container->setParameter('open_telemetry.service.namespace', $config['namespace']);
100✔
75
        $container->setParameter('open_telemetry.service.name', $config['name']);
100✔
76
        $container->setParameter('open_telemetry.service.version', $config['version']);
100✔
77
        $container->setParameter('open_telemetry.service.environment', $config['environment']);
100✔
78

79
        $container->getDefinition('open_telemetry.resource_info')
100✔
80
            ->setArguments([
100✔
81
                $config['namespace'],
100✔
82
                $config['name'],
100✔
83
                $config['version'],
100✔
84
                $config['environment'],
100✔
85
            ]);
100✔
86
    }
87

88
    private function registerTransportHttpClient(?string $httpClientServiceId, ContainerBuilder $container): void
89
    {
90
        $container->setAlias(
100✔
91
            'open_telemetry.transport_http_client',
100✔
92
            $httpClientServiceId ?? 'open_telemetry.transport_http_client.psr18',
100✔
93
        );
100✔
94
    }
95

96
    /**
97
     * @param array{
98
     *     cache: InstrumentationConfig,
99
     *     console: InstrumentationConfig,
100
     *     doctrine: InstrumentationConfig,
101
     *     http_client: InstrumentationConfig,
102
     *     http_kernel: InstrumentationConfig,
103
     *     mailer: InstrumentationConfig,
104
     *     messenger: InstrumentationConfig,
105
     *     twig: InstrumentationConfig,
106
     * } $config
107
     */
108
    private function registerInstrumentation(array $config, ContainerBuilder $container): void
109
    {
110
        $this->registerCacheTracingInstrumentationConfiguration($container, $config['cache']);
100✔
111

112
        $this->registerConsoleTracingInstrumentationConfiguration($container, $config['console']);
100✔
113
        $this->registerConsoleMeteringInstrumentationConfiguration($container, $config['console']);
100✔
114

115
        $this->registerDoctrineTracingInstrumentationConfiguration($container, $config['doctrine']);
100✔
116
        $this->registerHttpClientTracingInstrumentationConfiguration($container, $config['http_client']);
100✔
117

118
        $this->registerHttpKernelTracingInstrumentationConfiguration($container, $config['http_kernel']);
100✔
119
        $this->registerHttpKernelMeteringInstrumentationConfiguration($container, $config['http_kernel']);
100✔
120

121
        $this->registerMailerTracingInstrumentationConfiguration($container, $config['mailer']);
100✔
122
        $this->registerMessengerTracingInstrumentationConfiguration($container, $config['messenger']);
100✔
123
        $this->registerTwigTracingInstrumentationConfiguration($container, $config['twig']);
100✔
124
    }
125

126
    /**
127
     * @param InstrumentationConfig $config
128
     */
129
    private function registerCacheTracingInstrumentationConfiguration(ContainerBuilder $container, array $config): void
130
    {
131
        $isConfigEnabled = $this->isConfigEnabled($container, $config['tracing']);
100✔
132

133
        if ($isConfigEnabled && !class_exists(CacheItem::class)) {
100✔
UNCOV
134
            throw new \LogicException('Cache instrumentation cannot be enabled because the symfony/cache package is not installed.');
×
135
        }
136

137
        if (!$isConfigEnabled) {
100✔
138
            $container->removeDefinition('open_telemetry.instrumentation.cache.trace.adapter');
72✔
139
            $container->removeDefinition('open_telemetry.instrumentation.cache.trace.tag_aware_adapter');
72✔
140
        }
141

142
        $this->setTracingInstrumentationParams($container, 'cache', $config, $isConfigEnabled);
100✔
143
    }
144

145
    /**
146
     * @param InstrumentationConfig $config
147
     */
148
    private function registerConsoleTracingInstrumentationConfiguration(ContainerBuilder $container, array $config): void
149
    {
150
        $isConfigEnabled = $this->isConfigEnabled($container, $config['tracing']);
100✔
151

152
        if ($isConfigEnabled && !class_exists(Command::class)) {
100✔
UNCOV
153
            throw new \LogicException('Console instrumentation cannot be enabled because the symfony/console package is not installed.');
×
154
        }
155

156
        if (!$isConfigEnabled) {
100✔
157
            $container->removeDefinition('open_telemetry.instrumentation.console.trace.event_subscriber');
72✔
158
        }
159

160
        $this->setTracingInstrumentationParams($container, 'console', $config, $isConfigEnabled);
100✔
161
    }
162

163
    /**
164
     * @param InstrumentationConfig $config
165
     */
166
    private function registerConsoleMeteringInstrumentationConfiguration(ContainerBuilder $container, array $config): void
167
    {
168
        $isConfigEnabled = $this->isConfigEnabled($container, $config['metering']);
100✔
169

170
        if ($isConfigEnabled && !class_exists(Command::class)) {
100✔
UNCOV
171
            throw new \LogicException('Console instrumentation cannot be enabled because the symfony/console package is not installed.');
×
172
        }
173

174
        if (!$isConfigEnabled) {
100✔
175
            $container->removeDefinition('open_telemetry.instrumentation.console.metric.event_subscriber');
72✔
176
        }
177
    }
178

179
    /**
180
     * @param InstrumentationConfig $config
181
     */
182
    private function registerDoctrineTracingInstrumentationConfiguration(ContainerBuilder $container, array $config): void
183
    {
184
        $isConfigEnabled = $this->isConfigEnabled($container, $config['tracing']);
100✔
185

186
        if ($isConfigEnabled && !class_exists(DoctrineBundle::class)) {
100✔
UNCOV
187
            throw new \LogicException('DBAL tracing support cannot be enabled because the doctrine/doctrine-bundle Composer package is not installed.');
×
188
        }
189

190
        if (!$isConfigEnabled) {
100✔
191
            $container->removeDefinition('open_telemetry.instrumentation.doctrine.trace.middleware');
76✔
192
        }
193

194
        $this->setTracingInstrumentationParams($container, 'doctrine', $config, $isConfigEnabled);
100✔
195
    }
196

197
    /**
198
     * @param InstrumentationConfig $config
199
     */
200
    private function registerHttpClientTracingInstrumentationConfiguration(ContainerBuilder $container, array $config): void
201
    {
202
        $isConfigEnabled = $this->isConfigEnabled($container, $config['tracing']);
100✔
203

204
        if ($isConfigEnabled && !class_exists(HttpClient::class)) {
100✔
UNCOV
205
            throw new \LogicException('Http client tracing support cannot be enabled because the symfony/http-client Composer package is not installed.');
×
206
        }
207

208
        if (!$isConfigEnabled) {
100✔
209
            $container->removeDefinition('open_telemetry.instrumentation.http_client.trace.client');
72✔
210
        }
211

212
        $this->setTracingInstrumentationParams($container, 'http_client', $config, $isConfigEnabled);
100✔
213
    }
214

215
    /**
216
     * @param InstrumentationConfig $config
217
     */
218
    private function registerHttpKernelTracingInstrumentationConfiguration(ContainerBuilder $container, array $config): void
219
    {
220
        $isConfigEnabled = $this->isConfigEnabled($container, $config['tracing']);
100✔
221

222
        if (!$isConfigEnabled) {
100✔
223
            $container->removeDefinition('open_telemetry.instrumentation.http_kernel.trace.event_subscriber');
72✔
224
            $container->removeDefinition('open_telemetry.instrumentation.http_kernel.trace.route_loader');
72✔
225
        }
226

227
        $this->setTracingInstrumentationParams($container, 'http_kernel', $config, $isConfigEnabled);
100✔
228
    }
229

230
    /**
231
     * @param InstrumentationConfig $config
232
     */
233
    private function registerHttpKernelMeteringInstrumentationConfiguration(ContainerBuilder $container, array $config): void
234
    {
235
        $isConfigEnabled = $this->isConfigEnabled($container, $config['metering']);
100✔
236

237
        if (!$isConfigEnabled) {
100✔
238
            $container->removeDefinition('open_telemetry.instrumentation.http_kernel.metric.event_subscriber');
72✔
239
        }
240
    }
241

242
    /**
243
     * @param InstrumentationConfig $config
244
     */
245
    private function registerMailerTracingInstrumentationConfiguration(ContainerBuilder $container, array $config): void
246
    {
247
        $isConfigEnabled = $this->isConfigEnabled($container, $config['tracing']);
100✔
248

249
        if ($isConfigEnabled && !interface_exists(MailerInterface::class)) {
100✔
UNCOV
250
            throw new \LogicException('Mailer instrumentation cannot be enabled because the symfony/mailer package is not installed.');
×
251
        }
252

253
        if (!$isConfigEnabled) {
100✔
254
            $container->removeDefinition('open_telemetry.instrumentation.mailer.trace.transports');
72✔
255
            $container->removeDefinition('open_telemetry.instrumentation.mailer.trace.default_transport');
72✔
256
            $container->removeDefinition('open_telemetry.instrumentation.mailer.trace.mailer');
72✔
257
        }
258

259
        $this->setTracingInstrumentationParams($container, 'mailer', $config, $isConfigEnabled);
100✔
260
    }
261

262
    /**
263
     * @param InstrumentationConfig $config
264
     */
265
    private function registerMessengerTracingInstrumentationConfiguration(ContainerBuilder $container, array $config): void
266
    {
267
        $isConfigEnabled = $this->isConfigEnabled($container, $config['tracing']);
100✔
268

269
        if ($isConfigEnabled && !class_exists(Envelope::class)) {
100✔
UNCOV
270
            throw new \LogicException('Messenger instrumentation cannot be enabled because the symfony/messenger package is not installed.');
×
271
        }
272

273
        if (!$isConfigEnabled) {
100✔
274
            $container->removeAlias('messenger.transport.open_telemetry_tracer.factory');
72✔
275
            $container->removeAlias('messenger.middleware.open_telemetry_tracer');
72✔
276
            $container->removeDefinition('open_telemetry.instrumentation.messenger.trace.transport');
72✔
277
            $container->removeDefinition('open_telemetry.instrumentation.messenger.trace.transport_factory');
72✔
278
            $container->removeDefinition('open_telemetry.instrumentation.messenger.trace.middleware');
72✔
279
        }
280

281
        $this->setTracingInstrumentationParams($container, 'messenger', $config, $isConfigEnabled);
100✔
282
    }
283

284
    /**
285
     * @param InstrumentationConfig $config
286
     */
287
    private function registerTwigTracingInstrumentationConfiguration(ContainerBuilder $container, array $config): void
288
    {
289
        $isConfigEnabled = $this->isConfigEnabled($container, $config['tracing']);
100✔
290

291
        if ($isConfigEnabled && !class_exists(TwigBundle::class)) {
100✔
UNCOV
292
            throw new \LogicException('Twig instrumentation cannot be enabled because the symfony/twig-bundle package is not installed.');
×
293
        }
294

295
        if (!$isConfigEnabled) {
100✔
296
            $container->removeDefinition('open_telemetry.instrumentation.twig.trace.extension');
72✔
297
        }
298

299
        $this->setTracingInstrumentationParams($container, 'twig', $config, $isConfigEnabled);
100✔
300
    }
301

302
    /**
303
     * @param InstrumentationConfig $config
304
     */
305
    private function setTracingInstrumentationParams(ContainerBuilder $container, string $name, array $config, bool $enabled): void
306
    {
307
        $container->setParameter(sprintf('open_telemetry.instrumentation.%s.tracing.enabled', $name), $enabled);
100✔
308
        if (isset($config['type'])) {
100✔
309
            $container->setParameter(
100✔
310
                sprintf('open_telemetry.instrumentation.%s.type', $name),
100✔
311
                InstrumentationTypeEnum::from($config['type']),
100✔
312
            );
100✔
313
        }
314

315
        if ('http_kernel' === $name) {
100✔
316
            if (isset($config['tracing']['exclude_paths'])
100✔
317
                && 0 < \count($config['tracing']['exclude_paths'])
100✔
318
            ) {
319
                $container->setParameter(
12✔
320
                    sprintf('open_telemetry.instrumentation.%s.tracing.exclude_paths', $name),
12✔
321
                    $config['tracing']['exclude_paths'],
12✔
322
                );
12✔
323
            }
324
        }
325

326
        if ('console' === $name) {
100✔
327
            if (isset($config['tracing']['exclude_commands'])
100✔
328
                && 0 < \count($config['tracing']['exclude_commands'])
100✔
329
            ) {
330
                $container->setParameter(
12✔
331
                    sprintf('open_telemetry.instrumentation.%s.tracing.exclude_commands', $name),
12✔
332
                    $config['tracing']['exclude_commands'],
12✔
333
                );
12✔
334
            }
335
        }
336

337
        $container->setParameter(
100✔
338
            sprintf('open_telemetry.instrumentation.%s.tracing.tracer', $name),
100✔
339
            $config['tracing']['tracer'] ?? 'default_tracer',
100✔
340
        );
100✔
341
    }
342
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc