Passed
Pull Request — master (#175)
by Jérémy
02:09
created

getTransactionNamingService()   B

Complexity

Conditions 5
Paths 5

Size

Total Lines 28
Code Lines 19

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 28
rs 8.439
c 0
b 0
f 0
cc 5
eloc 19
nc 5
nop 1
1
<?php
2
3
declare(strict_types=1);
4
5
/*
6
 * This file is part of Ekino New Relic bundle.
7
 *
8
 * (c) Ekino - Thomas Rabaix <[email protected]>
9
 *
10
 * For the full copyright and license information, please view the LICENSE
11
 * file that was distributed with this source code.
12
 */
13
14
namespace  Ekino\NewRelicBundle\DependencyInjection;
15
16
use Ekino\NewRelicBundle\Listener\CommandListener;
17
use Ekino\NewRelicBundle\Listener\RequestListener;
18
use Ekino\NewRelicBundle\Listener\ResponseListener;
19
use Ekino\NewRelicBundle\NewRelic\BlackholeInteractor;
20
use Ekino\NewRelicBundle\NewRelic\Config;
21
use Ekino\NewRelicBundle\NewRelic\LoggingInteractorDecorator;
22
use Ekino\NewRelicBundle\NewRelic\NewRelicInteractor;
23
use Ekino\NewRelicBundle\NewRelic\NewRelicInteractorInterface;
24
use Ekino\NewRelicBundle\TransactionNamingStrategy\ControllerNamingStrategy;
25
use Ekino\NewRelicBundle\TransactionNamingStrategy\RouteNamingStrategy;
26
use Ekino\NewRelicBundle\TransactionNamingStrategy\TransactionNamingStrategyInterface;
27
use Symfony\Component\Config\FileLocator;
28
use Symfony\Component\DependencyInjection\ContainerBuilder;
29
use Symfony\Component\DependencyInjection\ContainerInterface;
30
use Symfony\Component\DependencyInjection\Loader;
31
use Symfony\Component\DependencyInjection\Reference;
32
use Symfony\Component\HttpKernel\DependencyInjection\Extension;
33
34
/**
35
 * This is the class that loads and manages your bundle configuration.
36
 *
37
 * To learn more see {@link http://symfony.com/doc/current/cookbook/bundles/extension.html}
38
 */
39
class EkinoNewRelicExtension extends Extension
40
{
41
    public function load(array $configs, ContainerBuilder $container): void
42
    {
43
        $configuration = new Configuration();
44
        $config = $this->processConfiguration($configuration, $configs);
45
46
        $loader = new Loader\XmlFileLoader($container, new FileLocator(__DIR__.'/../Resources/config'));
47
        $loader->load('services.xml');
48
49
        $container->setAlias(NewRelicInteractorInterface::class, $this->getInteractorServiceId($config))->setPublic(false);
50
        $container->setAlias(TransactionNamingStrategyInterface::class, $this->getTransactionNamingServiceId($config))->setPublic(false);
51
52
        if ($config['logging']) {
53
            $container->register(LoggingInteractorDecorator::class)
54
                ->setDecoratedService(NewRelicInteractorInterface::class)
55
                ->setArguments(
56
                    [
57
                        '$interactor' => new Reference(LoggingInteractorDecorator::class.'.inner'),
58
                        '$logger' => new Reference('logger', ContainerInterface::NULL_ON_INVALID_REFERENCE),
59
                    ]
60
                )
61
                ->setPublic(false)
62
            ;
63
        }
64
65
        if (!empty($config['deployment_names'])) {
66
            $config['deployment_names'] = \array_values(\array_filter(\explode(';', $config['application_name'])));
67
        }
68
69
        $container->getDefinition(Config::class)
70
            ->setArguments(
71
                [
72
                    '$name' => $config['application_name'],
73
                    '$apiKey' => $config['api_key'],
74
                    '$licenseKey' => $config['license_key'],
75
                    '$xmit' => $config['xmit'],
76
                    '$deploymentNames' => $config['deployment_names'],
77
                ]
78
            );
79
80
        if ($config['http']['enabled']) {
81
            $loader->load('http_listener.xml');
82
            $container->getDefinition(RequestListener::class)
83
                ->setArguments(
84
                    [
85
                        '$ignoreRoutes' => $config['http']['ignored_routes'],
86
                        '$ignoredPaths' => $config['http']['ignored_paths'],
87
                        '$symfonyCache' => $config['http']['using_symfony_cache'],
88
                    ]
89
                );
90
91
            $container->getDefinition(ResponseListener::class)
92
                ->setArguments(
93
                    [
94
                        '$instrument' => $config['http']['instrument'],
95
                        '$symfonyCache' => $config['http']['using_symfony_cache'],
96
                    ]
97
                );
98
        }
99
100
        if ($config['commands']['enabled']) {
101
            $loader->load('command_listener.xml');
102
            $container->getDefinition(CommandListener::class)
103
                ->setArguments(
104
                    [
105
                        '$ignoredCommands' => $config['commands']['ignored_commands'],
106
                    ]
107
                );
108
        }
109
110
        if ($config['exceptions']['enabled']) {
111
            $loader->load('exception_listener.xml');
112
        }
113
114
        if ($config['deprecations']['enabled']) {
115
            $loader->load('deprecation_listener.xml');
116
        }
117
118
        if ($config['twig']) {
119
            $loader->load('twig.xml');
120
        }
121
122
        if ($config['enabled'] && $config['monolog']['enabled']) {
123
            if (!\class_exists(\Monolog\Handler\NewRelicHandler::class)) {
124
                throw new \LogicException('The "symfony/monolog-bundle" package must be installed in order to use "monolog" option.');
125
            }
126
            $loader->load('monolog.xml');
127
            $container->setParameter('ekino.new_relic.monolog.channels', $config['monolog']['channels']);
128
            $container->setAlias('ekino.new_relic.logs_handler', $config['monolog']['service'])->setPublic(false);
129
130
            $level = $config['monolog']['level'];
131
            // This service is used by MonologHandlerPass to inject into Monolog Service
132
            $container->findDefinition('ekino.new_relic.logs_handler')
133
                ->setArguments(
134
                    [
135
                        '$level' => \is_int($level) ? $level : \constant('Monolog\Logger::'.\strtoupper($level)),
136
                        '$appName' => $config['application_name'],
137
                    ]
138
                );
139
        }
140
    }
141
142
    private function getInteractorServiceId(array $config): string
143
    {
144
        if (!$config['enabled']) {
145
            return BlackholeInteractor::class;
146
        }
147
148
        if (isset($config['interactor'])) {
149
            return $config['interactor'];
150
        }
151
152
        // Fallback to see if the extension is loaded or not
153
        return \extension_loaded('newrelic') ? NewRelicInteractor::class : BlackholeInteractor::class;
154
    }
155
156
    private function getTransactionNamingServiceId(array $config): string
157
    {
158
        switch ($config['http']['transaction_naming']) {
159
            case 'controller':
160
                return ControllerNamingStrategy::class;
161
            case 'route':
162
                return RouteNamingStrategy::class;
163
            case 'service':
164
                if (!isset($config['http']['transaction_naming_service'])) {
165
                    throw new \LogicException(
166
                        'When using the "service", transaction naming scheme, the "transaction_naming_service" config parameter must be set.'
167
                    );
168
                }
169
170
                return $config['http']['transaction_naming_service'];
171
            default:
172
                throw new \InvalidArgumentException(
173
                    \sprintf(
174
                        'Invalid transaction naming scheme "%s", must be "route", "controller" or "service".',
175
                        $config['http']['transaction_naming']
176
                    )
177
                );
178
        }
179
    }
180
}
181