trd-rdm / stack-logger
一个可以同时记录多个通道的复合日志记录器。
Requires
- php: >=7.1.0|^8.0
- google/cloud: ^0.158
- nunomaduro/collision: >=2.0
README
简介
使用Laravel框架的logging与facades功能组成的复合型工具,可以在程序的任何一处通过facade调用,方便开发使用
目录
1. 安装步骤 [返回目录]
(1) 执行安装指令
composer require trd-rdm/stack-logger --with-all-dependencies
(2) 注册Service Provider以使用Log Facade
打开config/app.php,在providers数组底部添加RDM\StackLogger\StackLoggerServiceProvider注册facade
'providers' => [ /* * Package Service Providers... */ RDM\StackLogger\StackLoggerServiceProvider::class, ]
(3) 添加注册多种loggers以支持facade功能
打开config/logging.php,将以下logger添加到channels数组中,根据需求调整stack_logger中channels的内容,但不建议添加storage。
return [ 'channels' => [ /** * Log Facade * 主要 logger , 以 stack driver 結合多個 custom log 同時呼叫 * 加入 channels 的 driver 可以在 GCPLog 中呼叫 */ 'stack_logger' => [ 'driver' => 'stack', 'channels' => ['console', 'file'], // 指定多種 log 頻道, 可以自由添加移除 (可添加選項 : ['console', 'file', 'storage', 'stackdriver', 'telegram']) 'ignore_exceptions' => false, ], /** * 1. 螢幕輸出: 彩色字體 */ 'console' => [ 'driver' => 'monolog', 'level' => env('LOG_LEVEL', 'debug'), // The minimum logging level at which this handler will be triggered 'handler' => RDM\StackLogger\Handlers\ConsoleLogger::class, 'formatter' => env('LOG_STDERR_FORMATTER'), 'with' => [ ], ], /** * 2. 文件檔案 : 需要指定寫入檔案路徑 */ 'file' => [ 'driver' => 'monolog', 'level' => env('LOG_LEVEL', 'debug'), 'handler' => RDM\StackLogger\Handlers\FileLogger::class, 'formatter' => env('LOG_STDERR_FORMATTER'), 'with' => [ // handler constructor 額外參數 'default_path' => storage_path('default.log'), // 預設檔案路徑 'permission' => 0775, // The log file's permissions 'locking' => false, // Attempt to lock the log file before writing to it ], ], /** * 3. GCP Storage 儲存空間 : 需要指定本地上傳檔案路徑 與 storage 路徑 * * 結果請至 GCP Cloud Storage - Browser查看 * * @link https://console.cloud.google.com/storage/browser */ 'storage' => [ 'driver' => 'monolog', 'level' => env('LOG_LEVEL', 'debug'), 'handler' => RDM\StackLogger\Handlers\GcpStorageLogger::class, 'formatter' => env('LOG_STDERR_FORMATTER'), 'with' => [ 'gcp_project_id' => 'your-gcp-project', // GCP Project 'credential_path' => 'your-local-credential-file-path', // 憑證路徑 (專案根目錄為 root) 'bucket_id' => 'your-storage-bucket-id', // GCP Storage bucket 名稱 'bucket_folder' => 'bucket-folder1/folder2', // 此 logger 在 bucket id 底下的 root 路徑 'bucket_path' => '', // bucket_folder 底下的檔案路徑, 需要使用者用 setPath() 設置後才能寫入 'ignore_exceptions' => false, // 上傳失敗時不要拋出例外 ], ], /** * 4. GCP Stackdriver : 需要指定 log 名稱 * * 輸出結果請至 Google Console 查詢 Log * * @link https://console.cloud.google.com/logs */ 'stackdriver' => [ 'driver' => 'monolog', 'level' => env('LOG_LEVEL', 'debug'), 'handler' => RDM\StackLogger\Handlers\StackdriverLogger::class, 'formatter' => env('LOG_STDERR_FORMATTER'), 'with' => [ 'name' => 'your-stackdriver-logging-name', // log 名稱 (在 google console 查詢過濾條件 logName 的值) 'gcp_project_id' => 'rdm-bbos', 'credential_path' => '/rdm-bbos.json', // 憑證路徑 (專案根目錄為 root) 'batch_enabled' => true, // 允許批次送出多筆 log 紀錄, 避免每次送出產生高延遲 ], ], /** * 5. Telegram 通知 : 需要指定 接收者 chat_id 與 api_key 機器人群組 */ 'telegram' => [ 'driver' => 'monolog', 'level' => env('LOG_LEVEL', 'debug'), // The minimum logging level at which this handler will be triggered 'handler' => RDM\StackLogger\Handlers\TelegramLogger::class, 'formatter' => env('LOG_STDOUT_FORMATTER'), 'with' => [ 'chat_ids' => ['1378441015'], // 收信者 'disable_notification' => false, // 關閉通知提示音 'api_key' => (env('APP_ENV') === 'prod') ? env('TELEGRAM_BOT_TOKEN', 'xxxxx') // 正式 Bot : env('TELEGRAM_BOT_TOKEN', 'xxxxx'), // 測試 Bot ], ], ] ];
调整stack_logger的channels以选择你需要的channels,并对以下五种log设置参数。这五种log都是monolog log,关于这些参数定义可以参考Laravel Logging - Creating Monolog Handler Channel
2. Logger各自的介绍与配置 [返回目录]
打开config/logging.php中可以看到新添加入的logger底下将各自作介绍。
-
stack_logger
首先stack_logger即GCPLog Facade功能,它是一种Laravel Log stack类型,
需要设置的参数有
- channels: 添加或移除你需要的log名称,可以开启或关闭指定log功能,让你在调用此log时可以一次执行多种channels中的log,而不用分别调用。
例如,如果channel中包含'console', 'file', 'storage', 'stackdriver', 'telegram'。
则调用以下这一行
Log::channel('stack_logger')->info('info message');
相当于执行以下几行
Log::channel('console')->info('info message'); Log::channel('file')->info('info message'); Log::channel('storage')->info('info message'); Log::channel('stackdriver')->info('info message'); Log::channel('telegram')->info('info message');
-
console
屏幕输出,即传统意义上的print,只是根据log等级会有不同的文字色彩,根据信息重要程度增加辨识度。
需要设置的参数有
- level: 什么等级(含)以上的log才需要被执行,例如将level设置为'info',则debug等级的log不会印到屏幕上
-
file
写入本地文件。
需要设置的参数有
- default_path: 指定预写入的log文件路径
-
storage
上传文件到Google Cloud Storage,使用此log的话每写入一行log就会,同步上传file logger设置的文件内容到你指定的Storage Bucket文件之中。
* 请注意两次调用storage logger(上传)的时间间隔过短,会使Google API上传抛出异常,如果想要忽略异常的话,请将
ignore_exceptions参数设成true。需要设置的参数有
- gcp_project_id: GCP项目名称
- credential_path: GCP API凭证文件,请设置本地相对于项目根目录的文件路径
- bucket_id: Storage Bucket名称
- bucket_folder: Storage文件在bucket底下的文件夹,通常执行时不变动
- bucket_path: Storage文件在bucket_folder底下的路径
- ignore_exceptions: 写log(上传文件)失败时不抛出异常
-
stackdriver
写入的log会通过GCP API传送到Google Stackdriver存储,可以通过GCP Log记录文件探索工具查看,查询时的过滤条件就可以带入 logName="your-stackdriver-logging-name",以查到执行结果,目前此stackdriver log记录是30日后会自动消失。
需要设置的参数有
- gcp_project_id: GCP项目名称
- credential_path: GCP API凭证文件,请设置本地相对于项目根目录的文件路径
- name: log名称,在google console查询过滤条件logName的值
- [batch_enabled: 允许批量送出多笔log记录,避免每次送出API产生高延迟,影响程序效率
-
telegram
通过telegram bot通知发送消息给指定一位或多位收信者。
需要设置的参数有
- chat_ids: 收信者的telegram user id
- disable_notification: 关闭通知提示音
- api_key: 注册机器人时Telegram官方提供的Telegram Bot API Token
3. Logger 使用方法 [返回目录]
您可以使用集成到 stack_logger 驱动的 GCPLog Facade(以下简称 GCPLog)。
也可以使用 Laravel 原生的 Log Facade(以下简称 Log)进行日志记录。
但是 Log 只支持 PSR-3 标准的接口函数,您无法在程序执行期间动态修改 config/logging.php 中的参数,以修改 logger 参数,例如设置文件路径等,执行期间对 config 的更改不会影响到已经建立的静态(static)实例的 Log。
GCPLog 提供了一些接口,让您能够在执行期间设置参数,以及集成部分日志记录之外的调试函数,方便程序员开发。
以下为 GCPLog 支持的函数介绍
代码示例 [返回目录]
-
Log 成功与错误消息 跳至函数
use RDM\StackLogger\Facades\GCPLog; use \Psr\Log\LogLevel; // 成功訊息 GCPLog::info('success'); // 同上成功訊息 GCPLog::log(LogLevel::INFO, 'success', ['success' => true, 'result' => []]); try { // ... } catch (\Exception $exception) { // 錯誤訊息 GCPLog::error('something wrong'); // 印出漂亮格式的錯誤訊息 GCPLog::renderException($exception); // 匯出例外訊息成 HTML 檔 GCPLog:dumpExceptionPrettyPage($exception, storage_path('exception.html')); }
-
设置 Log 路径 跳至函数
use RDM\StackLogger\Facades\GCPLog; // 設置路徑參數 GCPLog::setLocalLogPath(storage_path('logs/err.log')) // 設置 log 檔案參數 ->setStackDriverLogName('stack-driver-log-name'); // 設置 stackdriver log 名稱 GCPLog::info("message"); // 讀取路徑參數 fprintf("All messages are written at file %s", GCPLog::getLocalLogPath()); // 取得 log 檔案路徑 fprintf("All messages are export to stackdriver: %s", GCPLog::getStackDriverLink()); // 取得 stackdriver log 存取連結
-
Telegram 跳至函数
use RDM\StackLogger\Facades\GCPLog; try { $john_user_id = '12345'; GCPLog::setTelegramChatIds([$john_user_id]) // 設置收訊者 ->disableTelegramNotification(); // 關閉通知聲響 GCPLog::info('<b>TITLE</b> message'); // 送出通知 (支援 html 格式,若要避免請使用 `htmlspecialchars()` 跳脫或是 <pre> 包覆) } catch (\Throwable $e) { // html tag 限制 https://core.telegram.org/api/entities#allowed-entities // 最大文字長度 : 4096 字元 dump($e); }
如果 config/logging.php 默认调用通道 channels.stack_logger.channels 中没有
telegram,则应使用 调用内部 logger 函数GCPLog::telegram()->info('<b>TITLE</b> message');
-
计时器 1 跳至函数
use RDM\StackLogger\Facades\GCPLog; GCPLog::watch(); // 開始計時 /* * Code Block 1 */ GCPLog::timing('執行 Code Block 1'); /* * Code Block 2 */ GCPLog::timing('執行 Code Block 2'); /** 範例輸出結果: 執行 Code Block 1 1.500 sec 執行 Code Block 2 1.500 sec */
-
计时器 2 跳至函数
use RDM\StackLogger\Facades\GCPLog; $timer = GCPLog::createTimer(); $timer->setDescription('執行 Code Block 1'); for($i = 5; $i > 0; $i--) { $timer->start(); sleep(1); $timer->stop(); sleep(2); } echo (string)$timer; /** 範例輸出結果: 執行 Code Block 1 花費 : 5.01 秒 */
-
SQL Log 跳至函数
use RDM\StackLogger\Facades\GCPLog; use Illuminate\Support\Facades\DB; $connection = 'mysql'; GCPLog::enableMysqlGeneralLog($connection); // 啟用 mysql general log DB::connection($connection)->table('users')->get(); // send query GCPLog::disableMysqlGeneralLog($connection); // 停用 mysql general log
-
调用内部 logger:当函数 config/logging.php 默认调用通道 channels.stack_logger.channels 中不包含的通道时,可以使用此方法单独调用。 跳至函数
use RDM\StackLogger\Facades\GCPLog; use Illuminate\Support\Facades\DB; // 選取 GCPLog 中的特定 logger, 執行其內部函式 GCPLog::file()->setPath(storage_path('laravel.log')); GCPLog::console()->info('message'); GCPLog::telegram()->info('<b>TITLE</b> message');