はじめに
CloudWatch Logs Insightsのコンソールでログを検索すると、その内容がURLに反映されます。例えば次のようなURLです。
https://ap-northeast-1.console.aws.amazon.com/cloudwatch/home?region=ap-northeast-1#logsV2:logs-insights$3FqueryDetail$3D$257E$2528end$257E0$257Estart$257E-3600$257EtimeType$257E$2527RELATIVE$257Eunit$257E$2527seconds$257EeditorString$257E$2527fields$252A20$252A40timestamp$252A2C$252A20$252A40message$252A20$252A7C$252A20limit$252A2020$257Esource$257E$2528$257E$2527log_group_1$257E$2527log_group_2$2529$2529
このURLを動的に生成したかったのですが、URLの生成ルールが複雑だったため、解析しました。
具体例
例として、log_group_1
とlog_group_2
というlog groupに対してfields @timestamp, @message | limit 20
というクエリを実行する場合を考えます。対象のログの期間は現在から1時間前までとします。
URLは複数のステップを経て生成されます。
STEP1
まず、ログを絞り込むための内容をCloudWatch Logs Insightsのkey-valueの形式に対応させます。上の例だと次のようになります。
end: 0
start: -3600
timeType: "RELATIVE"
unit: "seconds"
editorString: "fields @timestamp, @message | limit 20"
source: ["log_group_1", "log_group_2"]
次の点に注意が必要です。
- 原則velueは文字列型になる
-
end
とstart
は数値型として扱われる - 対象のロググループ
source
は配列として扱われる(ロググループは複数指定できるため)
STEP2
次に、各valueを次の規則に従って変換します。
文字列
URLエンコードした後、%
を*
に置換し、最後に先頭に'
を付けます。
例えば
fields @timestamp, @message | limit 20
の場合、URLエンコードすると
fields%20%40timestamp%2C%20%40message%20%7C%20limit%2020
になります。%
を*
に置換すると
fields*20*40timestamp*2C*20*40message*20*7C*20limit*2020
になります。最後に先頭に'
を付けると
'fields*20*40timestamp*2C*20*40message*20*7C*20limit*2020
となります。
数値
数値型の場合は特に変換はせず、そのままにします。
配列
配列の場合は少し面倒です。ロググループ名["log_group_1", "log_group_2"]
の例で考えます。
まず、配列の各要素を、その要素ごとの規則に従って変換します。
今回の例では各要素は文字列なので、文字列の規則で変換します。特殊文字を含まないので先頭に'
が付くだけです。
['log_group_1, 'log_group_2]
各要素ごとの規則に従って変換したら、次に各要素の先頭に~
を付けます。
[~'log_group_1, ~'log_group_2]
次に、全ての要素を繋げて一つの文字列にします。
~'log_group_1~'log_group_2
最後に、()
で囲めば完了です。
(~'log_group_1~'log_group_2)
以上の変換を行うと、例の各valueは次のようになります。
end: 0
start: -3600
timeType: 'RELATIVE
unit: 'seconds
editorString: 'fields*20*40timestamp*2C*20*40message*20*7C*20limit*2020
source: (~'log_group_1~'log_group_2)
STEP3
各パラメータの変換ができたら、それらを結合します。
まず、各key-valueをkey~value
の形にします。
end~0
start~-3600
timeType~'RELATIVE
unit~'seconds
editorString~'fields*20*40timestamp*2C*20*40message*20*7C*20limit*2020
source~(~'log_group_1~'log_group_2)
次にそれらを~
で連結し、一つの文字列にします。
end~0~start~-3600~timeType~'RELATIVE~unit~'seconds~editorString~'fields*20*40timestamp*2C*20*40message*20*7C*20limit*2020~source~(~'log_group_1~'log_group_2)
そうしたら全体を()
で囲い、その後さらに先頭に~
を付けます。
~(end~0~start~-3600~timeType~'RELATIVE~unit~'seconds~editorString~'fields*20*40timestamp*2C*20*40message*20*7C*20limit*2020~source~(~'log_group_1~'log_group_2))
STEP4
パラメータを一つに結合したら、最後にURLの形に整形します。
まず、全体をURLエンコードします。
%7E%28end%7E0%7Estart%7E-3600%7EtimeType%7E%27RELATIVE%7Eunit%7E%27seconds%7EeditorString%7E%27fields%2A20%2A40timestamp%2A2C%2A20%2A40message%2A20%2A7C%2A20limit%2A2020%7Esource%7E%28%7E%27log_group_1%7E%27log_group_2%29%29
次に、先頭に?queryDetail=
を付けます。
?queryDetail=%7E%28end%7E0%7Estart%7E-3600%7EtimeType%7E%27RELATIVE%7Eunit%7E%27seconds%7EeditorString%7E%27fields%2A20%2A40timestamp%2A2C%2A20%2A40message%2A20%2A7C%2A20limit%2A2020%7Esource%7E%28%7E%27log_group_1%7E%27log_group_2%29%29
もう一度全体をURLエンコードします。
%3FqueryDetail%3D%257E%2528end%257E0%257Estart%257E-3600%257EtimeType%257E%2527RELATIVE%257Eunit%257E%2527seconds%257EeditorString%257E%2527fields%252A20%252A40timestamp%252A2C%252A20%252A40message%252A20%252A7C%252A20limit%252A2020%257Esource%257E%2528%257E%2527log_group_1%257E%2527log_group_2%2529%2529
%
を$
に置換します。
$3FqueryDetail$3D$257E$2528end$257E0$257Estart$257E-3600$257EtimeType$257E$2527RELATIVE$257Eunit$257E$2527seconds$257EeditorString$257E$2527fields$252A20$252A40timestamp$252A2C$252A20$252A40message$252A20$252A7C$252A20limit$252A2020$257Esource$257E$2528$257E$2527log_group_1$257E$2527log_group_2$2529$2529
最後に先頭にhttps://{REGION}.console.aws.amazon.com/cloudwatch/home?region={REGION}#logsV2:logs-insights
を付ければ完成です。REGIONにはAWSのリージョンが入ります。
https://ap-northeast-1.console.aws.amazon.com/cloudwatch/home?region=ap-northeast-1#logsV2:logs-insights$3FqueryDetail$3D$257E$2528end$257E0$257Estart$257E-3600$257EtimeType$257E$2527RELATIVE$257Eunit$257E$2527seconds$257EeditorString$257E$2527fields$252A20$252A40timestamp$252A2C$252A20$252A40message$252A20$252A7C$252A20limit$252A2020$257Esource$257E$2528$257E$2527log_group_1$257E$2527log_group_2$2529$2529
補足
上の例では相対時刻でログの範囲を絞っていますが、絶対時刻で指定する場合は次のようになります。
end: "2022-04-01T00:00:00.000Z"
start: "2022-04-30T23:59:59.000Z"
timeType: "ABSOLUTE"
unit: "seconds"
editorString: "fields @timestamp, @message | limit 20"
source: ["log_group_1", "log_group_2"]
絶対時刻の場合はend
とstart
が文字列型になることに注意してください。
おわりに
以上の手順で、CloudWatch Logs InsightsのURLを生成することができます。
もちろん逆の手順を踏めばURLから各パラメータを得ることも可能です。
エンコードとデコードの例をPythonで作成したので、サンプルコードをGistに上げておきます。
https://gist.github.com/sin9270/9f529d8b96eff1da23caabc374dc7a05