Skip to content

Telemetry Service

Sam Betts edited this page Jun 23, 2026 · 2 revisions

Telemetry Service

Status: initial scaffold under src/TelemetryService/. The service is being built out — the API endpoint and Cosmos persistence are in place, the visualisation UI and MSAL sign-in are still a work in progress. Tracking issues and PRs will reference this page as it lands.

The Telemetry Service is a small companion web app, shipped alongside the analytics engine in this repository, that receives anonymous usage telemetry from running Microsoft365-Analytics-Insights deployments and visualises it for the project maintainers.

It is not a tenant-facing analytics report. It is the back-office dashboard the project team uses to understand how the engine is deployed in the wild (versions in use, which workloads are enabled, rough dataset sizes), so that compatibility, performance and upgrade work can be prioritised against real usage.

What it is, and what it is not

Audience Project maintainers only.
Hosted instance Private. Sign-in is MSAL-protected; the URL is not for public consumption.
Source code Public — lives in this repo under src/TelemetryService/. Anyone can read, fork, or self-host it.
Tenant data None. The service never sees customer content, user identities, mailboxes, audit events, files, or anything imported by the analytics engine.
What it stores Only the anonymous usage stats described below, keyed by a random per-install client GUID.

What gets sent to the service

Each deployed analytics engine can optionally post an AnonUsageStatsModel payload (defined in the existing UsageReporting library and shared with the Telemetry Service via a project reference). The payload contains:

Field Description
AnonClientId Random GUID generated once per install. Not linked to any tenant, user, domain or subscription.
BuildVersionLabel Build version of the engine sending the report (e.g. release tag).
ConfiguredSolutionsEnabledDescription Which solutions (Analytics, SharePoint Insights, Copilot, …) are switched on.
ConfiguredImportsEnabledDescription Which importers are switched on (SharePoint, Teams, Outlook, Sent Email, Power Platform, …).
TableStats[] Per-SQL-table row count and size in MB. No row content, only table-level totals.
DataPointsFromAITotal Total records enriched by Azure AI Language calls (sentiment / language / keyphrase).
Generated UTC timestamp the snapshot was produced.

Payloads are signed with a shared TelemetrySecret (verified server-side via AnonUsageStatsModel.IsValidSecretForThisObject) so unauthenticated traffic is rejected. Wire format compatibility with already-deployed importers must be preserved when the model evolves.

Architecture

[ Deployed engine ]  --HTTPS POST /api/telemetry-->  [ Telemetry Service ]  -->  [ Cosmos DB ]
   (anon stats)                                       ASP.NET Core API +          - current container
                                                       React / Vite SPA            - history container
                                                       MSAL sign-in (UI)

Components under src/TelemetryService/:

Folder Description
Web.Server/ ASP.NET Core (net10.0) host. Exposes POST /api/telemetry, validates the shared-secret hash, and persists via StatsSaveService + CosmosTelemetrySaveAdaptor from the shared UsageReporting project.
web.client/ React 19 + Vite SPA that will surface the dashboards (versions in use, enabled workloads, table-size distributions, AI usage).
TelemetryService.slnx Slim solution wiring the SPA, the server, and the shared UsageReporting project.

Cosmos DB stores two containers:

  • Current — one document per AnonClientId, overwritten on each update. Used by the dashboard for "what is deployed right now".
  • History — append-only HistoricalUpdate documents, used for trend lines over time.

Authentication

  • Inbound telemetry (engine → service) is authenticated by the per-install shared secret signed into each payload.
  • Cosmos DB access (service → data) uses Microsoft Entra ID (DefaultAzureCredential) — the Cosmos account has local key authorisation disabled, and the service signs in with the developer's Visual Studio / Azure CLI credentials locally and with a managed identity when running in Azure. Set AZURE_TENANT_ID if the Cosmos account is in a different tenant than your default sign-in.
  • Dashboard sign-in (user → UI) will be MSAL-protected (work in progress). Only members of the project maintainer group can load the SPA or query the read APIs.

Configuration

appsettings.json ships with logging defaults only. The runtime settings below come from user-secrets, environment variables, or App Service configuration — never committed:

Setting Required Description
TelemetrySecret yes Shared secret used to verify inbound payload hashes. Must match the secret configured in the importers that send to this instance.
CosmosDb:AccountEndpoint yes Cosmos account URL, e.g. https://<account>.documents.azure.com:443/.
CosmosDb:DatabaseName yes Database name.
CosmosDb:ContainerNameCurrent yes Container for the latest snapshot per client.
CosmosDb:ContainerNameHistory yes Container for historical snapshots.
AZURE_TENANT_ID optional Override when the Cosmos account is in a different Entra tenant than the developer's default sign-in.

Privacy

  • No tenant identifiers, user identifiers, domains, email addresses, file/site URLs, or audit event content are ever sent.
  • The AnonClientId is generated locally by the engine and is not correlatable to any tenant by the project maintainers.
  • Reporting is opt-in at the engine side; nothing is sent unless an operator configures the uploader.

Clone this wiki locally