Seldaek / monolog

Sends your logs to files, sockets, inboxes, databases and various web services
https://seldaek.github.io/monolog/
MIT License
20.96k stars 1.9k forks source link

can SocketHandler be made immune to "Failed connecting to ..." situations? #1822

Closed LiamFry closed 10 months ago

LiamFry commented 1 year ago

Monolog version 3

I'm using both a StreamHandler and a SocketHandler. Is there anyway way for my application to run if the StreamHandler is sucessful yet the SocketHandler fails to connect? I need my app to run - and log to a file (at a minimum) - even if a connection cannot be made to a remote service via SocketHandler.

Assuming the remote service is unavailable ... When I instantiate the SocketHandler, I receive no errors/exception. However, the first time a logging method is called, an attempt is made to open the connection to the remote service. The connection fails and UnexpectedValueException is thrown. What if the remote service goes down in the middle of my app running? Sudden my app will throw UnexpectedValueException on every logger call. It's not practical to wrap each and every call to a logging function in a try/catch.

It would be great if SocketHandler had an option to say "ignore failed connection." Does such a capability exist and I'm overlooking it?

zerowebcorp commented 1 year ago

Just encountered same issue. Try...catch isn't working.

I have both GelfHangler sending logs to Graylog and a StreamHandler sending logs to stdout. I took down the graylog server to simulate an outage. When graylog went down, my app also went down throwing RuntimeException error which I tried to catch but for some reason it is not working.

            $this->logger = new \Monolog\Logger('app');

            if ($this->getLogLevel() === "debug") {
                $logLevel = LogLevel::DEBUG;
            } else {
                $logLevel = LogLevel::INFO;
            }
            $this->logger->pushProcessor(new UidProcessor(15));

            if ($this->isDevelopment()) {
                $this->logger->pushHandler(new StreamHandler('php://stdout', $logLevel));
            } else {
                $this->logger->pushProcessor(function ($record) {
                    if (!empty($_SESSION['firstName'])) {
                        $record['extra']['loggedinUser'] = $_SESSION['firstName'];
                    }
                    $date = new \DateTime();
                    $record['extra']['logTime'] = $date->format("Y-m-d H:i:s.u");
                    $record['extra']['token'] = $_SESSION['token'];
                    return $record;
                });
                $this->logger->pushProcessor(new WebProcessor());
            }
            $gelfHandler = new GelfHandler(new Publisher(new UdpTransport($this->graylogDomain, $this->graylogPort)), $logLevel);
            $gelfHandler->setFormatter(new GelfMessageFormatter('app', 'ext_', 'ctx_'));
            $this->logger->pushHandler($gelfHandler);
Seldaek commented 10 months ago

You should wrap the unreliable handlers into a WhatFailureGroupHandler so that errors are ignored if they fail, and they don't bring the whole app down. This has the downside however that if they are misconfigured you'll never really notice though (except by the fact that nothing gets logged).