多くのPHP製のフレームワークではMonologが標準のLoggerとして採用されています。Laravelでも例にもれず、LoggerとしてMonologが採用されています。
Monologについてはこちらの記事が参考になります。
https://qiita.com/iakio/items/7b8539db928d2b419921
上の記事にもありますが、MonologではProcessorを用いることでログのextraフィールドに情報を付与することができます。Monologのリポジトリには、標準でこれだけのProcessorがあります。
https://github.com/Seldaek/monolog/tree/main/src/Monolog/Processor
この中にある、WebProcessor
を使うと、サーバーのアドレス、アクセスされたパス、メソッド、リファラー、クライアントのIPなどの情報を付与することができます。
こんな感じです。
$handler = new StreamHandler('php://stderr');
$webProcessor = new WebProcessor();
$logger = new Logger( 'app', [$handler], [$webProcessor]);
$logger->info('hoge');
[2021-03-24T11:58:43.973074+00:00] app.INFO: hoge [] {"url":"/","ip":"172.25.0.1","http_method":"GET","server":"0.0.0.0","referrer":null}
さて、こちらはローカル環境では正しく動きますが、AWSなどにデプロイし、ALBの配下で動かすと、クライアントのIPアドレスがALBのIPアドレスになってしまいます。
AWSのドキュメントを見ると、元々のクライアントIPはX-Forwarded-For
というヘッダーに格納されているようです。
https://aws.amazon.com/jp/premiumsupport/knowledge-center/elb-capture-client-ip-addresses/
また、PHPでは全てのヘッダーは$_SERVER
というグローバル変数へ格納されます。
https://www.php.net/manual/ja/reserved.variables.server.php#89567
このとき、添字は以下のように変換します。
HTTP_
のプレフィックスを付ける- ハイフンはアンダースコアに変換
- すべて大文字に変換
つまり、X-Forwarded-Forを取得するには、このようにします。
$myHeader = $_SERVER['HTTP_X_FORWARDED_FOR'];
クライアントのIPは取得できました。ではどうやってWebProcessorにIPの場所を教えれば良いのでしょうか。
答えはこうです。
$webProcessor = new WebProcessor();
$webProcessor->addExtraField('ip', 'HTTP_X_FORWARDED_FOR');
実装を見ればわかるのですが、WebProcessorは$_SERVER
から各種情報を抜き出してextraフィールドにセットしています。
上のようにaddExtraField()
メソッドを呼び出すことで、「ipの値は$_SERVERのHTTP_X_FORWARDED_FORキーから取得してね」というように伝えることができるのです。
これでALB配下でLaravelを動かした時も、クライアントのIPをログに出力することができます。