Put the accounts on the statistics dashboard, and leave our own out - #174
Open
Alexgodoroja wants to merge 2 commits into
Open
Alexgodoroja wants to merge 2 commits into
Alexgodoroja wants to merge 2 commits into
Conversation
… its own line The scheduled download check installed on three fresh GitHub runners every half hour, and the dashboard counted it: six installs, five installer fetches, three "ok" outcomes and three or four new machines per run, which is a day of ninety installs and fifty-six machines that never came back. Both install scripts now take SHELL_ONLINE_INSTALL_CHECK=1, which puts a check user agent on every request and reports nothing; the workflow sets it, and the Worker counts that agent, and monitors in general, as crawlers. HTTP libraries and PowerShell are tools rather than desktop browsers, so a Node script is not a person and a Windows install is a run. The installs tile drew the sessions line, since the trend had no installs series; it now has installs and started sessions, crawlers left out of every line. "New" is measured per surface from the day its people were first counted, and until a whole range has passed since then the split is replaced by the day it becomes meaningful. Machine rows keyed the old way are dropped once. Prefetched pages are not views, and the 24h range says people are counted by UTC day. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
The dashboard could already read account figures from the accounts app, but nothing was linked to it and the panel it drew was three numbers at the bottom of the page. Accounts are the one exact count of people the dashboard has -- everything else on it is a keyed hash guessing at a person -- so they now sit directly under the funnel, which ends at a first keystroke, and are laid out to be read in one pass: - four headline figures, each against the period before: how many accounts there are, how many signed up, how many opened the app, and how many of those had signed up earlier; - a line of sign-ups and use for every day since the first account, whatever range is selected, because accounts arrive a few a day and a day is the smallest step that says anything; - what accounts did in the app, how many separate days each of them has been in it, and which sign-up weeks came back. Our own accounts are dropped before any of it is counted. They are the most active accounts there are and were always going to use the product, so left in they make a quiet week look like a good one. STATS_EXCLUDE on the accounts app names them -- whole addresses, or domains and their subdomains -- and the dashboard says how many it left out, so the figure can be checked rather than taken on trust. The list is configuration rather than source because it names individual people and this repository is public. What those accounts do in the app is counted apart from what customers do: app_events gains an internal column, and the rows written before it existed are attributed to us, so the change can only ever understate what customers did. The address is read to decide that and for nothing else; the store answers the dashboard with a flag and never an identifier. Also: a chart now takes points and a step rather than the trend type and a range, which is what lets the accounts days be drawn by the same code; a tooltip on a point that covers a whole UTC day names that day instead of a local time in the middle of it; and the Worker's half of the accounts link moved into worker/account-stats.ts, where a Worker deployed ahead of the app fills in the figures the app does not send yet instead of reporting an error. Co-Authored-By: Claude Opus 5 (1M context) <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.
What changed
Builds on #173, whose commit is the first of the two here: merging this
lands both, so #173 can be closed rather than merged separately.
The dashboard could already read account figures from the accounts app, but
nothing was linked to it — the deployed relay Worker has
APP_STATS_TOKENandno
APP_STATS_URL, so the panel was never drawn — and the panel it would havedrawn was three numbers at the bottom of the page.
Accounts are the one exact count of people the dashboard has; everything else
on it is a keyed hash guessing at a person. So they now sit directly under the
funnel, which ends at a first keystroke, and are laid out to be read in one
pass:
are, how many signed up in the range, how many opened the app, and how many
of those had signed up earlier. The last one is the only number that says
whether anything is sticking.
account, whatever range is selected. Accounts arrive a few a day, so a day is
the smallest step that says anything and the range picker would reduce it to
one point.
commands sent, vaults, invites, feedback), how many separate days each
account has been in it, and which sign-up weeks came back.
The account days are only known from the day the app started recording them, so
an older account has days missing through no fault of its own. It is left out
of the "how much they use it" bands rather than counted as a bounce, and the
panel says which day the recording starts and how many accounts the bands are
over.
Leaving our own accounts out
Of the 43 accounts in production today, 26 are ours: founders, colleagues, and
the addresses the end-to-end tests sign up with. They are the most active
accounts there are and were always going to use the product, so left in they
make a quiet week look like a good one.
STATS_EXCLUDEon the accounts app names them — a whole address, or a domainand its subdomains, with a
+tagignored on both sides. Unset, nobody isexcluded. The dashboard reports how many accounts it left out, in the panel's
own sentence and in the page footer, so the figure can be checked rather than
taken on trust.
It is configuration rather than a list in the source because it names
individual people and this repository is public.
What those accounts do in the app is counted apart from what customers do:
app_eventsgains aninternalcolumn (migration014), andappEvents()reports only the customers' side. The rows written before the column existed
cannot be split any more, so the column arrives defaulting to
TRUE— itbackfills what is already there as ours and then defaults to
FALSE— whichmeans the change can only ever understate what customers did, never overstate
it, and no row is thrown away to get there.
The address is read to decide all of this and for nothing else. The store
applies the predicate while it still holds the email and answers with a
boolean, so nothing outside it is ever handed an identifier; the route's answer
still contains no uid and no address, and the tests assert it.
Incidental
which is what lets the account days be drawn by the same code.
local time in the middle of it. The 7d trend's step is six hours, so it keeps
its hour.
worker/account-stats.ts,where it is testable. A Worker deployed ahead of the app now fills in the
figures the app does not send yet instead of reporting the whole answer as
the wrong shape.
Verification
npm run checkat the root: three typecheck projects clean, 175 tests,installer, Docker entrypoint, deploy guard, QEMU manifest, landing SEO,
mobile controls and Homebrew formula all pass;
npm run build:websucceeds.
app:tsc -b --forceclean, 947 tests pass,oxlintadds no warning inany file touched here,
check-protocolpasses.store-postgres.test.tsrun against a real Postgres wire protocol(PGlite over a socket), which applies migration
014. Everyaccount activityandapp eventscase passes on both stores. Five failuresremain in
authorization codes,migrationsand the organization racetests — the same ones fail on this branch's base commit, so they are the
harness, not this change.
rows (read-only, through the Cloud SQL proxy) with the exclusion list
applied: 17 accounts, 26 excluded. Checked at 1440px and 390px, on every
range, plus the two degraded states — accounts not linked (the whole block
including its heading is absent) and accounts linked but unreachable (the
existing note naming the three variables). No console errors.
Deploy notes
014must be applied before theaccounts app starts writing
internal.deploy-app.ymlalready does this inthat order.
STATS_EXCLUDEis a secret on theshell-online-appWorker(
npx wrangler secret put STATS_EXCLUDE). Until it is set, nobody isexcluded and the dashboard says nothing about exclusions.
APP_STATS_URLadded to its (private) productionconfig and a deploy.
APP_STATS_TOKENis already set. Without the URL theaccounts block does not appear at all, which is the behaviour today.
web/**, so the dashboard changesreach nobody until it goes out.
🤖 Generated with Claude Code