Skip to content

Review app (WinForms)

src/FdaObservability.App is a .NET 8 WinForms desktop app for per-interaction drill-down: search the curated triple, review the full question → generated/executed DAX → answer for any row, and configure scope. It authenticates with the reviewer's own AAD identity (interactive MSAL — no secret on the client) and reads the Eventhouse through the stored KQL functions.

App vs dashboard

The app is for deep, single-interaction review (full DAX text, every query in the turn, errors). The Real-Time Dashboard is for fleet-level trends. Same FdaInteractions table behind both.

Build & run

  1. Open src/FdaObservability.sln in Visual Studio (or dotnet build), targeting .NET 8 / Windows.
  2. Run. On first launch (or incomplete config) the Configuration dialog appears — fill in identity, Eventhouse, and scope, then Test connection and Save.
  3. The main review window opens and runs an initial search over the default lookback window.

Requires the .NET 8 SDK and Windows. The reviewer needs Viewer on the observability KQL database.

Project layout

FdaObservability.App/
├─ Program.cs                 # entry point; forces config on first run, then opens MainForm
├─ app.manifest              # PerMonitorV2 high-DPI, supportedOS
├─ appsettings.sample.json   # seed config copied next to the exe
├─ Models/
│  ├─ AppConfig.cs           # persisted user/instance config (no secrets)
│  └─ Interaction.cs         # one row of FdaInteractions
├─ Services/
│  ├─ AuthService.cs         # interactive AAD (MSAL) → Kusto token
│  ├─ ConfigStore.cs         # load/save %APPDATA%\FdaObservability\config.json
│  └─ KustoService.cs        # queries via stored KQL functions
└─ Forms/
   ├─ ConfigForm.cs          # configuration dialog (code-built UI)
   └─ MainForm.cs            # filter bar + results grid + detail pane

Dependencies

Package Version Role
Microsoft.Identity.Client 4.61.3 Interactive AAD (MSAL) token acquisition
Microsoft.Azure.Kusto.Data 12.2.3 Kusto query provider

Project flags: net8.0-windows, UseWindowsForms, nullable + implicit usings enabled, PerMonitorV2 high-DPI.

Authentication — AuthService

PublicClientApplicationBuilder
    .Create(cfg.ClientId)
    .WithAuthority(AzureCloudInstance.AzurePublic, cfg.TenantId)
    .WithDefaultRedirectUri()   // http://localhost for desktop
    .Build();

GetKustoTokenAsync requests the https://<cluster>.../.default scope derived from the Eventhouse host. It tries silent acquisition from the cached account first and only falls back to interactive (SelectAccount) on MsalUiRequiredException — so the reviewer isn't prompted every launch.

Data access — KustoService

Builds a Kusto connection with WithAadUserTokenAuthentication(token) and exposes:

Method KQL Used for
PingAsync FdaInteractions \| count Connectivity + schema-present test (Configuration dialog)
SearchAsync(...) SearchFdaInteractions(...) The filtered results grid
KpisAsync(from,to) inline summarize The window KPI line (total / with DAX / errors / unmatched)

All user-supplied strings are escaped via a single-quote Lit() helper before being interpolated into KQL. MapRow defensively reads each column by name so a schema addition won't throw.

Configuration — AppConfig / ConfigStore

AppConfig is persisted to %APPDATA%\FdaObservability\config.json (no secrets — interactive AAD only). On first run ConfigStore.Load seeds from appsettings.sample.json shipped next to the exe, if present. IsComplete (Tenant + Client + Query URI + Database) gates whether the Configuration dialog is forced at startup. Full field list: Configuration reference.

UI

Configuration dialog (ConfigForm)

Code-built (no designer) for a self-contained project. Sections: Identity (public-client tenant/client), Observability Eventhouse (query URI/database), Scope (capacity/workspace/agent), Defaults (lookback / max rows). Test connection runs PingAsync against the entered values; Save validates IsComplete before closing.

Main review window (MainForm)

flowchart TD
    bar["Filter bar — search · from/to · user · status · matched-only · Search · ⚙ Config · KPI line"] --> grid
    grid["Results grid — When · User · Host · Question · Status · ms · Match (colour-coded)"] --> detail
    detail["Detail pane — meta line · Question · Generated DAX · Executed DAX (all turn queries) · Answer"]
  • The filter bar drives SearchFdaInteractions; Enter in the search box runs the query. A KPI line summarizes the window.
  • The grid colour-codes MatchConfidence (Exact green, Windowed amber, Unmatched red) and tints Error rows.
  • The detail pane shows the full triple. Generated/Executed DAX render in a monospace font; when the turn had multiple executions, all are listed from the DaxQueries array with per-query duration and status.
  • ⚙ Config reopens the dialog; saving rebuilds the auth + Kusto services and re-runs the search.

Security notes

  • No secrets are stored client-side; tokens are cached in MSAL's encrypted token cache.
  • The app reads only through the stored FDA functions and an inline KPI summarize — all read-only.
  • Restrict the KQL database (and therefore the app) to authorized reviewers, since prompts/answers may contain sensitive data.