TensorBoardLoggerExt: run-timing Summary tag + :compact-aware event show methods#649
Conversation
Emits a `Summary` text tag at step 1 alongside `EventCounts` with a one-shot timing rollup: model_build, inference, total_wall, and iteration aggregates (n_iterations, iter_total/mean/min/max). Missing measurements are skipped so partial runs still produce a useful table.
Adds the new `Summary` row (and a dedicated "Run summary" subsection) to the TensorBoard "What gets logged" section, and splits the prior combined Text-tab row so EventCounts (always-on), Summary (always-on), and the per-event narrative breadcrumbs (`log_text_events`-gated) each have their own line with accurate gating.
Collapse 14 per-distribution scalar-dispatch testitems into one table-driven testitem, and 3 Summary-writer testitems into one testitem with @testset blocks. Move shared @model / @Constraints / @initialization boilerplate for the IID Normal, coin-toss, and IID InverseGamma fixtures into helpers.jl as *_inference factories. Add a with_dispatch_logger helper that snapshots (tags, steps) before Windows tempdir teardown so direct-dispatch tests stay terse. Trim iteration counts to 2 and dataset / histogram sample counts to the minimum needed to verify per-iteration step semantics. ~30 -> 17 testitems; ~1490 -> ~590 lines. No behavioural change to extension code; per-concern parallelism and failure granularity preserved via @testset.
Compact, single-line repr for the 11 events emitted from the inference loop (Before/AfterModelCreation, Before/AfterInference, Before/AfterIteration, Before/AfterDataUpdate, OnMarginalUpdate, Before/AfterAutostart). Span identifiers are truncated to a 4-character prefix so trace output (e.g. TBLogger Text tag) stays readable. Refs #638
Cover all 11 events plus the `_show_span` helper (4-char prefix truncation and short-string passthrough). Uses local marker structs plus a `PayloadWrapper` that extends `ReactiveMP.getdata` so the `OnMarginalUpdateEvent` rendering is fully deterministic. Refs #638
Now that callback events define compact `Base.show` methods (RxInfer Tier A in this branch; ReactiveMP Tier B/C upstream), the `_format_fields` helper and the hand-built `"variable: ... | ..."` strings duplicate that work and reintroduce raw struct dumps for nested fields. Replace all `log_event` text bodies with `repr(ev)` and drop `_format_fields` entirely. Refs #638
…uct dumps
Capture ReactiveMP-level callback events from a tiny inference and
assert that `repr(ev)` (the string TBLogger now writes via
`_log_text!`) never contains `MessageMapping{` — the telltale of
the default struct printer. This guards the recent shift from
hand-built `"k: v | ..."` strings to `repr(ev)` in the ext.
The analogous `Message{` check is deferred to a ReactiveMP-side
follow-up, since only `DeferredMessage` currently has a compact
`Base.show`.
Refs #638
Document the Tier A `Base.show` additions and the TBLogger ext shift to `repr(ev)` under the existing [Unreleased] section. Refs #638
Captures the two-repo design (ReactiveMP for Tier B+C show methods, RxInfer for Tier A events plus TBLogger ext cleanup), branch strategy, event-by-event field/format table, and sequencing options. Refs #638
Mirror the ReactiveMP rework on the RxInfer side: every Tier A callback event Base.show method now branches on the standard :compact IOContext flag. Default form (REPL/Pluto/Jupyter — :compact => false) prints the event-struct constructor name, the full UUID span id, and delegates to the model/engine value's own show. Compact form (used by TensorBoardLoggerExt with :compact => true) keeps the previous EventName(model=TypeName, span=ab12…) shape so trace lines stay short and greppable. The _show_span helper now omits the span field entirely when span_id is nothing (no more span=nothing noise when callbacks are disabled), and accepts a leading_sep keyword for the only-field-on-the-line case (BeforeModelCreationEvent). Tests cover both forms and assert the span is omitted when nil.
Replace the 21 repr(ev) call sites in the per-event log_event methods with _compact_repr(ev) — sprint(show, ev; context = :compact => true). After the new event Base.show methods landed, repr(ev) produces the *full* form (actual messages, full UUID span ids), which is the right default for REPL/Pluto but allocates the full distribution data per event when called inside a trace logger. Passing :compact => true via sprint yields the short nmsgs=N / 4-char span form that the original trace summary was designed around, without the extra allocations.
Update the [Unreleased] entries to describe the :compact-flag-based design (full form by default, compact form for trace loggers), the span-omission behavior when callbacks are disabled, and the TensorBoardLoggerExt switch from repr(ev) to sprint with :compact context.
🤖 Code FormattingYour PR still has some code formatting issues. I've updated PR #650 with the necessary formatting changes. You can merge that PR into this branch to fix the code style check. Alternatively, you can run |
🤖 Code FormattingYour PR still has some code formatting issues. I've updated PR #650 with the necessary formatting changes. You can merge that PR into this branch to fix the code style check. Alternatively, you can run |
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #649 +/- ##
==========================================
+ Coverage 80.70% 81.49% +0.79%
==========================================
Files 30 30
Lines 2399 2513 +114
==========================================
+ Hits 1936 2048 +112
- Misses 463 465 +2 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
Closes #638.
Stacked work — combines two threads:
TensorBoardLoggerExt(originallytb_textsummary_update).Base.showfor Tier A callback events plus theTensorBoardLoggerExtswitch fromrepr(ev)to:compact-context rendering (originallyfeat/event-show-methods).Both are merged here as one PR since the second is stacked on the first.
Summary
TensorBoardLoggerExt: Summary tag
Summarytext tag alongsideEventCounts, with a single-snapshot timing rollup of the inference run:model_build(wall-clock betweenBeforeModelCreationEvent/AfterModelCreationEvent),inference(betweenBefore/AfterInferenceEvent),total_wall(first-to-last traced event), and per-iteration aggregates (n_iterations,iter_total,iter_mean,iter_min,iter_max).iteration_time_msper-iteration scalar series is unchanged.test/ext/TensorBoardLoggerExt/tensorboardlogger_tests.jlconsolidated: 14 per-distribution scalar-dispatch tests collapse into a single table-driven@testitem; three Summary-writer subtests collapse into one. Shared@model/@constraints/@initializationboilerplate moved intohelpers.jlfactories. ~30 → 17 testitems; ~1490 → ~480 lines.Tier A event
Base.showBase.showfor every Tier A callback event (Before/AfterModelCreationEvent,Before/AfterInferenceEvent,Before/AfterIterationEvent,Before/AfterDataUpdateEvent,OnMarginalUpdateEvent,Before/AfterAutostartEvent).IOContext:compactflag::compact => true(trace loggers) → shortEventName(model=Type, span=ab12…)form.:compact => false(default — REPL/Pluto/Jupyter) → full form with the canonical struct constructor name and full UUIDspan_id=…._show_spanhelper omits the field entirely whenspan_id === nothing.TensorBoardLoggerExtper-event text breadcrumbs now render viasprint(show, ev; context = :compact => true)(a small_compact_reprhelper) instead ofrepr(ev). Replaces ~110 LOC of bespoke"k1: v1 | k2: v2 | …"formatting and the now-removed_format_fieldshelper.Why
Base.showon the events, TBLogger Text-tag breadcrumbs (and anyrepr(ev)use) dumped the raw struct, including type parameters. Pairs with the upstream show methods on Tier B/C types ([Task]: Create show methods for Events ReactiveMP.jl#599 / PR Update debugging.md - [Using callbacks in the infer function] #602).