APM Tips

KQL · cost

Telemetry volume by table, in GB per day

Billed gigabytes per Application Insights table over the last 7 full days, with stored rows, items and the daily average, to see what drives the bill.

Updated

requestsdependenciesexceptionstracescustomEventspageViewsavailabilityResultsperformanceCounterscustomMetricsbrowserTimings cost

let lookback = 7d;
union withsource = source_table
    requests, dependencies, exceptions, traces, customEvents,
    pageViews, availabilityResults, performanceCounters, customMetrics, browserTimings
| where timestamp >= startofday(ago(lookback)) and timestamp < startofday(now())
| summarize
    billed_gb = sum(_BilledSize) / 1e9,
    stored_rows = count(),
    items = sum(coalesce(itemCount, int(1)))
    by source_table
| extend gb_per_day = round(billed_gb / (lookback / 1d), 3)
| extend billed_gb = round(billed_gb, 3)
| order by billed_gb desc

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.

Pitfalls

  • _BilledSize is a hidden standard column: it doesn't appear in the schema list or in results unless you name it, which is why the classic schema tables don't show it. Microsoft documents it on every ingested Application Insights event, for workspace-based and classic resources.
  • Billed size is per stored row. Sampling cuts the bill because it cuts rows; items shows how many events those rows stand for.
  • performanceCounters and customMetrics have no itemCount column, because they are never sampled; coalesce() counts each of their rows once.
  • Queries over raw data for long windows are slow on busy resources. Microsoft suggests restricting such queries to a day and tracking trends elsewhere.

How it works

Application Insights is billed by the gigabyte ingested, and the first step to a smaller bill is knowing which table the gigabytes land in. This query reads every Application Insights table for the last seven complete days and adds up the billed size of each.

Line by line

  • let lookback = 7d; covers a week of complete UTC days: from midnight seven days ago to midnight today.
  • union withsource = source_table ... reads all ten tables and adds a source_table column naming the table each row came from.
  • billed_gb = sum(_BilledSize) / 1e9 adds up the billed bytes. Azure Monitor bills in GB of 10^9 bytes, so dividing by 1e9 gives gigabytes in the unit you are billed by.
  • stored_rows = count() is the number of rows kept, and items = sum(coalesce(itemCount, int(1))) is the number of events they stand for. coalesce() fills in 1 for the two tables that have no itemCount column.
  • gb_per_day divides by the number of days in the window (lookback / 1d), the figure to multiply by your price per GB.

About _BilledSize and the two schemas

The table schemas on Microsoft’s migration page don’t list _BilledSize, which can make it look like a workspace-only column. It isn’t: Microsoft’s usage analysis page says the property is available on each ingested event for both workspace-based and classic resources, and gives a classic-name example (dependencies | summarize sum(_BilledSize) by operation_Name). It is a hidden standard column that only appears when you name it. In the workspace, the same query reads the App* tables, and you can also filter on _IsBillable:

let lookback = 7d;
union withsource = source_table
    AppRequests, AppDependencies, AppExceptions, AppTraces, AppEvents,
    AppPageViews, AppAvailabilityResults, AppPerformanceCounters, AppMetrics, AppBrowserTimings
| where TimeGenerated >= startofday(ago(lookback)) and TimeGenerated < startofday(now())
| where _IsBillable == true
| summarize billed_gb = round(sum(_BilledSize) / 1e9, 3) by source_table
| order by billed_gb desc

Reading the result

Start with the first row. A large traces row is usually verbose logging: see the noisiest trace messages. A large table with items far above stored_rows is already sampled; one with the two equal isn’t, and sampling rate in effect shows which. The pricing guide turns these gigabytes into money and lists the levers, and the sampling guide covers the biggest one.

Sources, checked

  1. Analyze usage in a Log Analytics workspace (Application Insights data volume)learn.microsoft.com · checked
  2. Standard columns in Azure Monitor log records (_BilledSize)learn.microsoft.com · checked
  3. Azure Monitor Logs cost calculations and options (GB is 10^9 bytes)learn.microsoft.com · checked
  4. union operator (Kusto)learn.microsoft.com · checked
  5. Telemetry sampling in Application Insightslearn.microsoft.com · checked
  6. Migrate an Application Insights classic resource to a workspace-based resource (table schemas)learn.microsoft.com · checked