ByeBuy.ai
BUILD YOUR ESCAPE ROUTE · ✦ CURSOR · HOST IT · ◫ SUPABASE · CONNECT IT · ↯ RELAY · BUILD YOUR ESCAPE ROUTE · ✦ CURSOR · HOST IT · ◫ SUPABASE · CONNECT IT · ↯ RELAY ·
CURRICULUM
← BYEBUY NOTES

September 12, 2026

EVERY FAILURE NEEDS A TRAIL YOU CAN FOLLOW

Every Failure Needs a Trail You Can Follow

Class 50 taught you to make the product prove itself with tests. Tests catch the failures you anticipated. This lesson is about the failures you did not anticipate — the ones a real user finds at 2 p.m. on a Tuesday. Without a trail, you are guessing. With one, you are investigating.

"Save is broken" versus something you can investigate

Imagine two bug reports land in your inbox.

Report A: "Save is broken. Please fix."

Report B: "Signed-in user clicks Save on /brief/AAPL at 14:03 UTC. Browser receives a 500 error. Request ID is req_abc123. Server log says the market-data provider timed out after 8 seconds."

Report A is a feeling. Report B is an investigation waiting to happen. It tells you who acted, where, when, what the system returned, which single request to look up, and what the server already believes went wrong.

Your job as a builder — especially a builder directing AI — is to make Report B the normal output of your system, not a lucky accident. That is what logs and observability buy you: every failure leaves a trail you can follow.

Logs, metrics, alerts: three different tools

Beginners lump all of this under "logs." Keep three ideas separate:

  • Log / event: a record of one thing that happened. "User u_418 saved AAPL to a watchlist at 14:02:11 UTC, request req_abc123, result success, 210 ms." Logs tell the story of individual events.
  • Error / warning: a log event with a severity level. An *error* means something failed and needs attention — a provider timeout, a denied write that should have succeeded. A *warning* means something unusual happened but the request still completed — a slow provider response, a retry that succeeded. Reserve errors for real failures or you will stop reading them.
  • Metric: a number aggregated over time. "Save success rate over the last hour: 98%." "Median save latency: 240 ms." "Provider timeouts per hour: 14." Metrics show patterns; logs show instances.
  • Trace / request ID: a single identifier stamped on every event belonging to one request, from browser to backend to provider adapter. It lets you pull one thread out of thousands of simultaneous requests.
  • Alert: a rule that tells a person when attention is needed. "If 500 errors exceed 5% for 10 minutes, message the owner." Without alerts, your logs are a library nobody visits.
  • Dashboard: a small set of charts you actually look at — error rate, latency, provider health. Not forty graphs. Five that answer "is the system healthy?"
  • Uptime check: an automated probe that loads a public URL every minute and reports whether it answered. It catches "the whole site is down" before a user tells you.

Think of it this way: logs answer "what happened to *this* request?", metrics answer "is this happening to *many* requests?", and alerts answer "should a human look *now*?"

This distinction matters because each failure mode in OWASP's logging and alerting guidance — missing events, missing context, alerts nobody reads — turns a diagnosable incident into a mystery.

What a structured log event looks like

A *structured log* is a machine-readable event record with consistent fields, usually one JSON object per line. Consistent matters: if every event uses the same field names, you (and your AI helper) can filter and search instead of squinting at prose.

Every important Research Desk event should carry these fields:

FieldExampleWhy it matters
time2026-09-12T14:03:22ZOrders events; correlates browser and server clocks
levelinfo / warn / errorLets you filter noise from failure
eventwatchlist.save.succeededA stable name you can count and alert on
requestIDreq_abc123Ties browser, route, and provider events together
route / actionPOST /api/watchlistLocates the code path
actorRefuser u_418 (never an email or password)Says who acted, safely
resourceRefwatchlist item wl_991, ticker AAPLSays what was touched, without private content
durationMs212Reveals slowness before users complain
depResultprovider: ok, 180ms or provider: timeout, 8000msNames the dependency outcome
errorClassProviderTimeout (not a stack trace to the user)Groups identical failures together

And a short list of fields to never log by default: passwords, tokens, API keys, session secrets, entire request bodies, private brief content, other users' personal data. Logging a secret to fix a bug creates a second, worse bug — anyone who can read logs now holds the key. OWASP calls this out explicitly: logging that leaks sensitive data, or logging so sparse it cannot support investigation, are both failures. Log references (user u_418, item wl_991), not contents.

Follow one request ID through Research Desk

Here is the journey that makes request IDs worth their weight:

Browser clicks Save on /brief/AAPL
  → frontend generates requestID req_abc123, sends POST /api/watchlist
  → API route logs: request received (req_abc123, user u_418, ticker AAPL)
  → route checks session + ownership policy
  → provider adapter calls market-data provider, logs result (ok / timeout)
  → route logs outcome (success / denied / provider-timeout, durationMs)
  → browser shows confirmation or useful error, tagged with req_abc123

When the user reports "500 at 14:03, request req_abc123," you search the server log for that single ID and see the whole chain in order: received, policy passed, provider timed out, 500 returned. No guessing which of 2,000 simultaneous requests failed. Without the ID, you are matching timestamps and hoping.

Give the ID back to the user, too. A small "Reference: req_abc123" on the error screen turns every future Report A into a Report B for free.

Three events: what to include, what to never include

Design these three Research Desk events now, before you need them:

1. Successful watchlist save — watchlist.save.succeeded (level: info) Include: time, request ID, route, actor reference (user u_418), ticker, item ID, duration, dependency result. Never include: the user's email, session token, or full profile. Success events feel boring, but they are your baseline — when saves stop succeeding, the *absence* of this event is the signal.

2. Denied watchlist edit — watchlist.edit.denied (level: warn) Include: time, request ID, route, actor reference, target item ID and its owner reference, policy outcome (owner mismatch), error class AuthzDenied. Never include: the other owner's private data, the full record body, or any credential. Denied events are security evidence — per the OWASP logging guidance, failed authorization attempts are exactly what must be recorded with enough context to detect abuse, without recording the sensitive data itself.

3. Provider refresh timeout — provider.refresh.timeout (level: error) Include: time, request ID (or job ID for background work), provider name, timeout duration, retry decision, error class ProviderTimeout. Never include: the provider API key, raw provider response dump, or user watchlist contents. Timeouts need the dependency result and duration most of all — "which provider, how long, what did we do next?"

Practical exercise: write your OBSERVABILITY.md

Create a file called OBSERVABILITY.md in your project with two sections:

1. Logging conventions: the field table above (adapted to your app), your level rules (when you use info vs. warn vs. error), and your never-log list (passwords, tokens, keys, bodies, private content). 2. Sample incident record: rewrite a vague report ("Refresh is broken") as a Report B — URL, action, expected result, actual result, time in UTC, request or job ID, and the one server event that explains it.

Finish line: an OBSERVABILITY.md plus one sample incident record a stranger could investigate without asking you for the missing pieces.

Verify quickly: pick one real action in your app, perform it, and confirm you can find its request ID in both the browser-visible result and your log output. If either side is missing the ID, the trail is broken.

Check your understanding

1. Why is "500 at 14:03, request req_abc123, provider timeout" investigable while "Save is broken" is not? 2. What is the difference between a log event and a metric, and what question does each answer? 3. Name three fields every important event should carry, and three fields that should never be logged by default.

Next, you will learn to read the *right layer* first — because even a perfect trail is useless if you search the browser console for a database-policy failure.

ARTICLE DISCUSSION

JOIN THE
CONVERSATION.

0 COMMENTS

BYEBUY ACCOUNT ACCESS

Sign in

Use your account to save routes and make the catalogue yours.

Enter your email and we’ll send a secure sign-in link and code.

NEW ROUTES ADDED WEEKLY · 9,235 CATALOGUE ENTRIES · BUILD · DEPLOY · QUERY · STACK · SAY BYE TO BUY · NEW ROUTES ADDED WEEKLY · 9,235 CATALOGUE ENTRIES · BUILD · DEPLOY · QUERY · STACK · SAY BYE TO BUY ·