6

I'm using Monolog in a project, it's not Symfony, just my own application that uses the stand-alone Monolog composer package.

What I'd like to do is programmatically turn off debugging logs. I'm writing to a log file and I'm using the Monolog::StreamHandler. I'm controlling whether the application is in debug mode or not with a Configuration class that gets the debug value from a configuration file. So when someone changes that value to debugging is false, debug logging should turn off.

I felt like the easiest way to do this would be to extend StreamHandler and override StreamHandler's write method like this.

class DurpLogger extends StreamHandler {
    protected function write(array $record) {
        if ($this->getLevel() == Durp::Debug && !Configuration::debug()) {
            return;
        }
        parent::write($record);
    }
}

So if a log request comes in and the log level for the handler is set to DEBUG and the application's Configuration::debug() is FALSE then just return without writing the log message. Otherwise, StreamHandler will do its thing.

I'm wondering if this is the best way to use Monolog or if there's perhaps a cleaner way to do this.

I envision there being a handler in my application for DEBUG, INFO, ERROR and whatever levels I might need for my application. Perhaps it makes sense to not rely on a Configuration::debug() that can only be TRUE or FALSE, but rather a Configuration::logLevel() that will allow me to more granularly control logging output.

But even still, does extending StreamHandler make the most sense when controlling Monolog at the application level?

UPDATE

Now, I'm thinking something like this, that uses level rather than just boolean debug.

class DurpLogger extends StreamHandler {
    public function __construct() {
        parent::__construct(Configuration::logFile(), Configuration::logLevel());
    }

    protected function write(array $record) {
        if (!($this->getLevel() >= Configuration::logLevel())) {
            return;
        }
        parent::write($record);
    }
}

Then I'd use it in the application like this.

class Durp {
  private $logger;
  public function __construct() {
        $this->logger = new Logger('durp-service');
        $this->logger->pushHandler(new DurpLogger());
        $this->logger->addDebug('Debugging enabled');
        $this->logger->addInfo('Starting Durp');
    }
}

I figured the StreamHandler handles the file writing stuff, so that's why I'm extending it. And if I turn up the log level in Configuration to Logger::INFO, the "Debugging enabled" message doesn't get logged.

Open to suggestions to make this better.

Halfstop
  • 1,710
  • 17
  • 34

1 Answers1

13

A common alternative would be to use the NullHandler instead of the StreamHandler.

Maybe switch between them depending on your condition like follows:

if (!Configuration::debug()) {
    $logger->pushHandler(new \Monolog\Handler\NullHandler());
}

I would like to give you an example that is more adapted to your usage,
but I need to see some code in order to know how you use it.

Update

For the question about default format, the empty [] at end represent the extra data that can be added with log entries.

From @Seldaek (Monolog's owner) :

The default format of the LineFormatter is: "[%datetime%] %channel%.%level_name%: %message% %context% %extra%\n". the username/age is the context, and extra that is typically empty results in this empty array [].

If you use processors to attach data to log records they typically write it to the extra key to avoid conflicts with context info. If it really is an issue for you you can change the default format and omit %extra%.

Edit: As of Monolog 1.11 the LineFormatter has a $ignoreEmptyContextAndExtra parameter in the constructor that lets you remove these, so you can use this:

// the last "true" here tells it to remove empty []'s

$formatter = new LineFormatter(null, null, false, true);
$handler->setFormatter($formatter);

See How not to show last bracket in a monolog log line? and Symfony2 : use Processors while logging in different files about the processors which @Seldaek is talking about.

Community
  • 1
  • 1
chalasr
  • 12,971
  • 4
  • 40
  • 82
  • I updated the question to include further thoughts on this question. – Halfstop Feb 24 '16 at 19:35
  • 1
    I think I read too quickly. You don't want to disable debug at all, just change the debugging level ? – chalasr Feb 24 '16 at 19:37
  • Right, that's what I figured out. Sometimes Stack Overflow serves as a great rubber ducky to talk things out. And hopefully this will help someone doing this very common task. – Halfstop Feb 24 '16 at 19:39
  • 1
    The way you are using is clean, also if it suit your needs, why not. – chalasr Feb 24 '16 at 19:41
  • 1
    I think it looks good, but unfortunately, or fortunately depending on your preference, I don't work with anyone who's thinking about PHP at this level. So I don't always know if I'm missing something or doing something in not the best way possible. – Halfstop Feb 24 '16 at 19:43
  • 1
    Well, I don't see any way to optimise your logic at the moment, maybe someone else will give your more inputs – chalasr Feb 24 '16 at 19:46
  • I am curious about the default format for monolog. [2016-02-24 14:35:59] durp-service.DEBUG: Debugging turned on [] [] What are those to brackets slots for and how do you put data in there or get rid of them? – Halfstop Feb 24 '16 at 19:48
  • I've updated my answer to give you some details about those brackets – chalasr Feb 24 '16 at 19:58