Monolog exposes circular dependency in logger.factory service

Created on 6 February 2023, over 1 year ago
Updated 12 April 2023, about 1 year ago

Problem/Motivation

Reported as notice, but this fatals locally.

NOTICE: PHP message: Failed to log error: Symfony\Component\DependencyInjection\Exception\ServiceCircularReferenceException: Circular reference detected for service "logger.factory", path: "file_system -> logger.channel.file -> logger.factory -> exception.logger". in Drupal\Component\DependencyInjection\Container->get() (line 147 of /data/app/core/lib/Drupal/Component/DependencyInjection/Container.php). #0 /data/app/core/lib/Drupal/Component/DependencyInjection/Container.php(434): Drupal\Component\DependencyInjection\Container->get()

Not sure if this is a core issue or something introduced by monolog.

Steps to reproduce

Proposed resolution

Remaining tasks

User interface changes

API changes

Data model changes

๐Ÿ› Bug report
Status

Postponed: needs info

Version

3.0

Component

Code

Created by

๐Ÿ‡ฆ๐Ÿ‡บAustralia kim.pepper ๐Ÿ„โ€โ™‚๏ธ๐Ÿ‡ฆ๐Ÿ‡บSydney, Australia

Live updates comments and jobs are added and updated live.
Sign in to follow issues

Comments & Activities

  • Issue created by @kim.pepper
  • Status changed to Postponed: needs info about 1 year ago
  • ๐Ÿ‡ฎ๐Ÿ‡นItaly lussoluca Italy

    I'm not able to reproduce it. Can you please post the contents of the Monolog configuration file?

  • ๐Ÿ‡ฌ๐Ÿ‡งUnited Kingdom adaddinsane

    I can confirm this happens and it's VERY problematic since I'm trying to upgrade a site that's still stuck on D8 and this is 100% blocker.

    Here's a dump (below) when I try to enable Monolog 2.2, this is on Drupal 8.9.20 and PHP 7.4.

    I have seen the issue in other module issue queues and they solve it by changing LoggerChannelInterface to LoggerInterface and I have done this for all my custom modules but that includes my "be_general" module but we're still getting the error.

    Several of the contrib modules also use LoggerChannelInterface and patching them all does not seem a good approach.

    The module logger definition services look like this in all cases:

    services:
      logger.channel.module_name:
        parent: logger.channel_base
        arguments: ['module_name']
    

    The dump:

    drush en monolog -d
     [preflight] Config paths: /app/vendor/drush/drush/drush.yml
     [preflight] Alias paths: /app/drush/sites,/drush/sites
     [preflight] Commandfile search paths: /app/vendor/drush/drush/src
     [debug] Bootstrap further to find pm:enable [0.11 sec, 2.96 MB]
     [debug] Trying to bootstrap as far as we can [0.11 sec, 2.96 MB]
     [bootstrap] Drush bootstrap phase: bootstrapDrupalRoot() [0.11 sec, 2.96 MB]
     [bootstrap] Change working directory to /app [0.11 sec, 2.96 MB]
     [bootstrap] Initialized Drupal 8.9.20 root directory at /app [0.11 sec, 2.96 MB]
     [bootstrap] Drush bootstrap phase: bootstrapDrupalSite() [0.12 sec, 3.11 MB]
     [bootstrap] Initialized Drupal site default at sites/default [0.12 sec, 3.11 MB]
     [bootstrap] Drush bootstrap phase: bootstrapDrupalConfiguration() [0.12 sec, 3.12 MB]
     [debug] Add service modifier [0.13 sec, 3.27 MB]
     [bootstrap] Drush bootstrap phase: bootstrapDrupalDatabase() [0.16 sec, 3.37 MB]
     [bootstrap] Successfully connected to the Drupal database. [0.16 sec, 3.37 MB]
     [bootstrap] Drush bootstrap phase: bootstrapDrupalFull() [0.16 sec, 3.37 MB]
     [debug] Start bootstrap of the Drupal Kernel. [0.16 sec, 3.37 MB]
     [debug] Finished bootstrap of the Drupal Kernel. [0.38 sec, 5.43 MB]
    
    In Container.php line 143:
                                                                                                             
      [Symfony\Component\DependencyInjection\Exception\ServiceCircularReferenceException]                    
      Circular reference detected for service "be_general.sfid.factory", path: "drush.command.services -> t  
      wig.commands -> twig -> twig.extension -> renderer -> plugin.manager.element_info -> cache_tags.inval  
      idator -> fastly.cache_tags.invalidator -> fastly.api -> logger.channel.fastly -> be_general.sfid.fac  
      tory -> be_general.verify -> logger.channel.be_general".                                               
                                                                                                             
    
    Exception trace:
      at /app/core/lib/Drupal/Component/DependencyInjection/Container.php:143
     Drupal\Component\DependencyInjection\Container->get() at /app/modules/custom/be_heroku_entities/src/Plugin/HerokuObjectBase.php:61
     Drupal\be_heroku_entities\Plugin\HerokuObjectBase::create() at /app/core/lib/Drupal/Core/Plugin/Factory/ContainerFactory.php:21
     Drupal\Core\Plugin\Factory\ContainerFactory->createInstance() at /app/core/lib/Drupal/Component/Plugin/PluginManagerBase.php:83
     Drupal\Component\Plugin\PluginManagerBase->createInstance() at /app/modules/custom/be_heroku_entities/src/HerokuEntityTypeAlter.php:60
     Drupal\be_heroku_entities\HerokuEntityTypeAlter->Drupal\be_heroku_entities\{closure}() at n/a:n/a
     array_walk() at /app/modules/custom/be_heroku_entities/src/HerokuEntityTypeAlter.php:71
     Drupal\be_heroku_entities\HerokuEntityTypeAlter->entityTypeAlter() at /app/modules/custom/be_heroku_entities/be_heroku_entities.module:10
     be_heroku_entities_entity_type_alter() at /app/core/lib/Drupal/Core/Extension/ModuleHandler.php:539
     Drupal\Core\Extension\ModuleHandler->alter() at /app/core/lib/Drupal/Core/Plugin/DefaultPluginManager.php:366
     Drupal\Core\Plugin\DefaultPluginManager->alterDefinitions() at /app/core/lib/Drupal/Core/Entity/EntityTypeManager.php:134
     Drupal\Core\Entity\EntityTypeManager->findDefinitions() at /app/core/lib/Drupal/Core/Plugin/DefaultPluginManager.php:175
     Drupal\Core\Plugin\DefaultPluginManager->getDefinitions() at /app/core/lib/Drupal/Component/Plugin/Discovery/DiscoveryCachedTrait.php:22
     Drupal\Core\Plugin\DefaultPluginManager->getDefinition() at /app/core/lib/Drupal/Core/Entity/EntityTypeManager.php:143
     Drupal\Core\Entity\EntityTypeManager->getDefinition() at /app/core/lib/Drupal/Core/Entity/EntityTypeManager.php:269
     Drupal\Core\Entity\EntityTypeManager->getHandler() at /app/core/lib/Drupal/Core/Entity/EntityTypeManager.php:208
     Drupal\Core\Entity\EntityTypeManager->getStorage() at /app/core/lib/Drupal/Core/Session/UserSession.php:206
     Drupal\Core\Session\UserSession->getRoleStorage() at /app/core/lib/Drupal/Core/Session/UserSession.php:111
     Drupal\Core\Session\UserSession->hasPermission() at /app/core/lib/Drupal/Core/Session/AccountProxy.php:119
     Drupal\Core\Session\AccountProxy->hasPermission() at /app/modules/contrib/monolog/src/Logger/MonologLoggerChannelFactory.php:67
     Drupal\monolog\Logger\MonologLoggerChannelFactory->get() at /app/modules/contrib/redirect/modules/redirect_404/src/Render/Redirect404LogSuppressor.php:55
     Drupal\redirect_404\Render\Redirect404LogSuppressor->get() at n/a:n/a
     call_user_func_array() at /app/core/lib/Drupal/Component/DependencyInjection/Container.php:255
     Drupal\Component\DependencyInjection\Container->createService() at /app/core/lib/Drupal/Component/DependencyInjection/Container.php:173
     Drupal\Component\DependencyInjection\Container->get() at /app/core/lib/Drupal/Component/DependencyInjection/Container.php:434
     Drupal\Component\DependencyInjection\Container->resolveServicesAndParameters() at /app/core/lib/Drupal/Component/DependencyInjection/Container.php:237
     Drupal\Component\DependencyInjection\Container->createService() at /app/core/lib/Drupal/Component/DependencyInjection/Container.php:173
     Drupal\Component\DependencyInjection\Container->get() at /app/core/lib/Drupal/Component/DependencyInjection/Container.php:434
     Drupal\Component\DependencyInjection\Container->resolveServicesAndParameters() at /app/core/lib/Drupal/Component/DependencyInjection/Container.php:237
     Drupal\Component\DependencyInjection\Container->createService() at /app/core/lib/Drupal/Component/DependencyInjection/Container.php:173
     Drupal\Component\DependencyInjection\Container->get() at /app/modules/custom/be_heroku_entities/src/Plugin/HerokuObjectBase.php:61
     Drupal\be_heroku_entities\Plugin\HerokuObjectBase::create() at /app/core/lib/Drupal/Core/Plugin/Factory/ContainerFactory.php:21
     Drupal\Core\Plugin\Factory\ContainerFactory->createInstance() at /app/core/lib/Drupal/Component/Plugin/PluginManagerBase.php:83
     Drupal\Component\Plugin\PluginManagerBase->createInstance() at /app/modules/custom/be_heroku_entities/src/HerokuEntityTypeAlter.php:60
     Drupal\be_heroku_entities\HerokuEntityTypeAlter->Drupal\be_heroku_entities\{closure}() at n/a:n/a
     array_walk() at /app/modules/custom/be_heroku_entities/src/HerokuEntityTypeAlter.php:71
     Drupal\be_heroku_entities\HerokuEntityTypeAlter->entityTypeAlter() at /app/modules/custom/be_heroku_entities/be_heroku_entities.module:10
     be_heroku_entities_entity_type_alter() at /app/core/lib/Drupal/Core/Extension/ModuleHandler.php:539
     Drupal\Core\Extension\ModuleHandler->alter() at /app/core/lib/Drupal/Core/Plugin/DefaultPluginManager.php:366
     Drupal\Core\Plugin\DefaultPluginManager->alterDefinitions() at /app/core/lib/Drupal/Core/Entity/EntityTypeManager.php:134
     Drupal\Core\Entity\EntityTypeManager->findDefinitions() at /app/core/lib/Drupal/Core/Plugin/DefaultPluginManager.php:175
     Drupal\Core\Plugin\DefaultPluginManager->getDefinitions() at /app/core/lib/Drupal/Component/Plugin/Discovery/DiscoveryCachedTrait.php:22
     Drupal\Core\Plugin\DefaultPluginManager->getDefinition() at /app/core/lib/Drupal/Core/Entity/EntityTypeManager.php:143
     Drupal\Core\Entity\EntityTypeManager->getDefinition() at /app/core/lib/Drupal/Core/Entity/EntityTypeManager.php:269
     Drupal\Core\Entity\EntityTypeManager->getHandler() at /app/core/lib/Drupal/Core/Entity/EntityTypeManager.php:208
     Drupal\Core\Entity\EntityTypeManager->getStorage() at /app/core/lib/Drupal/Core/Session/UserSession.php:206
     Drupal\Core\Session\UserSession->getRoleStorage() at /app/core/lib/Drupal/Core/Session/UserSession.php:111
     Drupal\Core\Session\UserSession->hasPermission() at /app/core/lib/Drupal/Core/Session/AccountProxy.php:119
     Drupal\Core\Session\AccountProxy->hasPermission() at /app/modules/contrib/monolog/src/Logger/MonologLoggerChannelFactory.php:67
     Drupal\monolog\Logger\MonologLoggerChannelFactory->get() at /app/modules/contrib/redirect/modules/redirect_404/src/Render/Redirect404LogSuppressor.php:55
     Drupal\redirect_404\Render\Redirect404LogSuppressor->get() at n/a:n/a
     call_user_func_array() at /app/core/lib/Drupal/Component/DependencyInjection/Container.php:255
     Drupal\Component\DependencyInjection\Container->createService() at /app/core/lib/Drupal/Component/DependencyInjection/Container.php:173
     Drupal\Component\DependencyInjection\Container->get() at /app/core/lib/Drupal/Component/DependencyInjection/Container.php:434
     Drupal\Component\DependencyInjection\Container->resolveServicesAndParameters() at /app/core/lib/Drupal/Component/DependencyInjection/Container.php:237
     Drupal\Component\DependencyInjection\Container->createService() at /app/core/lib/Drupal/Component/DependencyInjection/Container.php:173
     Drupal\Component\DependencyInjection\Container->get() at /app/core/lib/Drupal/Component/DependencyInjection/Container.php:434
     Drupal\Component\DependencyInjection\Container->resolveServicesAndParameters() at /app/core/lib/Drupal/Component/DependencyInjection/Container.php:237
     Drupal\Component\DependencyInjection\Container->createService() at /app/core/lib/Drupal/Component/DependencyInjection/Container.php:173
     Drupal\Component\DependencyInjection\Container->get() at /app/core/lib/Drupal/Component/DependencyInjection/Container.php:434
     Drupal\Component\DependencyInjection\Container->resolveServicesAndParameters() at /app/core/lib/Drupal/Component/DependencyInjection/Container.php:273
     Drupal\Component\DependencyInjection\Container->createService() at /app/core/lib/Drupal/Component/DependencyInjection/Container.php:173
     Drupal\Component\DependencyInjection\Container->get() at /app/core/lib/Drupal/Component/DependencyInjection/Container.php:434
     Drupal\Component\DependencyInjection\Container->resolveServicesAndParameters() at /app/core/lib/Drupal/Component/DependencyInjection/Container.php:237
     Drupal\Component\DependencyInjection\Container->createService() at /app/core/lib/Drupal/Component/DependencyInjection/Container.php:173
     Drupal\Component\DependencyInjection\Container->get() at /app/core/lib/Drupal/Component/DependencyInjection/Container.php:434
     Drupal\Component\DependencyInjection\Container->resolveServicesAndParameters() at /app/core/lib/Drupal/Component/DependencyInjection/Container.php:237
     Drupal\Component\DependencyInjection\Container->createService() at /app/core/lib/Drupal/Component/DependencyInjection/Container.php:173
     Drupal\Component\DependencyInjection\Container->get() at /app/core/lib/Drupal/Component/DependencyInjection/Container.php:434
     Drupal\Component\DependencyInjection\Container->resolveServicesAndParameters() at /app/core/lib/Drupal/Component/DependencyInjection/Container.php:237
     Drupal\Component\DependencyInjection\Container->createService() at /app/core/lib/Drupal/Component/DependencyInjection/Container.php:173
     Drupal\Component\DependencyInjection\Container->get() at /app/core/lib/Drupal/Component/DependencyInjection/Container.php:434
     Drupal\Component\DependencyInjection\Container->resolveServicesAndParameters() at /app/core/lib/Drupal/Component/DependencyInjection/Container.php:273
     Drupal\Component\DependencyInjection\Container->createService() at /app/core/lib/Drupal/Component/DependencyInjection/Container.php:173
     Drupal\Component\DependencyInjection\Container->get() at /app/core/lib/Drupal/Component/DependencyInjection/Container.php:434
     Drupal\Component\DependencyInjection\Container->resolveServicesAndParameters() at /app/core/lib/Drupal/Component/DependencyInjection/Container.php:237
     Drupal\Component\DependencyInjection\Container->createService() at /app/core/lib/Drupal/Component/DependencyInjection/Container.php:173
     Drupal\Component\DependencyInjection\Container->get() at /app/core/lib/Drupal/Component/DependencyInjection/Container.php:434
     Drupal\Component\DependencyInjection\Container->resolveServicesAndParameters() at /app/core/lib/Drupal/Component/DependencyInjection/Container.php:273
     Drupal\Component\DependencyInjection\Container->createService() at /app/core/lib/Drupal/Component/DependencyInjection/Container.php:173
     Drupal\Component\DependencyInjection\Container->get() at /app/vendor/drush/drush/src/Boot/DrupalBoot8.php:277
     Drush\Boot\DrupalBoot8->addDrupalModuleDrushCommands() at /app/vendor/drush/drush/src/Boot/DrupalBoot8.php:243
     Drush\Boot\DrupalBoot8->bootstrapDrupalFull() at /app/vendor/drush/drush/src/Boot/BootstrapManager.php:293
     Drush\Boot\BootstrapManager->doBootstrap() at /app/vendor/drush/drush/src/Boot/BootstrapManager.php:493
     Drush\Boot\BootstrapManager->bootstrapMax() at /app/vendor/drush/drush/src/Application.php:225
     Drush\Application->bootstrapAndFind() at /app/vendor/drush/drush/src/Application.php:192
     Drush\Application->find() at /app/vendor/symfony/console/Application.php:236
     Symfony\Component\Console\Application->doRun() at /app/vendor/symfony/console/Application.php:148
     Symfony\Component\Console\Application->run() at /app/vendor/drush/drush/src/Runtime/Runtime.php:118
     Drush\Runtime\Runtime->doRun() at /app/vendor/drush/drush/src/Runtime/Runtime.php:49
     Drush\Runtime\Runtime->run() at /app/vendor/drush/drush/drush.php:72
     require() at /app/vendor/drush/drush/drush:3
     include() at /app/vendor/bin/drush:115
    
  • ๐Ÿ‡ฎ๐Ÿ‡นItaly lussoluca Italy

    Can you please share your monolog.services.yml file?

  • ๐Ÿ‡ฌ๐Ÿ‡งUnited Kingdom adaddinsane

    Sorry, things got away from me.

    The only solution I had was to remove all definitions of LoggerChannelInterface, and module-specific logger channels in the module.services.yml file.

    I'm using LoggerChannelTrait but that isn't feeding anything into monolog, so I'm not getting any feedback (except on my local install which has monolog turned off and dblog switched on).

    parameters:
      # Handlers per channel.
      monolog.channel_handlers:
        # If not specified use the default handlers.
        default: ['syslog']
        # Log php channel to web server's error log.
        php: ['error_log']
      # Enabled processors.
      monolog.processors: ['message_placeholder', 'current_user', 'request_uri', 'ip', 'referer', 'filter_backtrace']
      # Logger levels.
      monolog.level.emergency: 'emergency'
      monolog.level.alert: 'alert'
      monolog.level.critical: 'critical'
      monolog.level.error: 'error'
      monolog.level.warning: 'warning'
      monolog.level.notice: 'notice'
      monolog.level.info: 'info'
      monolog.level.debug: 'debug'
    
    services:
      # Monolog handlers.
      monolog.handler.browser_console:
        class: Monolog\Handler\BrowserConsoleHandler
        shared: false
      monolog.handler.chrome_php:
        class: Monolog\Handler\ChromePHPHandler
        shared: false
      monolog.handler.fire_php:
        class: Monolog\Handler\FirePHPHandler
        shared: false
      monolog.handler.error_log:
        class: Monolog\Handler\ErrorLogHandler
        shared: false
      monolog.handler.syslog:
        class: Monolog\Handler\SyslogHandler
        arguments: ['drupal']
        shared: false
      monolog.handler.null:
        class: Monolog\Handler\NullHandler
        shared: false
    
      # Monolog processors.
      monolog.processor.current_user:
        class: Drupal\monolog\Logger\Processor\CurrentUserProcessor
        arguments: ['@current_user']
        shared: false
      monolog.processor.request_uri:
        class: Drupal\monolog\Logger\Processor\RequestUriProcessor
        arguments: ['@request_stack']
        shared: false
      monolog.processor.server_host:
        class: Drupal\monolog\Logger\Processor\ServerHostProcessor
        arguments: [ '@request_stack' ]
        shared: false
      monolog.processor.referer:
        class: Drupal\monolog\Logger\Processor\RefererProcessor
        arguments: ['@request_stack']
        shared: false
      monolog.processor.ip:
        class: Drupal\monolog\Logger\Processor\IpProcessor
        arguments: ['@request_stack']
        shared: false
      monolog.processor.message_placeholder:
        class: Drupal\monolog\Logger\Processor\MessagePlaceholderProcessor
        arguments: ['@logger.log_message_parser']
        shared: false
      monolog.processor.drupal_message_placeholder:
        class: Drupal\monolog\Logger\Processor\DrupalMessagePlaceholderProcessor
        arguments: ['@logger.log_message_parser']
        shared: false
      monolog.processor.filter_backtrace:
        class: Drupal\monolog\Logger\Processor\ContextKeyFilterProcessor
        arguments: [['backtrace']]
        shared: false
      monolog.processor.introspection:
        class: Drupal\monolog\Logger\Processor\IntrospectionProcessor
        shared: false
      monolog.processor.git:
        class: Monolog\Processor\GitProcessor
        shared: false
      monolog.processor.memory_usage:
        class: Monolog\Processor\MemoryUsageProcessor
        shared: false
      monolog.processor.memory_peak_usage:
        class: Monolog\Processor\MemoryPeakUsageProcessor
        shared: false
      monolog.processor.process_id:
        class: Monolog\Processor\ProcessIdProcessor
        shared: false
    
      # Monolog formatters.
      monolog.formatter.chrome_php:
        class: Monolog\Formatter\ChromePHPFormatter
        shared: false
      monolog.formatter.fluentd:
        class: Monolog\Formatter\FluentdFormatter
        shared: false
      monolog.formatter.gelf:
        class: Monolog\Formatter\GelfMessageFormatter
        shared: false
      monolog.formatter.html:
        class: Monolog\Formatter\HtmlFormatter
        shared: false
      monolog.formatter.json:
        class: Monolog\Formatter\JsonFormatter
        shared: false
      monolog.formatter.line:
        class: Monolog\Formatter\LineFormatter
        shared: false
      monolog.formatter.loggly:
        class: Monolog\Formatter\LogglyFormatter
        shared: false
      monolog.formatter.mongodb:
        class: Monolog\Formatter\MongoDBFormatter
        shared: false
      monolog.formatter.normalizer:
        class: Monolog\Formatter\NormalizerFormatter
        shared: false
      monolog.formatter.scalar:
        class: Monolog\Formatter\ScalarFormatter
        shared: false
      monolog.formatter.wildfire:
        class: Monolog\Formatter\WildfireFormatter
        shared: false
      monolog.formatter.drush:
        class: Drupal\monolog\Logger\Formatter\DrushLineFormatter
        shared: false
    
      # Should not be needed.
      monolog.processor.psr_log_message:
        class: Monolog\Processor\PsrLogMessageProcessor
        shared: false
      monolog.processor.tag:
        class: Monolog\Processor\TagProcessor
        shared: false
      monolog.processor.uid:
        class: Monolog\Processor\UidProcessor
        shared: false
      monolog.processor.web:
        class: Monolog\Processor\WebProcessor
        shared: false
    
  • ๐Ÿ‡จ๐Ÿ‡ญSwitzerland tcrawford

    If you are using a monolog handler for PHP and you get this error it could well be that your handler service is creating a php error while instantiating. Only apply the handler to 'default' and not to 'php' in your services file. Then when it instantiates you will log the PHP error (rather than causing a recursion) so that you can fix the issue. For me the issue was that I was using the STDOUT constant when instantiating the stream handler. The constant is only available for the CLI SAPI so instantiating the logger caused the logger to instantiate itself again and Symfony detects this as a circular dependency and bails. (As a side note I tested my logger using drush scr and it worked perfectly, and it was not until I stopped using the logger for PHP that I could see the issue that caused the error when handling web requests).

Production build 0.69.0 2024