re-frame.trace.projection¶
Group the development trace stream into one record per event. The raw stream arrives one trace event at a time; group-by-event folds it into an event bundle for each pipeline run (one dequeued event), with the event vector, handler, effects, subscription runs and renders already sorted into named slots. Xray's event panels and the re-frame2-pair tooling read bundles in this shape.
;; each event vector, with the number of renders it caused
(->> (rf/trace-buffer :app/main {:flat true})
projection/group-by-event
(map (fn [{:keys [event renders]}] [event (count renders)])))
These functions are not on the re-frame.core facade; require this namespace directly. rf/trace-buffer already returns bundles in this shape by default, plus a :trace-events vector of each run's raw events, so you call group-by-event only when you hold raw events: a flat buffer, a saved trace, or events collected by a :trace listener.
Both functions are pure, with no frame, registry or router, and run the same code on the JVM and in CLJS, so a tool folding a saved buffer gets the same shape as a live listener. In practice they are development-only, because their input is the development-only trace stream. Observability explains where the trace stream comes from.
Projection¶
group-by-event¶
- Kind: function
- Signature:
- Description: Groups trace events into one event bundle per pipeline run, keyed by
[frame dispatch-id], in emission order (runs are sorted by their lowest trace:id).- Trace events with no
:rf.trace/dispatch-idtag, such as registration-time emits, frame lifecycle and REPL evaluation outside an event, collect in one bundle whose:dispatch-idis:ungrouped. - Errors, effects, subscription runs and renders that happen during a run carry that run's dispatch id, so they land in its bundle.
- Each bundle is a map with these keys:
:dispatch-id— the run's:rf.trace/dispatch-id, or:ungrouped.:parent-dispatch-id— the dispatch id of the run that dispatched this event (through an:fxdispatch or a machine's internal dispatch), ornilfor a root dispatch.:frame— the run's frame id;nilonly on the:ungroupedbundle. A run's trace event that carries no frame joins the run's one known frame, or:rf/default.:event— the event vector.:dispatched— the full:rf.event/dispatchedtrace event, including top-level slots such as:rf.trace/call-site.:handler— the:rf.event/run-startor:rf.event/run-endtrace event; the last one seen wins, usually:run-end.:fx— the:rf.fx/do-fxtrace event.:effects— a vector of the other:rf.fxtrace events (:rf.fx/handled,:rf.fx/override-applied,:rf.fx/skipped-on-platform).:subs— a vector of the:rf.subtrace events (:rf.sub/run,:rf.sub/skip,:rf.sub/create,:rf.sub/dispose).:renders— a vector of the:rf.view/rendertrace events.:other— a vector of everything else: errors, warnings, machine transitions, frame lifecycle, flows. New kinds of trace event also land here, so existing consumers keep working.
- A slot with no matching trace event in the input stays
nil, or[]for the vector slots.:eventisnilon the:ungroupedbundle, and on a run whose:rf.event/dispatchedevent a ring buffer has already dropped. - An empty input returns
[]. Projection does not reconstruct dropped records: a partial buffer can omit the event vector or causal-parent link, and absence of an error trace is not proof that a run succeeded.
- Trace events with no
- Example:
;; In a test: collect the raw stream while one event runs, then read its bundle. (let [collected (atom [])] (rf/register-listener! :trace ::collect #(swap! collected conj %)) (try (rf/dispatch-sync [:todo/add "Buy milk"] {:frame :app/main}) (finally (rf/unregister-listener! :trace ::collect))) (let [bundle (->> (projection/group-by-event @collected) (filter #(= [:todo/add "Buy milk"] (:event %))) first)] (map :operation (:effects bundle)))) ;; e.g. (:rf.fx/handled …)
domino-bucket¶
- Kind: function
- Signature:
- Description: Returns the bucket
group-by-eventwould put a trace event in. Call it per event when you want your own rollup instead of whole bundles.:eventfills the bundle's:eventand:dispatchedslots;:handler,:fxand:otherfill the slots of the same name;:effect,:suband:renderfill the:effects,:subsand:rendersvectors.- It is total: anything outside the six pipeline stages (errors, warnings, machine transitions, frame lifecycle, flows) returns
:other. - The name comes from the "six dominoes", a mnemonic for the stages of the event pipeline.
- It is total: anything outside the six pipeline stages (errors, warnings, machine transitions, frame lifecycle, flows) returns
- Example: