LoginSignup
10
11

More than 3 years have passed since last update.

LaravelでCloudWatchへログ送信

Posted at

はじめに

LaravelのログをCloudWatchへ送信する方法は、CloudWatchエージェントを使う方法やaws firelensを使う方法などがあります。しかし、これらの方法はAWSのリソースを作らなくてはならず、設定などが少し手間です。
今回はLaravelのソース(とIAM Userの発行)だけで完結する方法を紹介します。

方法

まずは、ライブラリのインストールを行います。使用するライブラリはこちらです。
https://github.com/maxbanton/cwh

$ composer require maxbanton/cwh

インストールしたライブラリに含まれるLogハンドラーをコンテナに登録します。ポイントはCredentialProvider::defaultProvider()としているところで、このようにすることで、ローカル環境でも本番環境でもよしなに認証情報を取得してくれます。

app/Providers/AppServiceProvider.php
<?php

namespace App\Providers;

use Aws\CloudWatchLogs\CloudWatchLogsClient;
use Aws\Credentials\CredentialProvider;
use Illuminate\Support\ServiceProvider;
use Maxbanton\Cwh\Handler\CloudWatch;

class AppServiceProvider extends ServiceProvider
{
    /**
     * Register any application services.
     *
     * @return void
     */
    public function register()
    {
        $this->app->bind(CloudWatchLogsClient::class, function ($app) {
            return new CloudWatchLogsClient([
                'region' => config('aws.default_region'),
                'version' => 'latest',
                'credentials' => CredentialProvider::defaultProvider(),
            ]);
        });

        $this->app->bind(CloudWatch::class, function ($app) {
            return new CloudWatch(
                $app->make(CloudWatchLogsClient::class),
                config('aws.cloudwatch.log.group_name'),
                config('aws.cloudwatch.log.stream_name'),
                config('aws.cloudwatch.log.retention'),
                10000
            );
        });
    }

    /**
     * Bootstrap any application services.
     *
     * @return void
     */
    public function boot()
    {
        //
    }
}

続いて、configファイルの設定を行います。config/aws.phpというファイルを作り、環境変数から読み取った値をセットします。

config/aws.php
<?php

return [
    'cloudwatch' => [
        'log' => [
            'group_name' => env('AWS_CLOUDWATCH_LOG_GROUP_NAME'),
            'stream_name' => env('AWS_CLOUDWATCH_LOG_STREAM_NAME'),
            'retention' => env('AWS_CLOUDWATCH_LOG_RETENTION'),
        ]
    ],
    'default_region' => env('AWS_DEFAULT_REGION'),
];

そして、config/logging.phpにCloudWatchへログを送信するためのチャネルを追加します。handlerには先ほどコンテナへ登録したハンドラのクラスを設定します。json形式でログを出力したい場合はformatterのコメントを解除してください。

config/logging.php
....
        'emergency' => [
            'path' => storage_path('logs/laravel.log'),
        ],

        'cloudwatch' => [
            'driver' => 'monolog',
            'handler' => Maxbanton\Cwh\Handler\CloudWatch::class,
            // 'formatter' => Monolog\Formatter\JsonFormatter::class, json形式でログを送信する時はコメント解除する
        ],
    ],
];

最後に、.envファイルへ環境変数の登録をします。
LOG_CHANNELには先ほどconfig/logging.phpに追加したログチャネルの名前を設定します。
あとは、AWSの認証情報とロググループ、ログストリーム、ログの保存期間などの設定値を入れます。この時登録するIAM USERには対象のロググループとログストリームへのアクセス権が必要なので注意してください!

.env
...
LOG_CHANNEL=cloudwatch
...
AWS_ACCESS_KEY_ID=XXXX
AWS_SECRET_ACCESS_KEY=XXXX
AWS_DEFAULT_REGION=ap-northeast-1
AWS_CLOUDWATCH_LOG_GROUP_NAME=laravel_cloudwatch_group
AWS_CLOUDWATCH_LOG_STREAM_NAME=laravel_cloudwatch_stream
AWS_CLOUDWATCH_LOG_RETENTION=1

実行

routes/web.phpにログの出力を仕込んでアクセスします。

routes/web.php
...
Route::get('/', function () {
    \Illuminate\Support\Facades\Log::info('ok');
    return view('welcome');
});

AWSコンソールからCloudWatchログを確認すると、ログが飛んできてるのがわかると思います。

スクリーンショット 2021-03-04 21.25.06.png

最後に

今回の方法は、ログのフォーマット変換から送信まで全てPHPのレイヤーで行っています。お手軽な一方で、PHPの処理には負担がかかっていることが想定できます。大量のログを飛ばすような場合は、やはり一度標準出力に出してからCloudWatchエージェントなりaws firelensなりでCloudWatchへ飛ばすのが良いのかなと思います。
実際に計測したわけじゃないので、どれくらい負荷がかかっているのかは分かりませんが。。。

10
11
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
10
11