faustoff/laravel-contextify

Laravel中的上下文日志

2.7.0 2024-09-14 19:10 UTC

README

Packagist Version Packagist Downloads Packagist License GitHub Repo stars

Laravel Contextify

Laravel中的上下文日志

此包允许您编写带有执行上下文的日志消息,包括 PIDUID(等等),直接从您的应用程序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 接口一起处理来自控制台命令的关闭信号(默认为 SIGQUITSIGINTSIGTERM),以优雅地关闭命令执行。

<?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;
            }
        }
    }
}