{
  "$type": "site.standard.document",
  "canonicalUrl": "https://johnnyreilly.com/posts/reverse-engineering-azure-app-insights-transactions-url",
  "description": "This post reverse engineers the Azure Application Insights Transactions URL, showing how to make a link href, using both TypeScript and C#.",
  "path": "/posts/reverse-engineering-azure-app-insights-transactions-url",
  "publishedAt": "2022-09-03T00:00:00.000Z",
  "site": "at://did:plc:yy3apqjlms24kso7ahn7lbmb/site.standard.publication/3mova7c4nho2b",
  "tags": [
    "c#",
    "azure",
    "typescript"
  ],
  "textContent": "Logs matter. In Azure, logs generally live in Application Insights, in the Transaction Search section. This post reverse engineers the Azure Application Insights Transactions URL, and details how to construct a link to take you directly there, using both TypeScript and C#.\n\n\n\nBring me the logs!\n\nIf you've ever supported a production system, you will know this to be true: logs matter. Logs help you understand what's gone wrong. (You're never looking at logs when something has gone right.) When it comes to Azure, logs tend to reside in Application Insights, specifically Transactions:\n\nWhilst Transaction Search is very powerful, it can also be a little tough to find the things that you need. In a system I'm working on now, we've found ourselves building an application that allows us to provide support. We use it to bring together disparate pieces of information across our estate. As we use it, we're usually looking at a particular slice of time. If we don't find what we need in our application we'll find a need to dig into the logs for the same period.\n\nRather than manually logging into Azure, finding Application Insights, going to Transactions and entering the time period, what if we could just go there at the click of a link? We can.\n\nLook at the screenshot above, do you see the \"Copy link\" button? That button copies a URL to the clipboard which encapsulates the current search criteria. And it turns out we can reverse engineer it!\n\nBreaking down the link\n\nFirst of all, let's take a look at the incredibly long URL that's copied to the clipboard:\n\nThere's 1860 characters in there. That's a lot - but still less than the general limit of 2000 characters. This mighty long URL can be broken down into four distinct parts. Let's break it down:\n\n1. Main Azure Portal routing\n\nFirstly this:\n\nThis is a recognisable base URL and takes us to the relevant part of the Azure Portal.\n\n2. ResourceId\n\nNext we have a URL encoded ResourceId:\n\nIf we run it through decodeURIComponent you can see it in it's raw form:\n\nThis is the ResourceId of the Application Insights instance that we're looking at. This is the same as the one we saw in the URL when we were looking at the Application Insights instance in the Azure Portal, and it's the ResourceId that can be obtained by clicking on the \"JSON View\" link:\n\n3. More Azure Portal routing\n\nThe next part of the URL is just some more Azure Portal routing:\n\n4. The query\n\nFinally we have the (very long) query:\n\nInitially this doesn't look like much. It's just a long string of characters. But if we run it through decodeURIComponent we can see that it's actually a JSON object:\n\nAnd if we parse that JSON object we get:\n\nWe can clearly see in the object above the aspects that contribute to our query. It's worth highlighting that when I generated the above query, I had the traces table selected and I was searching for the phrase \"healthcheck\". If I had selected requests instead, the tables array would have contained requests instead of traces. If I had been searching for a different phrase, the searchPhrase and filterWhereClause objects would have contained different values.\n\nReverse engineering a link\n\nNow that we understand what makes up a URL, we're safe to build our own mechanisms to generate a URL.\n\nTypeScript URL builder\n\nWe'll start by creating the TypeScript version of the URL builder. We'll start by creating a new file called urlBuilder.ts and we'll add the following code:\n\nThe above code is a function that takes in an object with the following properties:\n\n- applicationInsightsId - the ID of the Application Insights resource\n- startDate - the start date of the time range\n- endDate - the end date of the time range\n\nYou can see that it takes these inputs and uses them to build up a URL made up of the four sections we identified earlier.\n\nThe URL it generates is the URL that will open the Application Insights logs blade in the Azure portal with the time range selected. This code is not including any kind of search phrase, but it could easily be adjusted to cater for that.\n\nCURL builder\n\nWe can do the same thing in C#. It's a bit more verbose than the TypeScript version, but it's still pretty straightforward. We'll create a new file called UrlBuilder.cs and add the following code:\n\nNote that most of the verbosity comes from the fact that we're using C9 record types to represent the JSON objects that we're serializing. If you're not familiar with C9 record types. We're also using JSON.Net for our serialization, but you could use System.Text.Json if you wanted to. You would need to amend the JsonProperty attributes to be JsonPropertyName attributes instead.\n\nConclusion\n\nIn this post we've understood what goes into the URL for Application Insights Transactions, and we've seen how to generate that URL in TypeScript and C#. We've also seen how to use the URL to search for transactions in Application Insights. I hope you found this post useful. Thanks for reading!",
  "title": "Reverse engineering the Azure Application Insights Transactions URL"
}