Analyst queries¶
Ready-to-paste KQL for the KQL query editor, from
fabric/kql/03_queries.kql.
These are ad-hoc — they are not part of provisioning.
The triple, most recent first¶
FdaInteractions
| order by Timestamp desc
| project Timestamp, User, Question, GeneratedDax, ExecutedDax, Answer, Status, DurationMs, MatchConfidence
| take 100
Pipeline health — are we capturing & correlating?¶
FdaInteractions
| summarize Total=count(),
WithQuestion=countif(isnotempty(Question)),
WithDax=countif(isnotempty(ExecutedDax)),
WithAnswer=countif(isnotempty(Answer)),
Unmatched=countif(MatchConfidence=="Unmatched")
by bin(Timestamp, 1h)
| order by Timestamp desc
A healthy pipeline shows most rows with question, DAX, and answer populated, and a low Unmatched count.
Source coverage — which surfaces are feeding us¶
FdaInteractions
| mv-expand Source = Sources to typeof(string)
| summarize Interactions=count() by Source, bin(Timestamp, 1d)
| order by Timestamp desc
If monitoring is present but graph is missing, you're getting DAX without question/answer text (check the Graph
user set / permissions). If graph is present but monitoring is missing, check workspace monitoring.
Tuning — slowest generated DAX¶
FdaInteractions
| where isnotempty(ExecutedDax)
| top 50 by DurationMs desc
| project Timestamp, User, DurationMs, CpuTimeMs, Question, ExecutedDax
Tuning — failing questions¶
NL2DAX errors / empty results / unmatched rows — the review backlog. See
FdaFailures.
Tuning — top question patterns¶
The highest-volume normalized questions — prime candidates to add as FDA example queries. See
FdaTopQuestions.
Raw executed DAX (debug correlation gaps)¶
Raw_ExecutedDax
| where Timestamp > ago(1d) and isnotempty(Dax)
| project Timestamp, ExecutingUser, SemanticModelName, DurationMs, CpuTimeMs, Status, Dax
| order by Timestamp desc
| take 100
Use this when curated rows are Unmatched — confirm the DAX is arriving from monitoring, then check the user /
time-window join.
SDK replay vs production¶
Raw_SdkRuns
| where ReplayedAt > ago(7d)
| extend QNorm = trim(@"\s+", tolower(Question))
| join kind=leftouter (
FdaInteractions
| where isnotempty(Question)
| extend QNorm = trim(@"\s+", tolower(Question))
| summarize arg_max(Timestamp, ExecutedDax) by QNorm
) on QNorm
| project Question, SdkStatus=Status, SdkGeneratedQueries=GeneratedQueries,
ProdExecutedDax=ExecutedDax
| take 100
Compares the SDK replay reconstruction to what M365 actually executed.
Did a specific user's question get a DAX match?¶
let u = "user@contoso.com";
Raw_GraphInteractions
| where User == u and InteractionType == "userPrompt"
| project PromptTime=CreatedDateTime, Question=Body
| join kind=leftouter (
Raw_ExecutedDax | where ExecutingUser == u | project DaxTime=Timestamp, Dax
) on $left.PromptTime == $right.DaxTime
| project PromptTime, Question, DaxTime, Dax
| order by PromptTime desc
A per-user correlation spot-check straight against the raw tables.
Quick verification (after first run)¶
FdaInteractions | take 50
FdaInteractions | summarize count() by MatchConfidence, bin(Timestamp, 1h)
If FdaInteractions has rows with GeneratedDax populated and MatchConfidence != "Unmatched", the pipeline
works.