Laravel-tips del 1 – Loggar

Marcus Olsson,

Dela upp loggarna per dag (och typ)

Tidigare versioner av Laravel (4.1 och neråt), delade upp loggarna per dag och typ (cli, apache2handler etc.). Men i och med introduktionen av artisan tail (se dokumentationen) så valde de att samla all loggning i en och samma fil. Men föredrar man den tidigare metoden och man inte använder tail-kommandot så är det enkelt fixat.

I app/start/global.php hittar man raden

1Log::useFiles(storage_path().'/logs/laravel.log');
1Log::useFiles(storage_path().'/logs/laravel.log');

Byt ut det mot följande istället:

1Log::useDailyFiles(storage_path().'/logs/laravel.log');
1Log::useDailyFiles(storage_path().'/logs/laravel.log');

Bonus; om man vill ha det riktigt i detalj, kör också med PHP-funktionen php_sapi_name() för att se vilket interface som PHP körs med när logfilen skrivs:

1$logFile = 'log-' . php_sapi_name() . '.txt';
2Log::useDailyFiles(storage_path() . '/logs/' . $logFile);
1$logFile = 'log-' . php_sapi_name() . '.txt';
2Log::useDailyFiles(storage_path() . '/logs/' . $logFile);

Nu kommer du direkt kunna söka upp dina loggfiler både baserade på interface och datum. Filnamnen kommer se ut något liknande som:

1log-fpm-fcgi-2014-07-02.txt
1log-fpm-fcgi-2014-07-02.txt

Logga SQL-queries

Jagar du efter SQL-optimeringar med hjälp av eager loading, eller testar du dina cache:ningsmetoder? Då bör du logga dina queries under utvecklingen så att du i detalj kan se vad som händer under huven när Eloquent (eller för all del Query Builder) gör sitt jobb.

Detta görs enklast via Event::listen, på illuminate.query:

1Event::listen('illuminate.query', function($query, $bindings, $time, $name) {
2 $query = str_replace(array('%', '?'), array('%%', '%s'), $query);
3 $query = vsprintf($query, $bindings);
4 $data = compact('query', 'time', 'name');
5 Log::info($data);
6});
1Event::listen('illuminate.query', function($query, $bindings, $time, $name) {
2 $query = str_replace(array('%', '?'), array('%%', '%s'), $query);
3 $query = vsprintf($query, $bindings);
4 $data = compact('query', 'time', 'name');
5 Log::info($data);
6});

Ett tips här är att i din miljös database-config sätta ett värde, t.ex. log till true eller false så att du enkelt kan styra i vilka miljöer du vill logga dina queries.

1if (Config::get('database.log', false)) {
2 // Code
3}
1if (Config::get('database.log', false)) {
2 // Code
3}

Att logga queries är smidigast om man samtidigt använder tail-kommandot för att få ut datan direkt i terminalen.

Ordna med irriterade 404-loggar

Som standard så loggar Laravel alla fel, inklusive 404:or, i samma format. T.ex:

1[2014-07-02 09:06:33] local.ERROR: exception 'Symfony\Component\HttpKernel\Exception\NotFoundHttpException' in /home/vagrant/Code/laravel/vendor/laravel/framework/src/Illuminate/Routing/RouteCollection.php:146
2
3// ## Stack trace
1[2014-07-02 09:06:33] local.ERROR: exception 'Symfony\Component\HttpKernel\Exception\NotFoundHttpException' in /home/vagrant/Code/laravel/vendor/laravel/framework/src/Illuminate/Routing/RouteCollection.php:146
2
3// ## Stack trace

Detta är minst sagt onödigt när det kommer till 404:or, och hjälper en inte särskilt mycket att ens se vilken URL som triggade felet.

Men, det är enkelt fixat!

Igen i app/start/global.php så finns den lilla kodsnutten:

1App::error(function(Exception $exception, $code)
2{
3 Log::error($exception);
4});
1App::error(function(Exception $exception, $code)
2{
3 Log::error($exception);
4});

Nu är det endast 404:or vi vill ordna annorlunda (fler exempel kommer i framtida blogginlägg), så det fixar man rimligtvis snyggast så här:

1App::error(function(Exception $exception, $code)
2{
3 switch ($code) {
4 case 404:
5 Log::error($code . ' thrown @ ' . Request::url());
6 break;
7
8 default:
9 Log::error($exception);
10 break;
11 }
12});
1App::error(function(Exception $exception, $code)
2{
3 switch ($code) {
4 case 404:
5 Log::error($code . ' thrown @ ' . Request::url());
6 break;
7
8 default:
9 Log::error($exception);
10 break;
11 }
12});

Nu kommer något liknande:

1[2014-07-02 09:16:33] local.ERROR: 404 thrown @ http://site.dev:8000/this/is/a/404 [] []
1[2014-07-02 09:16:33] local.ERROR: 404 thrown @ http://site.dev:8000/this/is/a/404 [] []

att dyka upp i loggen istället. Självklart kan man använda Log::error($exception); också om man vill ha hela trace:en.

Hoppas att det här är till användning för andra Laravel-fantaster, har du själv några tips? @olssonm är jag på Twitter.