vendor/symfony/monolog-bundle/DependencyInjection/MonologExtension.php line 98

Open in your IDE?
  1. <?php
  2. /*
  3.  * This file is part of the Symfony package.
  4.  *
  5.  * (c) Fabien Potencier <fabien@symfony.com>
  6.  *
  7.  * For the full copyright and license information, please view the LICENSE
  8.  * file that was distributed with this source code.
  9.  */
  10. namespace Symfony\Bundle\MonologBundle\DependencyInjection;
  11. use Monolog\Logger;
  12. use Monolog\Processor\ProcessorInterface;
  13. use Monolog\Handler\HandlerInterface;
  14. use Monolog\ResettableInterface;
  15. use Symfony\Bridge\Monolog\Handler\FingersCrossed\HttpCodeActivationStrategy;
  16. use Symfony\Bridge\Monolog\Processor\TokenProcessor;
  17. use Symfony\Bridge\Monolog\Processor\WebProcessor;
  18. use Symfony\Bundle\FullStack;
  19. use Symfony\Component\Config\FileLocator;
  20. use Symfony\Component\DependencyInjection\Argument\BoundArgument;
  21. use Symfony\Component\DependencyInjection\ContainerBuilder;
  22. use Symfony\Component\DependencyInjection\Definition;
  23. use Symfony\Component\DependencyInjection\Exception\ParameterNotFoundException;
  24. use Symfony\Component\DependencyInjection\Loader\XmlFileLoader;
  25. use Symfony\Component\DependencyInjection\Reference;
  26. use Symfony\Component\HttpKernel\DependencyInjection\Extension;
  27. use Symfony\Component\HttpKernel\Kernel;
  28. use Symfony\Contracts\HttpClient\HttpClientInterface;
  29. /**
  30.  * MonologExtension is an extension for the Monolog library.
  31.  *
  32.  * @author Jordi Boggiano <j.boggiano@seld.be>
  33.  * @author Christophe Coevoet <stof@notk.org>
  34.  */
  35. class MonologExtension extends Extension
  36. {
  37.     private $nestedHandlers = [];
  38.     private $swiftMailerHandlers = [];
  39.     private function levelToMonologConst($levelContainerBuilder $container)
  40.     {
  41.         if (null === $level || is_numeric($level)) {
  42.             return $level;
  43.         }
  44.         if (defined('Monolog\Logger::'.strtoupper($level))) {
  45.             return constant('Monolog\Logger::' strtoupper($level));
  46.         }
  47.         if ($container->hasParameter($level)) {
  48.             return $this->levelToMonologConst($container->getParameter($level), $container);
  49.         }
  50.         try {
  51.             $logLevel $container->resolveEnvPlaceholders($leveltrue);
  52.         } catch (ParameterNotFoundException $notFoundException) {
  53.             throw new \InvalidArgumentException(sprintf('Could not match "%s" to a log level.'$level));
  54.         }
  55.         if ($logLevel !== '') {
  56.             return $this->levelToMonologConst($logLevel$container);
  57.         }
  58.         throw new \InvalidArgumentException(sprintf('Could not match "%s" to a log level.'$level));
  59.     }
  60.     /**
  61.      * Loads the Monolog configuration.
  62.      *
  63.      * @param array            $configs   An array of configuration settings
  64.      * @param ContainerBuilder $container A ContainerBuilder instance
  65.      */
  66.     public function load(array $configsContainerBuilder $container)
  67.     {
  68.         if (class_exists(FullStack::class) && Kernel::MAJOR_VERSION && Logger::API >= 2) {
  69.             throw new \RuntimeException('Symfony 5 is required for Monolog 2 support. Please downgrade Monolog to version 1.');
  70.         }
  71.         $configuration $this->getConfiguration($configs$container);
  72.         $config $this->processConfiguration($configuration$configs);
  73.         if (isset($config['handlers'])) {
  74.             $loader = new XmlFileLoader($container, new FileLocator(__DIR__.'/../Resources/config'));
  75.             $loader->load('monolog.xml');
  76.             $container->setParameter('monolog.use_microseconds'$config['use_microseconds']);
  77.             $handlers = [];
  78.             foreach ($config['handlers'] as $name => $handler) {
  79.                 $handlers[$handler['priority']][] = [
  80.                     'id' => $this->buildHandler($container$name$handler),
  81.                     'channels' => empty($handler['channels']) ? null $handler['channels'],
  82.                 ];
  83.             }
  84.             $container->setParameter(
  85.                 'monolog.swift_mailer.handlers',
  86.                 $this->swiftMailerHandlers
  87.             );
  88.             ksort($handlers);
  89.             $sortedHandlers = [];
  90.             foreach ($handlers as $priorityHandlers) {
  91.                 foreach (array_reverse($priorityHandlers) as $handler) {
  92.                     $sortedHandlers[] = $handler;
  93.                 }
  94.             }
  95.             $handlersToChannels = [];
  96.             foreach ($sortedHandlers as $handler) {
  97.                 if (!in_array($handler['id'], $this->nestedHandlers)) {
  98.                     $handlersToChannels[$handler['id']] = $handler['channels'];
  99.                 }
  100.             }
  101.             $container->setParameter('monolog.handlers_to_channels'$handlersToChannels);
  102.             if (PHP_VERSION_ID 70000) {
  103.                 $this->addClassesToCompile([
  104.                     'Monolog\\Formatter\\FormatterInterface',
  105.                     'Monolog\\Formatter\\LineFormatter',
  106.                     'Monolog\\Handler\\HandlerInterface',
  107.                     'Monolog\\Handler\\AbstractHandler',
  108.                     'Monolog\\Handler\\AbstractProcessingHandler',
  109.                     'Monolog\\Handler\\StreamHandler',
  110.                     'Monolog\\Handler\\FingersCrossedHandler',
  111.                     'Monolog\\Handler\\FilterHandler',
  112.                     'Monolog\\Handler\\TestHandler',
  113.                     'Monolog\\Logger',
  114.                     'Symfony\\Bridge\\Monolog\\Logger',
  115.                     'Monolog\\Handler\\FingersCrossed\\ActivationStrategyInterface',
  116.                     'Monolog\\Handler\\FingersCrossed\\ErrorLevelActivationStrategy',
  117.                 ]);
  118.             }
  119.         }
  120.         $container->setParameter('monolog.additional_channels', isset($config['channels']) ? $config['channels'] : []);
  121.         if (method_exists($container'registerForAutoconfiguration')) {
  122.             if (interface_exists(ProcessorInterface::class)) {
  123.                 $container->registerForAutoconfiguration(ProcessorInterface::class)
  124.                     ->addTag('monolog.processor');
  125.             } else {
  126.                 $container->registerForAutoconfiguration(WebProcessor::class)
  127.                     ->addTag('monolog.processor');
  128.             }
  129.             $container->registerForAutoconfiguration(TokenProcessor::class)
  130.                 ->addTag('monolog.processor');
  131.             if (interface_exists(HttpClientInterface::class)) {
  132.                 $handlerAutoconfiguration $container->registerForAutoconfiguration(HandlerInterface::class);
  133.                 $handlerAutoconfiguration->setBindings($handlerAutoconfiguration->getBindings() + [
  134.                     HttpClientInterface::class => new BoundArgument(new Reference('monolog.http_client'), false),
  135.                 ]);
  136.             }
  137.         }
  138.     }
  139.     /**
  140.      * Returns the base path for the XSD files.
  141.      *
  142.      * @return string The XSD base path
  143.      */
  144.     public function getXsdValidationBasePath()
  145.     {
  146.         return __DIR__.'/../Resources/config/schema';
  147.     }
  148.     public function getNamespace()
  149.     {
  150.         return 'http://symfony.com/schema/dic/monolog';
  151.     }
  152.     private function buildHandler(ContainerBuilder $container$name, array $handler)
  153.     {
  154.         $handlerId $this->getHandlerId($name);
  155.         if ('service' === $handler['type']) {
  156.             $container->setAlias($handlerId$handler['id']);
  157.             if (!empty($handler['nested']) && true === $handler['nested']) {
  158.                 $this->markNestedHandler($handlerId);
  159.             }
  160.             return $handlerId;
  161.         }
  162.         $handlerClass $this->getHandlerClassByType($handler['type']);
  163.         $definition = new Definition($handlerClass);
  164.         $handler['level'] = $this->levelToMonologConst($handler['level'], $container);
  165.         if ($handler['include_stacktraces']) {
  166.             $definition->setConfigurator(['Symfony\\Bundle\\MonologBundle\\MonologBundle''includeStacktraces']);
  167.         }
  168.         if (null === $handler['process_psr_3_messages']) {
  169.             $handler['process_psr_3_messages'] = !isset($handler['handler']) && !$handler['members'];
  170.         }
  171.         if ($handler['process_psr_3_messages']) {
  172.             $processorId 'monolog.processor.psr_log_message';
  173.             if (!$container->hasDefinition($processorId)) {
  174.                 $processor = new Definition('Monolog\\Processor\\PsrLogMessageProcessor');
  175.                 $processor->setPublic(false);
  176.                 $container->setDefinition($processorId$processor);
  177.             }
  178.             $definition->addMethodCall('pushProcessor', [new Reference($processorId)]);
  179.         }
  180.         switch ($handler['type']) {
  181.         case 'stream':
  182.             $definition->setArguments([
  183.                 $handler['path'],
  184.                 $handler['level'],
  185.                 $handler['bubble'],
  186.                 $handler['file_permission'],
  187.                 $handler['use_locking'],
  188.             ]);
  189.             break;
  190.         case 'console':
  191.             $definition->setArguments([
  192.                 null,
  193.                 $handler['bubble'],
  194.                 isset($handler['verbosity_levels']) ? $handler['verbosity_levels'] : [],
  195.                 $handler['console_formater_options']
  196.             ]);
  197.             $definition->addTag('kernel.event_subscriber');
  198.             break;
  199.         case 'firephp':
  200.             $definition->setArguments([
  201.                 $handler['level'],
  202.                 $handler['bubble'],
  203.             ]);
  204.             $definition->addTag('kernel.event_listener', ['event' => 'kernel.response''method' => 'onKernelResponse']);
  205.             break;
  206.         case 'gelf':
  207.             if (isset($handler['publisher']['id'])) {
  208.                 $publisher = new Reference($handler['publisher']['id']);
  209.             } elseif (class_exists('Gelf\Transport\UdpTransport')) {
  210.                 $transport = new Definition("Gelf\Transport\UdpTransport", [
  211.                     $handler['publisher']['hostname'],
  212.                     $handler['publisher']['port'],
  213.                     $handler['publisher']['chunk_size'],
  214.                 ]);
  215.                 $transport->setPublic(false);
  216.                 $publisher = new Definition('Gelf\Publisher', []);
  217.                 $publisher->addMethodCall('addTransport', [$transport]);
  218.                 $publisher->setPublic(false);
  219.             } elseif (class_exists('Gelf\MessagePublisher')) {
  220.                 $publisher = new Definition('Gelf\MessagePublisher', [
  221.                     $handler['publisher']['hostname'],
  222.                     $handler['publisher']['port'],
  223.                     $handler['publisher']['chunk_size'],
  224.                 ]);
  225.                 $publisher->setPublic(false);
  226.             } else {
  227.                 throw new \RuntimeException('The gelf handler requires the graylog2/gelf-php package to be installed');
  228.             }
  229.             $definition->setArguments([
  230.                 $publisher,
  231.                 $handler['level'],
  232.                 $handler['bubble'],
  233.             ]);
  234.             break;
  235.         case 'mongo':
  236.             if (isset($handler['mongo']['id'])) {
  237.                 $client = new Reference($handler['mongo']['id']);
  238.             } else {
  239.                 $server 'mongodb://';
  240.                 if (isset($handler['mongo']['user'])) {
  241.                     $server .= $handler['mongo']['user'].':'.$handler['mongo']['pass'].'@';
  242.                 }
  243.                 $server .= $handler['mongo']['host'].':'.$handler['mongo']['port'];
  244.                 $client = new Definition('MongoClient', [
  245.                     $server,
  246.                 ]);
  247.                 $client->setPublic(false);
  248.             }
  249.             $definition->setArguments([
  250.                 $client,
  251.                 $handler['mongo']['database'],
  252.                 $handler['mongo']['collection'],
  253.                 $handler['level'],
  254.                 $handler['bubble'],
  255.             ]);
  256.             break;
  257.         case 'elasticsearch':
  258.             if (isset($handler['elasticsearch']['id'])) {
  259.                 $elasticaClient = new Reference($handler['elasticsearch']['id']);
  260.             } else {
  261.                 // elastica client new definition
  262.                 $elasticaClient = new Definition('Elastica\Client');
  263.                 $elasticaClientArguments = [
  264.                     'host' => $handler['elasticsearch']['host'],
  265.                     'port' => $handler['elasticsearch']['port'],
  266.                     'transport' => $handler['elasticsearch']['transport'],
  267.                 ];
  268.                 if (isset($handler['elasticsearch']['user']) && isset($handler['elasticsearch']['password'])) {
  269.                     $elasticaClientArguments array_merge(
  270.                         $elasticaClientArguments,
  271.                         [
  272.                             'headers' => [
  273.                                 'Authorization' => 'Basic ' base64_encode($handler['elasticsearch']['user'] . ':' $handler['elasticsearch']['password'])
  274.                             ]
  275.                         ]
  276.                     );
  277.                 }
  278.                 $elasticaClient->setArguments([
  279.                     $elasticaClientArguments
  280.                 ]);
  281.                 $elasticaClient->setPublic(false);
  282.             }
  283.             // elastica handler definition
  284.             $definition->setArguments([
  285.                 $elasticaClient,
  286.                 [
  287.                     'index' => $handler['index'],
  288.                     'type' => $handler['document_type'],
  289.                     'ignore_error' => $handler['ignore_error']
  290.                 ],
  291.                 $handler['level'],
  292.                 $handler['bubble'],
  293.             ]);
  294.             break;
  295.         case 'redis':
  296.         case 'predis':
  297.             if (isset($handler['redis']['id'])) {
  298.                 $clientId $handler['redis']['id'];
  299.             } elseif ('redis' === $handler['type']) {
  300.                 if (!class_exists(\Redis::class)) {
  301.                     throw new \RuntimeException('The \Redis class is not available.');
  302.                 }
  303.                 $client = new Definition(\Redis::class);
  304.                 $client->addMethodCall('connect', [$handler['redis']['host'], $handler['redis']['port']]);
  305.                 $client->addMethodCall('auth', [$handler['redis']['password']]);
  306.                 $client->addMethodCall('select', [$handler['redis']['database']]);
  307.                 $client->setPublic(false);
  308.                 $clientId uniqid('monolog.redis.client.'true);
  309.                 $container->setDefinition($clientId$client);
  310.             } else {
  311.                 if (!class_exists(\Predis\Client::class)) {
  312.                     throw new \RuntimeException('The \Predis\Client class is not available.');
  313.                 }
  314.                 $client = new Definition(\Predis\Client::class);
  315.                 $client->setArguments([
  316.                     $handler['redis']['host'],
  317.                 ]);
  318.                 $client->setPublic(false);
  319.                 $clientId uniqid('monolog.predis.client.'true);
  320.                 $container->setDefinition($clientId$client);
  321.             }
  322.             $definition->setArguments([
  323.                 new Reference($clientId),
  324.                 $handler['redis']['key_name'],
  325.                 $handler['level'],
  326.                 $handler['bubble'],
  327.             ]);
  328.             break;
  329.         case 'chromephp':
  330.             $definition->setArguments([
  331.                 $handler['level'],
  332.                 $handler['bubble'],
  333.             ]);
  334.             $definition->addTag('kernel.event_listener', ['event' => 'kernel.response''method' => 'onKernelResponse']);
  335.             break;
  336.         case 'rotating_file':
  337.             $definition->setArguments([
  338.                 $handler['path'],
  339.                 $handler['max_files'],
  340.                 $handler['level'],
  341.                 $handler['bubble'],
  342.                 $handler['file_permission'],
  343.             ]);
  344.             $definition->addMethodCall('setFilenameFormat', [
  345.                 $handler['filename_format'],
  346.                 $handler['date_format'],
  347.             ]);
  348.             break;
  349.         case 'fingers_crossed':
  350.             $handler['action_level'] = $this->levelToMonologConst($handler['action_level'], $container);
  351.             if (null !== $handler['passthru_level']) {
  352.                 $handler['passthru_level'] = $this->levelToMonologConst($handler['passthru_level'], $container);
  353.             }
  354.             $nestedHandlerId $this->getHandlerId($handler['handler']);
  355.             $this->markNestedHandler($nestedHandlerId);
  356.             if (isset($handler['activation_strategy'])) {
  357.                 $activation = new Reference($handler['activation_strategy']);
  358.             } elseif (!empty($handler['excluded_404s'])) {
  359.                 if (class_exists(HttpCodeActivationStrategy::class)) {
  360.                     @trigger_error('The "excluded_404s" option is deprecated in MonologBundle since version 3.4.0, you should rely on the "excluded_http_codes" option instead.'E_USER_DEPRECATED);
  361.                 }
  362.                 $activationDef = new Definition('Symfony\Bridge\Monolog\Handler\FingersCrossed\NotFoundActivationStrategy', [
  363.                     new Reference('request_stack'),
  364.                     $handler['excluded_404s'],
  365.                     $handler['action_level']
  366.                 ]);
  367.                 $container->setDefinition($handlerId.'.not_found_strategy'$activationDef);
  368.                 $activation = new Reference($handlerId.'.not_found_strategy');
  369.             } elseif (!empty($handler['excluded_http_codes'])) {
  370.                 if (!class_exists('Symfony\Bridge\Monolog\Handler\FingersCrossed\HttpCodeActivationStrategy')) {
  371.                     throw new \LogicException('"excluded_http_codes" cannot be used as your version of Monolog bridge does not support it.');
  372.                 }
  373.                 $activationDef = new Definition('Symfony\Bridge\Monolog\Handler\FingersCrossed\HttpCodeActivationStrategy', [
  374.                     new Reference('request_stack'),
  375.                     $handler['excluded_http_codes'],
  376.                     $handler['action_level']
  377.                 ]);
  378.                 $container->setDefinition($handlerId.'.http_code_strategy'$activationDef);
  379.                 $activation = new Reference($handlerId.'.http_code_strategy');
  380.             } else {
  381.                 $activation $handler['action_level'];
  382.             }
  383.             $definition->setArguments([
  384.                 new Reference($nestedHandlerId),
  385.                 $activation,
  386.                 $handler['buffer_size'],
  387.                 $handler['bubble'],
  388.                 $handler['stop_buffering'],
  389.                 $handler['passthru_level'],
  390.             ]);
  391.             break;
  392.         case 'filter':
  393.             $handler['min_level'] = $this->levelToMonologConst($handler['min_level'], $container);
  394.             $handler['max_level'] = $this->levelToMonologConst($handler['max_level'], $container);
  395.             foreach (array_keys($handler['accepted_levels']) as $k) {
  396.                 $handler['accepted_levels'][$k] = $this->levelToMonologConst($handler['accepted_levels'][$k], $container);
  397.             }
  398.             $nestedHandlerId $this->getHandlerId($handler['handler']);
  399.             $this->markNestedHandler($nestedHandlerId);
  400.             $minLevelOrList = !empty($handler['accepted_levels']) ? $handler['accepted_levels'] : $handler['min_level'];
  401.             $definition->setArguments([
  402.                 new Reference($nestedHandlerId),
  403.                 $minLevelOrList,
  404.                 $handler['max_level'],
  405.                 $handler['bubble'],
  406.             ]);
  407.             break;
  408.         case 'buffer':
  409.             $nestedHandlerId $this->getHandlerId($handler['handler']);
  410.             $this->markNestedHandler($nestedHandlerId);
  411.             $definition->setArguments([
  412.                 new Reference($nestedHandlerId),
  413.                 $handler['buffer_size'],
  414.                 $handler['level'],
  415.                 $handler['bubble'],
  416.                 $handler['flush_on_overflow'],
  417.             ]);
  418.             break;
  419.         case 'deduplication':
  420.             $nestedHandlerId $this->getHandlerId($handler['handler']);
  421.             $this->markNestedHandler($nestedHandlerId);
  422.             $defaultStore '%kernel.cache_dir%/monolog_dedup_'.sha1($handlerId);
  423.             $definition->setArguments([
  424.                 new Reference($nestedHandlerId),
  425.                 isset($handler['store']) ? $handler['store'] : $defaultStore,
  426.                 $handler['deduplication_level'],
  427.                 $handler['time'],
  428.                 $handler['bubble'],
  429.             ]);
  430.             break;
  431.         case 'group':
  432.         case 'whatfailuregroup':
  433.         case 'fallbackgroup':
  434.             $references = [];
  435.             foreach ($handler['members'] as $nestedHandler) {
  436.                 $nestedHandlerId $this->getHandlerId($nestedHandler);
  437.                 $this->markNestedHandler($nestedHandlerId);
  438.                 $references[] = new Reference($nestedHandlerId);
  439.             }
  440.             $definition->setArguments([
  441.                 $references,
  442.                 $handler['bubble'],
  443.             ]);
  444.             break;
  445.         case 'syslog':
  446.             $definition->setArguments([
  447.                 $handler['ident'],
  448.                 $handler['facility'],
  449.                 $handler['level'],
  450.                 $handler['bubble'],
  451.                 $handler['logopts'],
  452.             ]);
  453.             break;
  454.         case 'syslogudp':
  455.             $definition->setArguments([
  456.                 $handler['host'],
  457.                 $handler['port'],
  458.                 $handler['facility'],
  459.                 $handler['level'],
  460.                 $handler['bubble'],
  461.             ]);
  462.             if ($handler['ident']) {
  463.                 $definition->addArgument($handler['ident']);
  464.             }
  465.             break;
  466.         case 'swift_mailer':
  467.             $mailer $handler['mailer'] ?: 'mailer';
  468.             if (isset($handler['email_prototype'])) {
  469.                 if (!empty($handler['email_prototype']['method'])) {
  470.                     $prototype = [new Reference($handler['email_prototype']['id']), $handler['email_prototype']['method']];
  471.                 } else {
  472.                     $prototype = new Reference($handler['email_prototype']['id']);
  473.                 }
  474.             } else {
  475.                 $messageFactory = new Definition('Symfony\Bundle\MonologBundle\SwiftMailer\MessageFactory');
  476.                 $messageFactory->setLazy(true);
  477.                 $messageFactory->setPublic(false);
  478.                 $messageFactory->setArguments([
  479.                     new Reference($mailer),
  480.                     $handler['from_email'],
  481.                     $handler['to_email'],
  482.                     $handler['subject'],
  483.                     $handler['content_type']
  484.                 ]);
  485.                 $messageFactoryId sprintf('%s.mail_message_factory'$handlerId);
  486.                 $container->setDefinition($messageFactoryId$messageFactory);
  487.                 // set the prototype as a callable
  488.                 $prototype = [new Reference($messageFactoryId), 'createMessage'];
  489.             }
  490.             $definition->setArguments([
  491.                 new Reference($mailer),
  492.                 $prototype,
  493.                 $handler['level'],
  494.                 $handler['bubble'],
  495.             ]);
  496.             $this->swiftMailerHandlers[] = $handlerId;
  497.             $definition->addTag('kernel.event_listener', ['event' => 'kernel.terminate''method' => 'onKernelTerminate']);
  498.             $definition->addTag('kernel.event_listener', ['event' => 'console.terminate''method' => 'onCliTerminate']);
  499.             break;
  500.         case 'native_mailer':
  501.             $definition->setArguments([
  502.                 $handler['to_email'],
  503.                 $handler['subject'],
  504.                 $handler['from_email'],
  505.                 $handler['level'],
  506.                 $handler['bubble'],
  507.             ]);
  508.             if (!empty($handler['headers'])) {
  509.                 $definition->addMethodCall('addHeader', [$handler['headers']]);
  510.             }
  511.             break;
  512.         case 'symfony_mailer':
  513.             $mailer $handler['mailer'] ?: 'mailer.mailer';
  514.             if (isset($handler['email_prototype'])) {
  515.                 if (!empty($handler['email_prototype']['method'])) {
  516.                     $prototype = [new Reference($handler['email_prototype']['id']), $handler['email_prototype']['method']];
  517.                 } else {
  518.                     $prototype = new Reference($handler['email_prototype']['id']);
  519.                 }
  520.             } else {
  521.                 $prototype = (new Definition('Symfony\Component\Mime\Email'))
  522.                     ->setPublic(false)
  523.                     ->addMethodCall('from', [$handler['from_email']])
  524.                     ->addMethodCall('to'$handler['to_email'])
  525.                     ->addMethodCall('subject', [$handler['subject']]);
  526.             }
  527.             $definition->setArguments([
  528.                 new Reference($mailer),
  529.                 $prototype,
  530.                 $handler['level'],
  531.                 $handler['bubble'],
  532.             ]);
  533.             break;
  534.         case 'socket':
  535.             $definition->setArguments([
  536.                 $handler['connection_string'],
  537.                 $handler['level'],
  538.                 $handler['bubble'],
  539.             ]);
  540.             if (isset($handler['timeout'])) {
  541.                 $definition->addMethodCall('setTimeout', [$handler['timeout']]);
  542.             }
  543.             if (isset($handler['connection_timeout'])) {
  544.                 $definition->addMethodCall('setConnectionTimeout', [$handler['connection_timeout']]);
  545.             }
  546.             if (isset($handler['persistent'])) {
  547.                 $definition->addMethodCall('setPersistent', [$handler['persistent']]);
  548.             }
  549.             break;
  550.         case 'pushover':
  551.             $definition->setArguments([
  552.                 $handler['token'],
  553.                 $handler['user'],
  554.                 $handler['title'],
  555.                 $handler['level'],
  556.                 $handler['bubble'],
  557.             ]);
  558.             if (isset($handler['timeout'])) {
  559.                 $definition->addMethodCall('setTimeout', [$handler['timeout']]);
  560.             }
  561.             if (isset($handler['connection_timeout'])) {
  562.                 $definition->addMethodCall('setConnectionTimeout', [$handler['connection_timeout']]);
  563.             }
  564.             break;
  565.         case 'hipchat':
  566.             $definition->setArguments([
  567.                 $handler['token'],
  568.                 $handler['room'],
  569.                 $handler['nickname'],
  570.                 $handler['notify'],
  571.                 $handler['level'],
  572.                 $handler['bubble'],
  573.                 $handler['use_ssl'],
  574.                 $handler['message_format'],
  575.                 !empty($handler['host']) ? $handler['host'] : 'api.hipchat.com',
  576.                 !empty($handler['api_version']) ? $handler['api_version'] : 'v1',
  577.             ]);
  578.             if (isset($handler['timeout'])) {
  579.                 $definition->addMethodCall('setTimeout', [$handler['timeout']]);
  580.             }
  581.             if (isset($handler['connection_timeout'])) {
  582.                 $definition->addMethodCall('setConnectionTimeout', [$handler['connection_timeout']]);
  583.             }
  584.             break;
  585.         case 'slack':
  586.             $definition->setArguments([
  587.                 $handler['token'],
  588.                 $handler['channel'],
  589.                 $handler['bot_name'],
  590.                 $handler['use_attachment'],
  591.                 $handler['icon_emoji'],
  592.                 $handler['level'],
  593.                 $handler['bubble'],
  594.                 $handler['use_short_attachment'],
  595.                 $handler['include_extra'],
  596.             ]);
  597.             if (isset($handler['timeout'])) {
  598.                 $definition->addMethodCall('setTimeout', [$handler['timeout']]);
  599.             }
  600.             if (isset($handler['connection_timeout'])) {
  601.                 $definition->addMethodCall('setConnectionTimeout', [$handler['connection_timeout']]);
  602.             }
  603.             break;
  604.         case 'slackwebhook':
  605.             $definition->setArguments([
  606.                 $handler['webhook_url'],
  607.                 $handler['channel'],
  608.                 $handler['bot_name'],
  609.                 $handler['use_attachment'],
  610.                 $handler['icon_emoji'],
  611.                 $handler['use_short_attachment'],
  612.                 $handler['include_extra'],
  613.                 $handler['level'],
  614.                 $handler['bubble'],
  615.             ]);
  616.             break;
  617.         case 'slackbot':
  618.             $definition->setArguments([
  619.                 $handler['team'],
  620.                 $handler['token'],
  621.                 urlencode($handler['channel']),
  622.                 $handler['level'],
  623.                 $handler['bubble'],
  624.             ]);
  625.             break;
  626.         case 'cube':
  627.             $definition->setArguments([
  628.                 $handler['url'],
  629.                 $handler['level'],
  630.                 $handler['bubble'],
  631.             ]);
  632.             break;
  633.         case 'amqp':
  634.             $definition->setArguments([
  635.                 new Reference($handler['exchange']),
  636.                 $handler['exchange_name'],
  637.                 $handler['level'],
  638.                 $handler['bubble'],
  639.             ]);
  640.             break;
  641.         case 'error_log':
  642.             $definition->setArguments([
  643.                 $handler['message_type'],
  644.                 $handler['level'],
  645.                 $handler['bubble'],
  646.             ]);
  647.             break;
  648.         case 'sentry':
  649.             if (null !== $handler['client_id']) {
  650.                 $clientId $handler['client_id'];
  651.             } else {
  652.                 $options = new Definition(
  653.                     'Sentry\\Options',
  654.                     [['dsn' => $handler['dsn']]]
  655.                 );
  656.                 if (!empty($handler['environment'])) {
  657.                     $options->addMethodCall('setEnvironment', [$handler['environment']]);
  658.                 }
  659.                 if (!empty($handler['release'])) {
  660.                     $options->addMethodCall('setRelease', [$handler['release']]);
  661.                 }
  662.                 $builder = new Definition('Sentry\\ClientBuilder', [$options]);
  663.                 $client = new Definition('Sentry\\Client');
  664.                 $client->setFactory([$builder'getClient']);
  665.                 $clientId 'monolog.sentry.client.'.sha1($handler['dsn']);
  666.                 $container->setDefinition($clientId$client);
  667.                 if (!$container->hasAlias('Sentry\\ClientInterface')) {
  668.                     $container->setAlias('Sentry\\ClientInterface'$clientId);
  669.                 }
  670.             }
  671.             $hub = new Definition(
  672.                 'Sentry\\State\\Hub',
  673.                 [new Reference($clientId)]
  674.             );
  675.             // can't set the hub to the current hub, getting into a recursion otherwise...
  676.             //$hub->addMethodCall('setCurrent', array($hub));
  677.             $definition->setArguments([
  678.                 $hub,
  679.                 $handler['level'],
  680.                 $handler['bubble'],
  681.             ]);
  682.             break;
  683.         case 'raven':
  684.             if (null !== $handler['client_id']) {
  685.                 $clientId $handler['client_id'];
  686.             } else {
  687.                 $client = new Definition('Raven_Client', [
  688.                     $handler['dsn'],
  689.                     [
  690.                         'auto_log_stacks' => $handler['auto_log_stacks'],
  691.                         'environment' => $handler['environment']
  692.                     ]
  693.                 ]);
  694.                 $client->setPublic(false);
  695.                 $clientId 'monolog.raven.client.'.sha1($handler['dsn']);
  696.                 $container->setDefinition($clientId$client);
  697.             }
  698.             $definition->setArguments([
  699.                 new Reference($clientId),
  700.                 $handler['level'],
  701.                 $handler['bubble'],
  702.             ]);
  703.             if (!empty($handler['release'])) {
  704.                 $definition->addMethodCall('setRelease', [$handler['release']]);
  705.             }
  706.             break;
  707.         case 'loggly':
  708.             $definition->setArguments([
  709.                 $handler['token'],
  710.                 $handler['level'],
  711.                 $handler['bubble'],
  712.             ]);
  713.             if (!empty($handler['tags'])) {
  714.                 $definition->addMethodCall('setTag', [implode(','$handler['tags'])]);
  715.             }
  716.             break;
  717.         case 'logentries':
  718.             $definition->setArguments([
  719.                 $handler['token'],
  720.                 $handler['use_ssl'],
  721.                 $handler['level'],
  722.                 $handler['bubble'],
  723.             ]);
  724.             if (isset($handler['timeout'])) {
  725.                 $definition->addMethodCall('setTimeout', [$handler['timeout']]);
  726.             }
  727.             if (isset($handler['connection_timeout'])) {
  728.                 $definition->addMethodCall('setConnectionTimeout', [$handler['connection_timeout']]);
  729.             }
  730.             break;
  731.         case 'insightops':
  732.             $definition->setArguments([
  733.                 $handler['token'],
  734.                 $handler['region'] ? $handler['region'] : 'us',
  735.                 $handler['use_ssl'],
  736.                 $handler['level'],
  737.                 $handler['bubble'],
  738.             ]);
  739.             break;
  740.         case 'flowdock':
  741.             $definition->setArguments([
  742.                 $handler['token'],
  743.                 $handler['level'],
  744.                 $handler['bubble'],
  745.             ]);
  746.             if (empty($handler['formatter'])) {
  747.                 $formatter = new Definition("Monolog\Formatter\FlowdockFormatter", [
  748.                     $handler['source'],
  749.                     $handler['from_email'],
  750.                 ]);
  751.                 $formatterId 'monolog.flowdock.formatter.'.sha1($handler['source'].'|'.$handler['from_email']);
  752.                 $formatter->setPublic(false);
  753.                 $container->setDefinition($formatterId$formatter);
  754.                 $definition->addMethodCall('setFormatter', [new Reference($formatterId)]);
  755.             }
  756.             break;
  757.         case 'rollbar':
  758.             if (!empty($handler['id'])) {
  759.                 $rollbarId $handler['id'];
  760.             } else {
  761.                 $config $handler['config'] ?: [];
  762.                 $config['access_token'] = $handler['token'];
  763.                 $rollbar = new Definition('RollbarNotifier', [
  764.                     $config,
  765.                 ]);
  766.                 $rollbarId 'monolog.rollbar.notifier.'.sha1(json_encode($config));
  767.                 $rollbar->setPublic(false);
  768.                 $container->setDefinition($rollbarId$rollbar);
  769.             }
  770.             $definition->setArguments([
  771.                 new Reference($rollbarId),
  772.                 $handler['level'],
  773.                 $handler['bubble'],
  774.             ]);
  775.             break;
  776.         case 'newrelic':
  777.             $definition->setArguments([
  778.                 $handler['level'],
  779.                 $handler['bubble'],
  780.                 $handler['app_name'],
  781.             ]);
  782.             break;
  783.         case 'server_log':
  784.             if (!class_exists('Symfony\Bridge\Monolog\Handler\ServerLogHandler')) {
  785.                 throw new \RuntimeException('The ServerLogHandler is not available. Please update "symfony/monolog-bridge" to 3.3.');
  786.             }
  787.             $definition->setArguments([
  788.                 $handler['host'],
  789.                 $handler['level'],
  790.                 $handler['bubble'],
  791.             ]);
  792.             break;
  793.         // Handlers using the constructor of AbstractHandler without adding their own arguments
  794.         case 'browser_console':
  795.         case 'test':
  796.         case 'null':
  797.         case 'debug':
  798.             $definition->setArguments([
  799.                 $handler['level'],
  800.                 $handler['bubble'],
  801.             ]);
  802.             break;
  803.         default:
  804.             $nullWarning '';
  805.             if ($handler['type'] == '') {
  806.                 $nullWarning ', if you meant to define a null handler in a yaml config, make sure you quote "null" so it does not get converted to a php null';
  807.             }
  808.             throw new \InvalidArgumentException(sprintf('Invalid handler type "%s" given for handler "%s"' $nullWarning$handler['type'], $name));
  809.         }
  810.         if (!empty($handler['nested']) && true === $handler['nested']) {
  811.             $this->markNestedHandler($handlerId);
  812.         }
  813.         if (!empty($handler['formatter'])) {
  814.             $definition->addMethodCall('setFormatter', [new Reference($handler['formatter'])]);
  815.         }
  816.         if (!in_array($handlerId$this->nestedHandlers) && is_subclass_of($handlerClassResettableInterface::class)) {
  817.             $definition->addTag('kernel.reset', ['method' => 'reset']);
  818.         }
  819.         $container->setDefinition($handlerId$definition);
  820.         return $handlerId;
  821.     }
  822.     private function markNestedHandler($nestedHandlerId)
  823.     {
  824.         if (in_array($nestedHandlerId$this->nestedHandlers)) {
  825.             return;
  826.         }
  827.         $this->nestedHandlers[] = $nestedHandlerId;
  828.     }
  829.     private function getHandlerId($name)
  830.     {
  831.         return sprintf('monolog.handler.%s'$name);
  832.     }
  833.     private function getHandlerClassByType($handlerType)
  834.     {
  835.         $typeToClassMapping = [
  836.             'stream' => 'Monolog\Handler\StreamHandler',
  837.             'console' => 'Symfony\Bridge\Monolog\Handler\ConsoleHandler',
  838.             'group' => 'Monolog\Handler\GroupHandler',
  839.             'buffer' => 'Monolog\Handler\BufferHandler',
  840.             'deduplication' => 'Monolog\Handler\DeduplicationHandler',
  841.             'rotating_file' => 'Monolog\Handler\RotatingFileHandler',
  842.             'syslog' => 'Monolog\Handler\SyslogHandler',
  843.             'syslogudp' => 'Monolog\Handler\SyslogUdpHandler',
  844.             'null' => 'Monolog\Handler\NullHandler',
  845.             'test' => 'Monolog\Handler\TestHandler',
  846.             'gelf' => 'Monolog\Handler\GelfHandler',
  847.             'rollbar' => 'Monolog\Handler\RollbarHandler',
  848.             'flowdock' => 'Monolog\Handler\FlowdockHandler',
  849.             'browser_console' => 'Monolog\Handler\BrowserConsoleHandler',
  850.             'firephp' => 'Symfony\Bridge\Monolog\Handler\FirePHPHandler',
  851.             'chromephp' => 'Symfony\Bridge\Monolog\Handler\ChromePhpHandler',
  852.             'debug' => 'Symfony\Bridge\Monolog\Handler\DebugHandler',
  853.             'swift_mailer' => 'Symfony\Bridge\Monolog\Handler\SwiftMailerHandler',
  854.             'native_mailer' => 'Monolog\Handler\NativeMailerHandler',
  855.             'symfony_mailer' => 'Symfony\Bridge\Monolog\Handler\MailerHandler',
  856.             'socket' => 'Monolog\Handler\SocketHandler',
  857.             'pushover' => 'Monolog\Handler\PushoverHandler',
  858.             'raven' => 'Monolog\Handler\RavenHandler',
  859.             'sentry' => 'Sentry\Monolog\Handler',
  860.             'newrelic' => 'Monolog\Handler\NewRelicHandler',
  861.             'hipchat' => 'Monolog\Handler\HipChatHandler',
  862.             'slack' => 'Monolog\Handler\SlackHandler',
  863.             'slackwebhook' => 'Monolog\Handler\SlackWebhookHandler',
  864.             'slackbot' => 'Monolog\Handler\SlackbotHandler',
  865.             'cube' => 'Monolog\Handler\CubeHandler',
  866.             'amqp' => 'Monolog\Handler\AmqpHandler',
  867.             'error_log' => 'Monolog\Handler\ErrorLogHandler',
  868.             'loggly' => 'Monolog\Handler\LogglyHandler',
  869.             'logentries' => 'Monolog\Handler\LogEntriesHandler',
  870.             'whatfailuregroup' => 'Monolog\Handler\WhatFailureGroupHandler',
  871.             'fingers_crossed' => 'Monolog\Handler\FingersCrossedHandler',
  872.             'filter' => 'Monolog\Handler\FilterHandler',
  873.             'mongo' => 'Monolog\Handler\MongoDBHandler',
  874.             'elasticsearch' => 'Monolog\Handler\ElasticSearchHandler',
  875.             'server_log' => 'Symfony\Bridge\Monolog\Handler\ServerLogHandler',
  876.             'redis' => 'Monolog\Handler\RedisHandler',
  877.             'predis' => 'Monolog\Handler\RedisHandler',
  878.             'insightops' => 'Monolog\Handler\InsightOpsHandler',
  879.         ];
  880.         $v2HandlerTypesAdded = [
  881.             'elasticsearch' => 'Monolog\Handler\ElasticaHandler',
  882.             'fallbackgroup' => 'Monolog\Handler\FallbackGroupHandler',
  883.             'logmatic' => 'Monolog\Handler\LogmaticHandler',
  884.             'noop' => 'Monolog\Handler\NoopHandler',
  885.             'overflow' => 'Monolog\Handler\OverflowHandler',
  886.             'process' => 'Monolog\Handler\ProcessHandler',
  887.             'sendgrid' => 'Monolog\Handler\SendGridHandler',
  888.             'sqs' => 'Monolog\Handler\SqsHandler',
  889.             'telegram' => 'Monolog\Handler\TelegramBotHandler',
  890.         ];
  891.         $v2HandlerTypesRemoved = [
  892.             'hipchat',
  893.             'raven',
  894.             'slackbot',
  895.         ];
  896.         if (Logger::API === 2) {
  897.             $typeToClassMapping array_merge($typeToClassMapping$v2HandlerTypesAdded);
  898.             foreach($v2HandlerTypesRemoved as $v2HandlerTypeRemoved) {
  899.                 unset($typeToClassMapping[$v2HandlerTypeRemoved]);
  900.             }
  901.         }
  902.         if (!isset($typeToClassMapping[$handlerType])) {
  903.             if (Logger::API === && array_key_exists($handlerType$v2HandlerTypesAdded)) {
  904.                 throw new \InvalidArgumentException(sprintf('"%s" was added in Monolog v2, please upgrade if you wish to use it.'$handlerType));
  905.             }
  906.             if (Logger::API === && array_key_exists($handlerType$v2HandlerTypesRemoved)) {
  907.                 throw new \InvalidArgumentException(sprintf('"%s" was removed in Monolog v2.'$handlerType));
  908.             }
  909.             throw new \InvalidArgumentException(sprintf('There is no handler class defined for handler "%s".'$handlerType));
  910.         }
  911.         return $typeToClassMapping[$handlerType];
  912.     }
  913. }