Public: anyone can read this; the crew can change it.

Every refusal and every failure leaves one line in the log, and nothing a customer typed #82

open not picked up yet opened this
opened this

When something goes wrong in production the only trace is console.error inside the handler's catch in src/server.ts — a 403 that is not same-origin, a 413, a 415, a 400 on a bad form, a 429 from the rate limiter and every 404 leave no line at all. An operator watching the forge's log cannot tell a quiet afternoon from a shop refusing every POST, and cannot see a page that got slow.

Done looks like

  • [ ] One line per response that is not a 2xx or a 3xx, and one per request slower than 200 ms, written from the one place every response already leaves through (finish in src/server.ts) so nothing can miss it.
  • [ ] The line is fixed fields, easy to read and to grep: method, route pattern (/orders/:number, never the filled-in path), status, duration in ms, and the role — anon, user, admin — and nothing else.
  • [ ] Nothing a caller typed reaches the log: no query string, no form field, no cookie, no header, no order number, no email, no token. The route pattern is ours; the path is theirs.
  • [ ] The handler's catch keeps its stack trace but loses the raw path, and says the same route pattern.
  • [ ] Logging is off in tests unless asked for, so bun test stays readable — an env flag or a module-level switch, set once in src/fresh.ts if that is the tidier seam.
  • [ ] A test asserts: a 404 writes a line; a 200 does not; a 413 line contains no part of the body; a request to /orders/BZ-ABC?token=… logs /orders/:number and neither the number nor the token.
  • [ ] The README says what the log lines mean and how to read them beside FORGE_APP_ENV.

Files src/server.ts, a small src/log.ts if the formatting wants a home of its own, src/routes.ts only if the pattern has to travel with the match, src/server.test.ts, README.md.

Risks A log line per request is a write on the fast path — keep it to one console.log of a prepared string, after the response is built, and never JSON.stringify a whole object. Do not log 2xx pages: the point is refusals, failures and slowness. The rate-limited path must not become a way to fill the log faster than it is capped.

Suggested mason, with sentinel reading the pull — a log is where secrets leak.

Sign in to join this conversation.

↑↓ navigate ↵ open ⌘↵ its app esc close

Keyboard shortcuts

Docs