Skip to content

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

Open
Ahmed Magdy (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
Ahmed Magdy (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

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.

Ahmed Magdy (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

@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>
Minh Tran (dfx-minhtran) added a commit to dfx-minhtran/copilot-metrics-dashboard that referenced this pull request May 28, 2026
…rics API)

GitHub sunset the legacy /orgs/{org}/copilot/metrics endpoint on
2026-04-02 (changelog: https://github.blog/changelog/2026-01-29-closing-down-notice-of-legacy-copilot-metrics-apis/),
causing every call from copilot-metrics-service.ts to return HTTP 404
and the dashboard to render no data on a fresh deployment.

Switches the live ingestion path to the user-day usage report
(/copilot/metrics/reports/users-28-day/latest), joins each record with
seat assignments from /copilot/billing/seats so team filtering works
without the now-sunset team metrics endpoint, and aggregates results
into the existing CopilotUsageOutput shape so no UI changes are needed.

Also relaxes environment validation: scope=organization no longer
requires GITHUB_ENTERPRISE, scope=enterprise no longer requires
GITHUB_ORGANIZATION, scope defaults to organization when unset.

Adds tsconfig target=es2015 so the build accepts iteration over
Set used by the new aggregation helpers.

Adapted from microsoft#90 by @a-magdy.

Verified:
- npm run build passes
- GET /orgs/dealer-fx/copilot/metrics/reports/users-28-day/latest returns 200
- GET /orgs/dealer-fx/copilot/billing/seats returns 200
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