Skip to content

Show Agents usage metrics on the System Console System Statistics page#894

Open
nickmisasi wants to merge 16 commits into
masterfrom
cursor/agents-usage-system-statistics-262a
Open

Show Agents usage metrics on the System Console System Statistics page#894
nickmisasi wants to merge 16 commits into
masterfrom
cursor/agents-usage-system-statistics-262a

Conversation

@nickmisasi

@nickmisasi nickmisasi commented Jul 17, 2026

Copy link
Copy Markdown
Collaborator

Summary

Adds in-product visibility of Agents usage for admins on System Console → Reporting → Site Statistics, without any core Mattermost changes:

  • Always-on daily usage recording: every completion's aggregated token usage is upserted into a new plugin table LLM_Usage_Daily (Day, UserID, BotID PK; IsGuest, IsBot, InputTokens, OutputTokens, Cost). Recording is independent of EnableTokenUsageLogging, which remains purely an export (file/plugin-log) concern. Guest/bot status is snapshotted at usage time; MAU/active-user queries exclude guests and bot-originated usage, while token/cost totals include everything. No backfill — counting starts when this ships.
  • New sysadmin endpoint GET /plugins/mattermost-ai/admin/stats returning MAU, per-agent MAU (with display names), unique users over 7/60/90 days, 30-day token/cost totals, and a zero-filled 30-day tokens-per-day series.
  • Webapp site statistics handler (registerSiteStatisticsHandler) rendering six count tiles (Agents MAU, users 7/60/90d, tokens 30d, cost 30d), a "Monthly Active Users per Agent" doughnut, and an "Agents Tokens per Day (Input vs. Output)" line chart on the core System Statistics page. The handler resolves to {} on any failure so it can never break the page.
  • Data retention: the existing RunDataRetention hook now also purges usage rows older than the global message retention window when DataRetentionSettings.EnableMessageDeletion is enabled (enterprise-licensed servers).
  • Bug fix: TokenUsageLoggingWrapper previously consumed EventTypeUsage events when token usage logging was enabled, so LLM_Turns.TokensIn/TokensOut were persisted as 0. Usage events are now forwarded downstream while still being aggregated for the sinks.

QA test steps: enable the plugin, have users converse with agents, then open System Console → Reporting → Site Statistics as a sysadmin; the Agents tiles and charts appear below the built-in stats (they show zeros until usage accrues). GET /plugins/mattermost-ai/admin/stats returns the same data as JSON.

Demo against a seeded server (6 human users, 2 agents, ~40 days of usage; guest and bot rows seeded to verify exclusion):

agents_usage_metrics_system_console_demo.mp4

Screenshots

Agents count tiles on System Statistics
MAU per agent doughnut with tooltip
Tokens per day line chart

Release Note

Added Agents usage statistics to the System Console System Statistics page: monthly active users (overall and per agent, excluding guests and bots), unique users over 7/60/90 days, and 30-day token and estimated cost totals with a tokens-per-day chart. Added a new plugin database table LLM_Usage_Daily that records daily per-user token usage aggregates, and a new system admin endpoint GET /plugins/mattermost-ai/admin/stats. Usage rows are purged by the enterprise data retention job when message deletion is enabled. Fixed token usage logging consuming usage events, which caused conversation turns to persist zero token counts when token usage logging was enabled.

To show artifacts inline, enable in settings.

Open in Web Open in Cursor 

Summary by CodeRabbit

  • New Features
    • Added an admin usage statistics endpoint with active-user, token, cost, and per-agent metrics.
    • Added System Console analytics displaying monthly active users, token totals, costs, and usage charts.
    • Added persistent daily usage tracking and automatic retention cleanup.
    • Added token usage recording across bot and user interactions.
  • Bug Fixes
    • Improved bot identity tracking for usage reporting.
    • Added zero-filled results for missing daily usage data.
  • Tests
    • Added comprehensive API, storage, recorder, UI, and end-to-end coverage.

@github-actions

github-actions Bot commented Jul 17, 2026

Copy link
Copy Markdown

🤖 LLM Evaluation Results

OpenAI

⚠️ Overall: 21/28 tests passed (75.0%)

Provider Total Passed Failed Pass Rate
⚠️ OPENAI 28 21 7 75.0%

❌ Failed Evaluations

Show 7 failures

OPENAI

1. TestReactEval/[openai]_react_cat_message

  • Score: 0.00
  • Rubric: The word/emoji is a cat emoji or a heart/love emoji
  • Reason: The output is the text string "smiley_cat", not an actual cat emoji (e.g., 😺/🐱) or a heart/love emoji (e.g., ❤️/💕).

2. TestConversationMentionHandling/[openai]_conversation_from_attribution_long_thread.json

  • Score: 0.00
  • Rubric: is a list of bugs
  • Reason: The output does not provide a list of bugs; it states inability to create the list and requests the user to paste bug reports, only listing desired table columns and input formats.

3. TestConversationMentionHandling/[openai]_conversation_from_attribution_long_thread.json

  • Score: 0.00
  • Rubric: includes a description of each bug
  • Reason: The output does not include descriptions of any specific bugs; it requests the user to paste bug reports and only lists intended table columns. Therefore it does not include a description of each bug.

4. TestConversationMentionHandling/[openai]_conversation_from_attribution_long_thread.json

  • Score: 0.00
  • Rubric: attributes each bug to a user
  • Reason: The output does not attribute each bug to a user; it states it cannot create the list yet and asks the user to paste bug reports. No bugs are listed and no per-bug 'Reported by' attribution is provided.

5. TestConversationMentionHandling/[openai]_conversation_from_attribution_long_thread.json

  • Score: 0.00
  • Rubric: attributes the bug about trying to save without a color and the save button not doing anything to @maria.nunez
  • Reason: The output does not mention the specific bug about trying to save without a color or the save button not doing anything, nor does it attribute that bug to @maria.nunez. It only asks for bug reports to be pasted.

6. TestConversationMentionHandling/[openai]_conversation_from_attribution_long_thread.json

  • Score: 0.00
  • Rubric: the bug about the end user being able to change channel banner is attributed to @maria.nunez
  • Reason: The output does not mention any specific bug about an end user being able to change the channel banner, nor does it attribute that bug to @maria.nunez. It only asks for bug reports to be pasted.

7. TestDirectMessageConversations/[openai]_bot_dm_tool_introspection

  • Score: 0.00
  • Rubric: mentions Github and refers to the documentation
  • Reason: The output refers to documentation (Mattermost documentation) but does not mention GitHub anywhere. Since the rubric requires both mentioning GitHub and referring to the documentation, it fails.

Anthropic

⚠️ Overall: 21/28 tests passed (75.0%)

Provider Total Passed Failed Pass Rate
⚠️ ANTHROPIC 28 21 7 75.0%

❌ Failed Evaluations

Show 7 failures

ANTHROPIC

1. TestReactEval/[anthropic]_react_cat_message

  • Score: 0.00
  • Rubric: The word/emoji is a cat emoji or a heart/love emoji
  • Reason: The output is the text string "heart_eyes_cat" rather than an actual cat emoji or a heart/love emoji.

2. TestConversationMentionHandling/[anthropic]_conversation_from_attribution_long_thread.json

  • Score: 0.00
  • Rubric: is a list of bugs
  • Reason: The output states it cannot access bug trackers and suggests ways to compile a list, but it does not actually provide any bugs or a list of bugs.

3. TestConversationMentionHandling/[anthropic]_conversation_from_attribution_long_thread.json

  • Score: 0.00
  • Rubric: includes a description of each bug
  • Reason: The output does not list any bugs or provide descriptions of each bug; it only explains inability to access trackers and suggests ways to compile a list.

4. TestConversationMentionHandling/[anthropic]_conversation_from_attribution_long_thread.json

  • Score: 0.00
  • Rubric: attributes each bug to a user
  • Reason: The output does not list any bugs at all, and therefore does not attribute each bug to a user. It only states inability to access trackers and suggests ways to compile a list.

5. TestConversationMentionHandling/[anthropic]_conversation_from_attribution_long_thread.json

  • Score: 0.00
  • Rubric: attributes the bug about trying to save without a color and the save button not doing anything to @maria.nunez
  • Reason: The output does not mention @maria.nunez, nor does it attribute any bug (including saving without a color or the save button doing nothing) to her. It only states inability to access trackers and suggests ways to compile a list.

6. TestConversationMentionHandling/[anthropic]_conversation_from_attribution_long_thread.json

  • Score: 0.00
  • Rubric: the bug about the end user being able to change channel banner is attributed to @maria.nunez
  • Reason: The output only states it cannot access bug tracking systems and suggests ways to compile a list; it does not mention the specific bug about an end user changing the channel banner, nor does it attribute that bug to @maria.nunez.

7. TestDirectMessageConversations/[anthropic]_bot_dm_tool_introspection

  • Score: 0.50
  • Rubric: mentions Github and refers to the documentation
  • Reason: The output refers to documentation (docs.mattermost.com) but does not mention GitHub anywhere, so it does not satisfy the requirement to mention GitHub and refer to the documentation.

This comment was automatically generated by the eval CI pipeline.

@coderabbitai

coderabbitai Bot commented Jul 17, 2026

Copy link
Copy Markdown

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Adds daily LLM usage persistence and retention, records streamed token usage, exposes authenticated admin statistics, and renders localized site analytics with charts. The change includes dependency wiring, bridge identity enrichment, migrations, unit tests, and end-to-end coverage.

Changes

Usage statistics and token tracking

Layer / File(s) Summary
Daily usage storage and retention
store/migrations/*, store/usage.go, usage/*, server/data_retention*
Adds the daily usage schema, aggregation queries, recording adapter, batched deletion, retention orchestration, and tests for persistence and cleanup behaviour.
LLM token recording
llm/token_usage_recorder.go, llm/token_tracking.go, bots/*, conversations/*, api/api_llm_bridge*, server/main.go
Forwards aggregated stream usage to a recorder, preserves downstream events, tracks user and bot identity, wires the recorder into bot services, and enriches bridge request context.
Admin statistics API
api/api.go, api/api_stats.go, api/*stats*_test.go, api/api_admin_test.go
Adds the authenticated /admin/stats route, rolling-window queries, display-name resolution, token totals, zero-filled daily data, and API dependency wiring.
Site statistics reporting UI
webapp/src/client.tsx, webapp/src/site_stats.tsx, webapp/src/index.tsx, webapp/src/types/*, webapp/src/i18n/*, Makefile
Adds typed API access, localized analytics rows, per-agent and per-day charts, plugin registration, translations, extraction coverage, and frontend tests.
System-console validation
e2e/tests/system-console/usage_statistics.spec.ts, e2e/scripts/ci-test-groups.mjs
Validates zero-filled admin API responses, authorization, rendered analytics tiles, chart labels, and CI shard inclusion.

Estimated code review effort: 4 (Complex) | ~60 minutes

Sequence Diagram(s)

sequenceDiagram
  participant LLM
  participant TokenUsageLoggingWrapper
  participant UsageRecorder
  participant Store
  participant AdminStatsAPI
  participant SiteStatisticsUI

  LLM->>TokenUsageLoggingWrapper: Stream usage events
  TokenUsageLoggingWrapper->>UsageRecorder: Record aggregated token usage
  UsageRecorder->>Store: IncrementDailyUsage
  AdminStatsAPI->>Store: Query active users and token totals
  Store-->>AdminStatsAPI: Usage statistics
  SiteStatisticsUI->>AdminStatsAPI: GET /admin/stats
  AdminStatsAPI-->>SiteStatisticsUI: UsageStatsResponse
Loading
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 18.52% 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 clearly matches the main change: adding Agents usage metrics to the System Console statistics page.
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
  • Commit unit tests in branch cursor/agents-usage-system-statistics-262a

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

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 5

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
llm/token_tracking.go (1)

82-125: 🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

Don’t let token persistence block stream shutdown. emitTokenUsage() runs before interceptedStream is closed, and RecordTokenUsage() passes the detached context into store.IncrementDailyUsage(). A slow or hung write can hold this goroutine open and leave range-based consumers waiting. Wrap the recorder call in a short timeout or move it onto a bounded worker path.

🤖 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 `@llm/token_tracking.go` around lines 82 - 125, The stream-forwarding goroutine
must not wait indefinitely for token persistence before closing
interceptedStream. Update the hasUsage path around emitTokenUsage and
RecordTokenUsage so persistence runs with a short bounded timeout or through a
bounded asynchronous worker, while preserving usage aggregation and ensuring
interceptedStream is closed promptly even when store.IncrementDailyUsage is slow
or hung.
🧹 Nitpick comments (4)
store/usage_test.go (1)

383-438: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Convert the deletion subtests to a table-driven test.

Represent seed dates, cutoff, batch size, and expected deletion counts as cases instead of duplicating setup and invocation logic.

As per coding guidelines, “Go tests must be table-driven when they contain more than one case.”

🤖 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 `@store/usage_test.go` around lines 383 - 438, Convert TestDeleteUsageBefore
into a table-driven test by defining cases containing seed dates, cutoff, batch
size, and expected deletion counts. Iterate over the cases with subtests,
reusing shared store setup, seeding, invoking DeleteUsageBefore, and asserting
results; preserve the existing exclusive-cutoff, batch-limit, and empty-store
behaviors.

Source: Coding guidelines

usage/recorder.go (1)

41-58: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Add the required OpenTelemetry span to this LLM-path entry point.

Start the repository-standard span in RecordTokenUsage and pass its derived context to IncrementDailyUsage.

As per coding guidelines, “add OpenTelemetry spans with the repo's telemetry helpers and attribute keys.”

🤖 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 `@usage/recorder.go` around lines 41 - 58, The RecordTokenUsage entry point
lacks the required OpenTelemetry span and does not propagate a derived context.
Start the repository-standard span at the beginning of RecordTokenUsage using
the existing telemetry helper and attribute keys, then pass the span’s context
to IncrementDailyUsage while preserving the current early return and error
logging behavior.

Source: Coding guidelines

llm/token_tracking.go (1)

148-158: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Instrument the new recorder boundary.

Add an OpenTelemetry span using the repository telemetry helpers and standard attribute keys around recorder delivery.

As per coding guidelines, new LLM call-path entry points must add OpenTelemetry spans with the repository telemetry helpers and attribute keys.

🤖 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 `@llm/token_tracking.go` around lines 148 - 158, Update
TokenUsageLoggingWrapper.emitTokenUsage to create an OpenTelemetry span with the
repository’s telemetry helpers and standard attribute keys around the recorder
delivery path. Keep the existing nil-check and TokenUsageRecord construction
intact, and ensure the span is started and ended for each recorder invocation.

Source: Coding guidelines

llm/token_tracking_test.go (1)

785-795: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Assert stream forwarding while the recorder is active.

forwarded is only checked for the nil-recorder case. Populate and assert wantForwarded for recorder-enabled cases so this test catches usage events being consumed before downstream processing—the regression this PR targets.

🤖 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 `@llm/token_tracking_test.go` around lines 785 - 795, Update the stream
assertions in the test case loop around result.Stream so recorder-enabled cases
also populate and compare forwarded events against tc.wantForwarded. Keep the
existing passthrough assertions, but ensure the expected forwarding check runs
after recorder processing rather than only returning for tc.wantPassthrough,
catching events consumed before downstream handling.
🤖 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 `@api/api_stats.go`:
- Around line 59-63: Replace unknownAgentDisplayName in api/api_stats.go with an
empty or stable machine-readable fallback, and update the handler response to
use it without embedding user-facing English. In api/api_stats_test.go, assert
that machine-readable fallback; move verification of the localized “Unknown
agent” display text to frontend tests.

In `@e2e/tests/system-console/usage-statistics.spec.ts`:
- Around line 167-168: Update the chart-title assertion in the usage statistics
test to match the title registered by buildSiteStatsRows: “Agents Tokens per Day
(Input vs. Output)”. Keep the existing visibility assertion and locator approach
unchanged.
- Line 98: Rename the E2E spec file from usage-statistics.spec.ts to
usage_statistics.spec.ts to follow the snake_case convention. Update the
corresponding shard entry in e2e/scripts/ci-test-groups.mjs at line 27 to
reference tests/system-console/usage_statistics.spec.ts; no code changes are
needed in the test.describe.serial block.

In `@store/usage.go`:
- Around line 76-80: Update the per-agent MAU query in the usage statistics
function to exclude rows where BotID is empty, while preserving the existing
user and bot filters and ordering. Add regression coverage verifying that a
non-zero usage row with an empty BotID does not produce an agent statistics
entry.

In `@webapp/src/site_stats.tsx`:
- Around line 124-126: Remove the any cast in getSiteStatsIntl and access the
i18n locale through the existing GlobalState typing. Model the i18n slice or
reuse a typed selector so store.getState() remains strictly type-checked while
preserving the English fallback.

---

Outside diff comments:
In `@llm/token_tracking.go`:
- Around line 82-125: The stream-forwarding goroutine must not wait indefinitely
for token persistence before closing interceptedStream. Update the hasUsage path
around emitTokenUsage and RecordTokenUsage so persistence runs with a short
bounded timeout or through a bounded asynchronous worker, while preserving usage
aggregation and ensuring interceptedStream is closed promptly even when
store.IncrementDailyUsage is slow or hung.

---

Nitpick comments:
In `@llm/token_tracking_test.go`:
- Around line 785-795: Update the stream assertions in the test case loop around
result.Stream so recorder-enabled cases also populate and compare forwarded
events against tc.wantForwarded. Keep the existing passthrough assertions, but
ensure the expected forwarding check runs after recorder processing rather than
only returning for tc.wantPassthrough, catching events consumed before
downstream handling.

In `@llm/token_tracking.go`:
- Around line 148-158: Update TokenUsageLoggingWrapper.emitTokenUsage to create
an OpenTelemetry span with the repository’s telemetry helpers and standard
attribute keys around the recorder delivery path. Keep the existing nil-check
and TokenUsageRecord construction intact, and ensure the span is started and
ended for each recorder invocation.

In `@store/usage_test.go`:
- Around line 383-438: Convert TestDeleteUsageBefore into a table-driven test by
defining cases containing seed dates, cutoff, batch size, and expected deletion
counts. Iterate over the cases with subtests, reusing shared store setup,
seeding, invoking DeleteUsageBefore, and asserting results; preserve the
existing exclusive-cutoff, batch-limit, and empty-store behaviors.

In `@usage/recorder.go`:
- Around line 41-58: The RecordTokenUsage entry point lacks the required
OpenTelemetry span and does not propagate a derived context. Start the
repository-standard span at the beginning of RecordTokenUsage using the existing
telemetry helper and attribute keys, then pass the span’s context to
IncrementDailyUsage while preserving the current early return and error logging
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: Repository UI (base), Organization UI (inherited)

Review profile: CHILL

Plan: Pro

Run ID: 0ce75345-eefb-408a-a712-4ad3e137dd6d

📥 Commits

Reviewing files that changed from the base of the PR and between cf496cd and 3312bb0.

📒 Files selected for processing (39)
  • Makefile
  • api/api.go
  • api/api_admin_test.go
  • api/api_stats.go
  • api/api_stats_test.go
  • api/api_test.go
  • bots/bots.go
  • bots/bots_test.go
  • bots/permissions_test.go
  • conversations/agent_mention_reminder_test.go
  • conversations/ask_user_question_flow_test.go
  • conversations/conversations_test.go
  • conversations/direct_message_eval_test.go
  • conversations/dm_conversation_test.go
  • conversations/handle_messages_test.go
  • conversations/loaded_state_flow_test.go
  • e2e/scripts/ci-test-groups.mjs
  • e2e/tests/system-console/usage-statistics.spec.ts
  • llm/token_tracking.go
  • llm/token_tracking_bench_test.go
  • llm/token_tracking_test.go
  • llm/token_usage_recorder.go
  • server/data_retention.go
  • server/data_retention_test.go
  • server/main.go
  • store/migrations/000010_create_usage_daily_table.down.sql
  • store/migrations/000010_create_usage_daily_table.up.sql
  • store/migrations/reviews/000010_create_usage_daily_table.md
  • store/store_test.go
  • store/usage.go
  • store/usage_test.go
  • usage/recorder.go
  • usage/recorder_test.go
  • webapp/src/client.tsx
  • webapp/src/i18n/en.json
  • webapp/src/index.tsx
  • webapp/src/site_stats.test.tsx
  • webapp/src/site_stats.tsx
  • webapp/src/types/usage_stats.ts

Comment thread api/api_stats.go Outdated
Comment thread e2e/tests/system-console/usage_statistics.spec.ts
Comment thread e2e/tests/system-console/usage-statistics.spec.ts Outdated
Comment thread store/usage.go
Comment thread webapp/src/site_stats.tsx Outdated
@nickmisasi
nickmisasi marked this pull request as ready for review July 18, 2026 03:31

@cursor cursor 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.

Babysit pass: addressed CodeRabbit/CI issues on a703871d.

Fixed

  • Localized empty-agent label in the webapp (API returns "" for empty BotID)
  • Aligned e2e chart title with Agents Tokens per Day (Input vs. Output) (was breaking e2e-shard-1)
  • Removed as any i18n access in site_stats.tsx
  • Close intercepted token stream before persistence so a hung recorder cannot block consumers

Not applying (see inline notes)

  • Rename e2e spec to snake_case — kebab-case matches existing e2e conventions
  • Exclude empty BotID from per-agent MAU — empty BotID is intentional and shown as Unknown agent
Open in Web View Automation 

Sent by Cursor Automation: Matty Code (Babysit Until Human Review)

Comment thread e2e/tests/system-console/usage_statistics.spec.ts
Comment thread store/usage.go

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 3312bb0b6f

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread llm/token_tracking.go
UserID: sentinelToEmpty(dimensions.userID),
IsGuest: dimensions.isGuest,
IsBot: dimensions.isBot,
BotUserID: sentinelToEmpty(dimensions.botUserID),

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Preserve agent IDs when recording bridge usage

For /bridge/v1/completion/agent/:agent requests, convertAgentBridgeRequestToInternal builds a context with only RequestingUser/tools and never populates Context.BotUserID, even though the endpoint path is already the bot user ID. Persisting sentinelToEmpty(dimensions.botUserID) therefore stores these bridge-agent calls with an empty BotID, so the new per-agent MAU breakdown groups them under “Unknown agent” instead of the actual agent. Please add a bot-user-id fallback or populate the bridge context before recording.

Useful? React with 👍 / 👎.

await expect(page.getByTestId('mattermost-ai.agents_tokens_30dTitle')).toBeVisible();

await expect(page.getByText('Monthly Active Users per Agent')).toBeVisible();
await expect(page.getByText('Agents Tokens per Day (Last 30 Days)')).toBeVisible();

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Match the site stats chart title in the spec

This assertion waits for a title that the plugin never renders: webapp/src/site_stats.tsx defines the line-chart row as “Agents Tokens per Day (Input vs. Output)” and the unit test pins that string. In the Site Statistics e2e path this locator will time out, so the new shard fails even though the page rendered; update either this expectation or the row label.

Useful? React with 👍 / 👎.

@mm-cloud-bot

Copy link
Copy Markdown

Test server destroyed

@mm-cloud-bot

Copy link
Copy Markdown

Plugin test server update attempted, but encountered an issue:

⚠️ Install Error: failed to install plugin via mmctl: failed with status code 410

The test server is still available. You can manually download and install the updated plugin using the artifact link below.

Updated with git commit 5f50670e3e96cd8ebf4e2dd85a84ecd4b0520490

Plugin Version Artifact
agents 5f50670 Download

@cursor cursor 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.

@coderabbitai review

Please re-review the latest commits (5f50670e). Valid items from the prior review were addressed; two items were intentionally not applied (e2e kebab-case naming matches existing specs; empty BotID is intentional for Unknown agent).

Open in Web View Automation 

Sent by Cursor Automation: Matty Code (Babysit Until Human Review)

@mm-cloud-bot

Copy link
Copy Markdown

Plugin test server update attempted, but encountered an issue:

⚠️ Install Error: failed to wait for S3 artifact: timed out waiting for S3 artifact

The test server is still available. You can manually download and install the updated plugin using the artifact link below.

Updated with git commit a703871d2058775dae47c75db4d54d473ea166e8

Plugin Version Artifact
agents a703871 Download

@cursor cursor 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.

@coderabbitai review

CI is green on HEAD 37466227. Please re-review.

Addressed since your last review:

  • Localized empty-agent label in webapp (API returns "")
  • Fixed e2e chart title assertion
  • Removed as any i18n cast
  • Close token stream before persistence
  • Set BotUserID on agent bridge completion context

Intentionally not applying (see prior notes):

  • Rename e2e spec to snake_case — kebab-case matches existing e2e conventions in this repo
  • Exclude empty BotID from per-agent MAU — empty BotID is intentional and shown as Unknown agent
Open in Web View Automation 

Sent by Cursor Automation: Matty Code (Babysit Until Human Review)

@cursor cursor 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.

@coderabbitai resolve

Please resolve the two remaining open threads (intentionally not applied):

  1. e2e kebab-case filename — matches existing e2e specs in this repo
  2. empty BotID filter — empty BotID is intentional Unknown-agent usage

All other prior feedback is addressed and CI is green on HEAD. Please approve if you agree.

Open in Web View Automation 

Sent by Cursor Automation: Matty Code (Babysit Until Human Review)

@cursor cursor 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.

@coderabbitai review

Addressed remaining Major: renamed e2e spec to usage_statistics.spec.ts per AGENTS.md.

Still intentionally keeping empty BotID in per-agent MAU (documented on GetActiveUserCountPerBot) so Unknown-agent usage remains visible.

Open in Web View Automation 

Sent by Cursor Automation: Matty Code (Babysit Until Human Review)

Comment thread store/usage.go Outdated

@cursor cursor 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.

@coderabbitai resume
@coderabbitai review

Open in Web View Automation 

Sent by Cursor Automation: Matty Code (Babysit Until Human Review)

@cursor cursor 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.

@coderabbitai resume
@coderabbitai review

Addressed the remaining open thread: per-agent MAU now excludes empty BotID (AND BotID <> '') with regression coverage in store/usage_test.go.

Open in Web View Automation 

Sent by Cursor Automation: Matty Code (Babysit Until Human Review)

@cursor cursor 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.

e2e-shard-3 failure is unrelated flake

tests/llmbot-post-component/streaming-persistence.spec.ts → “Stop Generating Button” timed out waiting for channel_view during login (e2e/helpers/mm.ts). That path is unrelated to Agents usage stats / System Statistics changes on this PR.

Re-running the failed job. Other shards (1/2/4), lint, build, and plugin-tests are green; CodeRabbit has approved.

Open in Web View Automation 

Sent by Cursor Automation: Matty Code (Babysit Until Human Review)

@cursor cursor 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.

Babysit complete — ready for human review

Acceptance criteria

  • CodeRabbitAI: APPROVED on HEAD 11b9bfd5
  • CI: all green (lint, build, plugin-tests, e2e-shard-1..4, evals, security)
  • Mergeable: MERGEABLE (no conflicts)

Labels

  • Removed AI/Babysit
  • Added Setup Cloud Test Server

Note: This PR has no Jira key in the description, so request_human_review could not resolve a Matty Code Assigner from a ticket. PR author @nickmisasi — please take the human review (or assign the appropriate reviewer).

Open in Web View Automation 

Sent by Cursor Automation: Matty Code (Babysit Until Human Review)

@mm-cloud-bot

Copy link
Copy Markdown

Test server destroyed

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.

4 participants