Azure Data Explorer Telemetry Digest
Each morning the flow runs KQL queries against an Azure Data Explorer (Kusto) cluster (usage trends, anomaly counts, top errors), formats the results into an HTML report, posts it to a Teams channel, and emails stakeholders. Threshold breaches are highlighted and logged to Dataverse for trend tracking. Turns high-volume telemetry into a daily readout.
Provided as-is, without warranty of any kind. Review and test each pattern in a non-production environment before deploying it to live automations. See our Terms.
Overview
This flow turns an Azure Data Explorer (Kusto) cluster into a daily telemetry readout. Every morning it runs three KQL queries (usage/volume trend, anomaly count, top errors) against a configurable cluster + database, assembles the results into a branded HTML report with threshold-breach highlighting, posts the digest to a Microsoft Teams channel, emails stakeholders, and writes a snapshot row to a Dataverse table for trend tracking.
Why it matters: ADX holds huge volumes of telemetry but nobody opens the Kusto web UI daily. A scheduled digest surfaces the signal — trends, anomalies, top errors — where the team already works, and the Dataverse log builds a day-over-day history.
Status: Built and verified (Flow Checker 0 errors / 0 warnings). Ships Off — going live requires only authorizing the connections and setting the env-var values (cluster URL, database, KQL, Teams IDs, recipients, thresholds).
Use Case
A team storing product/infra telemetry in Azure Data Explorer wants a no-click daily summary — usage volume, anomaly counts, and the worst recurring errors — with breaches flagged, instead of manually opening the Kusto UI. The digest lands in Teams and email each morning, and every run is logged to Dataverse so trends can be charted over time.
Flow Architecture
Daily Telemetry Digest
Recurrence (Day/1, 07:30 ET)Fires the morning digest.
Initialize correlation id, snapshot time + thresholds
Initialize VariableMint a correlation id, capture one consistent utcNow(), and load the anomaly/error thresholds.
Run Usage KQL
Azure Data Explorer — listKustoResultsPostUsage/volume-trend query (returns usageCount).
Run Anomaly KQL
Azure Data Explorer — listKustoResultsPostAnomaly-count query (returns anomalyCount).
Run Top Errors KQL
Azure Data Explorer — listKustoResultsPostTop-errors query (returns errorMessage / errorCount rows).
Compose counts + breach status
ComposeExtract scalar usage/anomaly/top-error counts and set RED if a threshold is breached, else GREEN.
Build error rows + report HTML
Select + ComposeMap each top-error row to an HTML row and assemble the full branded HTML digest.
Post Teams Digest
Microsoft Teams — PostMessageToConversationPosts the digest to the Teams channel.
Send Email Stakeholders
Office 365 Outlook — SendEmailV2Emails the digest with breach status in the subject.
Log Trend Snapshot
Microsoft Dataverse — CreateRecordPersists the daily snapshot row (whole-row Compose bind) for trend tracking.
Environment Variables
| Schema name | Type | Default | Description |
|---|---|---|---|
| flowlibs_AdxClusterUrl | String | https://help.kusto.windows.net | ADX cluster URI the digest queries. |
| flowlibs_AdxDatabase | String | Samples | Target Kusto database. |
| flowlibs_AdxUsageKql | String | Telemetry | where Timestamp > ago(1d) | summarize usageCount = count(), uniqueUsers = dcount(UserId) | Usage/volume query — must return a usageCount column. |
| flowlibs_AdxAnomalyKql | String | Telemetry | where Timestamp > ago(1d) | summarize anomalyCount = countif(Level == 'Critical') | Anomaly query — must return an anomalyCount column. |
| flowlibs_AdxTopErrorsKql | String | Telemetry | where Timestamp > ago(1d) | where Level == 'Error' | summarize errorCount = count() by errorMessage = Message | top 5 by errorCount desc | Top-errors query — returns errorMessage / errorCount rows. |
| flowlibs_AnomalyThreshold | String | 5 | Anomaly count above which the digest is RED. |
| flowlibs_ErrorThreshold | String | 100 | Top-error count above which the digest is RED. |
| flowlibs_TeamsGroupId | String | <your-team-id> | Target Teams team (group) id. |
| flowlibs_TeamsChannelId |
Connectors & Connections
| Connector | API name | Actions used |
|---|---|---|
| Azure Data Explorer | shared_kusto | listKustoResultsPost |
| Microsoft Teams | shared_teams | PostMessageToConversation |
| Office 365 Outlook | shared_office365 | SendEmailV2 |
| Microsoft Dataverse | shared_commondataserviceforapps | CreateRecord |
Note — All connections are referenced as solution connection references; the flow is portable between environments as long as a connection is mapped at import time.
Customization Guide
Almost every realistic variant of this flow can be implemented by changing environment variable values. A few cases require small edits inside the flow definition — those are called out explicitly below.
- Point at your data
- Set flowlibs_AdxClusterUrl + flowlibs_AdxDatabase, then tune the three KQL env vars to your schema (keep the output column names usageCount / anomalyCount / errorMessage / errorCount).
- Statistical anomalies
- Replace the simple countif in flowlibs_AdxAnomalyKql with series_decompose_anomalies() for real anomaly detection, projecting the flagged count as anomalyCount.
- Tune thresholds
- Adjust flowlibs_AnomalyThreshold / flowlibs_ErrorThreshold to control when the digest is flagged RED.
- Per-service digests
- Clone the KQL with a service filter, or wrap the queries in a loop scoped per service.
- Escalation
- Add a Condition after the breach status: on RED, raise a PagerDuty/Teams urgent alert instead of waiting for tomorrow's digest.
- Trend reporting
- Point Power BI at flowlibs_telemetrydigestsnapshots for a day-over-day usage/anomaly/error trend dashboard.
Key Expressions
The flow is intentionally light on Power Fx / WDL gymnastics — the heaviest expressions are the branch-name concatenation and the approval outcome check. They are listed below in the order they appear in the flow.
EXPR.01Scalar read
Read a scalar count from the Kusto result set.
EXPR.02Breach flag
RED when anomalies or top-error count breach thresholds.
EXPR.03Error-row HTML unwrap
Unwrap the Select object output into a clean row string.
EXPR.04Dataverse whole-row bind
Bind the whole snapshot row as one Compose object.
Customize & download
Generate a ready-to-import copy of this solution with your environment-variable values baked in — available on Base, Pro, or Team.
Upgrade to customize
Comments
Sign in to join the conversation.
Sign inNo comments yet. Be the first to share your experience with this flow.