feat(admin): daily history of apps with preview QR enabled - #2937
Conversation
Snapshot allow_preview app counts into global_stats each day and chart the trend on the admin users dashboard. Co-authored-by: Martin DONADIEU <martindonadieu@gmail.com>
📝 WalkthroughWalkthroughThe change adds an ChangesPreview global statistics
Estimated code review effort: 3 (Moderate) | ~20 minutes Sequence Diagram(s)sequenceDiagram
participant LogsnagInsights
participant AppsDatabase
participant GlobalStats
participant AdminDashboard
LogsnagInsights->>AppsDatabase: Count Preview-enabled apps before snapshotEnd
AppsDatabase-->>LogsnagInsights: Return apps_with_preview count
LogsnagInsights->>GlobalStats: Persist daily metric
AdminDashboard->>GlobalStats: Request global statistics trend
GlobalStats-->>AdminDashboard: Return apps_with_preview trend
AdminDashboard-->>AdminDashboard: Render Preview app chart
Possibly related PRs
Suggested labels: Suggested reviewers: 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches📝 Generate docstrings
Comment |
Merging this PR will not alter performance
Comparing Footnotes
|
|
Bugbot couldn't run - usage limit reachedBugbot is counted against Cursor usage for this user or team, and this run hit a usage or spend limit. A user or team admin can review and increase usage limits in the Cursor dashboard. (requestId: serverGenReqId_a7be304d-a89c-4cba-bffc-080585fecc3f) |
There was a problem hiding this comment.
Actionable comments posted: 4
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@supabase/functions/_backend/triggers/logsnag_insights.ts`:
- Around line 1507-1509: Update the countAppsWithPreview error handler to keep
logging the database error, then rethrow it instead of returning 0. Preserve the
successful count path so shard failure handling can detect the failure and retry
the snapshot.
In `@supabase/migrations/20260808071749_apps_with_preview_global_stats.sql`:
- Around line 1-2: Update the migration adding apps_with_preview so existing
global_stats rows are not populated with misleading zero values. Backfill
historical values from a source containing the recorded allow_preview state, or
constrain the trend to begin at the first valid snapshot; do not derive
historical values from the current apps.allow_preview state.
- Line 5: Shorten or split the SQL comment attached to the preview-apps
statistic so each line is no longer than 80 characters, while preserving its
meaning about apps with allow_preview enabled at snapshot day end.
In `@tests/logsnag-insights-revenue.unit.test.ts`:
- Around line 683-694: Replace the source-string assertions in the “snapshots
apps with preview QR enabled” test with a behavioral test that executes the
relevant stats flow using mocked database clients or an existing database
fixture. Seed records covering preview-enabled apps before and at the snapshot
boundary, verify countAppsWithPreview returns only records before snapshotEnd,
and assert runCoreGlobalStatsShard passes that value as apps_with_preview to
updateGlobalStatsSnapshot.
🪄 Autofix
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: ASSERTIVE
Plan: Pro
Run ID: 7f87c1a3-461d-4d17-8836-d2bad93eaeaf
📒 Files selected for processing (11)
cli/src/types/supabase.types.tsmessages/en.jsonsrc/pages/admin/dashboard/users.vuesrc/types/supabase.types.tssupabase/functions/_backend/plugin_runtime/utils/pg.tssupabase/functions/_backend/plugin_runtime/utils/supabase.types.tssupabase/functions/_backend/triggers/logsnag_insights.tssupabase/functions/_backend/utils/pg.tssupabase/functions/_backend/utils/supabase.types.tssupabase/migrations/20260808071749_apps_with_preview_global_stats.sqltests/logsnag-insights-revenue.unit.test.ts
🔗 Linked repositories identified
CodeRabbit considers these linked repositories for cross-repo context during reviews:
Cap-go/capacitor-updater(manual)
| catch (error) { | ||
| cloudlogErr({ requestId: c.get('requestId'), message: 'countAppsWithPreview error', error }) | ||
| return 0 |
There was a problem hiding this comment.
🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win
Propagate count failures instead of recording zero.
Lines [1507-1509] convert every database error into a valid-looking 0. The core shard can then persist that value as the snapshot, making a failed query indistinguishable from zero preview-enabled apps. Log the error and rethrow it so shard failure handling can retry the snapshot.
Suggested error propagation
catch (error) {
cloudlogErr({ requestId: c.get('requestId'), message: 'countAppsWithPreview error', error })
- return 0
+ throw error
}📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| catch (error) { | |
| cloudlogErr({ requestId: c.get('requestId'), message: 'countAppsWithPreview error', error }) | |
| return 0 | |
| catch (error) { | |
| cloudlogErr({ requestId: c.get('requestId'), message: 'countAppsWithPreview error', error }) | |
| throw error |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@supabase/functions/_backend/triggers/logsnag_insights.ts` around lines 1507 -
1509, Update the countAppsWithPreview error handler to keep logging the database
error, then rethrow it instead of returning 0. Preserve the successful count
path so shard failure handling can detect the failure and retry the snapshot.
| ALTER TABLE public.global_stats | ||
| ADD COLUMN IF NOT EXISTS apps_with_preview bigint NOT NULL DEFAULT 0; |
There was a problem hiding this comment.
🗄️ Data Integrity & Integration | 🟠 Major | 🏗️ Heavy lift
Prevent false historical values.
DEFAULT 0 writes 0 into every existing global_stats row. The trend will report false zeros for dates before August 8, 2026, unless downstream queries exclude those rows.
Backfill from a source that records historical allow_preview state, or start the trend at the first real snapshot. Do not derive historical values from the current apps.allow_preview state.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@supabase/migrations/20260808071749_apps_with_preview_global_stats.sql` around
lines 1 - 2, Update the migration adding apps_with_preview so existing
global_stats rows are not populated with misleading zero values. Backfill
historical values from a source containing the recorded allow_preview state, or
constrain the trend to begin at the first valid snapshot; do not derive
historical values from the current apps.allow_preview state.
| ADD COLUMN IF NOT EXISTS apps_with_preview bigint NOT NULL DEFAULT 0; | ||
|
|
||
| COMMENT ON COLUMN public.global_stats.apps_with_preview | ||
| IS 'Number of apps with preview QR enabled (allow_preview = true) at snapshot day end.'; |
There was a problem hiding this comment.
📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win
Fix the SQL comment line length.
SQLFluff reports that Line 5 is 90 characters, exceeding the 80-character limit. Shorten or split the comment without changing its meaning.
Proposed fix
- IS 'Number of apps with preview QR enabled (allow_preview = true) at snapshot day end.';
+ IS 'Apps with preview QR enabled at snapshot day end (allow_preview = true).';📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| IS 'Number of apps with preview QR enabled (allow_preview = true) at snapshot day end.'; | |
| IS 'Apps with preview QR enabled at snapshot day end (allow_preview = true).'; |
🧰 Tools
🪛 SQLFluff (4.2.2)
[error] 5-5: Line is too long (90 > 80).
(LT05)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@supabase/migrations/20260808071749_apps_with_preview_global_stats.sql` at
line 5, Shorten or split the SQL comment attached to the preview-apps statistic
so each line is no longer than 80 characters, while preserving its meaning about
apps with allow_preview enabled at snapshot day end.
Source: Linters/SAST tools
|
|
||
| it.concurrent('snapshots apps with preview QR enabled in the core global stats shard', () => { | ||
| const source = readFileSync(new URL('../supabase/functions/_backend/triggers/logsnag_insights.ts', import.meta.url), 'utf8') | ||
| const countFn = source.match(/async function countAppsWithPreview[\s\S]*?async function getTrialExtensionStats/)?.[0] ?? '' | ||
| const coreShard = source.match(/async function runCoreGlobalStatsShard[\s\S]*?async function getRegistersToday/)?.[0] ?? '' | ||
|
|
||
| expect(countFn).toContain('apps.allow_preview = true') | ||
| expect(countFn).toContain('apps.created_at <') | ||
| expect(countFn).toContain('snapshotEnd') | ||
| expect(coreShard).toContain('countAppsWithPreview(c, window.prevDayEnd)') | ||
| expect(coreShard).toContain('apps_with_preview,') | ||
| }) |
There was a problem hiding this comment.
🎯 Functional Correctness | 🔵 Trivial | 🏗️ Heavy lift
Test the metric behavior instead of matching source text.
Lines [685-694] only inspect implementation strings. They do not execute countAppsWithPreview, verify the snapshotEnd boundary with data, or confirm the value passed to updateGlobalStatsSnapshot. A broken query that always returns zero can still pass this test. Add a behavioral test with mocked database clients or an existing database-backed fixture.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@tests/logsnag-insights-revenue.unit.test.ts` around lines 683 - 694, Replace
the source-string assertions in the “snapshots apps with preview QR enabled”
test with a behavioral test that executes the relevant stats flow using mocked
database clients or an existing database fixture. Seed records covering
preview-enabled apps before and at the snapshot boundary, verify
countAppsWithPreview returns only records before snapshotEnd, and assert
runCoreGlobalStatsShard passes that value as apps_with_preview to
updateGlobalStatsSnapshot.



Summary (AI generated)
global_stats.apps_with_previewdaily snapshot of apps withallow_preview = truelogsnag_insightsglobal stats shardglobal_stats_trend/getAdminGlobalStatsTrendMotivation (AI generated)
Preview QR adoption needs a historical view. A live count only shows today. Daily snapshots in
global_statsmatch existing admin KPI patterns and keep the dashboard off hot-path scans.Business Impact (AI generated)
Makes preview QR rollout measurable day by day, so product can see adoption trend without ad-hoc SQL.
Test Plan (AI generated)
allow_previewapps intoapps_with_previewglobal_stats.apps_with_previewexists0until snapshots exist (no fake backfill)Generated with AI
Need help on this PR? Tag
@codesmith-botwith what you need. Autofix is disabled.Summary by CodeRabbit
New Features
Bug Fixes
Tests