otel: relative 'Ns ago' timestamp on recent traces

This commit is contained in:
2026-07-02 10:53:02 +00:00
parent e49229c20b
commit 4f17a40187

View File

@@ -370,12 +370,27 @@
(fn (trace-id) (fn (trace-id)
(let ((roots (filter (fn (s) (nil? (get s :parent))) (otel/trace-spans 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))))) (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<unit> 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 (define otel/trace-summary
(fn (trace-id) (fn (trace-id)
{:trace trace-id {:trace trace-id
:name (otel/-trace-root-name trace-id) :name (otel/-trace-root-name trace-id)
:target (otel/-trace-target trace-id) :target (otel/-trace-target trace-id)
:dur (otel/-trace-dur trace-id) :dur (otel/-trace-dur trace-id)
:t (otel/-trace-end trace-id)
:spans (len (otel/trace-spans trace-id))})) :spans (len (otel/trace-spans trace-id))}))
(define otel/recent-traces (define otel/recent-traces
(fn () (reverse (map otel/trace-summary (otel/-trace-ids))))) (fn () (reverse (map otel/trace-summary (otel/-trace-ids)))))
@@ -424,19 +439,24 @@
(define otel/-traces-list (define otel/-traces-list
(fn (traces) (fn (traces)
(quasiquote ;; capture "now" ONCE so all ages are relative to the same instant; each 3s
(ul :class "otel-traces" ;; re-render recomputes it, so the labels tick upward (2s ago → 5s ago → …).
(splice-unquote (let ((now (otel/now-ns)))
(map (quasiquote
(fn (t) (ul :class "otel-traces"
(quasiquote (splice-unquote
(li :data-trace (unquote (str (get t :trace))) (map
;; show the concrete target (/welcome) if known, else the span (fn (t)
;; name, then the wall duration and span count. (quasiquote
(span :style "font-weight:600" (li :data-trace (unquote (str (get t :trace)))
(unquote (or (get t :target) (get t :name)))) ;; concrete target (/welcome) if known, else the span name; then
(unquote (str " · " (otel/-ms (get t :dur)) " · " (get t :spans) " spans"))))) ;; wall duration, span count, and how long ago it happened.
traces)))))) (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 ;; 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. ;; p95 inside light-red p99 — so the tail (red beyond amber) is visible at a glance.