fix(traces): stop an unreadable span timestamp from becoming a real duration - #1881
Conversation
|
Thanks for opening this — it has been seen, and it is queued. This note is automated, but it is not a brush-off: it exists so you know where your PR stands instead of having to guess from silence. Current review status: working through a backlog. What that means for this PR, concretely:
Things that will genuinely speed it up whenever review does happen:
If this fixes a bug, a reproduction we can run is worth more than a description of the symptom. Thanks for contributing, and sorry in advance for the wait. |
…uration
strtoll answers 0 for text it cannot read, and cbm_parse_duration handed that
0 straight into its subtraction. The report of this said the result was a
false duration of zero. It is worse than that. An unreadable START time reads
as 0, so the span reports the whole END time as its duration:
FAIL tests/test_traces.c:340: info.duration_ns == 1050000000,
expected CBM_DURATION_UNKNOWN == -1
That is 1.05 seconds of measured time for a span whose start was never read.
Nothing downstream can tell that number from a real one.
The fix keeps cbm_parse_duration exactly as it is. It is public, it is
declared in traces.h, and eight tests pin its answers -- 0 for a NULL
argument, 0 for an end at or before the start. None of that moves.
A companion carries the extra answer instead:
int64_t cbm_parse_duration_checked(const char *start, const char *end, bool *ok);
Both reads go through one small reader that follows src/main.c:1104 -- an end
pointer, errno, and a check that nothing was left over -- plus a refusal of a
leading blank, which strtoll would otherwise step over.
cbm_extract_http_info now uses the companion and writes CBM_DURATION_UNKNOWN
(-1) when the timestamps do not read. It still returns true, because the
method and path on that span are still good data and dropping them would
punish them for a fault they had no part in. -1 as "not recorded" is the
sentinel this codebase already uses for the same question, in
CBM_EDGE_CONF_ABSENT. The duration_ns field comment in traces.h now says so,
so a reader who meets -1 has something to read.
Scope note: cbm_extract_http_info has no production caller on this tree. rg
finds it only in src/traces/traces.c, src/traces/traces.h and tests, and
handle_ingest_traces in src/mcp/mcp.c never touches a timestamp. So this is a
defect in a public, tested function rather than one putting bad rows in a
graph today.
Two tests come with the change. The one that pins the behaviour was seen
failing first -- the FAIL line above is from that run. After the fix,
TEST_SUITES="traces" reports 32 passed, 0 failed, exit 0.
The full suite reports 7633 passed, 2 failed. Both failures are in
tests/test_cli.c (lines 1749 and 6725), print "error: one or more agent
cleanup operations failed", and reproduce on a clean tree without this
change. make -f Makefile.cbm lint-ci passes.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Signed-off-by: Joshua Richter <jrichter5781@gmail.com>
48c2d2e to
c368954
Compare
|
Same shape as #1922: an input the code cannot read becomes a plausible value, and nothing downstream can tell it from a real one. Here The scope note in the description is deliberate — The One of four from a single scan for siblings of #1875. Context for the set is on #1877. |
|
Thank you for the careful sentinel analysis and for explicitly documenting that |
What this fixes
strtollanswers0for text it cannot read, andcbm_parse_durationhandsthat
0straight into its subtraction:The obvious harm is a false duration of zero — a span that took no time and
a span whose timestamps were garbage become the same row.
It is worse than that. An unreadable start time reads as
0, so the spanreports the whole end time as its duration. The test that pins this failed
like so before the fix:
That is 1.05 seconds of measured time for a span whose start was never read.
Nothing downstream can tell that number from a real one.
The fix
cbm_parse_durationdoes not move. It is public, it is declared intraces.h:66, and eight tests pin its answers —0for a NULL argument,0for an end at or before the start. All of that stays exactly as it is.
A companion carries the extra answer instead:
Both reads go through one small reader in the
src/main.c:1104shape — an endpointer,
errno, and a check that nothing was left over — plus a refusal of aleading blank, which
strtollwould otherwise step over.cbm_extract_http_infonow uses the companion and writesCBM_DURATION_UNKNOWN(
-1) when the timestamps do not read. It still returnstrue: the method andpath on that span are still good data, and dropping them would punish them for
a fault they had no part in.
-1as "not recorded" is the sentinel this codebase already uses for the samequestion —
CBM_EDGE_CONF_ABSENTinsrc/graph_buffer/graph_buffer.c, which iswhat #1877 is about. The
duration_nsfield comment intraces.hnow says so,so a reader who meets
-1has something to read.Scope note
cbm_extract_http_infohas no production caller on this tree.rgfinds itonly in
src/traces/traces.c,src/traces/traces.h, andtests/test_traces.c,and
handle_ingest_tracesinsrc/mcp/mcp.cnever touches a timestamp or aduration. So this is a defect in a public, tested function rather than one
putting bad rows into a graph today. Worth stating plainly rather than
overselling the impact.
Tests
Two tests. The one that pins the behaviour was seen failing before the fix —
the
FAILline above is from that run.traces_parse_duration_checked_reports_unreadable_timestampsabc, empty," 100",100ns,1e9, and NULL in either position; plus the positive controls that a good pair, an equal pair, and an end-before-start pair all read finetraces_extract_http_info_marks_unreadable_durationCBM_DURATION_UNKNOWNThe eight existing
cbm_parse_durationtests pass untouched.Checks run
make -f Makefile.cbm test-focused TEST_SUITES="traces"32 passed, 0 failed— exit 0make -f Makefile.cbm lint-ci=== CI linters passed ===— exit 0make -f Makefile.cbm cbmmake -f Makefile.cbm test7633 passed, 2 failed, 8 skippedThe two failures are in
tests/test_cli.c(lines 1749 and 6725), printerror: one or more agent cleanup operations failed, and reproduce on a cleantree without this change.
How this was found
By scanning for siblings of the parse bug fixed in #1875 — "a parse reports
success while the input stays unread". #1877 fixed the confidence pair and the
companion PR to this one fixes the environment-variable group.
Checklist
git commit -s(DCO)make -f Makefile.cbm testrunmake -f Makefile.cbm lint-cirunFixes #1982