如何自定义 Laravel 作业的日志输出?

How to customize the log output for a job in Laravel?

我看到 Laravel 使用 Monolog 库来处理日志。我在工作中有以下处理方法:

ApiUpdateItemJob.php:

public function handle()
{
    $data = [
        'id' => $this->item_id,
        'data[status]' => $this->status,
    ];

    $response = ApiFacedeClient::exec('Item', 'update', $data);

    $result = json_decode($response->getBody());
}

在工作人员(主管)的日志中,我看到以下内容:

[2019-12-17 02:13:13][40770367] Processed: App\Jobs\UpdateItemStatus
[2019-12-17 05:11:53][40792760] Processing: App\Jobs\UpdateItemStatus
[2019-12-17 05:11:54][40792761] Processing: App\Jobs\UpdateItemStatus
[2019-12-17 05:11:54][40792760] Processed: App\Jobs\UpdateItemStatus
[2019-12-17 05:11:54][40792762] Processing: App\Jobs\UpdateItemStatus

我应该在作业中添加什么才能看到以下行:

[2019-12-17 05:11:54][40792762] Processing item id #333333 (Status [200 OK]): App\Jobs\UpdateItemStatus

Supervisor 会将写入标准输出的任何内容输出到 it's config file 上定义的日志文件:

stdout_logfile=/home/forge/app.com/worker.log

因此您可以在 handle 工作方法上写信给 php://stdout,以便写在 Supervisor 工人的日志上:

public function handle()
{
    fwrite(STDOUT, "Processing item id #{$this->item_id} (Status [{$this->status}]): App\Jobs\UpdateItemStatus");

    //$data = [
    //    'id' => $this->item_id,
    //...
}

config/logging.php 添加新频道:

'updateItem' => [
    'driver' => 'single',
    'path' => storage_path('logs/updateItem.log'),
    'level' => 'info',
]

然后在 UpdateItemJob:

handle 中记录你想要的任何内容
Log::channel('updateItem')->info('Hello world!!');

然后实时查看您的日志文件。例如:

tail -f storage/logs/updateItem.log

如果您不想要自定义日志文件。只需使用 Log::info('Hello world!!');tail storage/logs

中的默认日志文件

Source

您在 worker 的日志文件中看到的日志是由 Laravel 输出的,并且是不可配置的。

您最好的选择是定义一个自定义日志通道,该通道记录到工作人员的文件并在您的 HTTP 请求后推送。

  1. 定义单个文件或基于路径的记录器通道config/logging.php:

    'supervisorLog' => [
        'driver' => 'single',
        'name' => 'supervisor-log',
        // ath should be same as stdout_logfile in supervisord.conf
        'path' => storage_path('path/to/supervisor/log/file'), 
        'locking' => false
    ],
    
  2. ApiUpdateItemJob.php 中的 $result = json_decode($response->getBody()); 之后添加:

    Log::channel('supervisorLog')->info("Processing item id " + $this->item_id +" (Status ["+ $response->status() +"]): App\Jobs\UpdateItemStatus");

结果将类似于:

[2019-12-17 05:11:53][40792760] Processing: App\Jobs\UpdateItemStatus

[2019-12-17 05:11:54][40792761] Processing item id #333333 (Status [200]): App\Jobs\UpdateItemStatus

[2019-12-17 05:11:54][40792760] Processed: App\Jobs\UpdateItemStatus

实际上你可以修改它,让它记录到你的常规日志中,然后你不需要关心为队列工作人员创建一个新的主管日志,它将使用你在 logging.php[ 中配置的日志输出=13=]

use App\Classes\Extensions\Queue\CustomWorkCommand;
class ArtisanServiceProvider extends ServiceProvider
{
    public function register()
    {
        $this->app->extend('command.queue.work', function ($command, $app) {
            return new CustomWorkCommand($app['queue.worker']);
        });
    }
}

在 app/Classes/Extensions/Queue 内或任何您喜欢的地方创建一个新的 class,并覆盖 writeStatus 命令:

namespace App\Classes\Extensions\Queue;

use Illuminate\Queue\Console\WorkCommand as ConsoleWorkCommand;

class WorkCommand extends ConsoleWorkCommand {

    protected function writeStatus(Job $job, $status, $type)
    {
        if($type == "comment"){
            $type = "info";
        }
        $output = sprintf("[%s][%s] %s %s",
            Carbon::now()->format('Y-m-d H:i:s'),
            $job->getJobId(),
            str_pad("{$status}:", 11), 
            $job->resolveName()
        );
        Log::$type($output);
    }
}

将此行添加到 app.php

'providers' => [
    ...
    App\Providers\ArtisanServiceProvider::class,
],