Search code examples
amazon-web-servicesamazon-cloudwatchaws-cloudwatch-log-insights

Is there a way to generate the AWS Console URLs for CloudWatch Log Group filters?


I would like to send my users directly to a specific log group and filter but I need to be able to generate the proper URL format. For example, this 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

will take you to a log group named /my/log/group/goes/here and filter messages with this pattern for the past 2 days:

[incoming_ip, user_name, user_ip , timestamp, request != "GET /health_checks/all *", status_code = 5* || status_code = 429, bytes, url, user_agent]

I can decode part of the URL but I don't know what some of the other characters should be (see below), but this doesn't really look like any standard HTML encoding to me. Does anyone know a encoder/decoder for this URL format?

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

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

Solution

  • I have created a bit of Ruby code that seems to satisfy the CloudWatch URL parser. I'm not sure why you have to double escape some things and then replace % with $ in others. I'm guessing there is some reason behind it but I couldn't figure out a nice way to do it, so I'm just brute forcing it. If you have something better, or know why they do this, please add a comment.

    NOTE: The filter I tested with is kinda basic and I'm not sure what might need to change if you get really fancy with it.

    # 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('%','$')