Laravel/Lumen的日志簡(jiǎn)單系統(tǒng)介紹:
Laravel/Lumen的日志默認(rèn)是基于Monolog進(jìn)行了一層封裝,如果要求不高,用起來(lái)還是十分容易的,本文基于laravel5.6/Lumen5.6版本進(jìn)行解說(shuō)。5.6版對(duì)日志系統(tǒng)做了升級(jí),將日志的配置單獨(dú)放以了config/logging.php 配置文件中,所以現(xiàn)在實(shí)用多了。
基本配置(解決日志路徑文件名和保存周期等)
開(kāi)始使用Laravel5.5時(shí)經(jīng)常遇到有人問(wèn)Laravel中日志的為什么只有一個(gè)文件,能不能修改日志目錄,能不能修改日志文件名?剛開(kāi)始用時(shí)我也有這樣的困惑,由于早期項(xiàng)目簡(jiǎn)單(其實(shí)是懶),沒(méi)有去深入研究。后來(lái)跟到了5.6,官方終于發(fā)飆了,完美通過(guò)配置解決問(wèn)題(5.5的版本其實(shí)也有解決方案,可以自行搜索一下,順便吐槽一下Lavavel官方文檔太簡(jiǎn)單了,感覺(jué)一大半的強(qiáng)大功能都沒(méi)有提及如何深度使用)。以下代理示例,大概的備注了一下參數(shù)說(shuō)明,還有一些可以挖掘。
<?php
// 配置文件路徑:/config/logging.php
return [
// 默認(rèn)用哪個(gè)
'default' => env('LOG_CHANNEL', 'stack'),
'channels' => [
//自定義頻道
'myapplog' => [
// 日志驅(qū)動(dòng)模式:
'driver' => 'daily',
// 日志存放路徑
'path' => storage_path('logs/myapplog.log'),
// 日志等級(jí):
'level' => 'info',
// 日志分片周期,多少天一個(gè)文件
'days' => 1,
],
// 系統(tǒng)默認(rèn),可以合并幾個(gè)頻道,按等級(jí)對(duì)應(yīng)記錄,符合等級(jí)條件的都記錄
'stack' => [
'driver' => 'stack',
'channels' => ['single','daily'],
],
'single' => [
'driver' => 'single',
'path' => storage_path('logs/laravel.log'),
'level' => 'debug',
],
'daily' => [
'driver' => 'daily',
'path' => storage_path('logs/laravel.log'),
'level' => 'info',
'days' => 7,
],
],
];
日志使用:
<?php
use Log;
class LogTestController extends Controller
{
$message = 'Some message';
$log = ['user_id'=>1,'user_name'=>'abcd'];
Log::channel('myapplog')->info($message, $log); //Log后的數(shù)組會(huì)自動(dòng)轉(zhuǎn)成Json存到日志記錄中
查看記錄到的效果:
[2018-02-23 10:22:28] local.INFO: Some message {'user_id':1,'user_name':'abcd'}
高階定制:(完全定義日志格式,本例為全Json格式)
踩了好多坑,開(kāi)始嘗試直接自己 new 一個(gè) monolog 的方案,雖然也實(shí)現(xiàn)了全 Json 記錄了,但有很多不想要的字段。達(dá)不到要求。
幾經(jīng)折騰,發(fā)現(xiàn) Monolog 有很多可以用的 Formatter ,但發(fā)現(xiàn)官方的把字段寫(xiě)死在里邊了,抓狂到了想直接改官方源碼的齷齪地步了,還是不死心,最終發(fā)現(xiàn)Laravel5.6的logging參數(shù)中有一個(gè)tap的接口可以用。順著這條線,最終通過(guò)重定義 Formatter 的 format() 方法實(shí)現(xiàn)了需求 :
1、配置logging.php中的 tap項(xiàng):
return [
'default' => env('LOG_CHANNEL', 'myapplog'),
'channels' => [
'myapplog' => [
'driver' => 'daily',
'path' => storage_path('logs/myapplog.log'),
// 掛載日志格式接口(重點(diǎn))
'tap' => [App\Logging\ApplogFormatter::class],
'level' => 'info',
'days' => 1,
],
],
];
新建App/Logging/ApplogFormatter.php
<?php
namespace App\Logging;
use App\Logging\JsonFormatter;
class ApplogFormatter
{
/**
* Customize the given logger instance.
*
* @param \Illuminate\Log\Logger $logger
* @return void
*/
public function __invoke($logger)
{
foreach ($logger->getHandlers() as $handler) {
$handler->setFormatter(new JsonFormatter());
}
}
}
重點(diǎn):新建/App/Logging/JsonFormatter.php
<?php
namespace App\Logging;
use Monolog\Formatter\JsonFormatter as BaseJsonFormatter;
class JsonFormatter extends BaseJsonFormatter
{
public function format(array $record)
{
// 這個(gè)就是最終要記錄的數(shù)組,最后轉(zhuǎn)成Json并記錄進(jìn)日志
$newRecord = [
'time' => $record['datetime']->format('Y-m-d H:i:s'),
'message' => $record['message'],
];
if (!empty($record['context'])) {
$newRecord = array_merge($newRecord, $record['context']);
}
//$json = 'aaa,bbb,ccc'; // 這是最終返回的記錄串,可以按自己的需求改
$json = $this->toJson($this->normalize($newRecord), true) . ($this->appendNewline ? "\n" : '');
return $json;
}
}
Log的記錄方法還是一樣用:
class LogTestController extends Controller
{
$message = 'Some message';
$log = ['user_id'=>1,'user_name'=>'abcd'];
Log::channel('myapplog')->info($message, $log); //Log后的數(shù)組會(huì)自動(dòng)轉(zhuǎn)成Json存
看看最終的效果:
{"time":"2018-06-09 13:39:39","message":"Some message","user_id":1,"user_name":"abcd"}
大功告成!