In an upcoming talk at Integrate 2021 in June (check out the sessions here) I will be talking about Log Analytics/Azure Monitor and App Insights when used with Logic Apps. This post is not exactly the same as the talk ill be doing but it touches on a similar area and I thought people will find this quite interesting and maybe wet the appetite a little to know more about what ive been up to recently.

In this post however I will be looking at the scenario where I am using Azure API Management as a proxy to some applications in the cloud and on-premise. I am routing my custom API calls through APIM for a number of reasons but one of the benefits is that my APIM is also connected to App Insights and as an effect of that I will have the ability to do some cool analysis of a number of things related to my Logic Apps consuming services from APIM.

One of the good things is that out of the box with the HTTP and APIM connectors logic apps will be injecting some headers listed below:

  • Request-x-ms-workflow-resourcegroup-name
  • Request-x-ms-workflow-run-id
  • Request-x-ms-workflow-name

This tells me the logic app, its run id and the resource group of the logic app which makes each call automatically. I can then see these headers in the app insights logs.

While there are loads of good features in App Insights which give me useful out of the box functionality, in this post I wanted to talk about what I can do by inspecting the app insights logs with kusto queries to analyst the goldmine of useful telemetry data. Below are a few of the useful queries I have used.

Errors by Logic App

If I want to get a list of the logic apps which got errors when calling APIM I can use the below query

requests  
| where resultCode != 200
| extend logicAppName_ = tostring(customDimensions.["Request-x-ms-workflow-name"])
| extend resourceGroup_ = tostring(customDimensions.["Request-x-ms-workflow-resourcegroup-name"])
| extend logicAppId_ = tostring(customDimensions.["Request-x-ms-workflow-run-id"])
| project logicAppName_, resourceGroup_, logicAppId_, name, timestamp, resultCode

I can also summarize the data to findout which logic apps are having the most errors

requests  
| where resultCode != 200
| extend logicAppName_ = tostring(customDimensions.["Request-x-ms-workflow-name"])
| summarize count() by logicAppName_

View the above query as a chart you can add the | render column chart to the end of the query

View Errors over time as a graph

If I want to see a profile of the errors by logic app over a period of time I can use the below query and render it as a chart to see which logic apps have errors when.

let min_t = toscalar(requests | summarize min(timestamp));
let max_t = toscalar(requests | summarize max(timestamp));
requests
| where resultCode != 200
| extend logicAppName_ = tostring(customDimensions.["Request-x-ms-workflow-name"])
| make-series num=count() default=0 on timestamp in range(min_t, max_t, 1h) by logicAppName_
| render timechart  

View Performance of API’s used by Logic Apps

Next I wanted to look at the requests in relation to the logic apps consuming them and see what the profile of average response time is from a Logic App perspective. This will help me see which logic apps might have performance bottlenecks in them from the API’s they consume.

let min_t = toscalar(requests | summarize min(timestamp));
let max_t = toscalar(requests | summarize max(timestamp));
requests
| extend logicAppName_ = tostring(customDimensions.["Request-x-ms-workflow-name"])
| where isnotnull(logicAppName_) and isnotempty(logicAppName_)
| make-series num=avg(duration) default=0 on timestamp in range(min_t, max_t, 1h) by logicAppName_
| render timechart  

This looks like the below

View usage of an API operation by Logic App over a period of time

In this case I want to look at an individual APIM operation and have a look at the profile of usage but break it down by logic app so I can see by hour how many times each logic app is using it. The below query will help me do this and show it as a chart like below.

let min_t = toscalar(requests | summarize min(timestamp));
let max_t = toscalar(requests | summarize max(timestamp));
requests
| extend logicAppName_ = tostring(customDimensions.["Request-x-ms-workflow-name"])
| extend logicAppName_ = tostring(customDimensions.["Request-x-ms-workflow-name"])
| extend resourceGroup_ = tostring(customDimensions.["Request-x-ms-workflow-resourcegroup-name"])
| extend API_Name_ = tostring(customDimensions.["API Name"])
| extend Operation_Name_ = tostring(customDimensions.["Operation Name"])
| where isnotnull(logicAppName_) and isnotempty(logicAppName_)
and operation_Name endswith "[Your operation name]"
| make-series num=count() default=0 on timestamp in range(min_t, max_t, 1h) by logicAppName_
| render timechart  



Which Logic app uses which API

This will give you a list of the API’s and which logic app names have used them over the period of data you look at.

requests
| extend logicAppName_ = tostring(customDimensions.["Request-x-ms-workflow-name"])
| extend resourceGroup_ = tostring(customDimensions.["Request-x-ms-workflow-resourcegroup-name"])
| extend API_Name_ = tostring(customDimensions.["API Name"])
| where isnotnull(logicAppName_) and isnotempty(logicAppName_)
| summarize by API_Name_, logicAppName_, resourceGroup_

How many times is each API used by each Operation

This will extend the above query to show you how many times each API has been used by each logic app.

requests
| extend logicAppName_ = tostring(customDimensions.["Request-x-ms-workflow-name"])
| extend resourceGroup_ = tostring(customDimensions.["Request-x-ms-workflow-resourcegroup-name"])
| extend API_Name_ = tostring(customDimensions.["API Name"])
| where isnotnull(logicAppName_) and isnotempty(logicAppName_)
| summarize count() by API_Name_, logicAppName_, resourceGroup_

Which Logic App uses which API operation

If we want to break down the data further we can use the below query to see which logic apps use which API operation

requests
| extend logicAppName_ = tostring(customDimensions.["Request-x-ms-workflow-name"])
| extend resourceGroup_ = tostring(customDimensions.["Request-x-ms-workflow-resourcegroup-name"])
| extend API_Name_ = tostring(customDimensions.["API Name"])
| extend Operation_Name_ = tostring(customDimensions.["Operation Name"])
| where isnotnull(logicAppName_) and isnotempty(logicAppName_)
| summarize by API_Name_, Operation_Name_, logicAppName_, resourceGroup_


How many times is each API operation used by each logic app

As we did earlier we can also break down that query to also show how many times each logic app has used each API operation

requests
| extend logicAppName_ = tostring(customDimensions.["Request-x-ms-workflow-name"])
| extend resourceGroup_ = tostring(customDimensions.["Request-x-ms-workflow-resourcegroup-name"])
| extend API_Name_ = tostring(customDimensions.["API Name"])
| extend Operation_Name_ = tostring(customDimensions.["Operation Name"])
| where isnotnull(logicAppName_) and isnotempty(logicAppName_)
| summarize count() by API_Name_, Operation_Name_, logicAppName_, resourceGroup_


 

Buy Me A Coffee