Logs you can actually parse
One child logger per module, a strict (msg, extras?) signature, and errors serialized depth-first with cycle detection. At LOG_LEVEL=trace you can reconstruct the whole decision chain.
const log = logger.child({ section: "retry" })
log.debug("retry decision", { status, willRetry })
stdout · tracejson
{"level":30,"section":"retry","msg":"request: 1 url","cid":4182}
{"level":10,"attempt":1,"status":503,"willRetry":true,"elapsedMs":1204}
{"level":10,"attempt":2,"status":503,"willRetry":true,"elapsedMs":2731}
{"level":10,"attempt":3,"status":429,"willRetry":true,"elapsedMs":5110}
{"level":20,"msg":"ok after 4 attempts","status":200}