在實際開發中,我們發現在 Debug 的時候經常需要查詢日誌。而傳統的方式是需要 SSH 到生產環境,然後使用 cat
,tail
和 grep
等命令查詢日誌,且無法進行日誌的統計和分析,深度挖掘這些日誌的價值。
本片文章的側重點在於優雅的讓 Laravel 直接將日誌寫入 Elasticsearch,當然你也可以選擇使用 Logstash 採集 Laravel 的本地日誌。
環境搭建可以參考 《Elastic Stack 之 Elasticsearch》 和 《Elastic Stack 之 Kibana》 這兩篇博文。
- elasticsearch/elasticsearch
- betterde/logger(如果需要)
Laravel 使用 monolog/monolog 作為預設日誌處理模組。monolog 自帶了很多 Handler 其中就有 ElasticsearchHandler。
生命週期
-
在
Illuminate\Foundation\Application
的建構函式中註冊基本的服務提供者
,其中就有Illuminate\Log\LogServiceProvider
。 -
在
Illuminate\Log\LogServiceProvider
中將Illuminate\Log\LogManager
註冊到容器,此時還沒有 Logger。 -
當我們使用
Illuminate\Support\Facades\Log::info()
的時候,LogManager 會呼叫內部一系列方法根據配置檔案建立 Logger 和其所需的 Handlers -
最終呼叫 Logger 的 info()、error()、debug() 等方法,實現記錄日誌的功能。
簡單適配
只需要通過修改 config/logging.php
和 .env
檔案就可以實現,將日誌直接寫入 Elasticcsearch:
'elastic' => [
'driver' => 'monolog',
'level' => 'debug',
'name' => 'Develop',
'tap' => [],
'handler' => ElasticsearchHandler::class,
'formatter' => \Monolog\Formatter\ElasticsearchFormatter::class,
'formatter_with' => [
'index' => 'monolog',
'type' => '_doc'
],
'handler_with' => [
'client' => \Elasticsearch\ClientBuilder::create()->setHosts(['http://localhost:9200'])->build(),
],
],
LOG_CHANNEL=elastic
簡單適配後會發現當我們在寫入日誌的時候,Laravel 是單條同步進行的,對於我們使用原創儲存來說這將影響一定的效能。所以我們需要在整個生命週期中臨時儲存所有的日誌資訊,在請求結束前觸發同步或非同步將日誌批量寫入儲存。
為此我週末寫了一個擴充套件包betterde/logger,如果你在使用的過程中有任何問題可以在Github上提 Issue 和 PR
目前只支援 Laravel
^6.0.0
因為從 6.0 開始 monolog 的依賴是 2.,後面如果需要的話,會考慮開個1.分支相容5.* 的版本。
安裝
$ composer require betterde/logger
$ php artisan vendor:publish --tag=betterde.logger
配置
將如下配置追加到 config/logging.php
的 channels
中:
use Betterde\Logger\ElasticsearchLogger;
'channels' => [
'elastic' => [
'driver' => 'custom',
'via' => ElasticsearchLogger::class,
],
],
將 \Betterde\Logger\Http\Middleware\BulkCollectionLog
中介軟體新增到 App\Http\Kernel.php
檔案中
/**
* The application's global HTTP middleware stack.
*
* These middleware are run during every request to your application.
*
* @var array
*/
protected $middleware = [
\Illuminate\Foundation\Http\Middleware\CheckForMaintenanceMode::class,
\Illuminate\Foundation\Http\Middleware\ValidatePostSize::class,
\App\Http\Middleware\TrimStrings::class,
\Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull::class,
\App\Http\Middleware\TrustProxies::class,
\Betterde\Logger\Http\Middleware\BulkCollectionLog::class
];
在 .env
檔案中新增如下配置項:
LOG_CHANNEL=elastic
ELASTICSEARCH_HOST=localhost
ELASTICSEARCH_PORT=9200
ELASTICSEARCH_SCHEME=http
ELASTICSEARCH_USER=
ELASTICSEARCH_PASS=
修改 config/logger.php
配置檔案:
<?php
return [
/*
* 是否開啟批量寫入,需要設定中介軟體
*/
'batch' => false,
/*
* 是否使用佇列
*/
'queue' => [
'enable' => false,
'name' => env('LOG_QUEUE_NAME', 'logging')
],
/*
* 日誌級別,值可以參考 Monolog\Logger.php 中的定義
*/
'level' => 200,
/*
* 是否在多個 Handler 中流轉日誌資料
*/
'bubble' => false,
/*
* Elasticsearch DB
*/
'elasticsearch' => [
'hosts' => [
[
/*
* host 是必填項
*/
'host' => env('ELASTICSEARCH_HOST', 'localhost'),
'port' => env('ELASTICSEARCH_PORT', 9200),
'scheme' => env('ELASTICSEARCH_SCHEME', 'http'),
'user' => env('ELASTICSEARCH_USER', null),
'pass' => env('ELASTICSEARCH_PASS', null)
],
],
'retries' => 2,
/*
* 證照路徑
*/
'cert' => ''
],
/*
* Handler 的設定
*/
'options' => [
'index' => 'monolog', // Elastic index name
'type' => '_doc', // Elastic document type
'ignore_error' => false, // Suppress Elasticsearch exceptions
],
/*
* 對於異常日誌是否記錄追蹤詳情
*/
'exception' => [
'trace' => false,
],
/*
* 擴充套件屬性,你可以用於 Elasticsearch Index,extra 陣列裡的 Key 都是可以自定義的,我這裡只是舉例
*/
'extra' => [
'host' => 'example.com',
'php' => '7.3.5',
'laravel' => '6.5.2'
]
];
好了現在可以盡情的享受寫 CURD 的樂趣了!