feat: emit-time enrichers; thread-safe date formatting - #2
Open
Flawless wants to merge 3 commits into
Open
Conversation
Flawless
force-pushed
the
emit-time-enrichers
branch
2 times, most recently
from
August 27, 2026 12:31
97eaaf7 to
5f0d10d
Compare
format-date shares one SimpleDateFormat across all emitting threads; format mutates its internal Calendar. With per-thread distinct dates, 16x500 concurrent formats reliably garble output or throw ArrayIndexOutOfBoundsException out of the JDK calendar — and format-date runs in mk-log on the caller thread, so that throw escapes into application code. Identical dates race invisibly, which is why the test uses divergent ones. Fails on this commit by design; fixed in the next. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01C6nThfB7TczmTgk5Xb3MJq
ThreadLocal keeps the produced string bit-identical to the shared instance — same class, same pattern — so nothing parsing ts can drift. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01C6nThfB7TczmTgk5Xb3MJq
Flawless
force-pushed
the
emit-time-enrichers
branch
from
August 27, 2026 12:37
5f0d10d to
d744085
Compare
Author
|
Restructured test-first per review; the history now proves the bug:
Ops note: no occurrence of the AIOOBE fingerprint in 15 days of retained billing logs — production formats "now" across threads, so fields rarely diverge; boundary rollovers are the realistic trigger. Latent, not observed. |
Flawless
force-pushed
the
emit-time-enrichers
branch
from
August 27, 2026 12:42
d744085 to
96babcb
Compare
add-enricher! registers a fn applied to every log map on the emitting thread before publish — the one point where thread-scoped context (an active trace, MDC) is still visible; appenders run on the publisher agent and cannot see it. Throwing or non-map-returning enrichers are skipped per log. Test pins the thread with a raw ThreadLocal: dynamic bindings are conveyed by send-off and would pass on the wrong thread. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01C6nThfB7TczmTgk5Xb3MJq
Flawless
force-pushed
the
emit-time-enrichers
branch
from
August 27, 2026 12:43
96babcb to
6b7e055
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Why
Consumers need to attach thread-scoped context to every log — the concrete case:
dd.trace_id/dd.span_idfrom the active Datadog span, so Datadog links logs to traces (HealthSamurai/billing#277 does this today with a per-call-site ctx workaround that misses forked threads). Appenders can't do it: they run on the publisher agent thread, where the emitting thread's span/MDC is gone. The only correct interception point islogon the caller thread.What
add-enricher!/rm-enricher!: id-keyed registry (re-registration replaces — reload-safe); every enricher runs against the assembled log map on the emitting thread beforesend-off. A throw or non-map return skips that enricher for that log — a bad enricher can't break logging or other enrichers.format-date: the sharedSimpleDateFormatis not thread-safe (mutates state onformat); concurrent emission could garblets. NowThreadLocal.Notes
format-daterace.Verification
Downstream chain once merged: sha bump in aidbox-billing-core → billing replaces its per-site capture with one
add-enricher!registration.🤖 Generated with Claude Code
https://claude.ai/code/session_01C6nThfB7TczmTgk5Xb3MJq