Building Investigation Timelines with KQL
Security events rarely happen in isolation.
An email arrives.
A link is clicked.
A sign-in follows.
A process starts on a device.
The truth is often hidden in the order of events.
In this Agent Foskett Academy lesson, you will learn how defenders use timestamps, project, sort, union and clear event labels to build readable investigation timelines inside Microsoft Defender XDR and Microsoft Sentinel.
Lesson overview
Learn how to turn Microsoft Defender XDR telemetry into a clear timeline that explains what happened, when it happened and why it matters.
Why timelines matter
The question is often: what happened first, what happened next and what changed after that?
A timeline helps defenders explain the story in a way that analysts, managers and responders can understand. It also helps separate coincidence from cause and effect.
Investigation scenario
The user clicked the link. Minutes later, there was a suspicious sign-in and then endpoint activity from the same account.
The analyst needs to build a simple timeline so the incident can be explained clearly.
Step 1 — Start with one table and sort by time
- 1
- 2
- 3
- 4
- 5
- 6
- 7
EmailEvents | where Timestamp > ago(7d) | where RecipientEmailAddress == "user@contoso.com" | project Timestamp, RecipientEmailAddress, SenderFromAddress, Subject, DeliveryAction | sort by Timestamp asc
Step 2 — Add an event label
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
EmailEvents | where Timestamp > ago(7d) | where RecipientEmailAddress == "user@contoso.com" | extend EventType = "Email delivered" | project TimelineTime = Timestamp, EventType, Account = RecipientEmailAddress, Detail = Subject, Source = SenderFromAddress | sort by TimelineTime asc
Step 3 — Build a timeline from multiple tables
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
let targetUser = "user@contoso.com"; let emailEvents = EmailEvents | where Timestamp > ago(7d) | where RecipientEmailAddress == targetUser | project TimelineTime = Timestamp, EventType = "Email delivered", Account = RecipientEmailAddress, Detail = Subject, Source = SenderFromAddress; let urlClicks = UrlClickEvents | where Timestamp > ago(7d) | where AccountUpn == targetUser | project TimelineTime = Timestamp, EventType = "URL clicked", Account = AccountUpn, Detail = Url, Source = ActionType; union emailEvents, urlClicks | sort by TimelineTime asc
What union does
For timeline work, this is useful because each table can be shaped into the same column structure first. Once the columns match, the events can be displayed together in time order.
Step 4 — Add sign-in activity
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
SigninLogs | where TimeGenerated > ago(7d) | where UserPrincipalName == "user@contoso.com" | project TimelineTime = TimeGenerated, EventType = "User sign-in", Account = UserPrincipalName, Detail = ResultDescription, Source = IPAddress
Step 5 — Build a fuller incident timeline
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
let targetUser = "user@contoso.com"; let emailEvents = EmailEvents | where Timestamp > ago(7d) | where RecipientEmailAddress == targetUser | project TimelineTime = Timestamp, EventType = "Email delivered", Account = RecipientEmailAddress, Detail = Subject, Source = SenderFromAddress; let urlClicks = UrlClickEvents | where Timestamp > ago(7d) | where AccountUpn == targetUser | project TimelineTime = Timestamp, EventType = "URL clicked", Account = AccountUpn, Detail = Url, Source = ActionType; let signIns = SigninLogs | where TimeGenerated > ago(7d) | where UserPrincipalName == targetUser | project TimelineTime = TimeGenerated, EventType = "User sign-in", Account = UserPrincipalName, Detail = ResultDescription, Source = IPAddress; union emailEvents, urlClicks, signIns | sort by TimelineTime asc
Investigator notes
If another analyst cannot quickly understand the sequence, add clearer labels, remove unnecessary columns and keep the output focused on the investigation question.
What you learned
Continue your investigation
Continue learning with Connecting Tables with join, UrlClickEvents, EmailEvents KQL Guide, KQL Threat Hunting Guide and Microsoft Security.
Develop IT. Protect IT. GEMXIT PTY LTD | GEMXIT UK LTD