KDA: Echoes of Deception - Onboarding
Part of the "Kusto Detective Agency" series:
I’ll walk through the KDA UI and tackle the first challenge before diving into the real cases.
The UI layout ๐︎
This is what your layout might look like:
- LHS menu where you can switch challenges.
- All currently available cases. You’ll start with one and unlock new ones. Ordered like a mailbox, with the oldest at the bottom.
- Flavor text introducing the challenge.
- Ingestion script to load the data into your personal cluster.
- The main question that needs to be answered.
- Answer field โ usually includes hints about the expected answer format.
- Three hints โ IIRC, not all are available from the start; you might need to wait before requesting a hint.
- Training section โ introduces concepts and simpler challenges that help you with the main one.
Solving the case ๐︎
We need to answer this question:
Who is the detective that earned the most money in 2022?
We can see that only one table (DetectiveCases
) was added in the ingestion section. Let’s take a look at its data.
DetectiveCases
| take 50
It looks like the Bounty is a dynamic property and is only assigned when the status is CaseOpened.
We can test that hypothesis:
DetectiveCases
| where isnotempty(Properties)
| take 50
| extend toreal(Properties.Bounty)
Let’s also review all the rows for a single case.
I’ll use CASE_0521475
from the first result set.
DetectiveCases
| where CaseId == "CASE_0521475"
Only the CaseOpened status has a bounty.
I’m also assuming that only the first case solved receives the bounty.
The question specifies the year 2022.
I’ve verified that all values fall within this range.
DetectiveCases
| summarize min(Timestamp), max(Timestamp)
The correct approach is to add the time filter.
Always add the time filter first in Kusto queries to optimize performance due to partitioning.
Final query ๐︎
Putting it all together:
Summary:
- Find all solved cases in 2022 and get the first detective who solved each case.
- Cases may have started in previous years, but only the solve date matters.
- Self-join the data on
CaseId
and parse the bounty from theProperties
column. - Summarize and sort bounties by detective.
DetectiveCases
| where Timestamp >= datetime(2022,1,1) and Timestamp < datetime(2023,1,1)
| where EventType == "CaseSolved"
| summarize arg_min(Timestamp, DetectiveId) by CaseId
| project-rename FirstSolver = DetectiveId
| lookup kind=inner
(
DetectiveCases
| where EventType == 'CaseOpened'
| extend Bounty = toreal(Properties.Bounty)
| where Bounty > 0
| project CaseId, Bounty
) on CaseId
| summarize sum(Bounty) by FirstSolver
| top 3 by sum_Bounty desc
With the onboarding case solved, let’s move on to the first real case.
As always, thank you for reading.