Loupax
Loupax

Reputation: 4914

Is there a way to centrally preprocess all logs created by monolog?

I am currently working on a big application that uses monolog for logging and was asked to hide any sensitive information like passwords.

What I tried to do, was extending monolog so it would automatically replace sensitive information with asterics, but even though the data seems to be altered, in the end the original text gets logged.

use Monolog\Handler\AbstractProcessingHandler;

class FilterOutputHandler extends AbstractProcessingHandler
{
    private $filteredFields = [];

    public function __construct(array $filteredFields = [], $level = Monolog\Logger::DEBUG, $bubble = true)
    {
        $this->filteredFields = array_merge($filteredFields, $this->filteredFields);
        parent::__construct($level, $bubble);
    }

    protected function write(array $record)
    {
        foreach($record['context'] as $key=>$value){
            if(in_array($key, $this->filteredFields)){
                $record['context'][$key] = '*****';
            }
        }

        return $record;
    }

}

And when I initialize my logger I do this:

 $logger->pushHandler(new FilterOutputHandler(['username', 'password']));
 $logger->debug('Sensitive data incoming', ['username'=> 'Oh noes!', 'password'=> 'You shouldn\'t be able to see me!']);

I also tried overridding the handle and processRecord methods of the AbstractProcessingHandler interface but in vain. Can this be done in monolog?

Upvotes: 5

Views: 1996

Answers (1)

Loupax
Loupax

Reputation: 4914

Looks like I was trying the wrong thing.

Instead of adding a new handler to my logger, I had to add a new processor by using the pushProcessor(callable) method.

So, in my specific use case, I can add filters to my context like this:

function AddLoggerFilteringFor(array $filters){
    return function ($record) use($filters){
        foreach($filters as $filter){
            if(isset($record['context'][$filter])){
                $record['context'][$filter] = '**HIDDEN FROM LOG**';
            }
        }
        return $record;
    };
}

And later I can add filters simply by

(init)
$logger->pushProcessor(AddLoggerFilteringFor(['username', 'password']));

...
(several function definition and business logic later)
$logger->debug('Some weird thing happened, better log it', ['username'=> 'Oh noes!', 'password'=> 'You shouldn\'t be able to see me!']);

Upvotes: 5

Related Questions