
Debug Logs That Stay Useful Next Month. A Build Next Stack field guide for learners shipping small projects.
Structured beats printf—and stays grep-friendly
Printf debugging dies when logs scroll off terminal buffer. Taylor logs JSON lines locally and key=value in prod adapters: level=info event=upload_start user_id=abc bytes=8388608. Same fields every time so grep and log viewers filter without regex archaeology.
Minimum fields per log line:
- timestamp — ISO8601 UTC
- level — info, warn, error
- event — snake_case verb noun
- request_id — correlates one user action across lines
Human readability matters on solo projects—you read logs. Consistent field names matter more than fancy platforms.
Log at boundaries, not inside loops
Taylor logs when crossing boundaries: HTTP request in/out, DB query start/end slow threshold, external API call with latency and status code. Not inside tight loops—image pixel loops drowning disks taught that once.
Rule: if it happens more than ten times per request, aggregate or sample. Log thumbnails_generated=120 duration_ms=450 once, not one line per thumbnail.
Error logs carry context, not stack dumps alone
On error, include:
- What operation failed (event=stripe_charge_failed)
- Safe parameters—IDs yes, card numbers never
- Upstream status code or error class
- Whether retry is advisable
Stack traces help in dev; in prod trim or attach once per request_id. Pair errors with the info lines sharing request_id so timeline reconstructs without guessing.
Log levels with discipline
Define levels in README for future you:
- debug — local only; verbose internals
- info — normal lifecycle events
- warn — degraded but serving
- error — user-visible failure or data risk
Default prod to info. Temporarily enable debug on one instance via env flag when investigating—never globally forever. Warn fatigue is real; promote repeated warns to errors or fix root cause.
Retention and cost for side projects
Free tiers expire logs in days. Taylor exports error logs weekly to a dated file in private storage when on free plan—five minutes cron, grep later. Paid tiers get alert on error rate spike, not on every single error.
Rotate local log files if self-hosting; disk full stops app harder than missing ancient debug lines.
Debug toggles without redeploy nightmares
Feature flag or env LOG_VERBOSE=1 gates extra logs in hot paths. Document toggle in troubleshooting README section. Remove toggle after bug fixed or it becomes permanent scar.
Avoid logging secrets when verbose—redaction helper strips known env values from objects before log.
From log line to fix: keep a investigation template
When a log helps solve a bug, paste anonymized lines into issue comment with fix summary. Next month similar logs compare fast. Taylor’s template:
- Symptom — user report one line
- Log query — exact filter used
- Root cause — one sentence
- Fix — commit link
Logs stay useful when they connect to issues—not when they evaporate from terminal scrollback.
Taylor names log configuration in README—LOG_LEVEL default info; LOG_FORMAT json—so future contributors do not grep codebase for mystery env vars.
Local dev ergonomics: color without chaos
Pretty console colors help humans; structured files help machines. Taylor uses colored pretty in terminal during dev and JSON file append for integration tests. Switch via env without code changes.
Avoid logging full request bodies by default—PII hides in JSON you forgot. Log field names and sizes: body_bytes=842, not raw payload.
When debugging locally, temporary LOG_PRETTY=1 beats commenting out log statements you forget to restore before commit.
Alerts that wake you only when needed
Side projects should not page like payroll systems. Taylor alerts on error rate threshold—five errors in five minutes—not single 404s from bots. Alert channel matches CI: phone push you actually acknowledge.
Weekly review alert rules: mute noisy endpoints, fix recurring error at source, delete alert if never fired in ninety days. Alert fatigue on solo projects leads to disabling monitoring entirely—the worst outcome.
Document alert links in README troubleshooting—See Sentry issue #123 pattern for upload failures—when an alert saved time once.
Upgrade path when traffic grows
When free log tier becomes insufficient, Taylor upgrades to paid search before adding self-hosted Elasticsearch cosplay. Criteria: search across thirty days saved more than two hours in one month.
Until then, export errors weekly and grep locally. Boring works for side-project scale; infrastructure hobbies delay shipping.
Structured fields chosen day one migrate cleanly to better tools later—another reason event names stay stable.
Taylor keeps a logs/cheatsheet.md with three example queries that solved real bugs—copy-paste filters for host UI or jq one-liners. Cheatsheet grows slower than codebase and saves relearning syntax monthly.
Testing log output in CI
One CI test asserts critical startup log line appears—server_listening port=3000—when integration test boots app. Missing log means refactor broke logging config silently. Cheap test; catches rename of event strings that grep workflows depend on.
Do not snapshot entire log output—brittle. Assert presence of structured fields on one golden path.
When swapping log libraries, run diff on sample output file in repo tests/fixtures/sample.log—visual regression for logs catches missing request_id after refactor.
Privacy and compliance without enterprise theater
Solo projects still handle user emails and IPs. Taylor logs user_id hashed or internal UUID—not raw email in info lines. Error logs scrub attachments and query params known to carry tokens.
Document retention days in privacy policy link from README. Delete or rotate exported log files older than policy states. Small honesty beats copying enterprise compliance PDFs you do not enforce.
When logs justify a fix in pull request, paste one redacted line in PR description—reviewers see evidence without opening host UI. Habit bridges logging and shipping narratives.
Taylor sets calendar quarterly reminder to read last fifty error lines raw—patterns invisible in dashboards appear as repeated event names needing code fix not alert tweak.
Add request_id this week
Pick one boundary—HTTP middleware or CLI entry—and add request_id plus structured info/error lines. Grep one ID end-to-end before adding more fields.
Logs next month help when field names stay stable and secrets stay out. Fancy log SaaS optional; consistent events mandatory.
When a log line saves you an hour, paste it into the issue. That habit turns logging from noise into project memory.