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

FriendsOfOpenTelemetry / opentelemetry-bundle / 24246572588

10 Apr 2026 01:57PM UTC coverage: 91.751% (+0.07%) from 91.68%
24246572588

Pull #211

github

web-flow
Merge ae31d73a6 into 19c774f8e
Pull Request #211: chore: remove Nix and replace with shivammathur/setup-php in CI

2280 of 2485 relevant lines covered (91.75%)

14.95 hits per line

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

93.94
/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\HttpClient\Psr18Client;
15
use Symfony\Component\HttpKernel\DependencyInjection\ConfigurableExtension;
16
use Symfony\Component\Mailer\MailerInterface;
17
use Symfony\Component\Messenger\Envelope;
18

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

43
        $channels = $container->hasParameter('monolog.additional_channels')
25✔
44
            ? $container->getParameter('monolog.additional_channels')
7✔
45
            : [];
18✔
46
        $channels[] = 'open_telemetry';
25✔
47
        $container->setParameter('monolog.additional_channels', array_unique($channels));
25✔
48

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

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

60
        (new OpenTelemetryTracesExtension())($mergedConfig['traces'], $container);
25✔
61
        (new OpenTelemetryMetricsExtension())($mergedConfig['metrics'], $container);
24✔
62
        (new OpenTelemetryLogsExtension())($mergedConfig['logs'], $container);
23✔
63
    }
64

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

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

89
    private function registerTransportHttpClient(?string $httpClientServiceId, ContainerBuilder $container): void
90
    {
91
        if (null !== $httpClientServiceId) {
25✔
92
            $container->setAlias('open_telemetry.transport_http_client', $httpClientServiceId);
1✔
93

94
            return;
1✔
95
        }
96

97
        if (class_exists(Psr18Client::class)) {
24✔
98
            $container->register('open_telemetry.transport_http_client.psr18', Psr18Client::class);
24✔
99
            $container->setAlias('open_telemetry.transport_http_client', 'open_telemetry.transport_http_client.psr18');
24✔
100
        }
101
    }
102

103
    /**
104
     * @param array{
105
     *     cache: InstrumentationConfig,
106
     *     console: InstrumentationConfig,
107
     *     doctrine: InstrumentationConfig,
108
     *     http_client: InstrumentationConfig,
109
     *     http_kernel: InstrumentationConfig,
110
     *     mailer: InstrumentationConfig,
111
     *     messenger: InstrumentationConfig,
112
     *     twig: InstrumentationConfig,
113
     * } $config
114
     */
115
    private function registerInstrumentation(array $config, ContainerBuilder $container): void
116
    {
117
        $this->registerCacheTracingInstrumentationConfiguration($container, $config['cache']);
25✔
118

119
        $this->registerConsoleTracingInstrumentationConfiguration($container, $config['console']);
25✔
120
        $this->registerConsoleMeteringInstrumentationConfiguration($container, $config['console']);
25✔
121

122
        $this->registerDoctrineTracingInstrumentationConfiguration($container, $config['doctrine']);
25✔
123
        $this->registerHttpClientTracingInstrumentationConfiguration($container, $config['http_client']);
25✔
124

125
        $this->registerHttpKernelTracingInstrumentationConfiguration($container, $config['http_kernel']);
25✔
126
        $this->registerHttpKernelMeteringInstrumentationConfiguration($container, $config['http_kernel']);
25✔
127

128
        $this->registerMailerTracingInstrumentationConfiguration($container, $config['mailer']);
25✔
129
        $this->registerMessengerTracingInstrumentationConfiguration($container, $config['messenger']);
25✔
130
        $this->registerTwigTracingInstrumentationConfiguration($container, $config['twig']);
25✔
131
    }
132

133
    /**
134
     * @param InstrumentationConfig $config
135
     */
136
    private function registerCacheTracingInstrumentationConfiguration(ContainerBuilder $container, array $config): void
137
    {
138
        $isConfigEnabled = $this->isConfigEnabled($container, $config['tracing']);
25✔
139

140
        if ($isConfigEnabled && !class_exists(CacheItem::class)) {
25✔
141
            throw new \LogicException('Cache instrumentation cannot be enabled because the symfony/cache package is not installed.');
×
142
        }
143

144
        if (!$isConfigEnabled) {
25✔
145
            $container->removeDefinition('open_telemetry.instrumentation.cache.trace.adapter');
18✔
146
            $container->removeDefinition('open_telemetry.instrumentation.cache.trace.tag_aware_adapter');
18✔
147
        }
148

149
        $this->setTracingInstrumentationParams($container, 'cache', $config, $isConfigEnabled);
25✔
150
    }
151

152
    /**
153
     * @param InstrumentationConfig $config
154
     */
155
    private function registerConsoleTracingInstrumentationConfiguration(ContainerBuilder $container, array $config): void
156
    {
157
        $isConfigEnabled = $this->isConfigEnabled($container, $config['tracing']);
25✔
158

159
        if ($isConfigEnabled && !class_exists(Command::class)) {
25✔
160
            throw new \LogicException('Console instrumentation cannot be enabled because the symfony/console package is not installed.');
×
161
        }
162

163
        if (!$isConfigEnabled) {
25✔
164
            $container->removeDefinition('open_telemetry.instrumentation.console.trace.event_subscriber');
18✔
165
        }
166

167
        $this->setTracingInstrumentationParams($container, 'console', $config, $isConfigEnabled);
25✔
168
    }
169

170
    /**
171
     * @param InstrumentationConfig $config
172
     */
173
    private function registerConsoleMeteringInstrumentationConfiguration(ContainerBuilder $container, array $config): void
174
    {
175
        $isConfigEnabled = $this->isConfigEnabled($container, $config['metering']);
25✔
176

177
        if ($isConfigEnabled && !class_exists(Command::class)) {
25✔
178
            throw new \LogicException('Console instrumentation cannot be enabled because the symfony/console package is not installed.');
×
179
        }
180

181
        if (!$isConfigEnabled) {
25✔
182
            $container->removeDefinition('open_telemetry.instrumentation.console.metric.event_subscriber');
18✔
183
        }
184
    }
185

186
    /**
187
     * @param InstrumentationConfig $config
188
     */
189
    private function registerDoctrineTracingInstrumentationConfiguration(ContainerBuilder $container, array $config): void
190
    {
191
        $isConfigEnabled = $this->isConfigEnabled($container, $config['tracing']);
25✔
192

193
        if ($isConfigEnabled && !class_exists(DoctrineBundle::class)) {
25✔
194
            throw new \LogicException('DBAL tracing support cannot be enabled because the doctrine/doctrine-bundle Composer package is not installed.');
×
195
        }
196

197
        if (!$isConfigEnabled) {
25✔
198
            $container->removeDefinition('open_telemetry.instrumentation.doctrine.trace.middleware');
19✔
199
        }
200

201
        $this->setTracingInstrumentationParams($container, 'doctrine', $config, $isConfigEnabled);
25✔
202
    }
203

204
    /**
205
     * @param InstrumentationConfig $config
206
     */
207
    private function registerHttpClientTracingInstrumentationConfiguration(ContainerBuilder $container, array $config): void
208
    {
209
        $isConfigEnabled = $this->isConfigEnabled($container, $config['tracing']);
25✔
210

211
        if ($isConfigEnabled && !class_exists(HttpClient::class)) {
25✔
212
            throw new \LogicException('Http client tracing support cannot be enabled because the symfony/http-client Composer package is not installed.');
×
213
        }
214

215
        if (!$isConfigEnabled) {
25✔
216
            $container->removeDefinition('open_telemetry.instrumentation.http_client.trace.client');
18✔
217
        }
218

219
        $this->setTracingInstrumentationParams($container, 'http_client', $config, $isConfigEnabled);
25✔
220
    }
221

222
    /**
223
     * @param InstrumentationConfig $config
224
     */
225
    private function registerHttpKernelTracingInstrumentationConfiguration(ContainerBuilder $container, array $config): void
226
    {
227
        $isConfigEnabled = $this->isConfigEnabled($container, $config['tracing']);
25✔
228

229
        if (!$isConfigEnabled) {
25✔
230
            $container->removeDefinition('open_telemetry.instrumentation.http_kernel.trace.event_subscriber');
18✔
231
            $container->removeDefinition('open_telemetry.instrumentation.http_kernel.trace.route_loader');
18✔
232
        }
233

234
        $this->setTracingInstrumentationParams($container, 'http_kernel', $config, $isConfigEnabled);
25✔
235
    }
236

237
    /**
238
     * @param InstrumentationConfig $config
239
     */
240
    private function registerHttpKernelMeteringInstrumentationConfiguration(ContainerBuilder $container, array $config): void
241
    {
242
        $isConfigEnabled = $this->isConfigEnabled($container, $config['metering']);
25✔
243

244
        if (!$isConfigEnabled) {
25✔
245
            $container->removeDefinition('open_telemetry.instrumentation.http_kernel.metric.event_subscriber');
18✔
246
        }
247
    }
248

249
    /**
250
     * @param InstrumentationConfig $config
251
     */
252
    private function registerMailerTracingInstrumentationConfiguration(ContainerBuilder $container, array $config): void
253
    {
254
        $isConfigEnabled = $this->isConfigEnabled($container, $config['tracing']);
25✔
255

256
        if ($isConfigEnabled && !interface_exists(MailerInterface::class)) {
25✔
257
            throw new \LogicException('Mailer instrumentation cannot be enabled because the symfony/mailer package is not installed.');
×
258
        }
259

260
        if (!$isConfigEnabled) {
25✔
261
            $container->removeDefinition('open_telemetry.instrumentation.mailer.trace.transports');
18✔
262
            $container->removeDefinition('open_telemetry.instrumentation.mailer.trace.default_transport');
18✔
263
            $container->removeDefinition('open_telemetry.instrumentation.mailer.trace.mailer');
18✔
264
        }
265

266
        $this->setTracingInstrumentationParams($container, 'mailer', $config, $isConfigEnabled);
25✔
267
    }
268

269
    /**
270
     * @param InstrumentationConfig $config
271
     */
272
    private function registerMessengerTracingInstrumentationConfiguration(ContainerBuilder $container, array $config): void
273
    {
274
        $isConfigEnabled = $this->isConfigEnabled($container, $config['tracing']);
25✔
275

276
        if ($isConfigEnabled && !class_exists(Envelope::class)) {
25✔
277
            throw new \LogicException('Messenger instrumentation cannot be enabled because the symfony/messenger package is not installed.');
×
278
        }
279

280
        if (!$isConfigEnabled) {
25✔
281
            $container->removeAlias('messenger.transport.open_telemetry_tracer.factory');
18✔
282
            $container->removeAlias('messenger.middleware.open_telemetry_tracer');
18✔
283
            $container->removeDefinition('open_telemetry.instrumentation.messenger.trace.transport');
18✔
284
            $container->removeDefinition('open_telemetry.instrumentation.messenger.trace.transport_factory');
18✔
285
            $container->removeDefinition('open_telemetry.instrumentation.messenger.trace.middleware');
18✔
286
        }
287

288
        $this->setTracingInstrumentationParams($container, 'messenger', $config, $isConfigEnabled);
25✔
289
    }
290

291
    /**
292
     * @param InstrumentationConfig $config
293
     */
294
    private function registerTwigTracingInstrumentationConfiguration(ContainerBuilder $container, array $config): void
295
    {
296
        $isConfigEnabled = $this->isConfigEnabled($container, $config['tracing']);
25✔
297

298
        if ($isConfigEnabled && !class_exists(TwigBundle::class)) {
25✔
299
            throw new \LogicException('Twig instrumentation cannot be enabled because the symfony/twig-bundle package is not installed.');
×
300
        }
301

302
        if (!$isConfigEnabled) {
25✔
303
            $container->removeDefinition('open_telemetry.instrumentation.twig.trace.extension');
18✔
304
        }
305

306
        $this->setTracingInstrumentationParams($container, 'twig', $config, $isConfigEnabled);
25✔
307
    }
308

309
    /**
310
     * @param InstrumentationConfig $config
311
     */
312
    private function setTracingInstrumentationParams(ContainerBuilder $container, string $name, array $config, bool $enabled): void
313
    {
314
        $container->setParameter(sprintf('open_telemetry.instrumentation.%s.tracing.enabled', $name), $enabled);
25✔
315
        if (isset($config['type'])) {
25✔
316
            $container->setParameter(
25✔
317
                sprintf('open_telemetry.instrumentation.%s.type', $name),
25✔
318
                InstrumentationTypeEnum::from($config['type']),
25✔
319
            );
25✔
320
        }
321

322
        if ('http_kernel' === $name) {
25✔
323
            if (isset($config['tracing']['exclude_paths'])
25✔
324
                && 0 < \count($config['tracing']['exclude_paths'])
25✔
325
            ) {
326
                $container->setParameter(
3✔
327
                    sprintf('open_telemetry.instrumentation.%s.tracing.exclude_paths', $name),
3✔
328
                    $config['tracing']['exclude_paths'],
3✔
329
                );
3✔
330
            }
331
        }
332

333
        if ('console' === $name) {
25✔
334
            if (isset($config['tracing']['exclude_commands'])
25✔
335
                && 0 < \count($config['tracing']['exclude_commands'])
25✔
336
            ) {
337
                $container->setParameter(
3✔
338
                    sprintf('open_telemetry.instrumentation.%s.tracing.exclude_commands', $name),
3✔
339
                    $config['tracing']['exclude_commands'],
3✔
340
                );
3✔
341
            }
342
        }
343

344
        $container->setParameter(
25✔
345
            sprintf('open_telemetry.instrumentation.%s.tracing.tracer', $name),
25✔
346
            $config['tracing']['tracer'] ?? 'default_tracer',
25✔
347
        );
25✔
348
    }
349
}
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