Skip to content

feat: show user display names in usage analytics - #6259

Closed
lingfengchencn wants to merge 2 commits into
QuantumNous:mainfrom
lingfengchencn:codex/add-user-display-names-and-filtering
Closed

feat: show user display names in usage analytics#6259
lingfengchencn wants to merge 2 commits into
QuantumNous:mainfrom
lingfengchencn:codex/add-user-display-names-and-filtering

Conversation

@lingfengchencn

@lingfengchencn lingfengchencn commented Jul 17, 2026

Copy link
Copy Markdown

⚠️ 提交说明 / PR Notice

Important

  • 请提供人工撰写的简洁摘要,避免直接粘贴未经整理的 AI 输出。

📝 变更描述 / Description

  • 日志、异步任务和用户用量看板通过批量用户查询展示当前 display_name,未向历史日志冗余写入显示名称;显示名称缺失时回退到用户名。
  • 用户用量看板新增用户名模糊筛选。筛选先解析当前用户名对应的用户 ID,再查询这些 ID 的全部历史用量,因此用户改名后仍能看到改名前的记录。
  • 用户图表改为按正数 user_id 聚合;多个用户使用相同显示名称时,标签显示为 显示名称 (用户名)。缺少有效用户 ID 的旧数据继续按用户名区分,避免错误合并。
  • 补充后端及前端回归测试,覆盖改名历史、重复显示名称和旧数据兼容场景。

AI-assisted disclosure: 本 PR 的代码与说明由 AI 辅助生成;提交者应在合并前完成最终人工审阅。

🚀 变更类型 / Type of change

  • 🐛 Bug 修复 (Bug fix) - 请关联对应 Issue,避免将设计取舍、理解偏差或预期不一致直接归类为 bug
  • ✨ 新功能 (New feature) - 重大特性建议先通过 Issue 沟通
  • ⚡ 性能优化 / 重构 (Refactor)
  • 📝 文档更新 (Documentation)

🔗 关联任务 / Related Issue

✅ 提交前检查项 / Checklist

  • 人工确认: 我已亲自整理并撰写此描述,没有直接粘贴未经处理的 AI 输出。
  • 非重复提交: 我已搜索现有的 IssuesPRs,确认不是重复提交。
  • Bug fix 说明: 若此 PR 标记为 Bug fix,我已提交或关联对应 Issue,且不会将设计取舍、预期不一致或理解偏差直接归类为 bug。
  • 变更理解: 我已理解这些更改的工作原理及可能影响。
  • 范围聚焦: 本 PR 未包含任何与当前任务无关的代码改动。
  • 本地验证: 已在本地运行并通过测试或手动验证,维护者可以据此复核结果。
  • 安全合规: 代码中无敏感凭据,且符合项目代码规范。

📸 运行证明 / Proof of Work

  • go test ./...
  • bun run typecheckweb/default
  • bun test src/features/dashboard/lib(33 passed, 0 failed)
  • bun run buildweb/default
  • gofmt -d 检查本 PR 修改的 Go 文件,无差异
  • oxfmt --check 检查本 PR 修改的 11 个前端文件,全部通过
  • oxlint 检查除 charts.ts 外的本 PR 前端修改文件,全部通过;charts.ts 的现有基线规则告警未由本 PR 引入

Summary by CodeRabbit

  • New Features

    • Added user display names to log, task, and quota history results.
    • Added username filtering for quota history, including records created under previous usernames.
    • Quota history now includes usernames and display names for clearer identification.
  • Bug Fixes

    • Prevented chart data from merging users who share the same display name.
    • Charts now distinguish duplicate names using the associated username while preserving separate user totals.

@coderabbitai

coderabbitai Bot commented Jul 17, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: e4b4d621-866d-4b8f-96ec-9609b49a5ef8

📥 Commits

Reviewing files that changed from the base of the PR and between 603ba20 and df1e7fc.

📒 Files selected for processing (11)
  • controller/log.go
  • controller/task.go
  • controller/usedata.go
  • controller/usedata_test.go
  • docs/superpowers/specs/2026-07-17-user-chart-identity-design.md
  • dto/task.go
  • model/log.go
  • model/task.go
  • model/usedata.go
  • model/user.go
  • relay/relay_task.go
🚧 Files skipped from review as they are similar to previous changes (10)
  • model/log.go
  • controller/usedata_test.go
  • controller/usedata.go
  • model/user.go
  • controller/task.go
  • relay/relay_task.go
  • controller/log.go
  • model/task.go
  • docs/superpowers/specs/2026-07-17-user-chart-identity-design.md
  • model/usedata.go

Walkthrough

The change adds display-name fields and batch identity resolution for logs, tasks, and quota data. Quota history now filters through matching user IDs, preserves rows across username changes, aggregates by user identity, and documents stable chart identity and label handling.

Changes

User identity presentation

Layer / File(s) Summary
Identity contracts and DTO fields
model/user.go, model/log.go, model/task.go, model/usedata.go, dto/task.go, relay/relay_task.go
Adds non-persisted DisplayName fields, a bulk identity lookup helper, and DTO propagation for task display names.
Log and task identity enrichment
controller/log.go, controller/task.go
Batch-resolves identities and assigns display names to log responses and task DTOs while retaining username mapping.
Quota history identity filtering
model/usedata.go, controller/usedata.go, controller/usedata_test.go, docs/superpowers/specs/2026-07-17-user-chart-identity-design.md
Filters quota history by username-matched user IDs, groups rows by identity, enriches current identity fields, and documents chart disambiguation and regression coverage.

Estimated code review effort: 3 (Moderate) | ~25 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Dashboard
  participant GetQuotaDatesByUser
  participant GetQuotaDataGroupByUser
  participant GetUserIdentitiesByIds
  Dashboard->>GetQuotaDatesByUser: request username-filtered quota history
  GetQuotaDatesByUser->>GetQuotaDataGroupByUser: pass username and time range
  GetQuotaDataGroupByUser-->>GetQuotaDatesByUser: rows grouped by user ID
  GetQuotaDatesByUser->>GetUserIdentitiesByIds: resolve current identities
  GetUserIdentitiesByIds-->>GetQuotaDatesByUser: username and display name
  GetQuotaDatesByUser-->>Dashboard: enriched quota rows
Loading

Poem

I’m a rabbit with names in a row,
Display names bloom where records flow.
Old usernames still leave a trace,
Stable IDs keep every place.
Hop, hop—charts now know each face!

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 35.71% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title is concise and relevant, and it captures the main theme of adding user display names even though it omits logs and tasks.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

🧹 Nitpick comments (1)
model/user.go (1)

1256-1267: 🚀 Performance & Scalability | 🔵 Trivial | 💤 Low value

Pre-allocate map capacity.

Since you know the maximum number of items that will be added to the map (bounded by len(ids) or len(rows)), consider pre-allocating the map capacity to avoid reallocation overhead.

♻️ Proposed refactor
-	result := make(map[int]UserIdentity)
 	if len(ids) == 0 {
-		return result, nil
+		return make(map[int]UserIdentity), nil
 	}
 	var rows []UserIdentity
 	if err := DB.Model(&User{}).Select("id, username, display_name").Where("id IN ?", ids).Find(&rows).Error; err != nil {
 		return nil, err
 	}
+	result := make(map[int]UserIdentity, len(rows))
 	for _, r := range rows {
 		result[r.Id] = r
 	}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@model/user.go` around lines 1256 - 1267, Update the result map initialization
in the user identity lookup function to pre-allocate capacity based on len(ids),
preserving the existing empty-input, query, and population behavior.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@docs/superpowers/specs/2026-07-17-user-chart-identity-design.md`:
- Line 12: Update the user chart identity design document’s response/type
contract and username-filtering statements to match the implemented behavior,
including display_name. Replace the documented full-width Chinese-parenthesis
label format with the implemented `display name (username)` format wherever the
disambiguation behavior is described, including the referenced lines.

In `@web/default/src/features/dashboard/components/users/user-charts.tsx`:
- Around line 239-244: Add an accessible, localized name to the username filter
Input by supplying an aria-label through the existing t translation helper,
while preserving its current value, change handler, placeholder, and styling.

In `@web/default/src/features/dashboard/lib/charts.test.ts`:
- Around line 1-2: Update the test imports and assertions in the chart utility
test to use Vitest: replace node:test and node:assert with Vitest’s test and
expect APIs, and change assert.deepEqual assertions to expect(...).toEqual(...).
Keep the existing test behavior unchanged.

In `@web/default/src/features/dashboard/lib/charts.ts`:
- Around line 779-786: Update the label-generation logic around labelByKey to
track final labels already assigned and ensure every candidate is globally
unique; when a candidate collides, append an additional deterministic suffix
while preserving existing duplicate-base-label behavior. Add a regression test
covering a natural label collision such as “Alice (bob)” versus “Alice” with
username “bob”, verifying distinct series labels and color-map keys.

---

Nitpick comments:
In `@model/user.go`:
- Around line 1256-1267: Update the result map initialization in the user
identity lookup function to pre-allocate capacity based on len(ids), preserving
the existing empty-input, query, and population behavior.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 673d6f6b-5d24-4a6b-822c-a84c40779b7c

📥 Commits

Reviewing files that changed from the base of the PR and between a63364d and 603ba20.

📒 Files selected for processing (22)
  • controller/log.go
  • controller/task.go
  • controller/usedata.go
  • controller/usedata_test.go
  • docs/superpowers/specs/2026-07-17-user-chart-identity-design.md
  • dto/task.go
  • model/log.go
  • model/task.go
  • model/usedata.go
  • model/user.go
  • relay/relay_task.go
  • web/default/src/features/dashboard/api.ts
  • web/default/src/features/dashboard/components/users/user-charts.tsx
  • web/default/src/features/dashboard/index.tsx
  • web/default/src/features/dashboard/lib/charts.test.ts
  • web/default/src/features/dashboard/lib/charts.ts
  • web/default/src/features/dashboard/types.ts
  • web/default/src/features/usage-logs/components/columns/common-logs-columns.tsx
  • web/default/src/features/usage-logs/components/columns/task-logs-columns.tsx
  • web/default/src/features/usage-logs/components/usage-logs-mobile-card.tsx
  • web/default/src/features/usage-logs/data/schema.ts
  • web/default/src/features/usage-logs/types.ts

Comment thread docs/superpowers/specs/2026-07-17-user-chart-identity-design.md
Comment on lines +239 to +244
<Input
value={username}
onChange={(e) => handleUsernameChange(e.target.value)}
placeholder={t('Filter by username')}
className='h-8 w-36 shrink-0 text-xs sm:w-44'
/>

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔒 Security & Privacy | 🟡 Minor | ⚡ Quick win

Give the username filter an accessible name.

The input relies solely on its placeholder, so assistive technology lacks a reliable label. Add a localized aria-label or visible <label>.

Proposed fix
 <Input
   value={username}
   onChange={(e) => handleUsernameChange(e.target.value)}
+  aria-label={t('Filter by username')}
   placeholder={t('Filter by username')}

As per coding guidelines, associate form inputs with labels and add ARIA attributes when needed. <coding_guidelines>

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
<Input
value={username}
onChange={(e) => handleUsernameChange(e.target.value)}
placeholder={t('Filter by username')}
className='h-8 w-36 shrink-0 text-xs sm:w-44'
/>
<Input
value={username}
onChange={(e) => handleUsernameChange(e.target.value)}
aria-label={t('Filter by username')}
placeholder={t('Filter by username')}
className='h-8 w-36 shrink-0 text-xs sm:w-44'
/>
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@web/default/src/features/dashboard/components/users/user-charts.tsx` around
lines 239 - 244, Add an accessible, localized name to the username filter Input
by supplying an aria-label through the existing t translation helper, while
preserving its current value, change handler, placeholder, and styling.

Source: Coding guidelines

Comment on lines +1 to +2
import assert from 'node:assert/strict'
import { test } from 'node:test'

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📐 Maintainability & Code Quality | 🟠 Major | ⚡ Quick win

Use Vitest for this frontend utility test.

The new test uses node:test and node:assert, bypassing the project’s prescribed frontend test runner.

Proposed fix
-import assert from 'node:assert/strict'
-import { test } from 'node:test'
+import { expect, test } from 'vitest'

Replace assert.deepEqual(actual, expected) with expect(actual).toEqual(expected).

As per coding guidelines, unit tests under web/default/**/*.test.ts must use Vitest. <coding_guidelines>

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
import assert from 'node:assert/strict'
import { test } from 'node:test'
import { expect, test } from 'vitest'
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@web/default/src/features/dashboard/lib/charts.test.ts` around lines 1 - 2,
Update the test imports and assertions in the chart utility test to use Vitest:
replace node:test and node:assert with Vitest’s test and expect APIs, and change
assert.deepEqual assertions to expect(...).toEqual(...). Keep the existing test
behavior unchanged.

Source: Coding guidelines

Comment on lines +779 to +786
const labelByKey = new Map<string, string>()
for (const [key, identity] of identityByKey) {
const duplicate = (baseLabelCounts.get(identity.baseLabel) || 0) > 1
const suffix = identity.username || key.replace(/^id:/, '#')
labelByKey.set(
key,
duplicate ? `${identity.baseLabel} (${suffix})` : identity.baseLabel
)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Guarantee that final chart labels are globally unique.

Disambiguating only duplicate base labels can still collide with another identity’s natural label—for example, Alice (bob) and Alice with username bob. Both then use the same seriesField and color-map key, so separate identities can render as one series.

Track used final labels and append an additional stable suffix when a candidate already exists. Add a regression case for this collision.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@web/default/src/features/dashboard/lib/charts.ts` around lines 779 - 786,
Update the label-generation logic around labelByKey to track final labels
already assigned and ensure every candidate is globally unique; when a candidate
collides, append an additional deterministic suffix while preserving existing
duplicate-base-label behavior. Add a regression test covering a natural label
collision such as “Alice (bob)” versus “Alice” with username “bob”, verifying
distinct series labels and color-map keys.

@lingfengchencn
lingfengchencn force-pushed the codex/add-user-display-names-and-filtering branch from 603ba20 to df1e7fc Compare July 21, 2026 04:06
@seefs001 seefs001 closed this Jul 21, 2026
@seefs001

Copy link
Copy Markdown
Collaborator

本项目支持使用AI辅助开发,但是不代表人可以直接不看代码。
提交前检查项 / Checklist 并不是摆设。

@lingfengchencn

Copy link
Copy Markdown
Author

本项目支持使用AI辅助开发,但是不代表人可以直接不看代码。 提交前检查项 / Checklist 并不是摆设。

额,这个我测试验证了哇...是checklist 问题?

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.

2 participants