[GH-ISSUE #1434] Define custom handlers at runtime for daemons without duplicate log records #602

Closed
opened 2026-03-04 02:16:19 +03:00 by kerem · 1 comment
Owner

Originally created by @Clivern on GitHub (Mar 4, 2020).
Original GitHub issue: https://github.com/Seldaek/monolog/issues/1434

Monolog version 2

I am using monolog with a daemon and i am wondering if there is anyway to define handlers with identification string at runtime.

if we do something like this

<?php

require_once dirname(__FILE__) . "/vendor/autoload.php";

use Monolog\Logger;
use Monolog\Handler\StreamHandler;


# Defined on application level
$log = new Logger('app');

// ~~~Some handlers got defined here~~~

# A daemon running and the following handler defined at runtime to log to custom files
$i = 1;
while (true) {
    $log->pushHandler(new StreamHandler(dirname(__FILE__) . '/custom_log_file_a.log', Logger::INFO));
    
    // ~~ some handlers got defined here~~~
    $log->info(sprintf("Foo %d", $i));
    $i += 1;
    sleep(1);
}

handlers will increase at runtime at each iteration and we got a duplicate log records

[2020-03-04T14:48:42.805529+00:00] app.INFO: Foo 1 [] []
[2020-03-04T14:48:43.811813+00:00] app.INFO: Foo 2 [] []
[2020-03-04T14:48:43.811813+00:00] app.INFO: Foo 2 [] []
[2020-03-04T14:48:44.813441+00:00] app.INFO: Foo 3 [] []
[2020-03-04T14:48:44.813441+00:00] app.INFO: Foo 3 [] []
[2020-03-04T14:48:44.813441+00:00] app.INFO: Foo 3 [] []
[2020-03-04T14:48:45.824147+00:00] app.INFO: Foo 4 [] []
[2020-03-04T14:48:45.824147+00:00] app.INFO: Foo 4 [] []
[2020-03-04T14:48:45.824147+00:00] app.INFO: Foo 4 [] []
[2020-03-04T14:48:45.824147+00:00] app.INFO: Foo 4 [] []

the only way i come up with is to reset handlers or naive function to check if stream handler already there.

<?php

require_once dirname(__FILE__) . "/vendor/autoload.php";

use Monolog\Logger;
use Monolog\Handler\StreamHandler;
// create a log channel

# Defined on application level
$log = new Logger('app');

// ~~~Some handlers got defined here~~~

# A daemon running and the following handler defined at runtime to log to custom files
$i = 1;
while (true) {
    $log->pushHandler(new StreamHandler(dirname(__FILE__) . '/custom_log_file_a.log', Logger::INFO));
    $log->info(sprintf("Foo %d", $i));
    // ~~~Some handlers got defined here~~~
    $i += 1;
    sleep(1);
    $log->setHandlers([]);
}
<?php

require_once dirname(__FILE__) . "/vendor/autoload.php";

use Monolog\Logger;
use Monolog\Handler\StreamHandler;


// naive implementation to check if stream handler exist based on class & file path
function hasHandler($logger, $newHandler){
    $handlers = $logger->getHandlers();
    foreach ($handlers as $handler) {
        if ((get_class($handler) === StreamHandler::class) && $newHandler->getUrl() === $handler->getUrl()){
            return true;
        }
    }
    return false;
}



# Defined on application level
$log = new Logger('app');

// ~~~Some handlers got defined here~~~

# A daemon running and the following handler defined at runtime to log to custom files
$i = 1;
while (true) {
    $newHandler = new StreamHandler(dirname(__FILE__) . '/customer_log_file_a.log', Logger::INFO);

    if (!hasHandler($log, $newHandler)) {
        $log->pushHandler($newHandler);
    }

    // ~~ some handlers got defined here~~~
    $log->info(sprintf("Foo %d", $i));
    $i += 1;
    sleep(1);
}

is there is anyway i can do like $log->handlerExist(handler~ident~here) that will work with all possible handlers :). if there is a lot of logic/classes inside while call, I will need a way to identify if the previous call or previous class already registered/configured that handler.

while (true) {
       // ClassA -> is the handler that log records to file custom_log_file_x.log registered, if no -> add that handler
       // ClassB -> is the handler that log records to file custom_log_file_x.log registered, if no -> add that handler
       // ClassC -> is the handler that log records to file custom_log_file_x.log registered, if no -> add that handler
      // ....etc
}

May be this not requested a lot or usually handlers not configured at runtime but it would be a nice to have this & can be done on a backward compatible way or a workaround.

Originally created by @Clivern on GitHub (Mar 4, 2020). Original GitHub issue: https://github.com/Seldaek/monolog/issues/1434 Monolog version 2 I am using monolog with a daemon and i am wondering if there is anyway to define handlers with identification string at runtime. if we do something like this ```php <?php require_once dirname(__FILE__) . "/vendor/autoload.php"; use Monolog\Logger; use Monolog\Handler\StreamHandler; # Defined on application level $log = new Logger('app'); // ~~~Some handlers got defined here~~~ # A daemon running and the following handler defined at runtime to log to custom files $i = 1; while (true) { $log->pushHandler(new StreamHandler(dirname(__FILE__) . '/custom_log_file_a.log', Logger::INFO)); // ~~ some handlers got defined here~~~ $log->info(sprintf("Foo %d", $i)); $i += 1; sleep(1); } ``` handlers will increase at runtime at each iteration and we got a duplicate log records ```log [2020-03-04T14:48:42.805529+00:00] app.INFO: Foo 1 [] [] [2020-03-04T14:48:43.811813+00:00] app.INFO: Foo 2 [] [] [2020-03-04T14:48:43.811813+00:00] app.INFO: Foo 2 [] [] [2020-03-04T14:48:44.813441+00:00] app.INFO: Foo 3 [] [] [2020-03-04T14:48:44.813441+00:00] app.INFO: Foo 3 [] [] [2020-03-04T14:48:44.813441+00:00] app.INFO: Foo 3 [] [] [2020-03-04T14:48:45.824147+00:00] app.INFO: Foo 4 [] [] [2020-03-04T14:48:45.824147+00:00] app.INFO: Foo 4 [] [] [2020-03-04T14:48:45.824147+00:00] app.INFO: Foo 4 [] [] [2020-03-04T14:48:45.824147+00:00] app.INFO: Foo 4 [] [] ``` the only way i come up with is to reset handlers or naive function to check if stream handler already there. ```php <?php require_once dirname(__FILE__) . "/vendor/autoload.php"; use Monolog\Logger; use Monolog\Handler\StreamHandler; // create a log channel # Defined on application level $log = new Logger('app'); // ~~~Some handlers got defined here~~~ # A daemon running and the following handler defined at runtime to log to custom files $i = 1; while (true) { $log->pushHandler(new StreamHandler(dirname(__FILE__) . '/custom_log_file_a.log', Logger::INFO)); $log->info(sprintf("Foo %d", $i)); // ~~~Some handlers got defined here~~~ $i += 1; sleep(1); $log->setHandlers([]); } ``` ```php <?php require_once dirname(__FILE__) . "/vendor/autoload.php"; use Monolog\Logger; use Monolog\Handler\StreamHandler; // naive implementation to check if stream handler exist based on class & file path function hasHandler($logger, $newHandler){ $handlers = $logger->getHandlers(); foreach ($handlers as $handler) { if ((get_class($handler) === StreamHandler::class) && $newHandler->getUrl() === $handler->getUrl()){ return true; } } return false; } # Defined on application level $log = new Logger('app'); // ~~~Some handlers got defined here~~~ # A daemon running and the following handler defined at runtime to log to custom files $i = 1; while (true) { $newHandler = new StreamHandler(dirname(__FILE__) . '/customer_log_file_a.log', Logger::INFO); if (!hasHandler($log, $newHandler)) { $log->pushHandler($newHandler); } // ~~ some handlers got defined here~~~ $log->info(sprintf("Foo %d", $i)); $i += 1; sleep(1); } ``` **is there is anyway i can do like `$log->handlerExist(handler~ident~here)` that will work with all possible handlers** :). if there is a lot of logic/classes inside while call, I will need a way to identify if the previous call or previous class already registered/configured that handler. ```php while (true) { // ClassA -> is the handler that log records to file custom_log_file_x.log registered, if no -> add that handler // ClassB -> is the handler that log records to file custom_log_file_x.log registered, if no -> add that handler // ClassC -> is the handler that log records to file custom_log_file_x.log registered, if no -> add that handler // ....etc } ``` May be this not requested a lot or usually handlers not configured at runtime but it would be a nice to have this & can be done on a backward compatible way or a workaround.
kerem 2026-03-04 02:16:19 +03:00
  • closed this issue
  • added the
    Support
    label
Author
Owner

@Seldaek commented on GitHub (May 11, 2020):

IMO you should rather do $log->pushHandler($newHandler); ...do stuff here... $log->popHandler(); or if you can not trust this to work because some code pushes handlers without popping them within your loop, then you can also check for existence using in_array($handler, $log->getHandlers(), true) I would say... this only requires you keep track of the $handler instance you added somehow.

<!-- gh-comment-id:626709299 --> @Seldaek commented on GitHub (May 11, 2020): IMO you should rather do `$log->pushHandler($newHandler); ...do stuff here... $log->popHandler();` or if you can not trust this to work because some code pushes handlers without popping them within your loop, then you can also check for existence using `in_array($handler, $log->getHandlers(), true)` I would say... this only requires you keep track of the $handler instance you added somehow.
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#602
No description provided.