From 4f17a40187f754d5051b1053fa7be4a86d8b5511 Mon Sep 17 00:00:00 2001 From: giles Date: Thu, 2 Jul 2026 10:53:02 +0000 Subject: [PATCH] otel: relative 'Ns ago' timestamp on recent traces --- lib/host/otel.sx | 46 +++++++++++++++++++++++++++++++++------------- 1 file changed, 33 insertions(+), 13 deletions(-) diff --git a/lib/host/otel.sx b/lib/host/otel.sx index 5fbdfd89..08539ba2 100644 --- a/lib/host/otel.sx +++ b/lib/host/otel.sx @@ -370,12 +370,27 @@ (fn (trace-id) (let ((roots (filter (fn (s) (nil? (get s :parent))) (otel/trace-spans trace-id)))) (if (empty? roots) nil (get (get (first roots) :attrs) :http.target))))) +;; when the trace last did something (latest span end), epoch ns. +(define otel/-trace-end + (fn (trace-id) + (let ((spans (otel/trace-spans trace-id))) + (if (empty? spans) 0 (otel/-max-t1 spans))))) +;; a ns age → a coarse "N ago" label. +(define otel/-ago + (fn (age-ns) + (let ((s (quotient (if (< age-ns 0) 0 age-ns) 1000000000))) + (cond + ((< s 1) "just now") + ((< s 60) (str s "s ago")) + ((< s 3600) (str (quotient s 60) "m ago")) + (else (str (quotient s 3600) "h ago")))))) (define otel/trace-summary (fn (trace-id) {:trace trace-id :name (otel/-trace-root-name trace-id) :target (otel/-trace-target trace-id) :dur (otel/-trace-dur trace-id) + :t (otel/-trace-end trace-id) :spans (len (otel/trace-spans trace-id))})) (define otel/recent-traces (fn () (reverse (map otel/trace-summary (otel/-trace-ids))))) @@ -424,19 +439,24 @@ (define otel/-traces-list (fn (traces) - (quasiquote - (ul :class "otel-traces" - (splice-unquote - (map - (fn (t) - (quasiquote - (li :data-trace (unquote (str (get t :trace))) - ;; show the concrete target (/welcome) if known, else the span - ;; name, then the wall duration and span count. - (span :style "font-weight:600" - (unquote (or (get t :target) (get t :name)))) - (unquote (str " · " (otel/-ms (get t :dur)) " · " (get t :spans) " spans"))))) - traces)))))) + ;; capture "now" ONCE so all ages are relative to the same instant; each 3s + ;; re-render recomputes it, so the labels tick upward (2s ago → 5s ago → …). + (let ((now (otel/now-ns))) + (quasiquote + (ul :class "otel-traces" + (splice-unquote + (map + (fn (t) + (quasiquote + (li :data-trace (unquote (str (get t :trace))) + ;; concrete target (/welcome) if known, else the span name; then + ;; wall duration, span count, and how long ago it happened. + (span :style "font-weight:600" + (unquote (or (get t :target) (get t :name)))) + (unquote (str " · " (otel/-ms (get t :dur)) + " · " (get t :spans) " spans" + " · " (otel/-ago (- now (get t :t)))))))) + traces))))))) ;; a per-route latency bar chart: each row is a nested bar — teal p50 inside amber ;; p95 inside light-red p99 — so the tail (red beyond amber) is visible at a glance.