[cueweb/docs] Add per-user usage metrics (Prometheus) + Grafana dashboard#2459
Conversation
…oard
Instrument CueWeb end-to-end so operators can see who uses what, how often, and how fast - per user, per page/module, per action - with bounded Prometheus cardinality. Mirrors the asset-search metrics approach.
Metrics (GET /api/metrics, never gated by the authz gate):
- cueweb_page_views_total{user,page}, cueweb_actions_total{user,action}
- cueweb_api_requests_total{endpoint,status}, cueweb_api_request_duration_seconds{endpoint}
- cueweb_logins_total{user}, cueweb_facility_selected_total{user,facility}
Implementation:
- lib/metrics-service.ts: metric set + helpers + page/action allow-lists (unknown values map to "other" so cardinality stays bounded).
- lib/track-user.ts: extractUser() resolves the user server-side (session -> X-User/X-Forwarded-User -> anonymous); the client never sets it.
- app/api/track/route.ts + app/utils/usage_tracking.ts + components/ui/usage-tracker.tsx: client beacons for page views (on route change) and actions (via the shared accessActionApi dispatcher).
- app/utils/gateway_server.ts handleRoute: records API request count + latency for all proxy routes; best-effort, never affects responses.
- NEXT_PUBLIC_USAGE_TRACKING=off opts out the client beacon (the /api/metrics endpoint and server-side metrics stay enabled).
Wiring + dashboard:
- sandbox/config/prometheus-monitoring.yml: cueweb scrape job (cueweb:3000/api/metrics).
- sandbox/config/grafana/dashboards/cueweb-usage.json: "CueWeb User Usage" (overview, pages, actions, API p50/p90/p99 over a fixed 5m window, top-N users, $user variable).
Docs: reference (Usage metrics section + NEXT_PUBLIC_USAGE_TRACKING), developer-guide (instrumentation flow + files), and deploying-cueweb (scrape job + dashboard), with /api/metrics, Prometheus-query, and Grafana screenshots.
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (4)
✅ Files skipped from review due to trivial changes (2)
🚧 Files skipped from review as they are similar to previous changes (2)
📝 WalkthroughWalkthroughThis PR adds a full per-user usage tracking system to CueWeb. It introduces a ChangesCueWeb Usage Tracking System
Sequence Diagram(s)sequenceDiagram
participant Browser
participant UsageTracker
participant usage_tracking
participant POST_api_track as POST /api/track
participant extractUser
participant MetricsService
Browser->>UsageTracker: pathname changes
UsageTracker->>usage_tracking: trackPage(pathname)
usage_tracking->>usage_tracking: pageNameForPath(pathname)
usage_tracking->>POST_api_track: beacon({ kind: "page", name })
POST_api_track->>extractUser: extractUser(request)
extractUser-->>POST_api_track: username
POST_api_track->>MetricsService: recordPageView(user, page)
POST_api_track-->>Browser: 204 No Content
sequenceDiagram
participant Client
participant handleRoute
participant GatewayProxy
participant MetricsService
Client->>handleRoute: HTTP request
handleRoute->>handleRoute: shortEndpoint() + start timer
handleRoute->>GatewayProxy: forward request
GatewayProxy-->>handleRoute: response / error
handleRoute->>MetricsService: recordApiRequest(endpoint, status, duration)
handleRoute-->>Client: response
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes Possibly related issues
Suggested reviewers
Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
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. Comment |
There was a problem hiding this comment.
Actionable comments posted: 3
🤖 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 `@cueweb/lib/metrics-service.ts`:
- Around line 180-182: The recordFacility method is recording raw facility
values as metric labels, which creates unbounded Prometheus series cardinality
and degrades performance. Before incrementing the facilitySelected metric in the
recordFacility method, implement cardinality bounding for the facility parameter
by either limiting it to a known set of allowed values, normalizing unknown
values to a default category, or applying a safe transformation. Pass only the
bounded facility value to the this.facilitySelected.inc() call.
In `@cueweb/lib/track-user.ts`:
- Around line 41-43: The code in the header extraction logic that checks for
X-User and X-Forwarded-User headers does not validate whether the request is
coming from a trusted proxy before accepting these identity headers. This allows
callers to forge user identities in metrics. Add a trusted-proxy validation
check before accepting these headers (check the request origin or use an
existing trusted-proxy validation utility in your codebase), and only process
the localPart extraction and return when the request comes from a trusted
source; otherwise, fall back to ANONYMOUS_USER.
In `@docs/_docs/getting-started/deploying-cueweb.md`:
- Around line 895-897: The current documentation in the cueweb deploying guide
only describes the direct session-to-anonymous fallback for the user label
resolution, but does not mention the intermediate header fallback mechanism.
Update the documentation to clarify the complete user-resolution flow: first
attempt to resolve from the signed-in session, then fall back to trusted X-User
or X-Forwarded-User headers if authentication is disabled, and only resolve to
anonymous if neither session nor headers provide a user value. This ensures
readers understand the full behavior implemented in track-user.ts.
🪄 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: defaults
Review profile: CHILL
Plan: Pro
Run ID: 17d6aa73-9c56-4302-9098-56dda1057a27
⛔ Files ignored due to path filters (7)
docs/assets/images/cueweb/cueweb_user_usage_metrics_api_metrics_endpoint1.pngis excluded by!**/*.pngdocs/assets/images/cueweb/cueweb_user_usage_metrics_api_metrics_endpoint2.pngis excluded by!**/*.pngdocs/assets/images/cueweb/cueweb_user_usage_metrics_api_metrics_endpoint3.pngis excluded by!**/*.pngdocs/assets/images/cueweb/cueweb_user_usage_metrics_grafana_charts1.pngis excluded by!**/*.pngdocs/assets/images/cueweb/cueweb_user_usage_metrics_grafana_charts2.pngis excluded by!**/*.pngdocs/assets/images/cueweb/cueweb_user_usage_metrics_grafana_charts3.pngis excluded by!**/*.pngdocs/assets/images/cueweb/cueweb_user_usage_metrics_prometheus_query.pngis excluded by!**/*.png
📒 Files selected for processing (14)
cueweb/app/api/track/route.tscueweb/app/layout.tsxcueweb/app/utils/api_utils.tscueweb/app/utils/gateway_server.tscueweb/app/utils/usage_tracking.tscueweb/components/ui/usage-tracker.tsxcueweb/lib/metrics-service.tscueweb/lib/track-user.tsdocs/_docs/developer-guide/cueweb-development.mddocs/_docs/getting-started/deploying-cueweb.mddocs/_docs/reference/cueweb.mdsandbox/config/grafana/dashboards/cueweb-usage.jsonsandbox/config/prometheus-monitoring.ymlsandbox/config/prometheus/prometheus.yml
|
Deploy & verify
How to test it yourself?
|
Address review feedback on the usage-metrics instrumentation: - metrics-service: bound the cueweb_facility_selected_total `facility` label to the deployment's configured facilities (NEXT_PUBLIC_CUEBOT_FACILITIES); anything else maps to "other", so a crafted /api/track beacon can't create unbounded Prometheus series. - track-user: the signed-in NextAuth session stays the authoritative, non-spoofable source. The forgeable X-User / X-Forwarded-User identity headers are now honored only when CUEWEB_TRUST_IDENTITY_HEADER=true (off by default; for deployments behind a trusted reverse proxy that strips inbound copies and injects the identity), otherwise the user falls back to anonymous. Docs (reference + deploying-cueweb): document CUEWEB_TRUST_IDENTITY_HEADER and the full server-side user resolution order (session -> opt-in trusted header -> anonymous).
|
@DiegoTavares / @lithorus |
7f22324
into
AcademySoftwareFoundation:master
Related Issues
Main issue:
Issues related to this PR:
Summarize your change.
Instrument CueWeb end-to-end so operators can see who uses what, how often, and how fast - per user, per page/module, per action - with bounded Prometheus cardinality. Mirrors the asset-search metrics approach.
Metrics (GET /api/metrics, never gated by the authz gate):
Implementation:
Wiring + dashboard:
Docs: reference (Usage metrics section + NEXT_PUBLIC_USAGE_TRACKING), developer-guide (instrumentation flow + files), and deploying-cueweb (scrape job + dashboard), with /api/metrics, Prometheus-query, and Grafana screenshots.
LLM usage disclosure
Parts of this solution's implementation were developed with assistance from Claude Opus.