Repository navigation
Phase 5c: tracing and metrics — tests and doubles - #67
Merged
Merged
Conversation
Wahbeh-Mohammad
force-pushed
the
20-phase-5c-tracing-and-metrics
branch
from
September 18, 2026 08:55
e1094a8 to
5b63ef0
Compare
Wahbeh-Mohammad
force-pushed
the
20-phase-5c-tracing-and-metrics-tests
branch
from
September 18, 2026 08:56
d60425f to
0a581d5
Compare
Wahbeh-Mohammad
changed the base branch from
20-phase-5c-tracing-and-metrics
to
main
September 18, 2026 09:01
Phase 5c (issue #20), the tests PR over the code PR. Thirteen suites under gems/dexpace-core/test/dexpace/instrumentation/: six new mirrors (diagnostics, scope, tracing, meter, http_tracer, callable_adapter), four of phase 4a's widened in nested classes (no_span, no_tracer, trace_id_flavour's GenerationTest, bundle's SampledTest) and three with no lib mirror -- ordering_test.rb, OBS-29's own conformance clause driven through a conformant emitter by hand; independence_test.rb, R11's subprocess loading the ten 5c files alone and asserting Event, Logger, Keys and Configuration undefined, written against the file list and not the entry point so it still discriminates once 5b lands; and tracing_matrix_facts_test.rb, the design's floor-straddling facts as a standing test on every row. Two of those facts do not hold on the floor and the suite pins the boundaries rather than the 3.4.10 answer: `Fiber[:k] = nil` deletes from 3.3 and retains a nil-valued key on 3.2, and `Fiber["k"]` interns from 3.4 and raises TypeError on 3.2 and 3.3. support/fiber_storage_facts.rb probes both once per process and gives the scope and tracing suites their floor-aware "removed" assertion -- absent where `= nil` deletes, present-and-nil and never the pushed value on 3.2 (P5-72). support/allocation_delta.rb is the two-loop GC.stat delta OBS-25's zero-allocation assertions share, with the argument discipline that makes it caller-insensitive stated for phase 8a's conformance gem to copy. The four doubles are fakes (testing/7ecef8e8): RecordingSpan, RecordingTracer with its factory minting a fresh tracer per operation (P5-43), RecordingMeter minting a fresh instrument per call so the no-op's sharing is asserted against a fake without it, and RecordingHTTPTracer including the vocabulary and overriding all eleven. They are namespaced Dexpace::Recording* because 5b's plan consumes three of them by those names (P5-73). Every OBS-25 loop passes only frozen constants, Symbols and Integers; every suite touching Fiber[] restores its slots in a teardown the nested classes share; every raise is asserted on the raised object.
Wahbeh-Mohammad
force-pushed
the
20-phase-5c-tracing-and-metrics-tests
branch
from
September 18, 2026 09:03
0a581d5 to
59711ee
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.
Part of #20. Fifth PR of the nine-PR phase-5 stack — the tests for phase 5c's code PR below it. Targets that PR's branch; the phase record is the next PR up. Rebased onto 5a's stack with the code PR (byte-identical to the reviewed tip
169a511; the combined tree re-proven at 1,849 runs / 56,759 assertions, 99.97%, matrix green on all four Rubies).What lands
19 files, +1,919 / −38: thirteen suites under
gems/dexpace-core/test/dexpace/instrumentation/mirroringlib/one file per file (the four widened phase-4a suites gain nested cases; six new mirrors;ordering_test.rb,independence_test.rbandtracing_matrix_facts_test.rbcarry nolib/mirror and say so), plus the doubles and helpers the design's testing strategy names, one per file undertest/support/:Dexpace::RecordingSpan—recording: true/false,context:; readersattributes,events,errors,status,finished_at,context;#finishlatches so a second call exports nothing (theOBS-21clauseNO_SPANcannot assert).Dexpace::RecordingTracerFactory/RecordingTracer—#tracerin 4a's five-argument shape, minting a fresh tracer per call (theOBS-291:1 clauseNO_TRACER_FACTORYcannot assert); readerstracers,name,version,attributes,spans.Dexpace::RecordingMeter/RecordingCounter/RecordingHistogram— fresh instrument per call; readerscounters,histograms,records.Dexpace::RecordingHTTPTracer— includesHTTPTracerand overrides all eleven, appending frozen[name, *args]tuples to#events; the conformant emitterOBS-29's ordering test drives.AllocationDelta(the two-loopGC.stat(:total_allocated_objects)delta,#allocations_per_call) andFiberStorageFacts(theNIL_ASSIGNMENT_DELETES/STRING_KEY_INTERNEDprobes and the floor-awareassert_diagnostic_key_removed/assert_diagnostic_key_unset).The four doubles are namespaced
Dexpace::Recording*— against the tree's top-level convention, because 5b's plan consumes three of them by exactly those names and readers (P5-73). Every file's header names the requirement IDs it exercises; every class inheritsDexpaceTestCase; every thread is joined; nothing usesassert_nothing_raised;GC.statappears only inside the allocation assertions.What the suites prove rather than restate:
Bundle.membersunchanged; the three singletonsequal?toBundle::NONE's and to a freshrequire's; the smoke suite pins the thirteen constants underDexpace::Instrumentation;#withre-validates through.buildon 3.2.11 for the widenedDatatypes.OBS-25as a number — a two-loopGC.statdelta of exactly0.0per call over the whole span protocol, the tracer path, the untraced activation path,NULL's eleven callbacks and the two instruments, with only frozen constants, Symbols and Integers crossing the loop (5b's R8: a file without the magic comment would measure the caller).OBS-22with two distinctRecordingSpans at every nesting level (a one-span test passes under an implementation that restores nothing), the throw case asserting the slot afterassert_raises, and the bare handle nested and closed by hand — the non-lexical form 5b'sAsyncStepneeds.OBS-23— the push underFiber[]seen by a childThread,FiberandEnumeratorand byThread.current[]in none; a previously-set key restored; a previously-unset key removed on 3.3+ and present-and-nil on 3.2.11, asserted floor-aware and never as the pushed value (P5-72); the non-recording branch skipping the push with a non-recordingRecordingSpan, notNO_SPAN, so "still becomes current" is a real assertion;NO_SCOPEon the identity test (P5-47).OBS-27— a thousand W3C and DATADOG draws each; the zero-draw coercion reached through the injected generator seam; a seededRandomthrough the same seam;NONEthe sentinel by identity; a flavour outside the three raising.OBS-29— a succeeding and a retry-exhausted operation throughRecordingHTTPTracer: started first and once, succeeded/failed last, once and never both, retries-exhausted immediately followed by operation-failed with the same error byassert_same.OBS-30the way the sentence does not sound — araiseinsidewith_span,with_correlated_span,NO_TRACER#in_spanand a raising bus behindCallableAdapterall propagate with every slot restored; identity of the factory, the instruments andNULLacross sixteen threads.OBS-34's structural half (5b's ID, not discharged here) — a subprocess viaRbConfig.rubyloading the ten 5c files alone runs tracing and metrics end to end and assertsEvent,Logger,Keys,Events,HTTPLogging,StepandConfigurationundefined — written against the file list, not the entry point, so it still discriminates once 5b lands.Fiber[:k] = nildeletes from 3.3.0 and retains a nil on 3.2;Fiber["k"]interns from 3.4.0 and raisesTypeErroron 3.2/3.3;Fiber#storage=warns per call (recorded throughWarningCapture, never called by core); copy-on-write per slot;**-splat versus named keyword (≈1003 vs 1 objects per thousand calls);securerandomloads noopensslin a scrubbed subprocess.Verification
bundle exec rakeon Ruby 4.0.6 at the reviewed tip: exit 0, all seventeen gates green —test:gems1,640 runs / 20,939 assertions, line coverage 99.97% (the one line is phase 2's registry race branch); honest RuboCop 332 files clean. At this rebased tip the reconciliation agent re-ran the full set: 1,849 runs / 56,759 assertions, 99.97%, honest RuboCop 371 files clean.$LOADED_FEATURESunderbundle exec'sRUBYOPTon 3.4.10) was found by the matrix and fixed in this commit; every row re-run.Known follow-up (not blocking)
tracing_matrix_facts_test.rb:49callsFiber#storage=as a deliberate fact pin (twice, plus theensurerestore), each wrapped inWarningCapture.record; the brief's letter said "never in test". Could move into a subprocess like the fact-6 assertion.no_span_test.rbandno_tracer_test.rbchange in both this PR and the code PR: the stale-pin repair rides the code branch (the suites must be green there), the new nested cases ride here.