Skip to content

feat(workspaces): add statistics and metrics#20784

Merged
nijel merged 1 commit into
WeblateOrg:mainfrom
nijel:stats-workspace
Jul 23, 2026
Merged

feat(workspaces): add statistics and metrics#20784
nijel merged 1 commit into
WeblateOrg:mainfrom
nijel:stats-workspace

Conversation

@nijel

@nijel nijel commented Jul 20, 2026

Copy link
Copy Markdown
Member

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.

@nijel nijel added this to the 2026.8 milestone Jul 20, 2026
@nijel
nijel requested a review from amCap1712 July 20, 2026 18:54
@nijel nijel self-assigned this Jul 20, 2026
@nijel

nijel commented Jul 20, 2026

Copy link
Copy Markdown
Member Author

@amCap1712 I'd like to hear your opinion, especially on linking Metric to Workspace. I want to keep UUID as the primary key on Workspace and Metric uses int to reference the related object. I've chosen using sequence-based metric_id on Workspace, but there are definitely other options like converting the reference on Metric to char and storing UUID directly there.

@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

https://github.com/WeblateOrg/weblate/blob/e3e9a36b63c5e5879f229f91e88dd0e5a897b863/templates/workspace.html#L119-L120
P1 Badge 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".

@nijel
nijel force-pushed the stats-workspace branch from e3e9a36 to 997afca Compare July 21, 2026 05:31
Copilot AI review requested due to automatic review settings July 21, 2026 05:31

Copilot AI 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.

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 WorkspaceStats aggregation 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.

Comment thread weblate/workspaces/models.py Outdated
Copilot AI review requested due to automatic review settings July 21, 2026 07:01
@nijel
nijel force-pushed the stats-workspace branch from 997afca to f535dea Compare July 21, 2026 07:01

@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: 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".

Comment thread weblate/metrics/models.py
Comment thread weblate/templates/workspace.html
Comment thread weblate/wladmin/views.py

Copilot AI 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.

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

Comment thread weblate/wladmin/views.py
Comment thread weblate/wladmin/views.py
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.
Copilot AI review requested due to automatic review settings July 21, 2026 07:09
@nijel
nijel force-pushed the stats-workspace branch from f535dea to 0d3a8ae Compare July 21, 2026 07:09

Copilot AI 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.

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). Because missing only checks has_cached_data, the second call repeats the work even though stats_languages was 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
        ]

@nijel
nijel merged commit 00cf852 into WeblateOrg:main Jul 23, 2026
31 of 32 checks passed
@nijel
nijel deleted the stats-workspace branch July 23, 2026 07:24
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