Repository navigation
feat: structured JSON logging with request id tracing - #255
Conversation
|
@Nwapu-TrustJah Great news! 🎉 Based on an automated assessment of this PR, the linked Wave issue(s) no longer count against your application limits. You can now already apply to more issues while waiting for a review of this PR. Keep up the great work! 🚀 |
Ten call sites in src/index.ts passed a single object where the logger
declares `info(event: string, fields?: LogFields)`, so tsc refused:
error TS2345: Argument of type '{ event: string; route: string; ... }'
is not assignable to parameter of type 'string'.
Mechanical: the event name moves out to the first argument and the rest
stays as fields.
Claude-Session: https://claude.ai/code/session_01USgemLt4Rnz4SGB1Srf3GB
Miracle656
left a comment
There was a problem hiding this comment.
Structured logs with a request id is the right direction and I want it. Two problems, and the second is security-relevant.
I pushed the first one to your branch. Ten call sites in src/index.ts passed a single object where the logger declares info(event: string, fields?: LogFields):
error TS2345: Argument of type '{ event: string; route: string; status: number; … }'
is not assignable to parameter of type 'string'.
Mechanical — event name out to the first argument, the rest stays as fields. Done.
The blocker: the connection-string scrubber does not compile, and would not work if it did
src/logger.ts:42:
/\b(?:abcdefghijklmnopqrstuvwxyz{})?:(?:\/\/))[^\s]+/,src/logger.ts(42,48): error TS1508: Unexpected ')'. Did you mean to escape it with backslash?
The parenthesis is unbalanced, and abcdefghijklmnopqrstuvwxyz{} is clearly a placeholder that survived into the committed file — it matches no scheme. Something like this is what was meant:
/\b(?:postgres(?:ql)?|mysql|mongodb(?:\+srv)?|redis|rediss):\/\/[^\s]+/i,I have deliberately not written that for you. This is the pattern whose entire job is keeping a database password out of a log line, in a service that has already leaked a Postgres connection string through a raw error for roughly three months. It should be authored and tested by the person who owns the change, with cases proving it catches each scheme and does not catch ordinary text. Me guessing the intent and merging my own guess is exactly the wrong way for that to enter the codebase.
Also worth reconsidering
// 11-digit Nigerian identity number.
/\b(?:\d{11})\b/,That redacts any eleven-digit number. A ledger sequence, a timestamp in milliseconds, an order id, an amount in kobo — all eleven digits at some point, all scrubbed. Scrubbing a NIN is right; scrubbing every long number means the logs stop answering the questions they exist for, and the day someone needs a ledger number to diagnose a stuck transfer it will not be there.
A NIN is only ever submitted to one route. Scrubbing by field name on that path is precise; a bare digit-count pattern applied to every line is not.
What is good
One line per provider call with route, status and elapsed ms, through a single choke point, is exactly the shape the issue asked for — and logProviderCall being the only place that emits it is what stops it drifting.
Fix the regex with tests, and I will merge it. The 726 tests already pass, so it is genuinely close.
|
Merged. The redaction list is the part that earns this PR its place, and it's also where I found two real problems — both now fixed.
|
Overview
This PR replaces interpolated
console.warnprose with structured JSON logging — one object per line carrying level, event, route, status and duration — and threads a single request id from the inbound request through the provider call so one user's report can be traced end to end. It also adds a test that asserts no logged line ever contains a NIN, an API key or a connection string, and documents in the README how to find one user's requests from a support report.Related Issue
Changes
🧱 Structured Logger
[ADD]
src/logger.tslevel,event,route,statusanddurationMs.[ADD]
src/middleware/requestId.ts[MODIFY]
src/index.tsconsole.warncall sites through the structured logger, including the provider call path so each provider call logs one line with route, status and elapsed ms.[ADD]
src/__tests__/logger.test.tsVerification Results
route,status,durationMssrc/__tests__/logger.test.tsasserts redaction across captured linesCloses #240