Skip to content

Release: analytics for Plan Analyzer web app#223

Merged
erikdarlingdata merged 13 commits intomainfrom
dev
Apr 13, 2026
Merged

Release: analytics for Plan Analyzer web app#223
erikdarlingdata merged 13 commits intomainfrom
dev

Conversation

@erikdarlingdata
Copy link
Copy Markdown
Owner

Summary

  • Merge dev into main to deploy analytics JS snippet to plans.erikdarling.com
  • PlanShare server and stats dashboard already deployed on Hetzner

🤖 Generated with Claude Code

rferraton and others added 13 commits April 12, 2026 14:44
…ed rows in FetchGroupedPlansAsync, the first root row is recursively expanded to the deepest level so the user immediately sees the full hierarchy.

2. Load child plans (LoadHighlightedPlan_Click / LoadSelected_Click / CollectLeafPlans):
• "Load Plan" on a grouped row (QueryHash, PlanHash, or Module level) now recursively collects all descendant leaf plans where both PlanId > 0 and QueryId > 0
• Rows with PlanId == 0 or QueryId == 0 are never loaded
• "Load Selected" does the same expansion for each selected row
3. Golden headers (ApplyGroupByHeaderColors):
• When GroupBy=QueryHash: "Query Hash" and "Plan Hash" column headers get gold (#FFD700) foreground
• When GroupBy=Module: "Module" and "Query Hash" column headers get gold
• When GroupBy=None: all header colors are reset to default
4. Column reorder (ReorderColumnsForGroupBy):
• QueryId and PlanId columns are now pushed after the GroupBy key columns
• QueryHash mode: Expand → Checkbox → QueryHash → PlanHash → QueryId → PlanId → rest
• Module mode: Expand → Checkbox → Module → QueryHash → QueryId → PlanId → rest
• None mode: original column order is fully restored
…nts (query text and plan xml) after computations and top/bottom reduction
…ediate row, the code now picks the QueryText from the top representative leaf row (the one with IsTopRepresentative == true, falling back to the first available leaf) and assigns it to the parent's QueryStorePlan.QueryText. This is done at two levels:

1. Intermediate rows (PlanHash in QueryHash mode, QueryHash in Module mode): Gets the query text from the top representative leaf within that specific group.
2. Root rows (QueryHash level, Module level): Gets the query text from the top representative leaf across all leaves in that root group.
No additional database queries are made — the text comes entirely from grouped.LeafRows which was already fetched.
…alongside GridLoadingOverlay.IsVisible = true at the start of every fetch, so any lingering empty message is dismissed before the next request.

2. FetchGroupedPlansAsync — When IntermediateRows.Count == 0 and the mode is Module: sets the message text to "No module found in the selected period", shows the overlay, and returns — without writing to StatusText. For QueryHash mode (or any other non-Module grouped mode) that still hits the empty case, the original status bar message is preserved.
…nger

Feature/query store group by changer
… grouped fetches

The Step 3 ranked CTEs in both FetchGroupedByQueryHashAsync and
FetchGroupedByModuleAsync joined sys.query_store_query_text without
using any of its columns — the actual text fetch happens in the Final
select. Also fixes tab/space inconsistency in the doc comment blocks
for both methods.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…leanup

Remove unnecessary query_store_query_text joins in grouped fetches
- Add page_views table and POST /api/event endpoint for lightweight
  page view tracking (visitor hash from IP+UA+date, no PII stored)
- Expand GET /api/stats to return traffic data (views, visitors,
  referrers) alongside sharing stats
- Add analytics JS snippet to web app index.html
- Add Plan Analyzer tab to stats dashboard (dashboard.html)
- Auto-cleanup page views older than 90 days

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add built-in analytics to PlanShare and stats dashboard
@erikdarlingdata erikdarlingdata merged commit 32ed53d into main Apr 13, 2026
2 of 3 checks passed
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