Query several Application Insights resources at once with KQL
With workspace-based Application Insights, telemetry from every app that shares a Log Analytics workspace already sits in the same AppRequests, AppDependencies and other App tables, so one query covers them all; filter or group by _ResourceId or AppRoleName. For apps in other workspaces, add workspace("<id>").AppRequests to a union; app() is only for classic resources. One query can reach up to 100 workspaces or apps, and to find which resource an instrumentation key belongs to, ask Azure Resource Graph.
Most real systems have more than one Application Insights resource: one per service, per environment, sometimes per team. Questions like “which service fails most” or “what did this deployment do everywhere” need one query across all of them. How you write it depends on where the data lives.
Where the data lives now
Every Application Insights resource that still receives data is workspace-based: telemetry ingestion into classic resources stopped on June 15, 2025. A workspace-based resource stores its telemetry in a Log Analytics workspace, in tables with different names from the classic ones: requests is AppRequests, dependencies is AppDependencies, customMetrics is AppMetrics, and so on. Columns change too: timestamp is TimeGenerated, itemCount is ItemCount, cloud_RoleName is AppRoleName, customDimensions is Properties, and success becomes a real boolean Success.
Inside the Application Insights resource’s own Logs page, the classic names still work and are scoped to that one app. In the workspace, you get the App* tables for every app that sends there. The Azure Monitor vs Application Insights vs Log Analytics guide explains the layers.
Apps in one workspace
If several apps send to the same workspace, there’s nothing to join. Every row carries _ResourceId, the full Azure resource ID of the Application Insights resource it came from, which Microsoft recommends as the most consistent column for scoping and cross-correlation.
Failure rate per app and role across everything in the workspace:
AppRequests
| where TimeGenerated > ago(1h)
| summarize requests = sum(ItemCount),
failed = sumif(ItemCount, Success == false)
by app = tostring(split(_ResourceId, "/")[-1]), AppRoleName
| extend failurePct = round(100.0 * failed / requests, 2)
| order by failed desc
ItemCount keeps the counts right when apps sample at different rates; see sampling explained.
Two details matter once several apps share a query. Times are UTC everywhere: a datetime in Kusto is always UTC, so apps in different regions line up without conversion, and you convert only for display. And the workspace holds more than telemetry: platform logs and other resources’ data sit next to the App* tables and carry _ResourceId too, so one query can set an app’s failures beside its database’s diagnostics, each identified by its own resource ID.
Apps in other workspaces: workspace()
To include another workspace, reference it explicitly with workspace(). Microsoft recommends the workspace ID (a GUID) or the full Azure resource ID as the identifier; names alone are slower and can fail.
Slowest dependencies across this workspace and two others:
union withsource = SourceTable
AppDependencies,
workspace("00000000-0000-0000-0000-000000000001").AppDependencies,
workspace("/subscriptions/<sub>/resourcegroups/ops/providers/Microsoft.OperationalInsights/workspaces/ops-logs").AppDependencies
| where TimeGenerated > ago(1h)
| summarize calls = sum(ItemCount),
p95_ms = percentilew(DurationMs, ItemCount, 95)
by Target, AppRoleName
| top 20 by p95_ms desc
The rules Microsoft lists: up to 100 workspaces or classic apps in one query; many resources make queries slow; references must be literal (you can’t pass a workspace ID as a parameter); and a cross-resource query can’t call parameterized functions or functions that themselves contain workspace(), app() or similar expressions. Each workspace must also be one you can read. Log search alerts support cross-resource queries with the current scheduledQueryRules API, provided the resources are written in the query.
To avoid repeating the list in every query, save the union as a function (for example allRequests) and query the function. That works in the portal and in workbooks, but not in alert rules, because Azure validates access to each resource when the rule is created.
app() and resource()
app() reads a classic Application Insights resource by its application ID or resource ID, with the classic table names (app("<app-id>").requests). For workspace-based resources, Microsoft directs you to workspace(). resource() works in queries scoped to a resource and reads data for another resource. Resource-context queries, the implicit alternative, gather data for a resource, resource group or subscription from whichever workspaces hold it, but they don’t read classic data.
Find a resource from its instrumentation key
A connection string in an old config file, an ikey in a log, and the question is: which resource is that? Every component exposes InstrumentationKey (and its application ID as AppId) in its properties, so Azure Resource Graph can search all subscriptions you can read at once.
Look up an Application Insights resource by instrumentation key in Resource Graph Explorer:
resources
| where type =~ 'microsoft.insights/components'
| where tostring(properties.InstrumentationKey) =~ '<instrumentation key>'
| project name, resourceGroup, subscriptionId,
appId = tostring(properties.AppId),
workspace = tostring(properties.WorkspaceResourceId)
The same query runs from the command line with az graph query -q "<query>". The appId it returns is what app() expects for classic resources and what older API clients call the application ID.
Bring in reference data
The old Application Insights Analytics had an import feature for joining your own tables. Today there are two routes. For small lookup tables (a list of tenants, a mapping of role names to teams), the externaldata operator reads a CSV or JSON file from storage at query time; in Azure Monitor it’s meant for reference tables up to 100 MB and doesn’t work when the storage endpoint is behind a firewall. For anything larger or permanent, ingest it into a custom table in the workspace with the Logs Ingestion API, and join it like any other table.
Joining a small team lookup to request failures:
let owners = externaldata(AppRoleName: string, Team: string)
[h@"https://contosoref.blob.core.windows.net/ref/owners.csv?<SAS token>"]
with (format = "csv", ignoreFirstRecord = true);
AppRequests
| where TimeGenerated > ago(1d) and Success == false
| summarize failed = sum(ItemCount) by AppRoleName
| lookup kind=leftouter owners on AppRoleName
Dashboards and workbooks across apps
To reuse a dashboard for another app, open it and select Clone: the copy opens in edit mode, and you point its tiles at the other resource. Tiles built on a query that groups by _ResourceId or AppRoleName need no change at all, which is the better habit. Azure Workbooks go further: they combine log queries, metrics and parameters from several resources in one report, and their permissions follow the resources they read. The KQL library queries all work at workspace scope with the table renames above, and the KQL builder writes the classic forms.
Classic SDK 2.x and today’s SDKs
Which SDK sent the data doesn’t change any of this. The classic 2.x SDK, SDK 3.x and the Microsoft OpenTelemetry Distro all write the same tables in the same workspace, so a workspace query covers apps on different SDKs at once. The column to watch when you mix them is AppRoleName: 2.x sets it from the host or an initializer, while the Distro takes it from service.name, which its resource detectors fill in only on hosts they recognise. Set it explicitly, as covered in correlation and Application Map.
Troubleshooting
| Symptom | Likely cause | Fix |
|---|---|---|
Failed to resolve table for requests | Querying the workspace, which uses AppRequests | Use the workspace table names |
app() returns nothing | Resource is workspace-based | Use workspace() or the shared workspace |
| Query slow or timing out | Many workspaces or long time range | Narrow the time range; pre-aggregate in a function |
| Alert rule rejects the query | Resources listed in a saved function | Write workspace() references in the alert query |
| Missing rows from one app | No read access to its workspace | Get Log Analytics Reader on that workspace |
| Resource Graph finds no component | Subscription not visible to you | Run with an account that can read it |
Queries for this topic
-
End-to-end trace for one operation_Id
requestsdependenciestracesexceptionspageViewscustomEvents operations
Returns: Every telemetry item recorded with the given operation_Id in the last 7 days, oldest first, with its type, service, name or message, duration, outcome, severity, and the IDs that link parent and child.
-
Slowest dependencies by target
dependencies dependencies
Returns: Up to 20 rows, one per dependency type and target, with the call count, the p95 duration in milliseconds and the number of failed calls, slowest first.
Frequently asked questions
Should I use app() or workspace() for workspace-based resources?
workspace(). Microsoft states that app() targets classic Application Insights resources, and that apps sharing a workspace need no cross-resource expression at all. Classic resources stopped ingesting data on June 15, 2025, so app() only reaches their old data.
Can a log search alert query several resources?
Yes, with the current scheduledQueryRules API, as long as the resources are written explicitly in the query. A saved function that lists the resources can't be used for alerts, because access is checked when the rule is created.
How do I find which app an instrumentation key belongs to?
Query Azure Resource Graph for resources of type microsoft.insights/components whose properties.InstrumentationKey matches. You see results only for subscriptions you can read, so run it with an account that sees the whole tenant if the key could be anywhere.
Sources, checked
- Query across resources with Azure Monitor (workspace(), app(), resource())
- Standard columns in Azure Monitor Logs (_ResourceId)
- Migrate to workspace-based Application Insights resources (table and column names)
- Components - Get (Application Insights REST API, InstrumentationKey and AppId)
- externaldata operator (Kusto, Azure Monitor)
- Logs Ingestion API in Azure Monitor
- Create and share dashboards in the Azure portal (clone a dashboard)
- Azure Workbooks overview