SOLVED

How to programmatically generate a link to open an App Insights KQL query?

Microsoft

In the App Insights UI, I can generate a link to a query by clicking on Copy -> Copy Link to Query.

 

Is there some way to generate such a URL programmatically, If I know the query text and the App Insights endpoint?

12 Replies

@joruales would be great to know a bit more on the intention of the custom URL to the query, but would recommend to use Azure Monitor workbooks https://docs.microsoft.com/en-us/azure/azure-monitor/app/usage-workbooks

@Dave Rendón we have a tool that runs queries on App Insights DBs, and we would like to allow users to continue investigating by providing them a link that opens a starter query directly in app insights. I don't think that Azure Monitor workbooks fits this use case since we're not interested in a dashboard UI

best response confirmed by joruales (Microsoft)
Solution

@joruales Maybe a bit late, but as you probably noticed, a URL generated from "Copy Link to Query" has the following format:

 

https://portal.azure.com/#@TENANT_ID/blade/Microsoft_Azure_Monitoring_Logs/LogsBlade/resourceId/%2Fsubscriptions%2FSUBSCRIPTION_ID%2FresourceGroups%2FRESOURCEGROUP%2Fproviders%2Fmicrosoft.insights%2Fcomponents%2FAPPINSIGHTSINSTANCENAME/source/LogsBlade.AnalyticsShareLinkToQuery/q/ENCODEDSTRING/timespan/TIMESPAN

 

The ENCODEDSTRING is your query zipped and URL encoded/escaped. You must use this approach when the query has more than 1600 characters. Otherwise, if your query has less than 1600 characters, you can replace the q parameter by a query parameter and the encoded string will simply be your query URL escaped. For instance:

 

https://portal.azure.com/#@TENANT_ID/blade/Microsoft_Azure_Monitoring_Logs/LogsBlade/resourceId/%2Fsubscriptions%2FSUBSCRIPTION_ID%2FresourceGroups%2FRESOURCEGROUP%2Fproviders%2Fmicrosoft.insights%2Fcomponents%2FAPPINSIGHTSINSTANCENAME/source/LogsBlade.AnalyticsShareLinkToQuery/query/availabilityResults%20%7C%20where%20duration%20%3E%20500%20%7C%20take%201/timespan/TIMESPAN

 

would open your App Insights instance with the following query:

 

availabilityResults
| where duration > 500
| take 1

@hspinto Thanks for your answer and it was really helpful. 

 

Unfortunately My query was more than 1600 characters and I have tried encodeurl to my query and try to open Application Instance I am getting 'The query provided in the URL was in an incorrect format'. Error.

 

My Encoded URL query looks below: union%20exceptions%2C%20traces%20%7C%20order%20by%20timestamp%20%7C%20extend%20EAICode%20%3D%20tostring(customDimensions.%5B%22EAI%20Code%22%5D)%20%7C%20extend%20EventId%20%3D%20tostring(customDimensions.EventId)%20%7C%20extend%20User%20%3D%20tostring(customDimensions.UserId)%20%7C%20extend%20IsError%20%3D%20tostring(customDimensions.IsError)%20%7C%20extend%20Exception%20%3D%20tostring(details%5B0%5D.type)%20%7C%20project%20TimeStamp%20%3D%20timestamp%2C%20TransactionId%20%3D%20operation_Id%2C%20ParentServiceId%20%3D%20operation_ParentId%2C%20EventId%2C%20operation_Name%2C%20cloud_RoleName%2C%20cloud_RoleInstance%2C%20message%2C%20EAICode%2C%20IsError%2C%20Exception%20%7C%20where%20EventId%20%3D%3D%22578%22

 

Could you please help me in encoding my query string?

@krishnachandar 

 

if your query has more than 1600 chars, you must:

 

1) zip your query;

2) encode it;

3) use instead of query in the URL path.

@hspinto Thanks again for the reply. My question may be silly.

 

Not sure what zip means. Can we zip from client side i.e., from javascript / angular? 

 

Is encode mean encodeURI() method from javascript?

 

Any help by providing sample code to zip and encode from javascript / angular would be really helpful.

 

The reason for seeking this help is I need to prepare query dynamically and open Application Insights Instance from Angular. Please help me in this regard.

 

Thank you in Advance!

 

@krishnachandar, I am not a Javascript expert nor I have any code sample to share with you. But you can for sure zip from client side, as there are many libraries out there to perform that. I would however recommend you to first analyze the Azure portal Javascript code itself. When you click on the "Link to query" button, everything happens on the client side. If you manage to understand how that button click event is captured and processed, you'll for sure find the answer to your question in the event processor code itself.

@krishnachandar 

I'm not sure about how to do it in JS, but this is how I do it in C#:

The trick is utf8-encode the query, then gzip it, then base64-encode it, then url-encode it, and finally include it in the url.

        static private string EncodedQuery(string query)
        {
            var bytes = Encoding.UTF8.GetBytes(query);
            using (MemoryStream memoryStream = ExtendedStream.CreateMemoryStream())
            {
                using (GZipStream compressionStream = new GZipStream(memoryStream, CompressionMode.Compress, leaveOpen: true))
                {
                    compressionStream.Write(bytes, 0, bytes.Length);
                }
                memoryStream.Seek(0, SeekOrigin.Begin);
                Byte[] data = memoryStream.ToArray();
                string encodedQuery = Convert.ToBase64String(data);
                return HttpUtility.UrlEncode(encodedQuery);
            }
        }

 

@ krishnachandar, adding to @joruales great feedback, I recommend you to use the pako package to zip the query.

@krishnachandar Did you ever figure out how to encode and zip the query in javascript? None of the methods below worked for me.

@jorsmi 

Just incase anyone else comes here looking for a complete implementation, I figured it out using @hspinto :

 

import pako from 'pako'

const query = 'some query'
const compressed = pako.gzip(query, {to: "string"}) // gzip the query and set options to output as a string
const base64 = btoa(compressed) // base64 encode
const encodedQuery = encodeURIComponent(base64) // URI encode
console.log(encodedQuery)

 

Reference:

Can you reverse engineer Saved Query link to Application Insights? - Stack Overflow

pako - npm (npmjs.com)

How can you encode a string to Base64 in JavaScript? - Stack Overflow

1 best response

Accepted Solutions
best response confirmed by joruales (Microsoft)
Solution

@joruales Maybe a bit late, but as you probably noticed, a URL generated from "Copy Link to Query" has the following format:

 

https://portal.azure.com/#@TENANT_ID/blade/Microsoft_Azure_Monitoring_Logs/LogsBlade/resourceId/%2Fsubscriptions%2FSUBSCRIPTION_ID%2FresourceGroups%2FRESOURCEGROUP%2Fproviders%2Fmicrosoft.insights%2Fcomponents%2FAPPINSIGHTSINSTANCENAME/source/LogsBlade.AnalyticsShareLinkToQuery/q/ENCODEDSTRING/timespan/TIMESPAN

 

The ENCODEDSTRING is your query zipped and URL encoded/escaped. You must use this approach when the query has more than 1600 characters. Otherwise, if your query has less than 1600 characters, you can replace the q parameter by a query parameter and the encoded string will simply be your query URL escaped. For instance:

 

https://portal.azure.com/#@TENANT_ID/blade/Microsoft_Azure_Monitoring_Logs/LogsBlade/resourceId/%2Fsubscriptions%2FSUBSCRIPTION_ID%2FresourceGroups%2FRESOURCEGROUP%2Fproviders%2Fmicrosoft.insights%2Fcomponents%2FAPPINSIGHTSINSTANCENAME/source/LogsBlade.AnalyticsShareLinkToQuery/query/availabilityResults%20%7C%20where%20duration%20%3E%20500%20%7C%20take%201/timespan/TIMESPAN

 

would open your App Insights instance with the following query:

 

availabilityResults
| where duration > 500
| take 1

View solution in original post