Logs an entire array using Monolog

ReynierPM picture ReynierPM · Jun 16, 2015 · Viewed 13.7k times · Source

Is there any way to log an entire array using Monolog? I have been reading several docs but didn't find a way to log the entire array in a readable format, any advice?

Docs I've read:

Answer

Ugur picture Ugur · Jun 16, 2015

If you check the logger interface (https://github.com/php-fig/log/blob/master/Psr/Log/LoggerInterface.php) you will see all of the logging methods gets message as a string, thus you get a warning when you try to log with a variable type other than string.

I tried to use a processor to format the array in a custom manner, but as expected the processor is triggered after you send the variable to logger interface.

The dirtiest way of logging an array may be any of those for your choice;

$logger->info(json_encode($array));
$logger->info(print_r($array, true));
$logger->info(var_export($array, true));

On the other hand you may want to format your array in a single proccessor to centralize your formatting logic with DRY principles.

Json encode array -> Send as Json String -> json decode to array -> format -> json encode again

CustomRequestProcessor.php

<?php
namespace Acme\WebBundle;


class CustomRequestProcessor
{


    public function __construct()
    {
    }

    public function processRecord(array $record)
    { 
        try {
            //parse json as object and cast to array
            $array = (array)json_decode($record['message']);
            if(!is_null($array)) {
                //format your message with your desired logic
                ksort($array);
                $record['message'] = json_encode($array);
            }
        } catch(\Exception $e) {
            echo $e->getMessage();
        }
        return $record;
    }
}

Register request processor in your config.yml or services.yml, see the tags node for registering the processor for a custom channel.

services:
monolog.formatter.session_request:
    class: Monolog\Formatter\LineFormatter
    arguments:
        - "[%%datetime%%] %%channel%%.%%level_name%%: %%message%%\n"

monolog.processor.session_request:
    class: Acme\WebBundle\CustomRequestProcessor
    arguments:  []
    tags:
        - { name: monolog.processor, method: processRecord, channel: testchannel }

And in the controller log your array as a json string,

<?php

namespace Acme\WebBundle\Controller;

use Symfony\Bundle\FrameworkBundle\Controller\Controller;

class DefaultController extends Controller
{
    public function indexAction()
    {

        $logger = $this->get('monolog.logger.testchannel');
        $array = array(3=>"hello" , 1=>"world", 2=>"sf2");
        $logger->info(json_encode($array));

        return $this->render('AcmeWebBundle:Default:index.html.twig');
    }
}

Now you can format and log your array as your desire in a central request processor without sorting/formating/walking on the array in your every controller.