CloudWatch Logs Insights 使い方と注意点(Go)
高速でインタラクティブなログ分析!!!!
新機能 – Amazon CloudWatch Logs Insights – 高速でインタラクティブなログ分析 | Amazon Web Services ブログ
仕事で導入する機会があり、その時の使用感とハマりポイントをまとめてみました。
ユースケース
ログがレコード数6,500,000/1時間くらいあるものから、特定の文字列にヒットするものを取得したい。フルスキャンしなくていいので、1日の中から10件の対象ログを探したい。
使用感や注意点
※利用したログでの使用感です
- 日付の範囲を1日とかにすると、そこまで早くない(検索完了まで3分〜4分はかかった)
- 従来のログ検索だと、5分のレンジで検索しても、15分以上かかっていたけど、Insightsなら、10秒程度で検索が完了した
- リアルタイムに何か検知するのは無理。インデックスを作成しているか何かで、3分くらい経たないと検索結果に出てこなかった(インデックスが済むと速い)
- リアルタイムに検知したいなら、サブスクリプションフィルタのが優れている
- 検索結果が返ってくるまでの状態管理に、少しコツが必要だった(コードで説明する)
- limitがクエリにも、APIのインターフェイスにも用意されてるけど、使い分けが分からない
- フルスキャンして、高速検索はBigQueryでやろう
Goでの実装例
今回は、Golangで実装した例です。動作などは、godocを見れば、大体雰囲気わかります。
cloudwatchlogs - GoDoc
全体の流れ
StartQueryInput
でクエリを作成するStartQuery
にStartQueryInput
に渡し、queryId
を受け取る(この時、既にクエリが実行開始している)GetQueryResults
を実行して、実行中のクエリの結果を受け取る- 実行中のクエリのステータスを見て、結果を返すか決める(あとで、取り上げる)
- 結果を返す
4. 実行中のクエリのステータスを見て、結果を返すか決める
func getQueryResultsUntilCompleate(cwl *cloudwatchlogs.CloudWatchLogs, queryId string, limit int) (*cloudwatchlogs.GetQueryResultsOutput, error) { getQueryResultInput := &cloudwatchlogs.GetQueryResultsInput{} getQueryResultInput.SetQueryId(queryId) for { getQueryResultOutput, err := cwl.GetQueryResults(getQueryResultInput) if err != nil { return nil, err } time.Sleep(5 * time.Second) switch *getQueryResultOutput.Status { case "Running": if len(getQueryResultOutput.Results) < limit { continue } stopQueryInput := &cloudwatchlogs.StopQueryInput{} stopQueryInput.SetQueryId(queryId) stopResult, err := cwl.StopQuery(stopQueryInput) if err != nil { return nil, fmt.Errorf("stop query error=%s status=%v", err.Error(), stopResult) } return getQueryResultOutput, nil case "Scheduled": continue case "Failed": return nil, errors.New("job failed") case "Cancelled": return nil, errors.New("job cancelled") case "Complete": return getQueryResultOutput, nil default: return nil, fmt.Errorf("unknown status: %s", *getQueryResultOutput.Status) } } }
なぜ、forループで待ち続けているのか
StartQuery
を実行すると、クエリが走り始めます。そして、GetQueryResults
でクエリの状態を取得します。この時点では、完了していないことがほとんどです。そのため、time.Sleep(5 * time.Second)
などして、少し時間を置いてから再度取得しています。
ログの量にもよりますが、何周かすると、終了し、Completeに入ります。ステータスの種類はドキュメントに書いてあります。
GetQueryResults - Amazon CloudWatch Logs
Runningで途中でreturnしているのは?
途中でlimit来たら返しているかというと、全部見なくて良いので、あった結果をとりあえず、早く返してほしかった。
- 1日くらいのレンジで見ていたので、全部見るの待つと、とても時間がかかる
- limit 10と設定していても、10件あったらCompleteではなく、全部の結果を受け取った上で、ソートし直すなどをしてるっぽく、指定範囲をフルスキャンになり、時間がかかってしまう