Hello everyone!

We have been investing plenty of personal time and energy for many years to share our knowledge with you all. However, we now need your help to keep this blog running. All you have to do is just click one of the adverts on the site, otherwise it will sadly be taken down due to hosting etc. costs. Thank you.

Sometimes you'll want to log things the way you want with your custom loggers. Example below creates a custom channel, handler and formatter to log our data. We're going to log how long a search functionality takes and log some useful information in our custom log file.


Config.yml


monolog:
channels: [search] # Custom channel
handlers:
search: # Custom handler
type: stream
path: %kernel.logs_dir%/search_%kernel.environment%.log # Custom log file
channels: [search] # Custom channel
formatter: application_search.formatter.search # Custom formatter

SearchController


Logging logic doesn't actually belong here but I'll keep it here at this time just to keep the post shorter.


namespace Application\SearchBundle\Controller;

use Psr\Log\LoggerInterface;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Method;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;

/**
* @Route("/search", service="application_search.controller.search")
*/
class SearchController extends Controller
{
private $nativeLogger;
private $searchLogger;

public function __construct(
LoggerInterface $nativeLogger,
LoggerInterface $searchLogger
) {
$this->nativeLogger = $nativeLogger;
$this->searchLogger = $searchLogger;
}

/**
* @param Request $request
*
* @Method({"GET"})
* @Route("")
*
* @return Response
*/
public function indexAction(Request $request)
{
$seconds = [1, 2, 3];

$start = microtime(true);
sleep($seconds[array_rand($seconds)]); // Pretend like you did a search and it took 1, 2 or 3 seconds
$end = microtime(true);

$data = [
'start_microseconds' => $start,
'end_microseconds' => $end,
'query_string' => [
'field' => $request->query->get('field', 'name'),
'keyword' => $request->query->get('keyword', 'inanzzz')
]
];

if ($request->query->get('logger', 'native') == 'native') {
$this->nativeLogger($data);
} else {
$this->customLogger($data);
}

return new Response('All logged!');
}

/**
* @param array $data
*/
private function nativeLogger(array $data)
{
$this->nativeLogger->info('Native Search Logger', $data);
}

/**
* @param array $data
*/
private function customLogger(array $data)
{
$this->searchLogger->info('Custom Search Logger', $data);
}
}

Controllers.yml


services:
application_search.controller.search:
class: Application\SearchBundle\Controller\SearchController
arguments:
- @logger
- @monolog.logger.search

SearchFormatter


You could inject other services to this class such as "session" if you wanted log session data as well.


namespace Application\SearchBundle\Util;

use Monolog\Formatter\FormatterInterface;

class SearchFormatter implements FormatterInterface
{
public function format(array $record)
{
$start = $record['context']['start_microseconds'];
$end = $record['context']['end_microseconds'];

return json_encode([
'message' => $record['message'],
'timestamp' => date(DATE_ISO8601),
'elapsed_milliseconds' => round(($end-$start) * 1000),
'query_string' => $record['context']['query_string']
]).PHP_EOL;
}

public function formatBatch(array $records)
{
foreach ($records as $key => $record) {
$records[$key] = $this->format($record);
}

return $records;
}
}

Utils.yml


services:
application_search.formatter.search:
class: Application\SearchBundle\Util\SearchFormatter

Tests


Native logger


If you call GET /app_dev.php/search?logger=native&field=title&keyword=inanzzz, your "app/log/dev.log" file will contain log entry below.


# Original version
[2016-03-27 19:39:57] app.INFO: Native Search Logger {"start_microseconds":1459103996.8535,"end_microseconds":1459103997.8542,"query_string":{"field":"title","keyword":"inanzzz"}} []

# Beautified version
[
2016-03-2719: 39: 57
]
app.INFO: NativeSearchLogger{
"start_microseconds": 1459103996.8535,
"end_microseconds": 1459103997.8542,
"query_string": {
"field": "title",
"keyword": "inanzzz"
}
}
[
]

Custom logger


If you call GET /app_dev.php/search?logger=custom&field=title&keyword=inanzzz, your "app/log/search_dev.log" file will contain log entry below.


# Original version
{"message":"Custom Search Logger","timestamp":"2016-03-27T19:41:50+0100","elapsed_milliseconds":2001,"query_string":{"field":"title","keyword":"inanzzz"}}

# Beautified version
{
"message": "Custom Search Logger",
"timestamp": "2016-03-27T19:41:50+0100",
"elapsed_milliseconds": 2001,
"query_string": {
"field": "title",
"keyword": "inanzzz"
}
}