larave Monolog日志自定义配置
1、原有的日志记录文件只记录了时间和日志内容没有记录是在哪个文件记录的,给新来的人员查看日志增加了额外的负担。类似下面这样
[-- ::] local.INFO: 我是来测试日志的 {"content":}
[-- ::] local.DEBUG: 我是来测试日志的
[-- ::] local.ERROR: 我是来测试日志的
[-- ::] local.WARNING: 我是来测试日志的
2、基于公司需求对MonoLog模块的源码进行了分析,发布Laravel是对MonoLog之上做了一层封装,达到了如下效果
[-- ::] local.INFO: 我是来测试日志的 {"content":} {"pid":,"file":"App\\Http\\Controllers\\TestController->log:20","line":,"ip":"127.0.0.1"}
[-- ::] local.DEBUG: 我是来测试日志的 {"pid":,"file":"App\\Http\\Controllers\\TestController->log:21","line":,"ip":"127.0.0.1"}
[-- ::] local.ERROR: 我是来测试日志的 {"pid":,"file":"App\\Http\\Controllers\\TestController->log:22","line":,"ip":"127.0.0.1"}
[-- ::] local.WARNING: 我是来测试日志的 {"pid":,"file":"App\\Http\\Controllers\\TestController->log:23","line":,"ip":"127.0.0.1"}
接下来告诉大家怎么来实现它
1、重新建立一个
Writer.php
类 暂定目录存
app\Utils\Monolog
<?php
namespace App\Utils\Monolog;
use Illuminate\Log\Writer as BaseWriter;
use Monolog\Formatter\LineFormatter;
/**
* 时间精确到微秒
*
* @package app.Utils.Monolog
*/
class Writer extends BaseWriter
{
/**
* Get a default Monolog formatter instance.
*
* @return \Monolog\Formatter\LineFormatter
*/
protected function getDefaultFormatter()
{
return new LineFormatter(null, 'Y-m-d H:i:s.u', true, true);
}
2、建立处理程序
IntrospectionProcessor.php
目录
app\Utils\Monolog\Processor
<?php
namespace App\Utils\Monolog\Processor;
use Monolog\Logger;
/**
* Monolog用处理模块
* 标准IntrospectionProcessor的简化版
*
* @package app.Utils.Monolog.Processor
*/
class IntrospectionProcessor
{
private $level;
private $skipClassesPartials;
public function __construct($level = Logger::DEBUG, array $skipClassesPartials = ['Monolog\\', 'Illuminate\\'])
{
$this->level = Logger::toMonologLevel($level);
$this->skipClassesPartials = $skipClassesPartials;
}
/**
* @param array $record
* @return array
*/
public function __invoke(array $record)
{
// return if the level is not high enough
if ($record['level'] < $this->level) {
return $record;
}
$trace = debug_backtrace();
// skip first since it's always the current method
array_shift($trace);
// the call_user_func call is also skipped
array_shift($trace);
$i = ;
while (isset($trace[$i]['class'])) {
foreach ($this->skipClassesPartials as $part) {
if (strpos($trace[$i]['class'], $part) !== false) {
$i++;
continue ;
}
}
break;
}
$line = null;
if (isset($trace[$i]['class'])) {
$line = $trace[$i]['class'];
if (isset($trace[$i]['class'])) {
$line = $line . '->' . $trace[$i]['function'];
}
} else if (isset($trace[$i - ]['file'])) {
$line = $trace[$i - ]['file'];
}
if (null !== $line && isset($trace[$i - ]['line'])) {
$line = $line . ':' . $trace[$i - ]['line'];
}
$record['extra']['file'] = $line;
$record['extra']['line'] = $trace[$i - ]['line'];
$record['extra']['ip'] = $_SERVER["REMOTE_ADDR"];
return $record;
}
}
3、建立 处理模块
ProcessIdProcessor.php
目录
app\Utils\Monolog\Processor
<?php
namespace App\Utils\Monolog\Processor;
/**
* Monolog用处理模块
* 标准IntrospectionProcessor的简化版, 原输出键值文字长度过长
*
* @package app.Utils.Monolog.Processor
*/
class ProcessIdProcessor
{
/**
* @param array $record
* @return array
*/
public function __invoke(array $record)
{
$record['extra']['pid'] = getmypid();
return $record;
}
}
4、建立
ServiceProvider
文件
LogServiceProvider.php
目录
app\Providers
<?php
namespace App\Providers;
use Monolog\Logger as Monolog;
use Illuminate\Support\ServiceProvider;
use App\Utils\Monolog\Writer;
class LogServiceProvider extends ServiceProvider
{
/**
* Register the service provider.
*
* @return void
*/
public function register()
{
$this->app->singleton('log', function () {
return $this->createLogger();
});
}
/**
* Create the logger.
*
* @return \Illuminate\Log\Writer
*/
public function createLogger()
{
$processors = [
new \App\Utils\Monolog\Processor\ProcessIdProcessor(),
new \App\Utils\Monolog\Processor\IntrospectionProcessor()
];
$log = new \App\Utils\Monolog\Writer(
new Monolog($this->channel(), [], $processors), $this->app['events']
);
if ($this->app->hasMonologConfigurator()) {
call_user_func($this->app->getMonologConfigurator(), $log->getMonolog());
} else {
$this->configureHandler($log);
}
return $log;
}
/**
* Get the name of the log "channel".
*
* @return string
*/
protected function channel()
{
return $this->app->bound('env') ? $this->app->environment() : 'production';
}
/**
* Configure the Monolog handlers for the application.
*
* @param \Illuminate\Log\Writer $log
* @return void
*/
protected function configureHandler(Writer $log)
{
$this->{'configure'.ucfirst($this->handler()).'Handler'}($log);
}
/**
* Configure the Monolog handlers for the application.
*
* @param \Illuminate\Log\Writer $log
* @return void
*/
protected function configureSingleHandler(Writer $log)
{
$log->useFiles(
$this->app->storagePath().'/logs/laravel.log',
$this->logLevel()
);
}
/**
* Configure the Monolog handlers for the application.
*
* @param \Illuminate\Log\Writer $log
* @return void
*/
protected function configureDailyHandler(Writer $log)
{
$log->useDailyFiles(
$this->app->storagePath().'/logs/laravel.log', $this->maxFiles(),
$this->logLevel()
);
}
/**
* Configure the Monolog handlers for the application.
*
* @param \Illuminate\Log\Writer $log
* @return void
*/
protected function configureSyslogHandler(Writer $log)
{
$log->useSyslog('laravel', $this->logLevel());
}
/**
* Configure the Monolog handlers for the application.
*
* @param \Illuminate\Log\Writer $log
* @return void
*/
protected function configureErrorlogHandler(Writer $log)
{
$log->useErrorLog($this->logLevel());
}
/**
* Get the default log handler.
*
* @return string
*/
protected function handler()
{
if ($this->app->bound('config')) {
return $this->app->make('config')->get('app.log', 'single');
}
return 'single';
}
/**
* Get the log level for the application.
*
* @return string
*/
protected function logLevel()
{
if ($this->app->bound('config')) {
return $this->app->make('config')->get('app.log_level', 'debug');
}
return 'debug';
}
/**
* Get the maximum number of log files for the application.
*
* @return int
*/
protected function maxFiles()
{
if ($this->app->bound('config')) {
return $this->app->make('config')->get('app.log_max_files', );
}
return ;
}
}
5、最后注册新建的
LogServiceProvider.php
服务到容器里面覆盖掉底层的
LogServiceProvider
#打开 config/app.php在 providers数组里面添加上
App\Providers\LogServiceProvider::class,
到此大功完成,可以新建一个控制器来看看实现的效果
<?php
namespace App\Http\Controllers;
/**
* 数据
*/
class TestController extends Controller{
public function log()
{
echo "我是来测试的";
\Log::info('我是来测试日志的', ['content' => ]);
\Log::debug('我是来测试日志的');
\Log::error('我是来测试日志的');
\Log::warning('我是来测试日志的');
}
}