diff --git a/analytics/analytics_package/analytics/static_site/README.md b/analytics/analytics_package/analytics/static_site/README.md index 98166245e..7ce6ee676 100644 --- a/analytics/analytics_package/analytics/static_site/README.md +++ b/analytics/analytics_package/analytics/static_site/README.md @@ -52,9 +52,9 @@ For apps with dataset/project detail tables, a `title_resolver` callback enriche ├── config.json ├── meta.json ├── monthly_traffic.json - ├── pageviews.json - ├── outbound_links.json - ├── filter_selected.json + ├── pageviews.json # top 100 rows + ├── outbound_links.json # top 100 rows + ├── filter_selected.json # top 100 rows ├── file_downloads.json ├── custom_events.json ├── access_requests.json # AnVIL only diff --git a/analytics/analytics_package/analytics/static_site/export.py b/analytics/analytics_package/analytics/static_site/export.py index 66edb123f..6bef50b35 100644 --- a/analytics/analytics_package/analytics/static_site/export.py +++ b/analytics/analytics_package/analytics/static_site/export.py @@ -18,8 +18,16 @@ ) from .fetch import event_key +# Row cap for the exports the template renders as a fixed slice (top 20 +# pageviews and outbound links, top 30 filter selections); 100 leaves headroom +# for UI changes while keeping page-load payloads and monthly regen diffs +# bounded (e.g. AnVIL Portal shipped 1,810 pageviews rows). Event detail tables, +# access requests and search queries stay uncapped on purpose — the template +# renders every one of their rows. +MAX_TABLE_EXPORT_ROWS = 100 -def export_df_as_json(df, col_map, change_col, filename, output_dir): + +def export_df_as_json(df, col_map, change_col, filename, output_dir, max_rows=None): """Export a DataFrame to JSON with column renaming and NaN handling. Args: @@ -28,7 +36,13 @@ def export_df_as_json(df, col_map, change_col, filename, output_dir): change_col: Source column name for the change metric (may be absent). filename: Output JSON filename. output_dir: Output directory, as a Path. + max_rows: Maximum number of rows to export; the top rows are kept, so + df is expected to be sorted by relevance. None exports all rows. """ + total_rows = 0 if df is None else len(df) + if max_rows is not None and total_rows > max_rows: + df = df.head(max_rows) + print(f" Capped {filename} at top {max_rows} of {total_rows} rows") if df is None or len(df) == 0: records = [] else: @@ -108,6 +122,7 @@ def export_data( METRIC_PAGE_VIEWS["change_alias"], "pageviews.json", output_dir, + max_rows=MAX_TABLE_EXPORT_ROWS, ) print("Exporting outbound links data...") @@ -120,6 +135,7 @@ def export_data( SYNTHETIC_METRIC_CLICKS["change_alias"], "outbound_links.json", output_dir, + max_rows=MAX_TABLE_EXPORT_ROWS, ) print("Exporting filter selections data...") @@ -133,6 +149,7 @@ def export_data( METRIC_EVENT_COUNT["change_alias"], "filter_selected.json", output_dir, + max_rows=MAX_TABLE_EXPORT_ROWS, ) # File downloads diff --git a/analytics/analytics_package/analytics/static_site/template/index.html b/analytics/analytics_package/analytics/static_site/template/index.html index 95f4042ff..2b0c3bf94 100644 --- a/analytics/analytics_package/analytics/static_site/template/index.html +++ b/analytics/analytics_package/analytics/static_site/template/index.html @@ -845,6 +845,8 @@