feat(workspaces): add statistics and metrics#20784
Conversation
|
@amCap1712 I'd like to hear your opinion, especially on linking |
There was a problem hiding this comment.
💡 Codex Review
https://github.com/WeblateOrg/weblate/blob/e3e9a36b63c5e5879f229f91e88dd0e5a897b863/templates/workspace.html#L119-L120
Restrict workspace statistics to visible projects
When a visitor can access any public/protected project in a workspace but not another private project, detail() permits the workspace page based on request.user.allowed_projects while the information tab renders the unfiltered workspace.stats. WorkspaceStats.get_child_objects() aggregates workspace.projects without the request user's access filter, so this newly exposed tab reveals private projects' aggregate string/word/check/progress data (and historical contributor totals) to users who cannot view those projects; the existing project list correctly omits them.
ℹ️ 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".
There was a problem hiding this comment.
Pull request overview
Adds workspace-scoped aggregate translation statistics and historical metrics, integrating workspaces into the existing stats/metrics infrastructure while optimizing the management listing to avoid per-workspace queries.
Changes:
- Introduces
WorkspaceStatsaggregation and schedules workspace stats refreshes when projects move or component topology changes. - Adds
Workspace.metric_id(integer sequence) to support integer-indexed workspace metrics, plus workspace metric collection and lifecycle hooks. - Updates workspace UI and management pages to display workspace info/metrics and to support sortable listings with preserved search parameters.
Reviewed changes
Copilot reviewed 21 out of 21 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| weblate/workspaces/tests.py | Adds tests for metric_id behavior and workspace stats aggregation/refresh triggers. |
| weblate/workspaces/models.py | Adds metric_id, WorkspaceStats wiring, and billing_or_none helper. |
| weblate/workspaces/migrations/0004_workspace_metric_id.py | Creates the metric ID sequence and adds the metric_id field. |
| weblate/wladmin/views.py | Batches workspace listing annotations/prefetching and prepares language counts for uncached workspace stats. |
| weblate/wladmin/tests.py | Extends management UI tests for stats sorting, search preservation, and query batching. |
| weblate/utils/tasks.py | Adds update_workspace_stats task and ensures topology updates include workspace aggregates. |
| weblate/utils/stats.py | Adds cache helper has_cached_data, workspace aggregation class, and workspace update ordering. |
| weblate/trans/templatetags/translations.py | Extends show_info context to accept a workspace. |
| weblate/trans/models/project.py | Schedules workspace stats refresh when a project’s workspace changes. |
| weblate/trans/mixins.py | Updates cache key typing protocol to allow UUID IDs. |
| weblate/templates/workspace.html | Adds “Information” tab and renders workspace info + metrics. |
| weblate/templates/snippets/list-objects.html | Reuses listing table for workspaces, adds columns, and preserves query_string across sorts. |
| weblate/templates/snippets/info.html | Adds workspace-specific quick metrics blocks and disables contributor link for workspace context. |
| weblate/templates/manage/workspaces.html | Switches workspace management page to the shared list-objects snippet. |
| weblate/metrics/tests.py | Adds workspace metric collection and deletion lifecycle tests. |
| weblate/metrics/templatetags/metrics.py | Enables ` |
| weblate/metrics/tasks.py | Extends periodic metrics collection to include workspaces. |
| weblate/metrics/models.py | Adds workspace metric scope, collection, and create/delete hooks. |
| weblate/billing/views.py | Triggers workspace stats refresh when billing merge moves projects between workspaces. |
| weblate/billing/models.py | Triggers workspace stats refresh when billing changes a project’s workspace. |
| docs/changes.rst | Adds changelog entry announcing workspace statistics/metrics. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: f535dea499
ℹ️ 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".
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 21 out of 21 changed files in this pull request and generated 2 comments.
Comments suppressed due to low confidence (1)
weblate/workspaces/models.py:310
- billing_or_none only suppresses ObjectDoesNotExist, but when the billing app is disabled the reverse accessor (Workspace.billing) does not exist and this property will raise AttributeError if accessed. It should be safe to call regardless of INSTALLED_APPS.
@property
def billing_or_none(self) -> Billing | None:
"""Associated billing, or none for unbilled workspaces."""
with suppress(ObjectDoesNotExist):
return self.billing
return None
Expose aggregate translation health and historical trends at workspace scope. Keep metric lookups integer-indexed and batch the management listing to avoid per-workspace queries.
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 21 out of 21 changed files in this pull request and generated no new comments.
Comments suppressed due to low confidence (1)
weblate/wladmin/views.py:1094
prepare_workspace_stats()can run the (potentially expensive) translation-language union query twice when sorting by non-name columns: it’s called once before pagination (lines 1117–1120) and again after pagination (line 1127). Becausemissingonly checkshas_cached_data, the second call repeats the work even thoughstats_languageswas already populated.
Consider skipping workspaces that already have stats_languages set so the second call becomes a no-op for those objects.
"""Batch language counts needed to initialize uncached workspace stats."""
missing = [
workspace for workspace in workspaces if not workspace.stats.has_cached_data
]
Expose aggregate translation health and historical trends at workspace scope. Keep metric lookups integer-indexed and batch the management listing to avoid per-workspace queries.