feat(admin): add growth-report — cross-platform use-case growth & rates (HTML) - #25
Merged
Conversation
…periment/registry usage metrics
…I calls) Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…+ prediction-volume usage
…lements Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…sed imports/noqa Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…nder test; polish Removes bucket_events/workspace_creation_events/usage_by_workspace (verified unused by the pipeline), fixes _open() to resolve relative --output paths, drops a dead noqa line, and adds a full-chain generate_growth_report -> build() -> build_html() integration test.
The Comet EM projects endpoint returns a fallback set from another workspace (ignoring workspaceName) when the API key isn't a member of the requested workspace. That caused those foreign projects to be mis-attributed to every inaccessible workspace, showing as duplicate project names in the EM adoption table and inflating EM growth counts. Keep only projects whose own workspaceName matches the requested one; warn when projects are dropped, and still report the workspace at 0. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…ult) Wrap every report table in a native <details>/<summary> disclosure (no JS, stays self-contained). Tables start collapsed with the title + row count in the summary, so large tables don't dominate the page as data grows. Also give the per-product growth breakdown tables real titles so their summaries read meaningfully instead of a generic label. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- Rename 'Departments' -> 'Workspaces' everywhere, with a 'proxy for teams / departments' clarification (label was misleading; these are workspaces used as a department/group proxy). - Cumulative (area) charts: add per-point hover tooltips, x-axis time labels on both edges (+ intervals), a max-value gridline label, and the final cumulative value — previously they showed no numbers. - Adoption/usage sections: add usage growth KPIs (New / Growth% over the window) and a fastest-growing-project KPI, not just the total. - Adoption/usage sections: add a cumulative area chart alongside the per-period bars. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…ways show fastest-growing project 1. Replace flaky native SVG <title> tooltips with a real interactive tooltip (positioned div + vertical guide line) driven by per-column hit rects; shared across bar, area, and stacked charts. 2. Cumulative (area) charts now label only the earliest and latest dates on the x-axis (instead of every interval), per request. 3. Always surface the fastest-growing-project KPI for every product (incl. EM = most new experiments in the analysis window), showing '—' when nothing grew in-window so it never appears missing. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…x CI) CI installs only requirements.txt (opik present, comet_mpm not), but the growth-report tests patched comet_mpm/opik unconditionally, erroring at setup with ModuleNotFoundError. Guard the SDK-patching tests with skipif(find_spec(...) is None), and make the two cross-platform assembly tests env-independent by forcing the resolved platform set instead of relying on which optional extras happen to be installed. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
LeoRoccoBreedt
marked this pull request as ready for review
July 9, 2026 19:10
Non-numeric or mixed-type value/y from Opik SPAN_COUNT and MPM prediction responses could raise TypeError on `counts[...] += ...` and abort collection. Add _as_float() to coerce datapoints (None/blank/non-numeric -> 0.0). Addresses baz-reviewer Type Inconsistency findings. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
EM/Opik/MPM collectors each appended a near-identical workspace-level (project=None) UsageMetric block, so the summary shape could drift. Route all three through _workspace_usage_metric(). Addresses baz-reviewer Code Dedup finding. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…metadata The EM EXPERIMENT_COUNT total (and its workspace roll-up) was sourced from `numberOfExperiments` metadata while the chart series was built from experiments bucketed by start_server_timestamp. When those disagree, the adoption KPI total didn't equal the cumulative chart sum. Derive `total` from the same counts map that feeds the series so they always match. Add a regression test covering the metadata-disagrees case. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
User description
Summary
Adds a new
cometx admin growth-reportaction: a cross-platform use-case growth & rate-of-change report — per workspace (department) — spanning Opik, Experiment Management (EM), and MPM, rendered as a self-contained, theme-aware HTML dashboard.It is a sibling to
admin usage-report(which emits experiment-count-over-time as PDF/Streamlit) and stays deliberately distinct: this one is cross-platform use-case creation growth + rates, as one self-contained HTML file (no external assets, works offline, light/dark aware).Resolves #24.
What it does
+N), Growth % (new / installed-base-before-window, 0-guarded), and Workspaces.--units {month,week,day,hour}sets chart bucket granularity (charts are always all-time);--window(default7d) is the KPI analysis window, drawn as an "Option-A" shaded band on the charts.Example output
The report is a single self-contained HTML file (~190 KB in the live run below): inline CSS/JS, a light/dark theme toggle, per-collector status chips, JS-rendered interactive SVG charts (data embedded as JSON), and collapsible data tables. No external assets and no secrets in the output.
Topbar + collector status
KPI row + chart panel (JS-rendered SVG from embedded data)
Collapsible use-case table
Design notes & caveats
start_server_timestamp→lastUpdated. This affects only the precision of the EM growth line, not the use-case taxonomy. Documented in the READMEs.--unitsrequests weekly buckets and re-buckets them into months (no data loss).pip install 'cometx[all]'enables them; without them those sections are skipped cleanly.admin_usage_report.pyintocometx/utils.pyso both reports share one copy (and the new report avoids pulling in matplotlib/reportlab)._as_float()helper before summing, so a non-numeric/mixed-typevalue/yfrom an SDK or REST response falls back to0.0instead of raisingTypeErrorand aborting a workspace's collection.project=None) summaryUsageMetricis built by one_workspace_usage_metric()helper shared by all three collectors, so EM/Opik/MPM summaries can't drift.http(s)://in the output) and the renderer only ever receivesreport_data— the API key never reaches the HTML (regression-tested).Testing
scout-test-leo): produced a populated ~190 KB HTML with real Opik + EM KPIs/charts/tables, MPM gracefully absent (not provisioned on the test account), and the API key confirmed absent from the output viagrep.Not in scope
Three pre-existing flake8 findings in
admin_usage_report.py(jsonunused import,weeks_apartunused var, an f-string without placeholders) are present onmainand were left untouched — this branch only relocated the time helpers out of that file.🤖 Generated with Claude Code
Generated description
Below is a concise technical summary of the changes proposed in this PR:
graph LR admin_("admin"):::modified generate_growth_report_("generate_growth_report"):::added GrowthReporter_("GrowthReporter"):::added write_growth_html_("write_growth_html"):::added COMET_ML_API_("COMET_ML_API"):::modified COMET_MPM_API_("COMET_MPM_API"):::added write_html_("write_html"):::added build_html_("build_html"):::added admin_ -- "CLI growth-report calls generate_growth_report using workspaces, units, window." --> generate_growth_report_ generate_growth_report_ -- "GrowthReporter.build collects cross-platform events/usage and assembles report_data." --> GrowthReporter_ generate_growth_report_ -- "generate_growth_report passes report_data to write_growth_html for saving." --> write_growth_html_ GrowthReporter_ -- "Collector queries EM projects/experiments and registry models via COMET_ML_API." --> COMET_ML_API_ GrowthReporter_ -- "MPM collector fetches workspaces and prediction points using COMET_MPM_API." --> COMET_MPM_API_ write_growth_html_ -- "write_growth_html delegates report_data rendering to admin_growth_render.write_html." --> write_html_ write_html_ -- "write_html calls build_html to embed report_data into HTML." --> build_html_ classDef added stroke:#15AA7A classDef removed stroke:#CD5270 classDef modified stroke:#EDAC4C linkStyle default stroke:#CBD5E1,font-size:13pxIntroduce the
GrowthReporterorchestration and shared time-key helpers to collect Opik/EM/MPM creation and usage metrics, resolve workspaces/platforms, and assemble thereport_dataconsumed by the new renderer so thatcometx admin growth-reportdelivers a comprehensive, cross-platform growth narrative. Render that contract via a self-contained, theme-aware HTML dashboard that embeds inline CSS/JS/SVG without ever leaking secrets or requiring network assets while linking the new command into the CLI and documentation.report_datainto a standalone dashboard: inline theme-aware CSS, JS that draws interactive SVG charts with window bands/tooltips, collapsible tables, KPI/panel markup, collector chips, payload embedding, and a write helper so the output stays secret-free and offline-friendly.Modified files (1)
Latest Contributors(0)
README/README-ADMIN, ensuring users understand argument semantics, the two time concepts, caveats, and that the new growth report differs from the usage report, plus move the time-bucketing helpers out ofadmin_usage_report.pyso both reports rely on the sharedcometx.utilsutilities.Modified files (3)
Latest Contributors(0)
GrowthReporterflow: parse--window, resolve workspaces/platforms (guarding optionalopik/comet_mpmdeps), run each collector, zero-fill time buckets via the shared utils, build KPI/chart/table payloads per section/product, emit thereport_datacontract, exposegenerate_growth_reportthrough the CLI, and back it with exhaustive unit tests covering collectors, renderer security, and orchestration paths.Modified files (4)
Latest Contributors(0)