illuminated/console-logger

Laravel控制台命令的日志记录和通知。

10.0.0 2024-03-06 20:16 UTC

README

Logging and Notifications for Laravel Console Commands

Laravel Console Logger

Buy me a coffee

StyleCI Build Status Coverage Status

Packagist Version Packagist Stars Packagist Downloads Packagist License

Laravel控制台命令的日志记录和通知。

Laravel Console Logger - Demo

目录

使用方法

  1. 使用 Composer 安装包

    composer require illuminated/console-logger
  2. 使用 Illuminated\Console\Loggable 特质

    use Illuminated\Console\Loggable;
    
    class ExampleCommand extends Command
    {
        use Loggable;
    
        public function handle()
        {
            $this->logInfo('Hello World!');
        }
    
        // ...
    }
  3. 运行命令并检查您的日志

    [2020-05-11 17:19:21]: [INFO]: Command `App\Console\Commands\ExampleCommand` initialized.
    [2020-05-11 17:19:21]: [INFO]: Host: `MyHost.local` (`10.0.1.1`).
    [2020-05-11 17:19:21]: [INFO]: Database host: `MyHost.local`, port: `3306`, ip: ``.
    [2020-05-11 17:19:21]: [INFO]: Database date: `2020-05-11 17:19:21`.
    [2020-05-11 17:19:21]: [INFO]: Hello World!
    [2020-05-11 17:19:21]: [INFO]: Execution time: 0.009 sec.
    [2020-05-11 17:19:21]: [INFO]: Memory peak usage: 8 MB.
    

可用方法

Loggable 特质提供了这些 PSR-3 方法

  • logDebug()
  • logInfo()
  • logNotice()
  • logWarning()
  • logError()
  • logCritical()
  • logAlert()
  • logEmergency()

在您的控制台命令中使用它们来记录所需的信息。

通道

日志消息可以以多种不同的方式处理。

可能是将数据写入日志文件,存储在数据库中,发送电子邮件等。

文件通道

文件通道简单地将日志消息写入日志文件。

每个命令都会在 storage/logs 目录中有单独的文件夹。

例如,foo-bar 命令的日志将存储在 storage/logs/foo-bar 文件夹中。

您可以通过覆盖适当的方法自定义存储文件夹和存储日志文件的最大数量。

class ExampleCommand extends Command
{
    use Loggable;

    protected function getLogPath()
    {
        return storage_path('logs/custom-folder/date.log');
    }

    protected function getLogMaxFiles()
    {
        return 45;
    }

    // ...
}

通知通道

如果您想在控制台命令中通知错误,请使用通知通道。

通知通道是可选的,默认情况下是禁用的。每个通道都可以按需启用和配置。

默认情况下,您将收到高于 NOTICE 级别的通知(请参阅 PSR-3 日志级别)。这意味着您将默认收到 NOTICE、WARNING、ERROR、CRITICAL、ALERT 和 EMERGENCY 通知。

当然,您也可以自定义这一点,以及其他特定通道的详细信息。

邮件通道

邮件通道通过电子邮件提供通知。

设置收件人,邮件通知即可使用!

class ExampleCommand extends Command
{
    use Loggable;

    protected function getEmailNotificationsRecipients()
    {
        return [
            ['address' => 'john.doe@example.com', 'name' => 'John Doe'],
            ['address' => 'jane.smith@example.com', 'name' => 'Jane Smith'],
        ];
    }

    // ...
}

有许多与邮件通道相关的功能。

通过覆盖这些方法,您可以更改主题、from 地址、通知级别等。

去重是一个值得注意的另一个有用功能。有时相同的错误可能会连续发生多次。例如,您正在使用一个故障的外部网络服务。或者想象数据库服务器出现问题。在这些情况下,您将收到大量的类似电子邮件。去重是解决此问题的正确方法。

您可以选择它,并调整去重工作的时间(以秒为单位)。

class ExampleCommand extends Command
{
    use Loggable;

    protected function useEmailNotificationsDeduplication()
    {
        return true;
    }

    protected function getEmailNotificationsDeduplicationTime()
    {
        return 90;
    }

    // ...
}

数据库通道

数据库通道提供了一种在数据库中保存通知的方法。

开始使用它的最简单方法

class ExampleCommand extends Command
{
    use Loggable;

    protected function useDatabaseNotifications()
    {
        return true;
    }

    // ...
}

通知将存储在 iclogger_notifications 表中,如果尚不存在,将自动创建。

当然,您可以通过覆盖适当的方法自定义表名,甚至保存逻辑。

class ExampleCommand extends Command
{
    use Loggable;

    protected function useDatabaseNotifications()
    {
        return true;
    }

    protected function getDatabaseNotificationsTable()
    {
        return 'custom_notifications';
    }

    protected function getDatabaseNotificationsCallback()
    {
        return function (array $record) {
            CustomNotification::create([
                'level' => $record['level'],
                'level_name' => $record['level_name'],
                'message' => $record['message'],
                'context' => get_dump($record['context']),
                'custom_field' => 'Foo Bar Baz!',
            ]);
        };
    }

    // ...
}

错误处理

默认启用的另一个酷功能是错误处理。

该软件包会自动为您记录所有信息:严重问题 - 异常和致命错误,甚至是小事,例如PHP通知和警告。

添加通知,您将立即知道控制台命令中何时出现问题!

带上下文的异常

有时传递抛出异常的额外上下文是有用的。

请使用 Illuminated\Console\Exceptions\RuntimeException 来实现。

use Illuminated\Console\Exceptions\RuntimeException;

class ExampleCommand extends Command
{
    use Loggable;

    public function handle()
    {
        throw new RuntimeException('Whoops! We have a problem!', [
            'some' => 123,
            'extra' => true,
            'context' => null,
        ]);
    }

    // ...
}
[2020-05-11 17:19:21]: [ERROR]: Whoops! We have a problem!
array:5 [
    "code" => 0
    "message" => "Whoops! We have a problem!"
    "file" => "/Applications/MAMP/htdocs/icl-test/app/Console/Commands/ExampleCommand.php"
    "line" => 22
    "context" => array:3 [
        "some" => 123
        "extra" => true
        "context" => null
    ]
]

Guzzle 6+ 集成

如果您使用 Guzzle,您可能希望记录完整的HTTP交互日志。

函数 iclogger_guzzle_middleware() 提供了一个预配置的 Guzzle 中间件

use GuzzleHttp\Client;
use GuzzleHttp\HandlerStack;

// Create a log middleware
$logMiddleware = iclogger_guzzle_middleware($logger);

// Add it to the HandlerStack
$handler = HandlerStack::create();
$handler->push($logMiddleware);

// Use the created handler in your Guzzle Client
$client = new Client([
    'handler' => $handler,
    'base_uri' => 'https://example.com',
]);

// Now, all your HTTP requests and responses would be logged automatically!
// $client->get('/foo');

如果您使用JSON,您可能希望自动解码请求参数和响应体。

$logMiddleware = iclogger_guzzle_middleware($logger, 'json');

此外,您可以根据自定义逻辑禁用特定请求参数和/或响应体的记录。

use Psr\Http\Message\RequestInterface;
use Psr\Http\Message\ResponseInterface;

// Disable logging of request params for the `/foo` endpoint
$shouldLogRequestParams = function (RequestInterface $request) {
    return ! str_ends_with($request->getUri(), '/foo');
};

// Disable logging of response bodies greater than 100 KB
$shouldLogResponseBody = function (RequestInterface $request, ResponseInterface $response) {
    return $response->getHeaderLine('Content-Length') < 102400;
};

$logMiddleware = iclogger_guzzle_middleware($logger, 'json', $shouldLogRequestParams, $shouldLogResponseBody);

由 Monolog 提供支持

此软件包使用功能强大的 Monolog Logger

您可以通过以下方式访问Monolog的底层实例:

  • 使用命令的 icLogger() 方法

    class ExampleCommand extends Command
    {
        use Loggable;
    
        public function handle()
        {
            $logger = $this->icLogger();
        }
    
        // ...
    }
  • 或通过Laravel的服务容器

    $logger = app('log.iclogger');

故障排除

包含特质,但没有任何作用?

Loggable 特性覆盖了 initialize() 方法

trait Loggable
{
    protected function initialize(InputInterface $input, OutputInterface $output)
    {
        $this->initializeLogging();

        parent::initialize($input, $output);
    }

    // ...
}

如果您还覆盖了 initialize() 方法,您必须自行调用 initializeLogging() 方法

class ExampleCommand extends Command
{
    use Loggable;

    protected function initialize(InputInterface $input, OutputInterface $output)
    {
        // You have to call it first
        $this->initializeLogging();

        // Then goes your custom code
        $this->foo = $this->argument('foo');
        $this->bar = $this->argument('bar');
        $this->baz = $this->argument('baz');
    }

    // ...
}

几个特质冲突?

如果您正在使用另一个 illuminated/console-% 软件包,您将收到“特性冲突”错误。

例如,如果您正在构建一个可记录命令,该命令 不允许重叠

class ExampleCommand extends Command
{
    use Loggable;
    use WithoutOverlapping;

    // ...
}

您将收到特性冲突错误,因为这两个特性都覆盖了 initialize() 方法

如果两个特性插入了一个同名的方法,如果没有明确解决冲突,则会产生致命错误。

要修复此问题 - 覆盖 initialize() 方法并解决冲突

class ExampleCommand extends Command
{
    use Loggable;
    use WithoutOverlapping;

    protected function initialize(InputInterface $input, OutputInterface $output)
    {
        // Initialize conflicting traits
        $this->initializeMutex();
        $this->initializeLogging();
    }

    // ...
}

赞助商

Laravel Idea
Material Theme UI Plugin

许可证

Laravel Console Logger 是开源软件,许可协议为 MIT 许可证

Buy me a coffee