Ric*_*urt 14 amazon-web-services amazon-cloudwatch aws-cloudwatch-log-insights
我想将我的用户直接发送到特定的日志组和过滤器,但我需要能够生成正确的 URL 格式。例如,这个网址
https://console.aws.amazon.com/cloudwatch/home?region=us-east-1#logsV2:log-groups/log-group/
%252Fmy%252Flog%252Fgroup%252Fgoes%252Fhere/log-events/$3FfilterPattern$3D$255Bincoming_ip$252C$2Buser_name$252C$2Buser_ip$2B$252C$2Btimestamp$252C$2Brequest$2B$2521$253D$2B$2522GET$2B$252Fhealth_checks$252Fall$2B*$2522$252C$2Bstatus_code$2B$253D$2B5*$2B$257C$257C$2Bstatus_code$2B$253D$2B429$252C$2Bbytes$252C$2Burl$252C$2Buser_agent$255D$26start$3D-172800000
Run Code Online (Sandbox Code Playgroud)
将带您到一个名为的日志组,/my/log/group/goes/here并使用此模式过滤过去 2 天的消息:
[incoming_ip, user_name, user_ip , timestamp, request != "GET /health_checks/all *", status_code = 5* || status_code = 429, bytes, url, user_agent]
Run Code Online (Sandbox Code Playgroud)
我可以解码 URL 的一部分,但我不知道其他一些字符应该是什么(见下文),但这对我来说看起来并不像任何标准的 HTML 编码。有人知道这种 URL 格式的编码器/解码器吗?
%252F == /
$252C == ,
$255B == [
$255D == ]
$253D == =
$2521 == !
$2522 == "
$252F == _
$257C == |
$2B == +
$26 == &
$3D == =
$3F == ?
Run Code Online (Sandbox Code Playgroud)
小智 18
首先我要感谢其他人提供的线索。进一步完整解释了如何构建 Log Insights 链接。
总的来说,它只是一个对象结构的奇怪编码结合,其工作原理如下:
之后的部分?queryDetail=是对象表示,并{}表示为~()
对象被遍历到原始值,后者被转换如下:
encodeURIComponent(value)以便所有特殊字符都转换为%xxreplace(/%/g, "*")这样这个编码就不会受到顶级编码的影响string- 它以不匹配的单引号作为前缀为了显示:
"Hello world" -> "Hello%20world" -> "Hello*20world" -> "'Hello*20world"
Run Code Online (Sandbox Code Playgroud)
转换后的基元数组使用~并放入~()构造内部
然后,在完成基元转换后 - 使用“~”连接对象。
该字符串之后是escape()d (请注意,encodeURIComponent()调用 not 是因为它在 JS 中不进行转换~)。
之后?queryDetail=添加。
最后,这个字符串被我们encodeURIComponent()ed 和作为顶部的樱桃 -%替换为$。
让我们看看它在实践中是如何运作的。假设这些是我们的查询参数:
"Hello world" -> "Hello%20world" -> "Hello*20world" -> "'Hello*20world"
Run Code Online (Sandbox Code Playgroud)
首先对原语进行变换:
const expression = `fields @timestamp, @message
| filter @message not like 'example'
| sort @timestamp asc
| limit 100`;
const logGroups = ["/application/sample1", "/application/sample2"];
const queryParameters = {
end: 0,
start: -3600,
timeType: "RELATIVE",
unit: "seconds",
editorString: expression,
isLiveTrail: false,
source: logGroups,
};
Run Code Online (Sandbox Code Playgroud)
然后,使用连接对象~,因此我们有对象表示字符串:
const expression = "'fields*20*40timestamp*2C*20*40message*0A*20*20*20*20*7C*20filter*20*40message*20not*20like*20'example'*0A*20*20*20*20*7C*20sort*20*40timestamp*20asc*0A*20*20*20*20*7C*20limit*20100";
const logGroups = ["'*2Fapplication*2Fsample1", "'*2Fapplication*2Fsample2"];
const queryParameters = {
end: 0,
start: -3600,
timeType: "'RELATIVE",
unit: "'seconds",
editorString: expression,
isLiveTrail: false,
source: logGroups,
};
Run Code Online (Sandbox Code Playgroud)
现在我们escape():
const objectString = "~(end~0~start~-3600~timeType~'RELATIVE~unit~'seconds~editorString~'fields*20*40timestamp*2C*20*40message*0A*20*20*20*20*7C*20filter*20*40message*20not*20like*20'example'*0A*20*20*20*20*7C*20sort*20*40timestamp*20asc*0A*20*20*20*20*7C*20limit*20100~isLiveTrail~false~source~(~'*2Fapplication*2Fsample1~'*2Fapplication*2Fsample2))"
Run Code Online (Sandbox Code Playgroud)
现在我们添加?queryDetail=前缀:
const escapedObject = "%7E%28end%7E0%7Estart%7E-3600%7EtimeType%7E%27RELATIVE%7Eunit%7E%27seconds%7EeditorString%7E%27fields*20*40timestamp*2C*20*40message*0A*20*20*20*20*7C*20filter*20*40message*20not*20like*20%27example%27*0A*20*20*20*20*7C*20sort*20*40timestamp*20asc*0A*20*20*20*20*7C*20limit*20100%7EisLiveTrail%7Efalse%7Esource%7E%28%7E%27*2Fapplication*2Fsample1%7E%27*2Fapplication*2Fsample2%29%29"
Run Code Online (Sandbox Code Playgroud)
最后我们对其进行 URL 编码并替换%为$vois la:
const withQueryDetail = "?queryDetail=%7E%28end%7E0%7Estart%7E-3600%7EtimeType%7E%27RELATIVE%7Eunit%7E%27seconds%7EeditorString%7E%27fields*20*40timestamp*2C*20*40message*0A*20*20*20*20*7C*20filter*20*40message*20not*20like*20%27example%27*0A*20*20*20*20*7C*20sort*20*40timestamp*20asc*0A*20*20*20*20*7C*20limit*20100%7EisLiveTrail%7Efalse%7Esource%7E%28%7E%27*2Fapplication*2Fsample1%7E%27*2Fapplication*2Fsample2%29%29"
Run Code Online (Sandbox Code Playgroud)
把它们放在一起:
const result = "$3FqueryDetail$3D$257E$2528end$257E0$257Estart$257E-3600$257EtimeType$257E$2527RELATIVE$257Eunit$257E$2527seconds$257EeditorString$257E$2527fields*20*40timestamp*2C*20*40message*0A*20*20*20*20*7C*20filter*20*40message*20not*20like*20$2527example$2527*0A*20*20*20*20*7C*20sort*20*40timestamp*20asc*0A*20*20*20*20*7C*20limit*20100$257EisLiveTrail$257Efalse$257Esource$257E$2528$257E$2527*2Fapplication*2Fsample1$257E$2527*2Fapplication*2Fsample2$2529$2529"
Run Code Online (Sandbox Code Playgroud)
当然也可以进行反向操作。
这就是大家。玩得开心,小心,尽量避免自己做这种奇怪的事情。:)
我不得不做类似的事情来生成一个指向 lambda 日志的反向链接,并做了以下骇人听闻的事情来创建链接:
const link = `https://${process.env.AWS_REGION}.console.aws.amazon.com/cloudwatch/home?region=${process.env.AWS_REGION}#logsV2:log-groups/log-group/${process.env.AWS_LAMBDA_LOG_GROUP_NAME.replace(/\//g, '$252F')}/log-events/${process.env.AWS_LAMBDA_LOG_STREAM_NAME.replace('$', '$2524').replace('[', '$255B').replace(']', '$255D').replace(/\//g, '$252F')}`
Run Code Online (Sandbox Code Playgroud)
我的一位同事发现编码没有什么特别之处。它是标准的 URI百分比编码,但应用了两次 (2x)。在 javascript 中,您可以使用该encodeURIComponent函数进行测试:
let inp = 'https://console.aws.amazon.com/cloudwatch/home?region=us-east-1#logsV2:log-groups/log-group/'
console.log(encodeURIComponent(inp))
console.log(encodeURIComponent(encodeURIComponent(inp)))
Run Code Online (Sandbox Code Playgroud)
这段 javascript 在第二个编码阶段产生预期的输出:
https%3A%2F%2Fconsole.aws.amazon.com%2Fcloudwatch%2Fhome%3Fregion%3Dus-east-1%23logsV2%3Alog-groups%2Flog-group%2F
https%253A%252F%252Fconsole.aws.amazon.com%252Fcloudwatch%252Fhome%253Fregion%253Dus-east-1%2523logsV2%253Alog-groups%252Flog-group%252F
Run Code Online (Sandbox Code Playgroud)
至少有些位使用双重编码,但不是整个链接。否则所有特殊字符在双重编码后都会占用4个字符,但有些仍然只占用2个字符。无论如何,希望这会有所帮助;)
我创建了一些 Ruby 代码,似乎可以满足 CloudWatch URL 解析器的要求。我不知道为什么你必须双重转义一些东西,然后%用$其他东西替换。我猜这背后有一些原因,但我找不到一个好的方法来做到这一点,所以我只是暴力地强迫它。如果您有更好的东西,或者知道他们为什么这样做,请添加评论。
注意:filter我测试的有点基本,我不确定如果你真的喜欢它,可能需要改变什么。
# Basic URL that is the same across all requests
url = 'https://console.aws.amazon.com/cloudwatch/home?region=us-east-1#logsV2:log-groups/log-group/'
# CloudWatch log group
log_group = '/aws/my/log/group'
# Either specify the instance you want to search or leave it out to search all instances
instance = '/log-events/i-xxxxxxxxxxxx'
OR
instance = '/log-events'
# The filter to apply.
filter = '[incoming_ip, user_name, user_ip , timestamp, request, status_code = 5*, bytes, url, user_agent]'
# Start time. There might be an End time as well but my queries haven't used
# that yet so I'm not sure how it's formatted. It should be pretty similar
# though.
hours = 48
start = "&start=-#{hours*60*60*1000}"
# This will get you the final URL
final = url + CGI.escape(CGI.escape(log_group)) + instance + '$3FfilterPattern$3D' + CGI.escape(CGI.escape(filter)).gsub('%','$') + CGI.escape(start).gsub('%','$')
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
2338 次 |
| 最近记录: |