faustoff / laravel-contextify
Laravel中的上下文日志
Requires
- php: ^8.0
- illuminate/log: ^8.0|^9.0|^10.0
- illuminate/notifications: ^8.0|^9.0|^10.0
- illuminate/support: ^8.0|^9.0|^10.0
- monolog/monolog: ^2.0|^3.0
- nesbot/carbon: ^2.0
Requires (Dev)
Suggests
- ext-pcntl: Allows to use Faustoff\Contextify\Console\Terminatable trait
- laravel-notification-channels/telegram: Allows to send Telegram notifications
README
Laravel Contextify
Laravel中的上下文日志
此包允许您编写带有执行上下文的日志消息,包括 类、PID、UID(等等),直接从您的应用程序PHP类中。它提供了一个PHP特质,允许您实现此功能。此外,它还为Laravel的本地日志功能提供了各种增强。
当您的应用程序规模和复杂性增长时,将执行上下文添加到日志中非常有用,您开始面临来自应用程序各个部分的日志,包括多个进程,如队列工作者和守护进程。
通过检查日志记录的 类,您可以轻松确定其来源。它还组合同一个类的所有相关日志记录。
PID 将所有与特定进程相关的日志记录组合在一起,例如队列工作者或守护进程。
UID 将所有与单个用户请求的处理相关的日志记录组合在一起,例如单个控制台命令的执行。
MEM 表示在添加日志记录时从系统(包括未使用页面)分配给PHP的内存量。
日志记录将如下所示
[2023-03-07 19:26:26] local.NOTICE: [App\Services\OrderService] [PID:56] [UID:640765b20b1c0] [MEM:31457280] 订单已创建
此外,此包允许您
安装
composer require faustoff/laravel-contextify:^2.0
发布配置文件
可选地,您可以使用此命令发布健康配置文件
php artisan vendor:publish --tag="contextify-config"
用法
上下文日志
假设您在应用程序中有一个类似 OrderService
的类。
要将上下文日志添加到 OrderService
,请使用 Faustoff\Contextify\Loggable
特质和该特质提供的 $this->logInfo()
等方法
<?php namespace App\Services; use Faustoff\Contextify\Loggable; class OrderService { use Loggable; public function order(): void { // You business logic here // Just a log message $this->logSuccess('Order was created'); // Log message with context data $this->logSuccess('Order was created', ['key' => 'value']); // Log message with context data both in log and notification $this->logSuccess('Order was created', ['key' => 'value'], true); } }
日志
[2023-03-07 19:26:26] local.NOTICE: [App\Services\OrderService] [PID:56] [UID:640765b20b1c0] [MEM:31457280] Order was created
[2023-03-07 19:26:26] local.NOTICE: [App\Services\OrderService] [PID:56] [UID:640765b20b1c0] [MEM:31457280] Order was created {"key":"value"}
[2023-03-07 19:26:26] local.NOTICE: [App\Services\OrderService] [PID:56] [UID:640765b20b1c0] [MEM:31457280] Order was created {"key":"value"}
父上下文
如果您有多个级别的日志上下文,您可以通过使用 Faustoff\Loggable\HasLog
特质将“父”日志可记录对象传递给“子”对象。
假设您有一个“父”日志上下文 OrderController
和“子” OrderService
,并且您希望将 OrderController
的日志上下文传递给 OrderService
。
<?php namespace App\Services\OrderService; use Faustoff\Contextify\HasLog; class OrderService { use HasLog; public function order() { // ... $this->log->logSuccess('Order was created'); } }
<?php namespace App\Http\Controllers; use App\Services\OrderService; use Illuminate\Routing\Controller; use Faustoff\Contextify\Loggable; use Faustoff\Contextify\LoggableInterface; class OrderController extends Controller implements LoggableInterface { use Loggable; public function store() { (new OrderService())->setLog($this)->order(); } }
日志
[2023-03-07 19:26:26] local.NOTICE: [App\Http\Controllers\OrderController] [PID:56] [UID:640765b20b1c0] [MEM:31457280] Order was created
通知
默认情况下,通知可以通过以下方式发送
- 邮件
- Telegram
如果您想发送电子邮件通知,您应该配置 CONTEXTIFY_MAIL_ADDRESSES
环境变量。您可以像这样通过逗号分隔来传递多个地址
CONTEXTIFY_MAIL_ADDRESSES=foo@test.com,bar@test.com
如果您想发送Telegram通知,您应该安装 和 配置 laravel-notification-channels/telegram 包。然后您应该使用 检索到的Telegram Chat ID 设置 CONTEXTIFY_TELEGRAM_CHAT_ID
环境变量。
想要更多通知渠道?欢迎使用 Laravel Notifications Channels。
此外,您可以通过特定的通道发送特定通知时,覆盖默认使用的队列(默认为 default
队列)。这将在 contextify
配置中通过 notifications.list
键来完成,如下所示
// in config/contextify.php 'notifications' => [ // ... 'list' => [ \Faustoff\Contextify\Notifications\LogNotification::class => ['mail' => 'mail_queue1', 'telegram' => 'telegram_queue1'], \Faustoff\Contextify\Notifications\ExceptionOccurredNotification::class => ['mail' => 'mail_queue2', 'telegram' => 'telegram_queue2'], ], // ... ],
您可以通过设置环境变量 CONTEXTIFY_NOTIFICATIONS_ENABLED
来完全禁用通知。
日志通知
要发送日志通知,您应将 logInfo()
等方法的第三个参数设置为 true
<?php namespace App\Services; use Faustoff\Contextify\Loggable; class OrderService { use Loggable; public function order(): void { // You business logic here // Log message and notification with context data $this->logSuccess('Order was created', ['key' => 'value'], true); } }
异常通知
您将接收到任何未处理的报告性异常的通知。
要关闭,请将 contextify
配置文件中 notifications.exception_handler.reportable
键的值设置为空。
// in config/contextify.php 'notifications' => [ // ... 'exception_handler' => [ 'reportable' => null, ], // ... ],
控制台命令
如果您想在控制台命令中添加上下文日志记录,可以使用 Faustoff\Contextify\Console\Loggable
特性。它通过将日志写入控制台输出(终端)扩展了常见的 Faustoff\Contextify\Loggable
。
<?php namespace App\Console\Commands; use Illuminate\Console\Command; use Faustoff\Contextify\Console\Loggable; class SyncData extends Command { use Loggable; protected $signature = 'data:sync'; public function handle(): int { $this->logSuccess('Data was synced'); return self::SUCCESS; } }
日志
[2023-03-07 19:26:26] local.NOTICE: [App\Console\Commands\SyncData] [PID:56] [UID:640765b20b1c0] [MEM:31457280] Data was synced
终端输出
Data was synced
控制台命令跟踪
此外,您还可以使用 Faustoff\Contextify\Console\Trackable
特性来跟踪控制台命令的执行。它在控制台命令开始和结束时添加额外的调试日志条目,包括执行时间和峰值内存使用。
<?php namespace App\Console\Commands; use Illuminate\Console\Command; use Faustoff\Contextify\Console\Trackable; class SyncData extends Command { use Trackable; protected $signature = 'data:sync'; public function handle(): int { // You business logic here $this->logSuccess('Data was synced'); return self::SUCCESS; } }
日志
[2023-03-07 19:26:26] local.DEBUG: [App\Console\Commands\SyncData] [PID:56] [UID:640765b20b1c0] [MEM:31457280] Run with arguments {"command":"data:sync"}
[2023-03-07 19:26:26] local.NOTICE: [App\Console\Commands\SyncData] [PID:56] [UID:640765b20b1c0] [MEM:31457280] Data was synced
[2023-03-07 19:26:26] local.DEBUG: [App\Console\Commands\SyncData] [PID:56] [UID:640765b20b1c0] [MEM:31457280] Execution time: 1 second
[2023-03-07 19:26:26] local.DEBUG: [App\Console\Commands\SyncData] [PID:56] [UID:640765b20b1c0] [MEM:31457280] Peak memory usage: 4 MB.
终端输出
Data was synced
控制台命令输出捕获
此外,您还可以使用 Faustoff\Contextify\Console\Outputable
特性捕获由 info()
等方法产生的原生 Laravel 控制台命令输出,并将其存储到日志中。
<?php namespace App\Console\Commands; use Illuminate\Console\Command; use Faustoff\Contextify\Console\Outputable; class SyncData extends Command { use Outputable; protected $signature = 'data:sync'; public function handle(): int { // You business logic here $this->info('Data was synced'); return self::SUCCESS; } }
日志
[2023-03-07 19:26:26] local.NOTICE: [App\Console\Commands\SyncData] [PID:56] [UID:640765b20b1c0] [MEM:31457280] Data was synced
终端输出
Data was synced
控制台命令处理关闭信号
您可以使用 Faustoff\Contextify\Console\Terminatable
特性和 Symfony\Component\Console\Command\SignalableCommandInterface
接口一起处理来自控制台命令的关闭信号(默认为 SIGQUIT
、SIGINT
和 SIGTERM
),以优雅地关闭命令执行。
<?php namespace App\Console\Commands; use Faustoff\Contextify\Console\Loggable; use Illuminate\Console\Command; use Symfony\Component\Console\Command\SignalableCommandInterface; class ConsumeStats extends Command implements SignalableCommandInterface { use Terminatable; protected $signature = 'stats:consume'; public function handle(): void { while (true) { // ... if ($this->shouldTerminate) { // Execution terminated by handle shutdown signal break; } } } }