(+351) 21 24 10006  ·  info@bconcepts.pt
Carnaxide, Lisbon

How to aggregate session events in Real-Time Analytics: step by step

João Barros 06 de September de 2026 4 min read

This tutorial shows how to aggregate session events in Real-Time Analytics to obtain per-session metrics (duration, event count, last attributes). Aggregating by session is useful for behavioral analysis, measuring retention and detecting abnormal experiences in real time.

Prerequisites

  • Account and cluster with Real-Time Analytics support (for example, Azure Data Explorer / Kusto).
  • Event data with a session identifier (sessionId), timestamp and event type.
  • Basic knowledge of KQL (Kusto Query Language) and data ingestion.

Step 1: understand the goal and the schema

Before writing the query it is important to know which columns exist: sessionId, timestamp (datetime), eventType and, optionally, userId and properties. The goal is to aggregate by sessionId and produce metrics: start, end, duration, event_count, last_event_type.

Step 2: filter and normalize events

Filter the relevant time range and normalize the timestamp. This reduces processing cost and avoids including old sessions or events outside the window.

Events
| where Timestamp between (ago(1h) .. now())
| where isnotempty(sessionId)

Step 3: aggregate by session for basic metrics

Use summarize to get start, end and count. start=min(Timestamp) and end=max(Timestamp) provide the session period; duration is the difference between them.

Events
| where Timestamp between (ago(1h) .. now())
| where isnotempty(sessionId)
| summarize
    session_start = min(Timestamp),
    session_end = max(Timestamp),
    event_count = count()
  by sessionId, userId
| extend duration_sec = todouble(session_end - session_start) / 1s

Step 4: get the last event and other attributes per session

To know the last event type or the last value of a property use arg_max which selects the row with the highest timestamp per session.

let sessions_basic = Events
| where Timestamp between (ago(1h) .. now())
| where isnotempty(sessionId)
| summarize
    session_start = min(Timestamp),
    session_end = max(Timestamp),
    event_count = count()
  by sessionId, userId;

let sessions_last = Events
| where Timestamp between (ago(1h) .. now())
| where isnotempty(sessionId)
| summarize arg_max(Timestamp, *) by sessionId;

sessions_basic
| join kind=inner (sessions_last) on sessionId
| project sessionId, userId, session_start, session_end, duration_sec, event_count, last_event_type = eventType, last_properties = properties

Step 5: handle inactive sessions and false positives

Not all sessionId values represent valid sessions. Define a minimum threshold for duration or event count to filter noise (e.g., ignore sessions with ≤1 event or duration <5s).

// Filter very short sessions or those with few events
...
| where event_count > 1 and duration_sec > 5

Step 6: produce aggregated metrics in real time

With the sessions processed, compute aggregated metrics by time window (e.g., per minute) for Real-Time Analytics dashboards.

let sessions = (
  // final session query from the previous step
  Events
  | where Timestamp between (ago(1h) .. now())
  | where isnotempty(sessionId)
  | summarize session_start = min(Timestamp), session_end = max(Timestamp), event_count = count() by sessionId
  | extend duration_sec = todouble(session_end - session_start) / 1s
  | where event_count > 1 and duration_sec > 5
);

sessions
| summarize
    avg_duration = avg(duration_sec),
    sessions_count = count(),
    pct_long = 100.0 * sumif(1, duration_sec > 300) / count()
  by bin(session_start, 1m)
| order by session_start desc

Verify the result

To confirm that everything went well: 1) compare the number of original events with the sum of event_count per sessionId (they should match); 2) inspect example sessions (limit 10) to check start/end; 3) validate the aggregated metrics on a real-time dashboard and look for outliers (very long or very short durations).

Conclusion

You can now aggregate events by sessionId in Real-Time Analytics and generate per-session and time-window metrics. Next steps: enrich with segmentation by userId, deviceType or country and export sessions to a downstream ETL/streaming. Tip: if you notice high latency, reduce the query window and pre-aggregate events at ingestion.