su includes built-in tracing for debugging reactive state.
Call su/enable-trace to log all atom state changes to the browser console:
(ns my.app
(:require [su.core :as su]))
(su/enable-trace)Every reset! or swap! on any atom will print:
[atom:count] 0 → 1
[atom:tasks] [] → [{:id 1, :text "Buy milk", :done false}]
The label comes from the atom's second argument:
(atom 0 "count") ;; label: "count"
(atom [] "tasks") ;; label: "tasks"
(atom 0) ;; label: "?" (unlabeled)(su/disable-trace)Pass a filter function to trace only specific atoms:
(su/enable-trace
{:filter (fn [a] (= (.-label a) "tasks"))})This only traces atoms with the label "tasks", reducing console noise when
you have many atoms.
Enable tracing only during development:
(ns my.app
(:require [su.core :as su]))
;; Enable in dev, automatically stripped in production builds
(su/enable-trace)In a production build, you can remove the call or wrap it in a dev-only conditional. Tracing has no overhead when disabled.
- Label your atoms — always pass a label as the second argument
- Enable trace — add
(su/enable-trace)at the top of your main namespace - Open DevTools console — watch state changes flow as you interact
- Filter when noisy — use
:filterto focus on specific atoms - Check the flow — verify that state changes happen in the right order
Given this code:
(su/enable-trace)
(def count (atom 0 "count"))
(swap! count inc)
(swap! count inc)
(reset! count 0)The console shows:
[atom:count] 0 → 1
[atom:count] 1 → 2
[atom:count] 2 → 0
| Function | Description |
|---|---|
su/enable-trace |
Start logging atom changes |
su/disable-trace |
Stop logging atom changes |
atom val "label" |
Create labeled atom for tracing |
:filter option |
Trace only matching atoms |