diff --git a/project.clj b/project.clj index e454403a6e..06db657297 100644 --- a/project.clj +++ b/project.clj @@ -68,6 +68,7 @@ {:dependencies [[binaryage/devtools "1.0.0"] [day8.re-frame/re-frame-10x "0.6.0"] [day8.re-frame/tracing "0.5.3"] + [com.taoensso/tufte "2.2.0"] [cider/cider-nrepl "0.25.1"]] :source-paths ["dev"]} diff --git a/shadow-cljs.edn b/shadow-cljs.edn index 7c05b1edbe..1324540819 100644 --- a/shadow-cljs.edn +++ b/shadow-cljs.edn @@ -29,7 +29,8 @@ :closure-defines {re-frame.trace.trace-enabled? true} :output-feature-set :es-next} :devtools {:preloads [devtools.preload - day8.re-frame-10x.preload]}} + day8.re-frame-10x.preload + #_athens.tracing]}} ;; backend for electron (node.js) :main {:target :node-script diff --git a/src/cljs/athens/tracing.cljs b/src/cljs/athens/tracing.cljs new file mode 100644 index 0000000000..40c0857a0b --- /dev/null +++ b/src/cljs/athens/tracing.cljs @@ -0,0 +1,62 @@ +(ns athens.tracing + (:require + [reagent.impl.batching :as batching] + ;; This exists only in newer versions of re-frame-10x + ;; [day8.reagent.impl.batching :as day8.batching] + [taoensso.tufte :as tufte])) + + +(defonce reagent-next-tick batching/next-tick) + +;; This exists only in newer version of re-frame-10x: +;; (defonce reframe10x-next-tick day8.batching/next-tick) + + +(defonce stats-accumulator + (tufte/add-accumulating-handler! {:ns-pattern "*"})) + + +(defonce stats-total + (atom nil)) + + +(defn format-stats [stats] + (-> stats + (tufte/format-pstats + {:columns [:n-calls :p50 :p95 :p99 :max :clock :total] + :format-id-fn str}) + (println))) + + +(defn next-tick + [f] + ;; Schedule a trace to be emitted after a render if + ;; there is nothing else scheduled after that render. + ;; This signals the end of the epoch. + + (reagent-next-tick + ;; TODO: ideally, should also be wrapping re-frame-10x: + ;; reframe10x-next-tick day8.batching/next-tick + (fn [] + (tufte/profile {} (f)) + (when (false? (.-scheduled? batching/render-queue)) + (when-some [m (not-empty @stats-accumulator)] + (when (some-> m vals first deref :stats) + (let [stats (-> m vals first)] + (println "Epoch Stats:") + (format-stats stats) + (if @stats-total + (swap! stats-total tufte/merge-pstats stats) + (reset! stats-total stats)) + (println "Total Stats:") + (format-stats @stats-total)))))))) + + +(defn patch-next-tick + [] + (println "Patching with tufte profiling") + (set! batching/next-tick next-tick)) + + +;; TODO: assuming this namespace will only be loaded via shadow preloads +(patch-next-tick)