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

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