otel: robust SPA poll — stable #otel-body polls /otel/fragment (innerHTML)
This commit is contained in:
@@ -474,20 +474,15 @@
|
||||
(unquote (str "p99 " (otel/-ms (get r :p99))))))))))
|
||||
routes)))))))))
|
||||
|
||||
(define otel/dashboard
|
||||
;; the refreshing content — everything that changes as spans arrive. Served on its
|
||||
;; own at GET /otel/fragment; the poll swaps THIS into #otel-body.
|
||||
(define otel/-dashboard-body
|
||||
(fn ()
|
||||
(let ((m (otel/metrics (otel/recent)))
|
||||
(lt (otel/latest-trace))
|
||||
(traces (otel/recent-traces)))
|
||||
(quasiquote
|
||||
(div :id "otel-dashboard"
|
||||
;; SPA-native live refresh: the SX engine polls GET /otel every 3s and
|
||||
;; swaps this div in place (outerHTML). The poll is a boosted request, so
|
||||
;; the route returns the text/sx fragment — no full reload, stays in the
|
||||
;; SPA. (No <meta refresh>, which would blow away the SPA shell.)
|
||||
:sx-get "/otel" :sx-trigger "every 3s" :sx-target "#otel-dashboard" :sx-swap "outerHTML"
|
||||
(h1 "OpenTelemetry")
|
||||
(p :style "font-size:0.8em;opacity:0.7" "live · refreshes every 3s in-app")
|
||||
(div
|
||||
(h2 "latency by route")
|
||||
(p :style "font-size:0.75em;opacity:0.7"
|
||||
(span :style "color:#4c9a8f" "▉ p50") " "
|
||||
@@ -504,6 +499,19 @@
|
||||
(h2 "recent traces")
|
||||
(unquote (otel/-traces-list traces)))))))
|
||||
|
||||
(define otel/dashboard
|
||||
(fn ()
|
||||
(quasiquote
|
||||
(div :id "otel-dashboard"
|
||||
(h1 "OpenTelemetry")
|
||||
(p :style "font-size:0.8em;opacity:0.7" "live · refreshes every 3s in-app")
|
||||
;; STABLE polling element: it fetches GET /otel/fragment every 3s and swaps
|
||||
;; its OWN inner content (innerHTML), so #otel-body itself is never removed —
|
||||
;; its poll interval keeps firing (an outerHTML self-swap would delete the
|
||||
;; polling element after one tick). Boosted → text/sx, so no full reload.
|
||||
(div :id "otel-body" :sx-get "/otel/fragment" :sx-trigger "every 3s" :sx-swap "innerHTML"
|
||||
(unquote (otel/-dashboard-body)))))))
|
||||
|
||||
;; ── routes ────────────────────────────────────────────────────────────
|
||||
;; Dual-mode, wired into the SPA: a boosted (SX-Request) fetch — a link click OR
|
||||
;; the 3s poll — gets the dashboard as a text/sx fragment the WASM kernel renders
|
||||
@@ -515,11 +523,18 @@
|
||||
(fn (req)
|
||||
(host/blog--resp req 200
|
||||
(host/blog--page req "OpenTelemetry" (otel/dashboard))))))
|
||||
;; the poll target: always the refreshing body as a text/sx fragment (the WASM
|
||||
;; kernel swaps it into #otel-body). Two segments, so /:slug can't shadow it.
|
||||
(define otel/dashboard-fragment-route
|
||||
(dream-get "/otel/fragment"
|
||||
(fn (req)
|
||||
(dream-response 200 {:content-type "text/sx; charset=utf-8"}
|
||||
(serialize (otel/-dashboard-body))))))
|
||||
(define otel/stream-route
|
||||
(dream-get "/otel/stream"
|
||||
(fn (req)
|
||||
(dream-response 200 {:content-type "text/event-stream"} (otel/-stream-body)))))
|
||||
(define otel/routes (list otel/dashboard-route otel/stream-route))
|
||||
(define otel/routes (list otel/dashboard-route otel/dashboard-fragment-route otel/stream-route))
|
||||
|
||||
;; ── P7: OTLP-JSON export ──────────────────────────────────────────────
|
||||
;; Serialize spans to the OTLP/JSON schema (resourceSpans → scopeSpans → spans)
|
||||
|
||||
@@ -235,7 +235,16 @@
|
||||
(host-ot-test "dashboard SSRs the waterfall svg" (contains? host-ot-dash "<svg") true)
|
||||
(host-ot-test "dashboard shows a route in the strip" (contains? host-ot-dash "/feed") true)
|
||||
(host-ot-test "dashboard self-refreshes via SPA poll (sx-trigger)" (contains? host-ot-dash "every 3s") true)
|
||||
(host-ot-test "dashboard poll targets itself" (contains? host-ot-dash "otel-dashboard") true)
|
||||
(host-ot-test "dashboard polls the fragment endpoint" (contains? host-ot-dash "/otel/fragment") true)
|
||||
(host-ot-test "dashboard has a stable polling body" (contains? host-ot-dash "otel-body") true)
|
||||
|
||||
;; the poll endpoint: the refreshing body as text/sx
|
||||
(define host-ot-frag
|
||||
((dream-route-handler otel/dashboard-fragment-route) (dream-request "GET" "/otel/fragment" {} "")))
|
||||
(host-ot-test "GET /otel/fragment is text/sx"
|
||||
(contains? (str (dream-headers host-ot-frag)) "text/sx") true)
|
||||
(host-ot-test "GET /otel/fragment serves the latency chart"
|
||||
(contains? (dream-resp-body host-ot-frag) "latency by route") true)
|
||||
(host-ot-test "dashboard shows the latency chart legend" (contains? host-ot-dash "p99 (tail)") true)
|
||||
|
||||
;; the SSE endpoint emits a span event, SSE-framed
|
||||
|
||||
Reference in New Issue
Block a user