[GH-ISSUE #590] Fallback Logging #209

Closed
opened 2026-03-04 02:13:09 +03:00 by kerem · 6 comments
Owner

Originally created by @inssein on GitHub (Jun 24, 2015).
Original GitHub issue: https://github.com/Seldaek/monolog/issues/590

Are there any plans to add fallback mechanisms to logging? For example, I plan to use the ElasticSearchHandler, but if for whatever reason it cannot reach the elastic search instance, maybe it could be logged to disk?

I was thinking about perhaps checking the elastic search connection before creating the handler itself, but then this means that it will always open a connection to elastic search. Where as with Monolog, it only opens a connection if there is something to send.

Originally created by @inssein on GitHub (Jun 24, 2015). Original GitHub issue: https://github.com/Seldaek/monolog/issues/590 Are there any plans to add fallback mechanisms to logging? For example, I plan to use the ElasticSearchHandler, but if for whatever reason it cannot reach the elastic search instance, maybe it could be logged to disk? I was thinking about perhaps checking the elastic search connection before creating the handler itself, but then this means that it will always open a connection to elastic search. Where as with Monolog, it only opens a connection if there is something to send.
kerem closed this issue 2026-03-04 02:13:10 +03:00
Author
Owner

@Seldaek commented on GitHub (Jul 12, 2015):

I think for such specific cases it's better to create a custom handler that takes in two handler and calls the second one if the first one throws.

<!-- gh-comment-id:120707129 --> @Seldaek commented on GitHub (Jul 12, 2015): I think for such specific cases it's better to create a custom handler that takes in two handler and calls the second one if the first one throws.
Author
Owner

@Neirda24 commented on GitHub (Jan 22, 2018):

Hi Reopening this issue as it may lead to a feature of some kind.
We had exactly the same problem. So we created a custom handler based of the WhatFailureGroupHandler but added a break if no error was thrown (stop at first succeed)

But then we wanted to log the one that had fail because it means that one or more handlers failed and it is never a good sign... We have no idea as to how to implement it.

<!-- gh-comment-id:359461774 --> @Neirda24 commented on GitHub (Jan 22, 2018): Hi Reopening this issue as it may lead to a feature of some kind. We had exactly the same problem. So we created a custom handler based of the `WhatFailureGroupHandler` but added a break if no error was thrown (stop at first succeed) But then we wanted to log the one that had fail because it means that one or more handlers failed and it is never a good sign... We have no idea as to how to implement it.
Author
Owner

@masacc commented on GitHub (Jan 22, 2018):

Hi, I'm in the same team than @Neirda24 and here is the solution we have implemented :

Create a FallbackGroupHandler : src/LogBundle/Handler/FallbackGroupHandler.php

<?php

namespace LogBundle\Handler;

use Monolog\Handler\GroupHandler;
use Throwable;

class FallbackGroupHandler extends GroupHandler
{
    /**
     * {@inheritdoc}
     */
    public function handle(array $record)
    {
        if ($this->processors) {
            foreach ($this->processors as $processor) {
                $record = call_user_func($processor, $record);
            }
        }

        foreach ($this->handlers as $handler) {
            try {
                $handler->handle($record);
                break;
            } catch (Throwable $throwable) {
                // do nothing
            }
        }

        return false === $this->bubble;
    }

    /**
     * {@inheritdoc}
     */
    public function handleBatch(array $records)
    {
        foreach ($this->handlers as $handler) {
            try {
                $handler->handleBatch($records);
                break;
            } catch (Throwable $throwable) {
                // do nothing
            }
        }
    }
}

Define it as a service and inject into it two other handlers that we have previously declared as nested :

src/LogBundle/Resources/config/services/handler.yml :

services:
    my_monolog.handler.fallback_group:
        class: 'LogBundle\Handler\FallbackGroupHandler'
        arguments:
            - ['@monolog.handler.elasticsearch', '@monolog.handler.filesystem']

app/config/config_dev.yml :

monolog:
    handlers:
        elasticsearch:
            type: 'elasticsearch'
            elasticsearch:
                host: '%elasticsearch.host%'
                port: '%elasticsearch.port%'
            index: '%elasticsearch.index.monolog%'
            level: 'debug'
            nested: true
        filesystem:
            type: 'stream'
            path: '%kernel.logs_dir%/%kernel.environment%.log'
            level: 'debug'
            channels: ['!event']
            nested: true
        main:
            type: 'service'
            id: 'my_monolog.handler.fallback_group'
<!-- gh-comment-id:359484395 --> @masacc commented on GitHub (Jan 22, 2018): Hi, I'm in the same team than @Neirda24 and here is the solution we have implemented : Create a FallbackGroupHandler : `src/LogBundle/Handler/FallbackGroupHandler.php` ``` <?php namespace LogBundle\Handler; use Monolog\Handler\GroupHandler; use Throwable; class FallbackGroupHandler extends GroupHandler { /** * {@inheritdoc} */ public function handle(array $record) { if ($this->processors) { foreach ($this->processors as $processor) { $record = call_user_func($processor, $record); } } foreach ($this->handlers as $handler) { try { $handler->handle($record); break; } catch (Throwable $throwable) { // do nothing } } return false === $this->bubble; } /** * {@inheritdoc} */ public function handleBatch(array $records) { foreach ($this->handlers as $handler) { try { $handler->handleBatch($records); break; } catch (Throwable $throwable) { // do nothing } } } } ``` Define it as a service and inject into it two other handlers that we have previously declared as nested : `src/LogBundle/Resources/config/services/handler.yml` : ``` services: my_monolog.handler.fallback_group: class: 'LogBundle\Handler\FallbackGroupHandler' arguments: - ['@monolog.handler.elasticsearch', '@monolog.handler.filesystem'] ``` `app/config/config_dev.yml` : ``` monolog: handlers: elasticsearch: type: 'elasticsearch' elasticsearch: host: '%elasticsearch.host%' port: '%elasticsearch.port%' index: '%elasticsearch.index.monolog%' level: 'debug' nested: true filesystem: type: 'stream' path: '%kernel.logs_dir%/%kernel.environment%.log' level: 'debug' channels: ['!event'] nested: true main: type: 'service' id: 'my_monolog.handler.fallback_group' ```
Author
Owner

@inverse commented on GitHub (Jul 31, 2019):

@masacc thanks for sharing

@Seldaek Feels like this handler should be in the core. What were your objections against?

<!-- gh-comment-id:516746053 --> @inverse commented on GitHub (Jul 31, 2019): @masacc thanks for sharing @Seldaek Feels like this handler should be in the core. What were your objections against?
Author
Owner

@Seldaek commented on GitHub (Aug 15, 2019):

@masacc thanks to @inverse this will be part of 2.0

<!-- gh-comment-id:521765146 --> @Seldaek commented on GitHub (Aug 15, 2019): @masacc thanks to @inverse this will be part of 2.0
Author
Owner

@inverse commented on GitHub (Aug 15, 2019):

@Seldaek @masacc thanks for the help!

<!-- gh-comment-id:521771700 --> @inverse commented on GitHub (Aug 15, 2019): @Seldaek @masacc thanks for the help!
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
starred/monolog#209
No description provided.