Skip to content

fix(ui): use entity key for usage export display - #25153

Merged
ryan-crabbe-berri merged 2 commits into
litellm_ryan-apr-4from
litellm_fix-export
Apr 4, 2026
Merged

fix(ui): use entity key for usage export display#25153
ryan-crabbe-berri merged 2 commits into
litellm_ryan-apr-4from
litellm_fix-export

Conversation

@ryan-crabbe-berri

@ryan-crabbe-berri ryan-crabbe-berri commented Apr 4, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Usage exports (tags, orgs, customers, agents, users) were showing a team's name (e.g. "admins") in the entity column instead of the actual entity value.
  • The export util was extracting team_id/key_alias from api_key_breakdown[firstKey].metadata and using that for the display label and ID of every entity type. For team exports the entity key coincidentally equalled team_id, so the bug hid there; for all other entity types the team leaked through.
  • Fix replaces extractTeamIdFromApiKeyBreakdown with resolveEntityDisplay(entity, teamAliasMap) — uses the entity key directly as the ID, and resolves the alias via teamAliasMap (falling back to the entity key for non-team exports).
  • Updates utils.test.ts to match the new semantics: mock entity keys renamed entity1/entity2"team-1"/"team-2" to mirror real team-export payload shape; three tests whose assertions documented the removed behavior were rewritten.

Screenshots

Screenshot 2026-04-04 at 2 55 18 PM

Test plan

  • npx vitest run src/components/EntityUsageExport/ — 83 tests pass
  • QA'd end-to-end against a live proxy with controlled tag test data (3 distinct QA tags generated via tagged completion calls; export CSV showed the tag names in both Tag and Tag ID columns)
  • Verified team export control case still resolves team aliases (DataEnrichment, Alpha, Bravo, etc.)

… api_key_breakdown

The export utility always extracted team_id from api_key_breakdown
metadata to populate the entity label/ID columns. This worked for
team exports (where entity key = team_id) but was wrong for every
other entity type — tags, orgs, customers, agents, users all
showed the API key's team name (e.g. "admins") instead of the
actual entity value.

Replace extractTeamIdFromApiKeyBreakdown with resolveEntityDisplay
which uses the entity key directly. For teams the teamAliasMap
still resolves a human-readable alias; for all other types the
entity key itself is the correct label.
The previous fix (9dca431) switched the export display logic to use the
entity key directly, but left the unit tests asserting the old behavior
where id/alias were extracted from api_key_breakdown metadata.

Rename mock entity keys from entity1/entity2 to "team-1"/"team-2" to
reflect the real shape of team-export payloads (breakdown.entities is
keyed by the entity identifier). Replace three tests whose assertions
documented the removed behavior:

- "should use key alias when available" → entity key is the alias when
  no team alias map is supplied
- "should use team alias map when key alias is not available" → team
  alias map resolves from the entity key
- "should use dash when team id is not available" → entity key itself
  is the fallback label (illustrated with a tag export)
@vercel

vercel Bot commented Apr 4, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
litellm Ready Ready Preview, Comment Apr 4, 2026 9:46pm

Request Review

@greptile-apps

greptile-apps Bot commented Apr 4, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR fixes a bug where entity usage exports (tags, orgs, customers, agents, users) were displaying the team name/ID in the entity column instead of the actual entity value. The root cause was extractTeamIdFromApiKeyBreakdown always reading team_id/key_alias from api_key_breakdown metadata, which happened to be correct for team exports but leaked team data into every other entity type.

The fix introduces a focused resolveEntityDisplay(entity, teamAliasMap) helper that uses the entity key from breakdown.entities directly as the ID, and resolves a human-readable alias from teamAliasMap (falling back to the entity key for non-team exports). This is applied consistently across all four export generators (getEntityBreakdown, generateDailyData, generateDailyWithKeysData, generateDailyWithModelsData).

Key changes:

  • New resolveEntityDisplay helper replaces extractTeamIdFromApiKeyBreakdown at every call site
  • Entity label/ID columns in exported CSVs now correctly reflect the entity type being exported (tag names, customer IDs, etc.) rather than team metadata
  • Tests updated to rename entity1/entity2 fixture keys to \"team-1\"/\"team-2\" to mirror the real backend payload shape, and three test assertions rewritten to document the new semantics

Issue found:

  • One pre-existing test (\"should use dash when team alias is not available\") now has a guarded assertion (if (entryWithoutTeamId)) that silently never executes under the new implementation — the inner expect call is dead code. The test passes vacuously but no longer verifies anything.

Confidence Score: 5/5

Safe to merge — the bug fix is correct and all 83 tests pass; only a vacuous test (P2) warrants a follow-up cleanup.

The implementation change is clean and logically sound. The single issue found is a P2 style/test-quality concern: a guarded assertion that can no longer execute after the behavioral change. It does not mask a regression in the production code path; the correct behavior is covered by other new tests. All remaining findings are P2 and do not affect correctness or data integrity.

utils.test.ts — the "should use dash when team alias is not available" test contains a dead assertion that should be removed or rewritten.

Important Files Changed

Filename Overview
ui/litellm-dashboard/src/components/EntityUsageExport/utils.ts Replaces extractTeamIdFromApiKeyBreakdown with the clean resolveEntityDisplay helper that uses the entity key directly as the ID and resolves a human-readable alias via teamAliasMap — correctly fixing leakage of team metadata into non-team exports.
ui/litellm-dashboard/src/components/EntityUsageExport/utils.test.ts Tests updated to match new semantics with one vacuous test remaining: "should use dash when team alias is not available" has a guarded assertion that can never execute under the new code, effectively removing coverage of that branch without a visible test failure.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A[Export triggered] --> B[resolveEntities breakdown]
    B --> C{breakdown.entities populated?}
    C -- Yes --> D[Use breakdown.entities keyed by entity value e.g. team-id, tag-name, customer-id]
    C -- No --> E[aggregateApiKeysIntoEntities group api_keys by team_id]
    D --> F[resolveEntityDisplay entity, teamAliasMap]
    E --> F
    F --> G{teamAliasMap has entity key?}
    G -- Yes --> H[id = entity key, alias = teamAliasMap lookup e.g. Team One]
    G -- No --> I[id = entity key, alias = entity key e.g. my-tag, customer-42]
    H --> J[Export row: Entity column = alias, Entity ID column = id]
    I --> J
Loading

Comments Outside Diff (1)

  1. ui/litellm-dashboard/src/components/EntityUsageExport/utils.test.ts, line 379-386 (link)

    P2 Vacuous test — inner assertion never executes

    After this PR's change, generateDailyData always uses the entity key (or its alias) for the "Team" / "Team ID" columns — it never emits "-". Because mockSpendData contains entities keyed "team-1" and "team-2", the .find((r) => !r["Team ID"] || r["Team ID"] === "-") predicate returns undefined on every run, so the expect(...) inside the if block is unreachable. The test title implies coverage of a fallback path, but the assertion silently never runs — Vitest reports it as passing because there are zero failed expects.

    This should either be deleted (the new test at line 388 already documents the correct fallback) or rewritten to assert the actual new behavior:

    Rule Used: What: Flag any modifications to existing tests and... (source)

Reviews (1): Last reviewed commit: "test(ui): align EntityUsageExport tests ..." | Re-trigger Greptile

@ryan-crabbe-berri
ryan-crabbe-berri merged commit 55734ee into litellm_ryan-apr-4 Apr 4, 2026
51 of 59 checks passed
@ryan-crabbe-berri
ryan-crabbe-berri deleted the litellm_fix-export branch April 4, 2026 23:14
fzowl pushed a commit to fzowl/litellm that referenced this pull request Jun 24, 2026
fix(ui): use entity key for usage export display
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.

1 participant