Azure Monitor vs Application Insights vs Log Analytics
They aren't alternatives but layers. Azure Monitor is Microsoft's overall monitoring service; a Log Analytics workspace is where its log data, including all Application Insights telemetry, is stored and queried with KQL; Application Insights is the APM feature that collects telemetry from your application and adds app-specific views on top. The same request is a row in requests when you query through Application Insights and in AppRequests when you query the workspace.
The three names show up in the same portal blades, the same billing lines and the same Stack Overflow answers, so it’s natural to compare them as products. They’re better understood as a stack.
Three layers, one data store
| Layer | What it is | You use it for |
|---|---|---|
| Azure Monitor | Microsoft’s monitoring service for Azure and hybrid resources | Metrics, logs, alerts, workbooks, autoscale, for everything |
| Log Analytics workspace | The data store for Azure Monitor Logs, plus the Log Analytics query tool | Storing log and trace data and querying it with KQL |
| Application Insights | Azure Monitor’s APM feature, a resource linked to a workspace | Collecting app telemetry and the app views: map, failures, performance, live metrics |
Azure Monitor has two data platforms. Logs go to Log Analytics workspaces and are queried with KQL; Prometheus and OpenTelemetry metrics go to Azure Monitor workspaces and are queried with PromQL. Despite the similar names, Microsoft stresses they are separate resource types with different stores and languages.
Log Analytics means two things. The workspace is a data store of tables, each with its own retention and plan. The Log Analytics tool is the query editor in the portal, with a simple point-and-click mode and a KQL mode. When people say “query it in Log Analytics” they usually mean the tool pointed at a workspace.
Application Insights is a resource you create per application (or per environment), with a connection string your app sends telemetry to. It stores that telemetry in the workspace it’s linked to and builds the APM experiences on top: Application Map, transaction search, Failures and Performance, Live Metrics, availability tests, usage analytics.
Same data, two schemas
The table and column names differ depending on where you query from. Microsoft keeps both for backward compatibility with dashboards and queries written before the workspace names existed.
| Through Application Insights | In the workspace |
|---|---|
requests, dependencies, exceptions, traces | AppRequests, AppDependencies, AppExceptions, AppTraces |
customEvents, customMetrics, pageViews | AppEvents, AppMetrics, AppPageViews |
timestamp, duration | TimeGenerated, DurationMs |
operation_Id, operation_Name | OperationId, OperationName |
cloud_RoleName, cloud_RoleInstance | AppRoleName, AppRoleInstance |
customDimensions, itemCount | Properties, ItemCount |
success (string) | Success (bool) |
Failed requests per service in the last hour, from the Application Insights Logs blade:
requests
| where timestamp > ago(1h)
| summarize failed = sumif(itemCount, tostring(success) =~ "false") by cloud_RoleName
The same question in the workspace:
AppRequests
| where TimeGenerated > ago(1h)
| summarize failed = sumif(ItemCount, Success == false) by AppRoleName
Both count with the item count, because sampling is on by default; see the sampling guide. The queries in the KQL library use the classic names and note the workspace equivalents in their pitfalls.
Classic SDK 2.x and classic resources
The SDK version doesn’t decide the schema. A request recorded by the classic .NET SDK 2.x (deprecated, retiring March 31, 2027), by SDK 3.x or by an OpenTelemetry distro lands in the same AppRequests table.
What used to decide it was the resource. Classic Application Insights resources kept telemetry in their own store, outside any workspace, so they only had the classic schema and were queried across apps with the app() function. Telemetry ingestion into classic resources stopped on June 15, 2025, and migrated resources write to a workspace. Two migration details still trip people up:
- No old data was copied. Data from before the migration stays in the classic store under its old retention. Querying the workspace directly shows only data ingested after the migration; the Application Insights Logs blade shows both.
- Renaming a migrated resource makes its Logs blade lose the pre-rename telemetry; the workspace’s Logs blade still shows all of it.
Microsoft promises full backward compatibility for classic-schema queries, workbooks and log-based alerts within the Application Insights experience.
Today: SDK 3.x and the Microsoft OpenTelemetry Distro
Apps on the Microsoft OpenTelemetry Distro or SDK 3.x send to the same ingestion endpoint and land in the same App* tables, so everything above holds. The OpenTelemetry vocabulary maps cleanly: a server span is a request, client and internal spans are dependencies, a log record is a row in traces, and the trace ID is the operation ID.
One newer path is different. Telemetry sent through native OTLP ingestion (an OpenTelemetry Collector sending to a data collection endpoint) is stored in OTelSpans and OTelLogs rather than the App* tables, and its ClientIP is always 0.0.0.0. If you mix both paths, your queries need to read both sets of tables.
Which to query, when
| Task | Where |
|---|---|
| Investigate one app’s failures or slow operations | The Application Insights resource: Failures, Performance, Logs |
| Query several apps that share a workspace | The workspace; filter on _ResourceId to pick one app |
| Query apps in different workspaces | workspace("…") in a union, up to 100 workspaces per query |
| Query a remaining classic resource | app("…"); resource-context queries don’t read classic data |
| Join app telemetry with VM, container or diagnostic logs | The workspace that holds both |
| Alert on a KQL query | A log search alert on the workspace or the Application Insights resource |
One workspace or several?
Because the workspace is the unit of storage and billing, the layout decision is really a workspace decision. Pointing several Application Insights resources at one workspace lets a single query cover every service and the infrastructure under it, without workspace() unions, and lets one commitment tier cover the combined volume. Separate workspaces per environment or per team give each its own bill, its own retention settings and a clean boundary for who can read what.
A common middle ground is one workspace per environment: production apps share one, test apps another. That keeps a noisy load test from ever touching the production bill or alerts, while cross-service queries in production stay simple.
Who bills what
Because workspace-based Application Insights stores data in a Log Analytics workspace, the workspace bills ingestion and retention, and every Log Analytics pricing option, commitment tiers included, applies. Application Insights itself bills a few features of its own, such as standard availability test runs and alerting on custom metric dimensions. Live Metrics has no data charge. The numbers are in Application Insights pricing.
Troubleshooting
| Error or symptom | Cause | Fix |
|---|---|---|
A workspace query can’t resolve the table requests | Classic table name in a workspace query | Use AppRequests, or run it from the Application Insights Logs blade |
A workspace query can’t resolve the column timestamp | Classic column name in a workspace query | Use TimeGenerated |
| Workspace shows less history than the resource | Pre-migration data lives in the classic store | Query from the Application Insights Logs blade |
| Another team’s requests in your results | Several apps share the workspace | Filter on _ResourceId, or query from the resource |
success == false matches nothing | Classic success is a string | tostring(success) =~ "false", or Success == false in the workspace |
For a plain-language tour of the feature itself, start with What is Application Insights?
Queries for this topic
-
Telemetry volume by table, in GB per day
requestsdependenciesexceptionstracescustomEventspageViewsavailabilityResultsperformanceCounterscustomMetricsbrowserTimings cost
Returns: One row per table with the billed gigabytes over the last 7 complete days, the stored rows, the items they stand for after sampling, and the average gigabytes per day, largest first.
Frequently asked questions
Is Application Insights part of Log Analytics?
Not quite. Application Insights is a feature of Azure Monitor that stores its data in a Log Analytics workspace. You can query that data from the Application Insights resource (classic table names) or from the workspace (App* table names); it is the same data either way.
Which is cheaper, Application Insights or Log Analytics?
Neither, because they aren't billed separately for the same data. Workspace-based Application Insights telemetry is billed by the workspace it's stored in, at Log Analytics rates. What you pay depends on how many GB you send and how long you keep them.
Should I write queries against requests or AppRequests?
New queries, alerts and workbooks: AppRequests in the workspace, which Microsoft marks as recommended. Existing classic-schema queries keep working in the Application Insights Logs blade, so there is no need to rewrite them in a hurry.
Sources, checked
- Azure Monitor overview
- Migrate Application Insights Classic API SDKs to OpenTelemetry (terminology)
- Overview of Log Analytics in Azure Monitor
- Application Insights telemetry data model
- Migrate an Application Insights classic resource to a workspace-based resource
- Query across resources with Azure Monitor
- Azure Monitor Logs cost calculations and options
- Application Insights IP address collection