Skip to content

refactor(web): log one line per request or job with evlog - #459

Merged
botandbang merged 1 commit into
mainfrom
bnb/web-evlog
Nov 5, 2026
Merged

botandbang merged 1 commit into
mainfrom
bnb/web-evlog

Conversation

@botandbang

Copy link
Copy Markdown
Contributor

Moves the web app from pino to evlog. A request or background job now writes one line with everything that happened during it, in place of a line per log call. The reasoning and the options turned down are in ADR 0007.

Added:

  • logger.request() and logger.job() in logger.ts open a line, and an AsyncLocalStorage finds it, so services keep calling logger.warn() under either. Each note goes under notes with its own fields, because a service's did or status isn't the request's. evlog's own log.warn(message, fields) merges them into the line.
  • Jobs: every timer in app.ts, bootstrap, directory-sync, reindex-shows, notification-delivery, notification-recovery, db-backup and space-sync (one per space). A job that noted nothing writes no line, so the 15-second timers stay quiet.
  • A note that arrives after its line was written, like a streamed page's failed promise, gets its own line with the request's fields. So does a note past the 20 a line holds. evlog would drop the first and the second would make a very long line.
  • testing/written-log.ts: a real logger and the lines it wrote to stdout, which every test that reads the log now uses.
  • ADR 0007, and a Logs section in apps/web/README.md.

Changed:

  • 203 log calls take (message, fields), evlog's order, instead of pino's (fields, message).
  • Production lines go to stdout whatever their level. Railway's docs say logs from stderr become error, and evlog's console output writes warn to stderr. So lines are written from a drain, with level by name as fix(web): write log levels by name #446 did and message as Railway reads it.
  • message joins every note's message, so a --filter for "space sync failed", "background task failed" or "bootstrap failed" has the text to match, as it did with a line per note. level stays a name for @level:warn and @level:error.
  • level is the line's worst note, and for a request also its status: warn for a 4xx and error for a 5xx.
  • The first error on a line goes in error, where evlog prints it in full, and its note keeps the message. Later errors stay on their notes.
  • Requests the write limit turns away and redirects or errors thrown from handle now get a line. They had none.
  • Recordings and cards put their details on the request's line (recording, card) in place of a note each.
  • Field names: msg is message, ms is durationMs, name is service, and pid and hostname are gone. Two notes that called something else status now say channelStatus and backfillStatus, since status on a line means the response's.

The redact list is unchanged, with the same replacement, [redacted]. evlog matches a bare key at any depth where pino matched the top level and one level down, and its built-in patterns also mask emails, IP addresses, phone numbers, card numbers, JWTs and bearer tokens in any string, so this redacts more than before. Tests check each key at three depths in the written output, including what an error carries.

Removed: pino, pino-pretty, and createLogger's name and stream options. Other packages still pull pino in through @atproto, but the app no longer depends on it.

evlog is on 2.34.0 rather than 2.35.1, which came out on 2026-11-05 and doesn't pass pnpm's release age check yet. The logger is server code: the production build's budget tests pass, and no file in build/client names evlog.

evlog's CLI doesn't help here: evlog init and evlog map stop with "Could not detect a supported framework" on SvelteKit. The site's audit log stays as it is. It's its own hash-chained store, so evlog's log.audit would be a second one.

To check after this deploys, once a sync has failed: railway logs --service localnetwork --lines 20 --filter "@level:warn". The local run can't show Railway reading these lines, only that they're on stdout in the documented shape.

Requests and background jobs each write one wide line, and whatever
services note along the way joins it with its own fields. Services
keep a plain logger, and an AsyncLocalStorage finds the line.

Lines go to stdout with their level by name. Railway files stderr
under error, and evlog's console output sends warnings there.

pino and pino-pretty are gone. The redact list is unchanged.
@botandbang
botandbang requested a review from bnb as a code owner November 5, 2026 17:33
@github-actions github-actions Bot added documentation Improvements or additions to documentation dependencies Pull requests that update a dependency file web The Local Network website (apps/web) web: directory Directory search, the show matcher, genres and places web: projects Project profiles, claims, and the DJ stats and sets on them web: mixes Mixes, their tracklists and mix reports web: epk Press kits and who can see them web: bookings Booking inquiries and their threads web: planner Promoters' private planner web: staff Admin, moderation and the audit log web: accounts Signing in, sessions and the account pages web: server Spaces, sync, HappyView, the database and the server around them tests Tests, fixtures and test harnesses tooling Repo config, lint and build tooling, and GitHub settings labels Nov 5, 2026
@socket-security

Copy link
Copy Markdown

Review the following changes in direct dependencies. Learn more about Socket for GitHub.

Diff Package Supply Chain
Security
Vulnerability Quality Maintenance License
Addednpm/​evlog@​2.34.09810010096100

View full report

@github-actions

github-actions Bot commented Nov 5, 2026 •

Copy link
Copy Markdown

Coverage Report for apps/localtoolbox

Status Category Percentage Covered / Total
🟢 Lines 100% (🎯 100%)
🟰 ±0 pp
4430 / 4430
🟢 Statements 100% (🎯 100%)
🟰 ±0 pp
6009 / 6009
🟢 Functions 100% (🎯 100%)
🟰 ±0 pp
1759 / 1759
🟢 Branches 98.59% (🎯 50%)
🟰 ±0 pp
2875 / 2916
File CoverageNo changed files found.
Generated in workflow #377 for commit 8be86e3 by the Vitest Coverage Report Action

Size

Compared with main. KiB are 1,024 bytes.

This pull request main Change
Packaged (localtoolbox.zip) 359 KiB 359 KiB -7 B (-0%)
Unpacked (dist/) 806.4 KiB 806.4 KiB 0 B (0%)

@github-actions

github-actions Bot commented Nov 5, 2026 •

Copy link
Copy Markdown

Coverage Report for apps/web

Status Category Percentage Covered / Total
🟢 Lines 99.55% (🎯 99%)
⬆️ +0.02 pp
10428 / 10475
🟢 Statements 99.37% (🎯 99%)
⬆️ +0.01 pp
15939 / 16040
🟢 Functions 99.36% (🎯 99%)
🟰 ±0 pp
4258 / 4285
🟢 Branches 94.84% (🎯 94%)
⬆️ +0.02 pp
7783 / 8206
File Coverage
File Stmts Branches Functions Lines Uncovered Lines
Changed Files
apps/web/src/hooks.server.ts 100%
🟰 ±0 pp
100%
🟰 ±0 pp
100%
🟰 ±0 pp
100%
🟰 ±0 pp
apps/web/src/lib/server/actor-search.ts 100%
🟰 ±0 pp
95.45%
🟰 ±0 pp
100%
🟰 ±0 pp
100%
🟰 ±0 pp
apps/web/src/lib/server/app.ts 100%
🟰 ±0 pp
100%
🟰 ±0 pp
100%
🟰 ±0 pp
100%
🟰 ±0 pp
apps/web/src/lib/server/audio.ts 100%
🟰 ±0 pp
100%
🟰 ±0 pp
100%
🟰 ±0 pp
100%
🟰 ±0 pp
apps/web/src/lib/server/bootstrap.ts 94.44%
🟰 ±0 pp
92.85%
🟰 ±0 pp
100%
🟰 ±0 pp
97.05%
🟰 ±0 pp
57, 107
apps/web/src/lib/server/geocode.ts 97.77%
🟰 ±0 pp
75%
🟰 ±0 pp
100%
🟰 ±0 pp
100%
🟰 ±0 pp
124
apps/web/src/lib/server/images.ts 100%
🟰 ±0 pp
100%
🟰 ±0 pp
100%
🟰 ±0 pp
100%
🟰 ±0 pp
apps/web/src/lib/server/logger.ts 100%
⬆️ +10.00 pp
100%
🟰 ±0 pp
100%
🟰 ±0 pp
100%
⬆️ +10.00 pp
apps/web/src/lib/server/planner-page.ts 100%
🟰 ±0 pp
75%
🟰 ±0 pp
100%
🟰 ±0 pp
100%
🟰 ±0 pp
apps/web/src/lib/server/plyr.ts 100%
🟰 ±0 pp
100%
🟰 ±0 pp
100%
🟰 ±0 pp
100%
🟰 ±0 pp
apps/web/src/lib/server/sign-in.ts 100%
🟰 ±0 pp
100%
🟰 ±0 pp
100%
🟰 ±0 pp
100%
🟰 ±0 pp
apps/web/src/lib/server/atproto/credentials.ts 100%
🟰 ±0 pp
100%
🟰 ±0 pp
100%
🟰 ±0 pp
100%
🟰 ±0 pp
apps/web/src/lib/server/atproto/identity.ts 100%
🟰 ±0 pp
100%
🟰 ±0 pp
100%
🟰 ±0 pp
100%
🟰 ±0 pp
apps/web/src/lib/server/atproto/oauth.ts 100%
🟰 ±0 pp
100%
🟰 ±0 pp
100%
🟰 ±0 pp
100%
🟰 ±0 pp
apps/web/src/lib/server/atproto/root.ts 100%
🟰 ±0 pp
96.42%
🟰 ±0 pp
100%
🟰 ±0 pp
100%
🟰 ±0 pp
apps/web/src/lib/server/audit/log.ts 95.23%
🟰 ±0 pp
86.36%
🟰 ±0 pp
96.29%
🟰 ±0 pp
100%
🟰 ±0 pp
199, 320, 326, 371, 373, 400, 504, 552, 593
apps/web/src/lib/server/backup/backups.ts 98.86%
🟰 ±0 pp
92.3%
🟰 ±0 pp
100%
🟰 ±0 pp
100%
🟰 ±0 pp
51
apps/web/src/lib/server/happyview/backfills.ts 100%
🟰 ±0 pp
100%
🟰 ±0 pp
100%
🟰 ±0 pp
100%
🟰 ±0 pp
apps/web/src/lib/server/happyview/indexed.ts 98.27%
🟰 ±0 pp
100%
🟰 ±0 pp
94.11%
🟰 ±0 pp
100%
🟰 ±0 pp
29
apps/web/src/lib/server/happyview/offline.ts 100%
🟰 ±0 pp
100%
🟰 ±0 pp
100%
🟰 ±0 pp
100%
🟰 ±0 pp
apps/web/src/lib/server/happyview/refresh.ts 100%
🟰 ±0 pp
100%
🟰 ±0 pp
100%
🟰 ±0 pp
100%
🟰 ±0 pp
apps/web/src/lib/server/happyview/request-index.ts 100%
🟰 ±0 pp
100%
🟰 ±0 pp
100%
🟰 ±0 pp
100%
🟰 ±0 pp
apps/web/src/lib/server/media/audio.ts 100%
🟰 ±0 pp
100%
🟰 ±0 pp
100%
🟰 ±0 pp
100%
🟰 ±0 pp
apps/web/src/lib/server/notifications/channels.ts 98.8%
🟰 ±0 pp
98.85%
🟰 ±0 pp
100%
🟰 ±0 pp
100%
🟰 ±0 pp
125
apps/web/src/lib/server/notifications/dm.ts 100%
🟰 ±0 pp
92.1%
🟰 ±0 pp
100%
🟰 ±0 pp
100%
🟰 ±0 pp
apps/web/src/lib/server/notifications/email.ts 97.91%
🟰 ±0 pp
95.23%
🟰 ±0 pp
93.33%
🟰 ±0 pp
100%
🟰 ±0 pp
57
apps/web/src/lib/server/notifications/notifier.ts 98.38%
🟰 ±0 pp
100%
🟰 ±0 pp
94.73%
🟰 ±0 pp
98.11%
🟰 ±0 pp
107
apps/web/src/lib/server/notifications/outbox.ts 99.18%
⬆️ +0.01 pp
94.54%
🟰 ±0 pp
100%
🟰 ±0 pp
100%
🟰 ±0 pp
308
apps/web/src/lib/server/og/cards.ts 95%
🟰 ±0 pp
83.33%
🟰 ±0 pp
100%
🟰 ±0 pp
100%
🟰 ±0 pp
66
apps/web/src/lib/server/og/serve.ts 100%
🟰 ±0 pp
100%
🟰 ±0 pp
100%
🟰 ±0 pp
100%
🟰 ±0 pp
apps/web/src/lib/server/services/accounts.ts 100%
🟰 ±0 pp
100%
🟰 ±0 pp
100%
🟰 ±0 pp
100%
🟰 ±0 pp
apps/web/src/lib/server/services/bookings.ts 99.56%
🟰 ±0 pp
98.5%
🟰 ±0 pp
100%
🟰 ±0 pp
99.47%
🟰 ±0 pp
51
apps/web/src/lib/server/services/bug-reports.ts 100%
🟰 ±0 pp
100%
🟰 ±0 pp
100%
🟰 ±0 pp
100%
🟰 ±0 pp
apps/web/src/lib/server/services/dj.ts 100%
🟰 ±0 pp
100%
🟰 ±0 pp
100%
🟰 ±0 pp
100%
🟰 ±0 pp
apps/web/src/lib/server/services/epk-drafts.ts 99.45%
🟰 ±0 pp
99.44%
🟰 ±0 pp
100%
🟰 ±0 pp
100%
🟰 ±0 pp
329
apps/web/src/lib/server/services/epk-legacy.ts 100%
🟰 ±0 pp
100%
🟰 ±0 pp
100%
🟰 ±0 pp
100%
🟰 ±0 pp
apps/web/src/lib/server/services/epk-space-move.ts 100%
🟰 ±0 pp
100%
🟰 ±0 pp
100%
🟰 ±0 pp
100%
🟰 ±0 pp
apps/web/src/lib/server/services/epk-views.ts 100%
🟰 ±0 pp
88.88%
🟰 ±0 pp
100%
🟰 ±0 pp
100%
🟰 ±0 pp
apps/web/src/lib/server/services/epk.ts 99.4%
🟰 ±0 pp
98.13%
🟰 ±0 pp
100%
🟰 ±0 pp
99.61%
🟰 ±0 pp
226, 967
apps/web/src/lib/server/services/follows.ts 100%
🟰 ±0 pp
100%
🟰 ±0 pp
100%
🟰 ±0 pp
100%
🟰 ±0 pp
apps/web/src/lib/server/services/held-records.ts 100%
🟰 ±0 pp
100%
🟰 ±0 pp
100%
🟰 ±0 pp
100%
🟰 ±0 pp
apps/web/src/lib/server/services/listings.ts 100%
🟰 ±0 pp
100%
🟰 ±0 pp
100%
🟰 ±0 pp
100%
🟰 ±0 pp
apps/web/src/lib/server/services/manager-spaces.ts 100%
🟰 ±0 pp
100%
🟰 ±0 pp
100%
🟰 ±0 pp
100%
🟰 ±0 pp
apps/web/src/lib/server/services/own-repo.ts 100%
🟰 ±0 pp
100%
🟰 ±0 pp
100%
🟰 ±0 pp
100%
🟰 ±0 pp
apps/web/src/lib/server/services/planner.ts 98.85%
🟰 ±0 pp
97.22%
🟰 ±0 pp
100%
🟰 ±0 pp
98.64%
🟰 ±0 pp
40
apps/web/src/lib/server/services/profiles.ts 98.07%
🟰 ±0 pp
98.18%
🟰 ±0 pp
100%
🟰 ±0 pp
100%
🟰 ±0 pp
89
apps/web/src/lib/server/services/projects.ts 99.33%
🟰 ±0 pp
99.11%
🟰 ±0 pp
100%
🟰 ±0 pp
100%
🟰 ±0 pp
484
apps/web/src/lib/server/services/recordings.ts 100%
🟰 ±0 pp
100%
🟰 ±0 pp
100%
🟰 ±0 pp
100%
🟰 ±0 pp
apps/web/src/lib/server/services/requests.ts 100%
🟰 ±0 pp
100%
🟰 ±0 pp
100%
🟰 ±0 pp
100%
🟰 ±0 pp
apps/web/src/lib/server/services/sets.ts 100%
🟰 ±0 pp
100%
🟰 ±0 pp
100%
🟰 ±0 pp
100%
🟰 ±0 pp
apps/web/src/lib/server/services/shared-spaces.ts 99.62%
🟰 ±0 pp
99.36%
🟰 ±0 pp
100%
🟰 ±0 pp
99.57%
🟰 ±0 pp
780
apps/web/src/lib/server/services/shows.ts 98.73%
🟰 ±0 pp
98.61%
🟰 ±0 pp
100%
🟰 ±0 pp
98.49%
🟰 ±0 pp
97, 106
apps/web/src/lib/server/services/space-members.ts 100%
🟰 ±0 pp
100%
🟰 ±0 pp
100%
🟰 ±0 pp
100%
🟰 ±0 pp
apps/web/src/lib/server/services/staff.ts 100%
🟰 ±0 pp
100%
🟰 ±0 pp
100%
🟰 ±0 pp
100%
🟰 ±0 pp
apps/web/src/lib/server/services/supports.ts 100%
🟰 ±0 pp
100%
🟰 ±0 pp
100%
🟰 ±0 pp
100%
🟰 ±0 pp
apps/web/src/lib/server/services/tracklists.ts 100%
🟰 ±0 pp
100%
🟰 ±0 pp
100%
🟰 ±0 pp
100%
🟰 ±0 pp
apps/web/src/lib/server/services/verifications.ts 100%
🟰 ±0 pp
100%
🟰 ±0 pp
100%
🟰 ±0 pp
100%
🟰 ±0 pp
apps/web/src/lib/server/sync/engine.ts 100%
🟰 ±0 pp
99.15%
🟰 ±0 pp
100%
🟰 ±0 pp
100%
🟰 ±0 pp
apps/web/src/lib/server/sync/projections.ts 98.73%
🟰 ±0 pp
98.79%
🟰 ±0 pp
100%
🟰 ±0 pp
100%
🟰 ±0 pp
98
apps/web/src/lib/server/token-exchange/exchange.ts 100%
🟰 ±0 pp
97.82%
🟰 ±0 pp
100%
🟰 ±0 pp
100%
🟰 ±0 pp
apps/web/src/routes/admin/audit/export/+server.ts 100%
🟰 ±0 pp
100%
🟰 ±0 pp
100%
🟰 ±0 pp
100%
🟰 ±0 pp
apps/web/src/routes/admin/spaces/+page.server.ts 100%
🟰 ±0 pp
100%
🟰 ±0 pp
100%
🟰 ±0 pp
100%
🟰 ±0 pp
apps/web/src/routes/admin/spaces/[kind]/[skey]/+page.server.ts 100%
🟰 ±0 pp
100%
🟰 ±0 pp
100%
🟰 ±0 pp
100%
🟰 ±0 pp
apps/web/src/routes/admin/verifications/+page.server.ts 100%
🟰 ±0 pp
100%
🟰 ±0 pp
100%
🟰 ±0 pp
100%
🟰 ±0 pp
apps/web/src/routes/dashboard/+layout.server.ts 100%
🟰 ±0 pp
100%
🟰 ±0 pp
100%
🟰 ±0 pp
100%
🟰 ±0 pp
apps/web/src/routes/dashboard/+page.server.ts 100%
🟰 ±0 pp
100%
🟰 ±0 pp
100%
🟰 ±0 pp
100%
🟰 ±0 pp
apps/web/src/routes/dashboard/bookings/new/+page.server.ts 100%
🟰 ±0 pp
100%
🟰 ±0 pp
100%
🟰 ±0 pp
100%
🟰 ±0 pp
apps/web/src/routes/dashboard/data/+page.server.ts 89.47%
🟰 ±0 pp
50%
🟰 ±0 pp
83.33%
🟰 ±0 pp
100%
🟰 ±0 pp
11, 32
apps/web/src/routes/dashboard/inbox/settings/+page.server.ts 100%
🟰 ±0 pp
100%
🟰 ±0 pp
100%
🟰 ±0 pp
100%
🟰 ±0 pp
apps/web/src/routes/dashboard/projects/[slug]/+page.server.ts 100%
🟰 ±0 pp
100%
🟰 ±0 pp
100%
🟰 ±0 pp
100%
🟰 ±0 pp
apps/web/src/routes/dashboard/requests/[rkey]/avatar/+server.ts 100%
🟰 ±0 pp
100%
🟰 ±0 pp
100%
🟰 ±0 pp
100%
🟰 ±0 pp
apps/web/src/routes/login/+page.server.ts 100%
🟰 ±0 pp
100%
🟰 ±0 pp
100%
🟰 ±0 pp
100%
🟰 ±0 pp
apps/web/src/routes/login/create/+page.server.ts 100%
🟰 ±0 pp
100%
🟰 ±0 pp
100%
🟰 ±0 pp
100%
🟰 ±0 pp
apps/web/src/routes/media/[did]/[cid]/+server.ts 100%
🟰 ±0 pp
100%
🟰 ±0 pp
100%
🟰 ±0 pp
100%
🟰 ±0 pp
apps/web/src/routes/oauth/callback/+server.ts 100%
🟰 ±0 pp
100%
🟰 ±0 pp
100%
🟰 ±0 pp
100%
🟰 ±0 pp
apps/web/src/routes/projects/[slug]/+page.server.ts 100%
🟰 ±0 pp
100%
🟰 ±0 pp
100%
🟰 ±0 pp
100%
🟰 ±0 pp
apps/web/src/routes/report/+page.server.ts 100%
🟰 ±0 pp
100%
🟰 ±0 pp
100%
🟰 ±0 pp
100%
🟰 ±0 pp
apps/web/src/routes/sets/[did]/[rkey]/player.json/+server.ts 100%
🟰 ±0 pp
100%
🟰 ±0 pp
100%
🟰 ±0 pp
100%
🟰 ±0 pp
apps/web/src/routes/xrpc/com.atproto.space.notifySpaceDeleted/+server.ts 100%
🟰 ±0 pp
100%
🟰 ±0 pp
100%
🟰 ±0 pp
100%
🟰 ±0 pp
apps/web/src/routes/xrpc/com.atproto.space.notifyWrite/+server.ts 100%
🟰 ±0 pp
100%
🟰 ±0 pp
100%
🟰 ±0 pp
100%
🟰 ±0 pp
Generated in workflow #377 for commit 8be86e3 by the Vitest Coverage Report Action

Size

Compared with main. KiB are 1,024 bytes.

This pull request main Change
Client JavaScript 771.3 KiB 771.5 KiB -121 B (-0%)
Client JavaScript, brotli 259.3 KiB 259.3 KiB +9 B (+0%)
Client CSS 94.5 KiB 94.5 KiB 0 B (0%)
Client CSS, brotli 13.6 KiB 13.6 KiB 0 B (0%)

@botandbang
botandbang added this pull request to the merge queue Nov 5, 2026
Merged via the queue into main with commit 5eef1ce Nov 5, 2026
64 of 68 checks passed
@botandbang
botandbang deleted the bnb/web-evlog branch November 5, 2026 20:28
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

dependencies Pull requests that update a dependency file documentation Improvements or additions to documentation tests Tests, fixtures and test harnesses tooling Repo config, lint and build tooling, and GitHub settings web: accounts Signing in, sessions and the account pages web: bookings Booking inquiries and their threads web: directory Directory search, the show matcher, genres and places web: epk Press kits and who can see them web: mixes Mixes, their tracklists and mix reports web: planner Promoters' private planner web: projects Project profiles, claims, and the DJ stats and sets on them web: server Spaces, sync, HappyView, the database and the server around them web: staff Admin, moderation and the audit log web The Local Network website (apps/web)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants