Advanced KQL for Logic Apps Monitoring: Harnessing Custom Dimensions in Application Insights
Practical KQL techniques for Logic Apps Standard
In the world of serverless orchestration, Azure Logic Apps stand out for their ability to automate workflows with minimal overhead. But as these workflows grow in complexity—integrating APIs, handling high volumes of triggers, and spanning multiple actions—monitoring becomes crucial. Enter Application Insights, Azure’s powerhouse for telemetry, where logs are rich but often buried in JSON payloads. While Azure documentation skims the surface, advanced parsing of these logs using Kusto Query Language (KQL) remains under-explored outside the Azure echo chamber.
This post dives into practical KQL techniques for Logic Apps Standard (the single-tenant flavor), focusing on two high-impact areas: extracting custom dimensions for run IDs and action durations to spotlight the slowest performers, and aggregating API call metrics by URL while filtering out noisy internal hooks. These queries, drawn from real-world patterns, will help you shift from reactive firefighting to proactive optimization. Whether you’re troubleshooting latency spikes or auditing external dependencies, KQL’s flexibility shines here.
We’ll use the traces and requests tables in Application Insights, where Logic Apps telemetry lands. Custom dimensions—those extensible key-value pairs in telemetry events—are your gateway to granular insights. Always enable diagnostic settings to route Logic Apps logs to App Insights, and consider debug-level verbosity for deeper traces (just watch your ingestion costs).
Parsing Custom Dimensions: Unlocking Run IDs and Durations
Logic Apps actions emit traces with embedded JSON in customDimensions, holding gems like run IDs, workflow names, and execution times. Parsing this requires parse_json() to navigate the nested structure, often under prop__properties or resource.
Here’s a foundational query to extract run IDs, workflow details, and durations from traces. It filters for action-level events and projects key fields for easy scanning:
traces
| where cloud_RoleName contains “logicapp” // Filter to Logic Apps instances
| where timestamp > ago(7d) // Last 7 days
| extend properties = parse_json(tostring(customDimensions.prop__properties))
| extend resource = properties.resource
| extend actionDetails = parse_json(tostring(customDimensions.prop__action))
| project
timestamp,
WorkflowName = tostring(resource.workflowName),
RunId = tostring(customDimensions.prop__flowRunSequenceId),
ActionName = tostring(actionDetails.name),
Status = tostring(customDimensions.prop__status),
DurationMs = toint(actionDetails.endTime) - toint(actionDetails.startTime) // Milliseconds
| where isnotempty(RunId) and isnotempty(ActionName)
| order by timestamp descThis query reveals the “who, what, and how long” of each action. The DurationMs calculation derives from start/end timestamps in the action details—crucial since raw traces don’t always expose a top-level duration. Run it in the App Insights query editor to drill into specific runs via the extracted RunId, which you can hyperlink back to the Logic Apps designer.
Top-N Summaries: Hunting the Slowest Actions
With extracted durations in hand, summarizing for outliers is straightforward. This next query builds on the above, aggregating average durations by action and surfacing the top 10 slowest across successful runs. It excludes failures to focus on performance bottlenecks, not errors:
traces
| where cloud_RoleName contains “logicapp” and timestamp > ago(7d)
| where customDimensions.prop__status == “Succeeded” // Successful actions only
| extend properties = parse_json(tostring(customDimensions.prop__properties))
| extend resource = properties.resource
| extend actionDetails = parse_json(tostring(customDimensions.prop__action))
| extend DurationMs = toint(actionDetails.endTime) - toint(actionDetails.startTime)
| where isnotempty(DurationMs) and DurationMs > 0
| summarize
AvgDurationMs = avg(DurationMs),
TotalRuns = count(),
MinDurationMs = min(DurationMs),
MaxDurationMs = max(DurationMs)
by WorkflowName = tostring(resource.workflowName), ActionName = tostring(actionDetails.name)
| top 10 by AvgDurationMs desc
| project WorkflowName, ActionName, AvgDurationMs, TotalRuns, MinDurationMs, MaxDurationMs
| extend AvgDurationSec = AvgDurationMs / 1000.0Output might look like this (hypothetical results):
Spotting a CRM post averaging 4+ seconds? Time to investigate throttling or payload bloat. Tweak the top clause for your N, or add | render barchart for visuals.
Aggregating API Call Metrics: Focus on External Dependencies
HTTP actions in Logic Apps often manifest as requests in App Insights, capturing URL, duration, and success metrics. But internal callbacks (e.g., webhook endpoints like /runtime/webhooks) clutter the view. This aggregation query excludes them, rolling up total, average, and max durations by URL—ideal for dependency SLAs.
requests
| where cloud_RoleName contains “logicapp” and timestamp > ago(7d)
| where success == true // Successful calls only
| where isnotempty(url) and not(url contains “runtime/webhooks”) // Exclude internal hooks
| extend DurationSec = duration / 1000.0
| summarize
TotalDurationSec = sum(DurationSec),
AvgDurationSec = avg(DurationSec),
MaxDurationSec = max(DurationSec),
CallCount = count()
by url
| order by MaxDurationSec desc
| top 10 by MaxDurationSec
| project url, AvgDurationSec, MaxDurationSec, TotalDurationSec, CallCountSample results:
The max outlier screams for a retry policy or async pattern. Group further by workflow with by url, cloud_RoleName if needed, or join back to traces for run context.
TLDR: Elevate Your Logic Apps Observability
These KQL patterns transform raw App Insights logs into actionable intelligence, far beyond Azure’s canned dashboards. Start simple—paste these into the query editor—and iterate with filters for your environment. Pro tips: Use union traces, requests for holistic views, set up alerts on query results via Azure Monitor, and export to Power BI for stakeholder reports.
Monitoring isn’t just about logs; it’s about foresight. By mastering custom dimensions and targeted aggregations, you’ll keep your Logic Apps humming efficiently, even as they scale. Got tweaks or war stories? Drop them in the comments.




