23
votes
// in my PHP code
$log = new Logger('LaurentCommand');
$log->pushHandler(new StreamHandler('./app/logs/LaurentCommand.log'));
$log->addInfo("Start command",array('username' => 'Joe', 'Age' => '28'));

Result in log file LaurentCommand.log :

[2012-12-20 10:28:11] LaurentCommand.INFO: Start command {"username":"Joe","Age":"28"} []

Why this bracket at the end ?

4

4 Answers

53
votes

That's the extra data. 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);
9
votes

Old question, but throwing out another simple option:

$slackHandler = new \Monolog\Handler\SlackWebhookHandler(...);
$slackHandler->getFormatter()->ignoreEmptyContextAndExtra(true);
4
votes

I know this is an old question, but I ran into it too and I want to share my solution.

The brackets at the end of log lines are due to how Monolog's LineFormatter tries to json_encode() the data in %extra%. The brackets are a JSON representation of an empty array.

To turn off those brackets, I ended up having to subclass Monolog\Formatter\LineFormatter with my own class and overwrite its convertToString($data) function so it returns an empty string if there's no data present. Here's my new subclass:

namespace My\Fancy\Monolog;
use Monolog\Formatter\LineFormatter;

class LineFormatter extends LineFormatter {

    protected function convertToString($data)
    {
        if (null === $data || is_scalar($data)) {
            return (string) $data;
        }

        // BEGIN CUSTOM CODE - This section added to prevent empty 
        // brackets from appearing at the end of log lines:
        if ((is_array($data) && !$data) 
            || is_object($data) && !get_object_vars($data)) {
            return '';
        }
        // END CUSTOM CODE 

        $data = $this->normalize($data);
        if (version_compare(PHP_VERSION, '5.4.0', '>=')) {
            return $this->toJson($data);
        }

        return str_replace('\\/', '/', json_encode($data));
    }
}

You can use this class by injecting an instance of it into your Monolog handler class, like so:

$handler = new Monolog\Handler\StreamHandler('/path/to/my/logfile', 'debug');
$handler->setFormatter(new My\Fancy\Monolog\LineFormatter());
$monolog->pushHandler($handler);

Enjoy!

1
votes

Symfony 4 solution:

  1. Create logger:

    use Monolog\Formatter\LineFormatter;
    
    class Formatter extends LineFormatter
    {
        public function __construct(
            $format = null,
            $dateFormat = null,
            $allowInlineLineBreaks = false,
            $ignoreEmptyContextAndExtra = false
        ) {
            parent::__construct($format, $dateFormat, $allowInlineLineBreaks, true);
        }
    }
    
  2. Define formatter in services.yml:

    log.custom.formatter:
      class: App\Formatter
    
  3. Define formatter in monolog.yml for needed environment(s):

    handlers:
      main:
        type: stream
        path: "%kernel.logs_dir%/%kernel.environment%.log"
        level: debug
        channels: ["!event"]
        formatter: log.custom.formatter