参考文献
原理流程
1. 客户端调用 Log::info('你好啊');2. config('logging.default') = stack
3. config('logging.channels.stack.channels') 由于这个值是个数组,设置了 daily 跟 custom
4. 以custom为例, config('logging.channels.custom.via') = \App\Log\Handler\CreateEsLogger::class
5. \App\Log\Handler\CreateEsLogger.__invoke($config)
6. PushEsHandler->handler($recored); $record包含Log::info()的传递的相关数据7.LogEsclient->write()
8. LogModel->save()
9. 把save的数据同步道 elasticsearch
app/logging.php
<?php
use Monolog\Handler\StreamHandler;
use Monolog\Handler\SyslogUdpHandler;
return [
/*
|--------------------------------------------------------------------------
| Default Log Channel
|--------------------------------------------------------------------------
|
| This option defines the default log channel that gets used when writing
| messages to the logs. The name specified in this option should match
| one of the channels defined in the "channels" configuration array.
|
*/
'default' => env('LOG_CHANNEL', 'stack'),
/*
|--------------------------------------------------------------------------
| Log Channels
|--------------------------------------------------------------------------
|
| Here you may configure the log channels for your application. Out of
| the box, Laravel uses the Monolog PHP logging library. This gives
| you a variety of powerful log handlers / formatters to utilize.
|
| Available Drivers: "single", "daily", "slack", "syslog",
| "errorlog", "monolog",
| "custom", "stack"
|
*/
'channels' => [
'stack' => [
'driver' => 'stack',
'channels' => ['daily', 'custom'], //注意,这里加上custom,而custom对应着elasticsearch的handler
'ignore_exceptions' => false,
],
'single' => [
'driver' => 'single',
'path' => storage_path('logs/laravel.log'),
'level' => 'debug',
],
'daily' => [
'driver' => 'daily',
'path' => storage_path('logs/laravel.log'),
'level' => 'debug',
'days' => 14,
],
'slack' => [
'driver' => 'slack',
'url' => env('LOG_SLACK_WEBHOOK_URL'),
'username' => 'Laravel Log',
'emoji' => ':boom:',
'level' => 'critical',
],
'papertrail' => [
'driver' => 'monolog',
'level' => 'debug',
'handler' => SyslogUdpHandler::class,
'handler_with' => [
'host' => env('PAPERTRAIL_URL'),
'port' => env('PAPERTRAIL_PORT'),
],
],
'stderr' => [
'driver' => 'monolog',
'handler' => StreamHandler::class,
'formatter' => env('LOG_STDERR_FORMATTER'),
'with' => [
'stream' => 'php://stderr',
],
],
'syslog' => [
'driver' => 'syslog',
'level' => 'debug',
],
'errorlog' => [
'driver' => 'errorlog',
'level' => 'debug',
],
//elasticsearch
'custom' => [
'driver' => 'custom',
'via' => \App\Log\Handler\CreateEsLogger::class, //用来生成elastic的日志工厂
'url' => 'http://es.wlcat.com', //es的超链接
'port'=> '9200', //es的端口
'index'=> 'laralog', //es的索引名
'toDB' => false, //是否写入数据库
]
],
];
/*
文件: app/Log/Handler/CreateEsLogger.php
这个文件,用来当客户端调用Log::info() Log::debug() 等等不同级别的写入日志方法时候
自动调用这个类的__invoke方法,并把在logging.php配置的custom配置数组传递该函数中
这个文件做了monolog对象,该对象传递一个 推送到es的handler<PushEsHandler>
*/
<?php
namespace App\Log\Handler;
use Illuminate\Log\ParsesLogConfiguration;
use Monolog\Formatter\LineFormatter;
use Monolog\Handler\FormattableHandlerInterface;
use Monolog\Handler\HandlerInterface;
use Monolog\Logger as Monolog;
class CreateEsLogger {
use ParsesLogConfiguration;
/**
* The standard date format to use when writing logs.
*
* @var string
*/
protected $dateFormat = 'Y-m-d H:i:s';
/**
* 创建一个 Monolog 实例.
*
* @param array $config
* @return \Monolog\Logger
*/
public function __invoke(array $config)
{
return (new Monolog($config['driver'], [
$this->prepareHandler((new PushEsHandler(
$config['url'], $config['port'], $config['index'], $config['toDB'] ?? false, $this->level($config),
$config['bubble'] ?? true
)), $config),
]));
}
/**
* Prepare the handler for usage by Monolog.
*
* @param \Monolog\Handler\HandlerInterface $handler
* @param array $config
* @return \Monolog\Handler\HandlerInterface
*/
protected function prepareHandler(HandlerInterface $handler, array $config = [])
{
$isHandlerFormattable = false;
if (Monolog::API === 1) {
$isHandlerFormattable = true;
} elseif (Monolog::API === 2 && $handler instanceof FormattableHandlerInterface) {
$isHandlerFormattable = true;
}
if ($isHandlerFormattable && ! isset($config['formatter'])) {
$handler->setFormatter($this->formatter());
} elseif ($isHandlerFormattable && $config['formatter'] !== 'default') {
$handler->setFormatter($this->app->make($config['formatter'], $config['formatter_with'] ?? []));
}
return $handler;
}
/**
* Get a Monolog formatter instance.
*
* @return \Monolog\Formatter\FormatterInterface
*/
protected function formatter()
{
return tap(new LineFormatter(null, $this->dateFormat, true, true), function ($formatter) {
$formatter->includeStacktraces();
});
}
/**
* Get fallback log channel name.
*
* @return string
*/
protected function getFallbackChannelName()
{
return $this->app->bound('env') ? $this->app->environment() : 'production';
}
}