Skip to content

Migrate metrics to the user-day usage report (legacy /copilot/metrics API was sunset 2026-04-02)#90

Open
a-magdy wants to merge 3 commits into
microsoft:mainfrom
a-magdy:feat/user-day-metrics-and-seats
Open

Migrate metrics to the user-day usage report (legacy /copilot/metrics API was sunset 2026-04-02)#90
a-magdy wants to merge 3 commits into
microsoft:mainfrom
a-magdy:feat/user-day-metrics-and-seats

Conversation

@a-magdy
Copy link
Copy Markdown

@a-magdy a-magdy commented Apr 30, 2026

Warning

The Copilot Metrics API used by main was sunset on 2026-04-02.
Without this PR, every metrics call from services/copilot-metrics-service.ts returns 404 and the dashboard renders no data on a fresh deployment today.
Tracking issue: microsoft/copilot-metrics-dashboard#87 · GitHub changelog: "Closing down notice of legacy Copilot metrics APIs" (2026-01-29).

Closes #87

What this changes

This PR rewires services/copilot-metrics-service.ts to source metrics from the user-day usage report instead of the per-day metrics endpoint, joins the result with seat assignments, and relaxes environment-variable validation so org-only deployments don't have to set GITHUB_ENTERPRISE.

The output type (CopilotUsageOutput[]) consumed by the dashboard UI is unchanged, so no UI work is required.

See #87 for the rationale and docs/metrics-ingestion.md added in this PR for an end-to-end walkthrough.

Data flow summary

GET /copilot/metrics/reports/users-28-day/latest
  -> { download_links: [...] }
  -> for each link, GET <link>
       -> JSON or NDJSON of UsageMetricsUserDayRecord rows

GET /copilot/billing/seats?per_page=100  (paginated)
  -> SeatAssignment[]
  -> derive userLogin -> teams[] map

Join, filter by date / team, aggregate by (day, language, IDE, feature),
output CopilotUsageOutput[].

Why move off the per-day endpoint?

The per-day endpoint (/orgs/{org}/copilot/metrics) returns counters already aggregated by day/IDE/language. It does not expose per-user data, so we couldn't:

  • Distinguish licensed-but-inactive users from engaged ones.
  • Group by team without one extra API call per team.
  • Cleanly separate chat usage from completion usage.

The user-day usage report exposes the underlying per-user, per-day rows. All three become local computations; the cost is the extra download + aggregation that this PR adds.

Why touch env-service.ts?

Today the validator requires all of GITHUB_ORGANIZATION, GITHUB_ENTERPRISE, GITHUB_TOKEN, GITHUB_API_VERSION regardless of GITHUB_API_SCOPE. That contradicts the README and forces org-scope users to set a dummy GITHUB_ENTERPRISE value. This PR makes the requirement scope-aware:

  • scope=organization → require GITHUB_ORGANIZATION, ignore GITHUB_ENTERPRISE.
  • scope=enterprise → require GITHUB_ENTERPRISE, ignore GITHUB_ORGANIZATION.
  • scope defaults to organization if unset.

Why tsconfig.json?

The new aggregation iterates over Set values. TypeScript's default target: "es5" rejects native for ... of over Set (--downlevelIteration would also work but is global noise). Setting target: "es2015" is the simplest fix and matches what every supported Node version runs natively.

Files

File Change
src/dashboard/services/copilot-metrics-service.ts Switch live ingestion to the user-day usage report; join with seat data; aggregate by day/team/feature. File header explains the three back-ends.
src/dashboard/services/env-service.ts Scope-aware env validation, default scope to organization.
src/dashboard/tsconfig.json target: "es2015".
docs/metrics-ingestion.md End-to-end documentation of the new flow, field reference, and migration rationale.

Verification

  • npm run build — lint + type-check + production build all pass.
  • npm run dev/ and /seats render against a live org.

Notes for reviewers

  • Each download_link may return either a JSON array or NDJSON; both are handled in parseUsageUserReport.
  • All HTTP calls use cache: "no-store" because the dashboard always wants fresh data.
  • A user is "engaged" on a day when any activity counter or LOC sum is > 0 (hasUsageActivity).
  • Chat-vs-completion classification is feature-name based: chat_* or anything containing agent is chat; everything else is treated as completion.

Context — why now?

The user-day usage report API didn't exist when the dashboard was last updated.

Date Event
Oct 2024 Per-day Copilot Metrics API (the one main currently uses) goes GA.
Feb 2025 Beta /usage endpoints deprecated.
2025-07-29 Last upstream commit on main (01ef37d).
2025-10-28 Copilot usage metrics dashboard + user-day usage report API enters public preview (changelog). This is the /copilot/metrics/reports/users-28-day/latest endpoint this PR adopts.

So the new endpoint is roughly three months newer than main. The motivation for switching to it (per-user granularity, native team attribution, clean chat-vs-completion split) is described in #87.

a-magdy and others added 2 commits April 29, 2026 18:16
Switch the GitHub-API metrics path to consume the user-day usage report
(`/copilot/metrics/reports/users-28-day/latest`), correlate each record
with seat assignments, and aggregate results into the existing
CopilotUsageOutput shape so the dashboard renders without further
changes.

- copilot-metrics-service.ts: download the report, join with
  /copilot/billing/seats data, and roll usage up by day plus team.
- env-service.ts: only require GITHUB_ORGANIZATION when scope is
  organization, and only require GITHUB_ENTERPRISE when scope is
  enterprise; default scope to organization.
- tsconfig.json: set target to es2015 so the build accepts iteration
  over Set used by the new aggregation helpers.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Adds docs/metrics-ingestion.md with a sequence overview, field
  reference, and an explanation of why we moved off the per-day
  metrics endpoint.
- Adds a file header to copilot-metrics-service.ts so the three
  back-ends (CosmosDB / GitHub API / sample) are obvious to the next
  reader.

Refs #2

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@a-magdy
Copy link
Copy Markdown
Author

a-magdy commented Apr 30, 2026

@microsoft-github-policy-service agree

…trics migration

- Replace stale /copilot/metrics API link with users-28-day report endpoint
- Link to docs/metrics-ingestion.md from the intro
- Replace bullet-list env var sections with tables; clarify that only
  GITHUB_ORGANIZATION or GITHUB_ENTERPRISE is needed depending on scope
  (GITHUB_API_VERSION added as it was previously undocumented)
- Update Azure deploy prereqs and azd example to show scope-conditional
  org/enterprise values; note that Bicep still requires both at deploy time

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

The Copilot Metrics API will sunset on April 2, 2026

1 participant