KQL · usage
Daily active users and sessions
Distinct users and sessions per day across requests and page views for the last 30 full days, charted, with notes on what the IDs measure.
requestspageViews usage
let lookback = 30d;
union requests, pageViews
| where timestamp >= startofday(ago(lookback)) and timestamp < startofday(now())
| where isnotempty(user_Id)
| summarize
users = dcount(user_Id),
sessions = dcount(session_Id)
by bin(timestamp, 1d)
| order by timestamp asc
| render timechart Returns: One point per UTC day for the last 30 complete days with the number of distinct user IDs and distinct session IDs seen on requests and page views.
Pitfalls
- Users are anonymous IDs kept in a browser cookie. One person on two browsers is two users, and clearing cookies makes a new one.
- API apps called by other services rarely have a user_Id at all, so their traffic drops out at the isnotempty filter. That is correct: they have no users to count.
- dcount() is an estimate on large sets and can't be weighted by itemCount. Under heavy sampling, users with very few requests can be missed entirely.
- A distinct count per day doesn't add up across days: monthly active users is its own query, not the sum of the daily numbers.
How it works
“How many people use this?” is the question every product owner asks of the monitoring team. Application Insights can answer it from the user and session IDs on each item, as long as you know what those IDs measure.
Line by line
let lookback = 30d;covers a month of complete UTC days; the time filter starts at midnight 30 days ago and stops at midnight today, so no partial day drags the end of the line down.union requests, pageViewsreads both tables. Page views come from the browser; requests carry the same IDs when the server picks them up, so a user who only calls your API from a single-page app is still counted.where isnotempty(user_Id)drops items without a user ID, such as calls from other services.dcount(user_Id)anddcount(session_Id)count distinct IDs per day. At the default accuracy,dcount()is exact up to about 1,000 values and an estimate above that, with a documented error of 0.8% (one standard deviation).render timechartdraws one line for users and one for sessions.
What the numbers mean
Microsoft’s usage documentation is plain about it: users are counted by anonymous IDs stored in browser cookies, and a person using different browsers or machines, or clearing cookies, is counted more than once. A session is a period of activity that ends after half an hour of inactivity or 24 hours of continuous use. So treat these as trends, not census figures, and expect them to read higher than a sign-in count.
For a count of signed-in people instead, set the authenticated user ID and count user_AuthenticatedId. API apps without a browser need a different approach to users and sessions altogether, which the users and sessions in API apps guide covers. The JavaScript snippet guide explains where the browser IDs come from.
Variations
- Signed-in users: replace
user_Idwithuser_AuthenticatedIdin the filter and thedcount(). - Per page: see page views by name and country.
- Workspace tables: use
union AppRequests, AppPageViews,TimeGenerated,UserId,SessionIdandUserAuthenticatedId.