はじめに
LaravelのログをCloudWatchへ送信する方法は、CloudWatchエージェントを使う方法やaws firelensを使う方法などがあります。しかし、これらの方法はAWSのリソースを作らなくてはならず、設定などが少し手間です。
今回はLaravelのソース(とIAM Userの発行)だけで完結する方法を紹介します。
方法
まずは、ライブラリのインストールを行います。使用するライブラリはこちらです。
https://github.com/maxbanton/cwh
$ composer require maxbanton/cwh
インストールしたライブラリに含まれるLogハンドラーをコンテナに登録します。ポイントはCredentialProvider::defaultProvider()
としているところで、このようにすることで、ローカル環境でも本番環境でもよしなに認証情報を取得してくれます。
<?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
というファイルを作り、環境変数から読み取った値をセットします。
<?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のコメントを解除してください。
....
'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には対象のロググループとログストリームへのアクセス権が必要なので注意してください!
...
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
にログの出力を仕込んでアクセスします。
...
Route::get('/', function () {
\Illuminate\Support\Facades\Log::info('ok');
return view('welcome');
});
AWSコンソールからCloudWatchログを確認すると、ログが飛んできてるのがわかると思います。
最後に
今回の方法は、ログのフォーマット変換から送信まで全てPHPのレイヤーで行っています。お手軽な一方で、PHPの処理には負担がかかっていることが想定できます。大量のログを飛ばすような場合は、やはり一度標準出力に出してからCloudWatchエージェントなりaws firelensなりでCloudWatchへ飛ばすのが良いのかなと思います。
実際に計測したわけじゃないので、どれくらい負荷がかかっているのかは分かりませんが。。。