CloudWatchLogs InsigthsでALBのログを見やすくする
自分の苦悩解消用にALBのアクセスログを見やすい形で表示できるようにクエリを作ってみた。
ターゲット:CloudWatchLogs InsigthsでApplication Load Balancer(ALB)のログが見づらいと思っている人
- ログが一行で表示されるから調べたいIPアドレスがぱっとわからなかったり、いろんな数字並んでるからパッと見た瞬間に、どれ見ればいいんだよ!と嘆くことが多い
- 1レコードごとに長大な1行で結果を返してくるから障害発生してログを調査する際には発狂したくなる。
という人は試してみて。
ALBのアクセスログに合わせたクエリ
フィールドを分割したクエリ
まずは、丁寧にALBのフィールドごとに項目を分割して表示するようにクエリでログを区切る。
parse @message /^(?<type>[^ ]*) (?<time>[^ ]*) (?<elb>[^ ]*) (?<client:port>[^ ]*) (?<target:port>[^ ]*) (?<request_processing_time>[^ ]*) (?<target_processing_time>[^ ]*) (?<response_processing_time>[^ ]*) (?<elb_status_code>[^ ]*) (?<target_status_code>[^ ]*) (?<received_bytes>[^ ]*) (?<sent_bytes>[^ ]*) "(?<request>[^"]*)" "(?<user_agent>[^"]*)" (?<ssl_cipher>[^ ]*) (?<ssl_protocol>[^ ]*) (?<target_group_arn>[^ ]*) "(?<trace_id>[^"]*)" "(?<domain_name>[^"]*)" "(?<chosen_cert_arn>[^"]*)" (?<matched_rule_priority>[^ ]*) (?<request_creation_time>[^ ]*) "(?<actions_executed>[^"]*)" "(?<redirect_url>[^"]*)" "(?<error_reason>[^"]*)" "(?<target:port_list>[^"]*)" "(?<target_status_code_list>[^"]*)" "(?<classification>[^"]*)" "(?<classification_reason>[^"]*)"(?<new_field>.*)$/
| fields @timestamp, @message
- parse(1行目)の最後にnew_fieldを宣言しているのは、ログの仕様変更で何か追加された時のために一応書いている。
- parseで宣言しているキーは、ALBのアクセスログに書かれているフィールドに合わせている。
ALBのアクセスログの各フィールドについては 公式をのドキュメント を参照
ただ、そのまま結果を取得しても、このparse文のように右端が切れてしまい、ほしいデータにすぐたどり着けないことがある。(自分の場合、上のクエリだけでは今のところ100%たどり着けていない)
見たいフィールドだけを表示するようにする
以下の一行をクエリに追加してあげる。
| display @timestamp, elb_status_code, request, error_reason
displayで表示したいフィールドを制限すれば画面を横スクロールすることなく目的の情報を確認できる。(上の例では、@timestamp, elb_status_code, request, error_reasonだが、好きなフィールドを指定)
自分がログを確認する時は、障害発生時の調査が多いので以下のフィルタも追加したりする。
| filter elb_status_code != 200
HttpStatusが200以外を検索する。
上だと400系のエラーも含むため、 >=500
とすることもある。
全部つなげると以下(ついでにレコードの表示順も時間でソートしたりして)
これで調査がだいぶ楽になった。
parse @message /^(?<type>[^ ]*) (?<time>[^ ]*) (?<elb>[^ ]*) (?<client:port>[^ ]*) (?<target:port>[^ ]*) (?<request_processing_time>[^ ]*) (?<target_processing_time>[^ ]*) (?<response_processing_time>[^ ]*) (?<elb_status_code>[^ ]*) (?<target_status_code>[^ ]*) (?<received_bytes>[^ ]*) (?<sent_bytes>[^ ]*) "(?<request>[^"]*)" "(?<user_agent>[^"]*)" (?<ssl_cipher>[^ ]*) (?<ssl_protocol>[^ ]*) (?<target_group_arn>[^ ]*) "(?<trace_id>[^"]*)" "(?<domain_name>[^"]*)" "(?<chosen_cert_arn>[^"]*)" (?<matched_rule_priority>[^ ]*) (?<request_creation_time>[^ ]*) "(?<actions_executed>[^"]*)" "(?<redirect_url>[^"]*)" "(?<error_reason>[^"]*)" "(?<target:port_list>[^"]*)" "(?<target_status_code_list>[^"]*)" "(?<classification>[^"]*)" "(?<classification_reason>[^"]*)"(?<new_field>.*)$/
| fields @timestamp, @message
| display @timestamp, elb_status_code, request, error_reason
| filter elb_status_code != 200
| sort @timestamp desc
(おまけ)
AWS管理コンソールでは自作のクエリ定義を保存できる。
毎回ブログを探したり、ローカルでテキストとして保存したものをコピペすることなく利用できるので便利だから、保存してもいいかもしれない。
保存したい人は、管理コンソール上のCloudWatchでInsightsの画面を開くと右のほうにQueryというリンクがあるのでそこから以下の項目を書いて保存
- クエリの名称(区別がつくようになにか名称を保存)
- 対象のロググループ(複数選択可)
- クエリ
ただし、クエリ定義を表示・編集するには以下の権限が必要
logs:DescribeQueryDefinitions
logs:PutQueryDefinition
logs:DeleteQueryDefinition
Discussion