From 66b978c01e6df06301bd1add8e24a53acf0a365d Mon Sep 17 00:00:00 2001 From: Andrey Antukh Date: Thu, 23 Jul 2026 07:31:43 +0000 Subject: [PATCH] :sparkles: Add wall-clock timestamps to last-events buffer Each event entry in `last-events` is now wrapped as `{:name :t (app.common.time/now)}` so every event carries a wall-clock timestamp. A new helper `format-last-events` renders the buffer as a multi-line string with ISO time and delta-since-previous- event in ms, replacing the previous pprint dump in error reports. This lets support/devs tell whether the events leading up to a crash were spaced out (user action) or jammed together (runaway loop). AI-assisted-by: minimax-m3 Signed-off-by: Andrey Antukh --- frontend/src/app/main/errors.cljs | 2 +- frontend/src/app/main/store.cljs | 25 +++++++++++++++++++++++++ 2 files changed, 26 insertions(+), 1 deletion(-) diff --git a/frontend/src/app/main/errors.cljs b/frontend/src/app/main/errors.cljs index 532a05061c..a0028d9484 100644 --- a/frontend/src/app/main/errors.cljs +++ b/frontend/src/app/main/errors.cljs @@ -151,7 +151,7 @@ (println "Last events:") (println "--------------------") - (pp/pprint @st/last-events {:length 200}) + (println (st/format-last-events)) (println))) (catch :default cause (.error js/console "error on generating report" cause) diff --git a/frontend/src/app/main/store.cljs b/frontend/src/app/main/store.cljs index 160a16ac9d..9ecfc39284 100644 --- a/frontend/src/app/main/store.cljs +++ b/frontend/src/app/main/store.cljs @@ -7,6 +7,7 @@ (ns app.main.store (:require [app.common.logging :as log] + [app.common.time :as ct] [app.util.object :as obj] [app.util.timers :as tm] [beicon.v2.core :as rx] @@ -94,6 +95,7 @@ (rx/filter #(not (contains? omitset %))) (rx/map str) (rx/pipe (rxo/distinct-contiguous)) + (rx/map (fn [event] {:name event :t (ct/now)})) (rx/scan (fn [buffer event] (cond-> (conj buffer event) (> (count buffer) 50) @@ -102,6 +104,29 @@ (rx/subs! #(reset! buffer (vec %)))) buffer)) +(defn format-last-events + "Render the `last-events` buffer as a multi-line string with the + wall-clock time of each event and the delta (ms) since the previous + entry. The first entry has no delta. Useful for embedding in error + reports." + ([] (format-last-events @last-events)) + ([events] + (let [lines + (loop [prev-t nil + xs (seq events) + out (transient [])] + (if xs + (let [{:keys [name t]} (first xs) + iso (ct/format-inst t :iso) + tail (if prev-t + (str " (+" (ct/diff-ms prev-t t) "ms)") + "")] + (recur t + (next xs) + (conj! out (str iso tail " " name)))) + (persistent! out)))] + (str/join "\n" lines)))) + (defn emit! ([] nil) ([event]