Artisanコマンドはコマンドラインで手動で実行するだけでなく、クロンジョブでの実行でも使用します。時間を設定して自動的に実行されるゆえに、実際に実行されたのか、どれだけ時間かかったのか、いくつのレコードを処理したのかなどをログに記録しておきたいです。そして、わかりやすいようにコマンドごとに違うログファイルを作成したいです。となると、config/logging.phpでそれぞれのコマンドのチャンネルを作成することになるのでしょうか? つまり50個コマンドあれば50個のチャンネルの作成です。それは面倒だな、ということで良いアイデアを思いつきました。

要は、コマンドごとにログファイル名を変えれば良いことなので、前回の月次ごとのログの作成をベースとして変更します。

まず、config/logging.phpに新しいチャンネルcliを追加します。

...
   'channels' => [
...
        'monthly' => [
            'driver' => 'daily', // use RotatingHandler
            'tap' => [App\Logging\MonthlyFileNameForRotatingHandler::class],
            'path' => storage_path('logs/laravel.log'),
            'level' => 'info',
            'permission' => 0666,
            'days' => 12, // 12ヶ月でローテーション
        ],

        'cli' => [
            'driver' => 'daily', // use RotatingHandler
            'tap' => [App\Logging\CommandFileNameForRotatingHandler::class],
            'path' => storage_path('logs/cli.log'),
            'level' => 'info',
            'permission' => 0666,
            'days' => 12, // 12ヶ月でローテーション
        ],
...

前回のmonthlyのチャンネルの設定と比較すると、変わっているのはtapで指定したクラス名とpathのログファイル名だけです。

そして、以下の新規のクラスの定義は、これまた前回のMonthlyFileNameForRotatingHandlerクラスとほとんど変わりません。


namespace App\Logging;

class CommandFileNameForRotatingHandler
{
    /**
     * Customize the given logger instance.
     *
     * @param  \Illuminate\Log\Logger  $logger
     * @return void
     */
    public function __invoke($logger)
    {
        foreach ($logger->getHandlers() as $handler) {
       	    $name = $_SERVER['argv'][1]; //実行されるArtisanのコマンド名を取得して、以下でそれを使用
            $handler->setFilenameFormat("{filename}-$name-{date}", 'Y-m');
        }
    }
}

変更した部分は、ファイル名の作成の部分だけです。
そして、この設定により以下のようなコマンドラインを実行するなら、

$ php artisan command:log

作成されるログファイル名は、cli-command:log-2021-04.logのようになります。

違うコマンドを実行するなら、

$ php artisan task:something

ログファイル名は、cli-task:something-2021-04.logとなります。

もちろんArtisanのコマンドでは以下の例のように、Logの関数のコールが必要です。


namespace App\Console\Commands;

use Illuminate\Console\Command;
use Illuminate\Support\Facades\Log;

class LogCommand extends Command
{
    /**
     * The name and signature of the console command.
     *
     * @var string
     */
    protected $signature = 'command:log {action} {--option=}';

    /**
     * The console command description.
     *
     * @var string
     */
    protected $description = 'Command description';

    /**
     * Create a new command instance.
     *
     * @return void
     */
    public function __construct()
    {
        parent::__construct();
    }

    /**
     * Execute the console command.
     *
     * @return int
     */
    public function handle()
    {
        Log::channel('cli')->info('start', $_SERVER['argv']); // ここでcliのチャンネルを使用してコール

        return 0;
    }
}

上のコマンドを実行すると、cli-command:log-2021-04.logの中身は、以下のようになります。
info()の2番目の引数には配列を渡すことが可能です。ここではコマンドラインの引数を記録します。

$ php artisan command:log run --option=x
$ cat storage/logs/cli-command:log-2021-04.log
[2021-04-24 23:45:46] local.INFO: start ["artisan","command:log","run","--option=x"]

By khino