Generate AWS `Logs Insights` URL with query and search creteria

Viewed 745

I'd like to generate a URL for AWS Cloud Watch Logs Insights page where I can customize the following parameters:

  1. The query string
  2. The log groups I'd like to search with-in
  3. The time range

enter image description here

I couldn't find any official documentation for the structure of the URL. Also no API (at least not in boto3) would help me in this.

Here is an example:

https://eu-west-1.console.aws.amazon.com/cloudwatch/home?region=eu-west-1#logsV2:logs-insights$3FqueryDetail$3D$257E$2528end$257E$25272021-07-18T20*3a59*3a59.000Z$257Estart$257E$25272021-07-15T21*3a00*3a00.000Z$257EtimeType$257E$2527ABSOLUTE$257Etz$257E$2527Local$257EeditorString$257E$2527fields*20*40timestamp*2c*20*40message*0a*7c*20sort*20*40timestamp*20desc*0a*7c*20filter*20*40message*20*3d*7e*20*22Exception*22*0a*7c*20limit*20200$257EisLiveTail$257Efalse$257EqueryId$257E$2527####$257Esource$257E$2528$257E$2527*2faws*2flambda*2f######$2529$2529$26tab$3Dlogs

What is the encoding used to generate the URL above?

I'm thinking about simply replace the strings above with the desired params, any better way to achieve this ?

1 Answers

Replacing the strings in the URL isn't that direct, I did the following in Python that will generate link for the logs insights page:


def generate_cloudwatch_url(log_groups, query):
    def escape(s):
        for c in s:
            if c.isalpha() or c.isdigit() or c in ["-", "."]:
                continue
            c_hex = "*{0:02x}".format(ord(c))
            s = s.replace(c, c_hex)
        return s

    def gen_log_insights_url(params):
        S1 = "$257E"
        S2 = "$2528"
        S3 = "$2527"
        S4 = "$2529"

        res = f"{S1}{S2}"
        for k in params:
            value = params[k]
            if isinstance(value, str):
                value = escape(value)
            elif isinstance(value, list):
                for i in range(len(value)):
                    value[i] = escape(value[i])
            prefix = S1 if list(params.items())[0][0] != k else ""
            suffix = f"{S1}{S3}"
            if isinstance(value, list):
                value = "".join([f"{S1}{S3}{n}" for n in value])
                suffix = f"{S1}{S2}"
            elif isinstance(value, int) or isinstance(value, bool):
                value = str(value).lower()
                suffix = S1

            res += f"{prefix}{k}{suffix}{value}"
        res += f"{S4}{S4}"
        QUERY = f"logsV2:logs-insights$3Ftab$3Dlogs$26queryDetail$3D{res}"
        return f"https://eu-west-1.console.aws.amazon.com/cloudwatch/home?region=eu-west-1#{QUERY}"
    query_vars = {"sample":"value"}
    query = "\n".join([f'| filter {k}="{v}"' for (k, v) in query_vars.items()])
    params = {
        "end": 0,  # "2021-07-18T20:00:00.000Z",
        "start": -60 * 60 * 24,  # "2021-07-15T21:00:00.000Z",
        "unit": "seconds",
        "timeType": "RELATIVE",  # "ABSOLUTE",  # OR RELATIVE and end = 0 and start is negative  seconds
        "tz": "Local",  # OR "UTC"
        "editorString": f"fields @timestamp, @message\n| sort @timestamp desc\n{query}\n| limit 200",
        "isLiveTail": False,
        "source": [f"/aws/lambda/{lg}" for lg in log_groups],
    }
    return gen_log_insights_url(params)

I know it's aweful implementation, but it works!

Related