Amazon web services 有没有办法为CloudWatch日志组筛选器生成AWS控制台URL?

Amazon web services 有没有办法为CloudWatch日志组筛选器生成AWS控制台URL?,amazon-web-services,amazon-cloudwatch,aws-cloudwatch-log-insights,Amazon Web Services,Amazon Cloudwatch,Aws Cloudwatch Log Insights,我想把我的用户直接发送到一个特定的日志组和过滤器,但我需要能够生成正确的URL格式。例如,这个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_nam

我想把我的用户直接发送到一个特定的日志组和过滤器,但我需要能够生成正确的URL格式。例如,这个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
将带您进入名为
/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]
我可以解码URL的一部分,但我不知道其他字符应该是什么(见下文),但我觉得这与任何标准的HTML编码都不一样。有人知道这种URL格式的编码器/解码器吗

%252F == /
$252C == ,
$255B == [
$255D == ]
$253D == =
$2521 == !
$2522 == "
$252F == _
$257C == |

$2B == +
$26 == &
$3D == =
$3F == ?

我已经创建了一些Ruby代码,似乎满足CloudWatch URL解析器的要求。我不知道为什么有些东西必须双重转义,而另一些东西必须用
$
替换
%
。我猜这背后有一些原因,但我想不出一个好的方法来做,所以我只是野蛮地强迫它。如果你有更好的,或者知道他们为什么这样做,请添加评论

注意:我测试的
过滤器
有点基本,如果你真的喜欢它,我不确定需要修改什么

#在所有请求中都相同的基本URL
url='1〕https://console.aws.amazon.com/cloudwatch/home?region=us-east-1#logsV2:日志组/日志组/'
#CloudWatch日志组
log_group='/aws/my/log/group'
#指定要搜索的实例,或将其保留以搜索所有实例
实例='/log events/i-xxxxxxxxxx'
或
实例=“/log事件”
#要应用的筛选器。
筛选器=“[传入的\u ip、用户名、用户\u ip、时间戳、请求、状态\u代码=5*、字节、url、用户\u代理]”
#开始时间。可能还有一个结束时间,但我的查询没有使用
#但我不确定它是如何格式化的。应该很相似
#不过。
小时=48
start=“&start=-#{hours*60*60*1000}”
#这将获得最终的URL
final=url+CGI.escape(CGI.escape(log_group))+instance+'$3FfilterPattern$3D'+CGI.escape(CGI.escape(filter)).gsub('%,'$)+CGI.escape(start).gsub('%,'$'))

我必须做一件类似的事情来为lambda生成一个指向日志的反向链接,并做了以下骇人的事情来创建链接:

const link=`https://${process.env.AWS_REGION}.console.AWS.amazon.com/cloudwatch/home?REGION=${process.env.AWS_REGION}logsV2:log groups/log groups/${process.env.AWS_LAMBDA_log_group_NAME.replace(//\//\///g,$252F')}/log events/${process env.AWS.AWS_da_log_logā流名.replace('$$),$4'),$255D'),$replace($25d'))(//\//g,$252F')}`

我的一位同事发现编码没有什么特别之处。它是标准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)))
这段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
小心
至少有些位使用双重编码,而不是整个链接。否则,所有特殊字符在双重编码后将占用4个字符,但有些字符仍然只占用2个字符。希望这能有所帮助;)

我基于@isaias-b answer的完整Javascript解决方案,它还在日志上添加了时间戳过滤器:

const logBaseUrl='1〕https://console.aws.amazon.com/cloudwatch/home?region=us-east-1#logsV2:日志组/日志组';
const encode=text=>encodeURIComponent(text).replace(/%/g,“$”);
const awsEncode=text=>encodeURIComponent(encodeURIComponent(text)).replace(/%/g,“$”);
const encodeTimestamp=timestamp=>encode('?start=')+awsEncode(新日期(timestamp).toJSON());
const awsLambdaLogBaseUrl=`${logBaseUrl}/${awsEncode('/aws/lambda/')}`;
const logStreamUrl=(日志组、日志流、时间戳)=>
`${awsLambdaLogBaseUrl}${logGroup}/log events/${awsEncode(logStream)}${timestamp?encodeTimestamp(timestamp):''};

基于@pål Brattberg答案的Python解决方案:

cloudwatch_log_template=“https://{AWS_REGION}.console.AWS.amazon.com/cloudwatch/home?REGION={AWS_REGION}\logsV2:log groups/log group/{log_group_NAME}/log events/{log_STREAM u NAME}”
log\u url=cloudwatch\u log\u template.format(
AWS\u REGION=AWS\u REGION,LOG\u GROUP\u NAME=CLOUDWATCH\u LOG\u GROUP,LOG\u STREAM\u NAME=LOG\u STREAM\u NAME
)

如果您使用了任何非法字符,请确保首先替换它们(请参见OP)。

有点晚,但这里有一个python实现

def get_cloud_watch_search_url(search, log_group, log_stream, region=None,):
    """Return a properly formatted url string for search cloud watch logs

    search = "{$.message: "You are amazing"}
    log_group = Is the group of message you want to search
    log_stream = The stream of logs to search
    """

    url = f'https://{region}.console.aws.amazon.com/cloudwatch/home?region={region}'

    def aws_encode(value):
        """The heart of this is that AWS likes to quote things twice with some substitution"""
        value = urllib.parse.quote_plus(value)
        value = re.sub(r"\+", " ", value)
        return re.sub(r"%", "$", urllib.parse.quote_plus(value))

    bookmark = '#logsV2:log-groups'
    bookmark += '/log-group/' + aws_encode(log_group)
    bookmark += "/log-events/" + log_stream
    bookmark += re.sub(r"%", "$", urllib.parse.quote("?filterPattern="))
    bookmark += aws_encode(search)

    return url + bookmark
这样您就可以快速验证它

>>> real = 'https://us-west-2.console.aws.amazon.com/cloudwatch/home?region=us-west-2#logsV2:log-groups/log-group/$252Fapp$252Fdjango/log-events/production$3FfilterPattern$3D$257B$2524.msg$253D$2522$2525s$2525s+messages+to+$2525s+pk$253D$2525d...$2522$257D'
>>> constructed = get_cloud_watch_search_url(None, search='{$.msg="%s%s messages to %s pk=%d..."}', log_group='/app/django', log_stream='production', region='us-west-2')
>>> real == constructed
True

我最近在想生成cloudwatch insights URL时遇到了这个问题。打字稿版本如下:

导出函数getInsightsUrl(
开始日期:,
完:日期:,
查询:字符串,
sourceGroup:string,
region=“us-east-1”
) {
常量p=(m:string)=>转义(m);
//对内部值进行编码
常量s=(m:string)=>转义(m)。替换(/\%/gi,“*”);
常数queryDetail=
p(`~(end~'``)+
s(end.toISOString())+
p(`~start~``)+
s(start.toISOString())+
p(`~timeType~'ABSOLUTE~tz~'UTC~editorString~'`)+
s(查询)+
p(`~isLiveTail~false~queryId~ ``)+
s(v4())+
p(`~源~'`)+
s(资源组)+
p(`))`;
返回(
`https://console.aws.amazon.com/cloudwatch/home?region=${region}#logsV2:logs insights`+
转义(“?queryDetail=“+queryDetail”)。替换(/\%/gi,“$”)
);
}

这对我来说非常有效。请注意,如果手头没有这些环境变量,那么process.env.AWS\u LAMBDA\u LOG\u STREAM\u NAME对我来说是由
ecs/main/[taskArn:resource id]
组成的。这是一个很好的解决方案,但我认为您仍然需要将
%
替换为
$
?我有一个
const awsEncode=text=>encodeURIComponent(encodeURIComponent(text)).replace(/%/g,“$”)函数来帮助我这样做是有意义的,我可以使用您的提示相应地编辑我的解决方案吗?