otel: wire /otel into the SPA (dual-mode SX + sx-trigger poll refresh)
This commit is contained in:
@@ -481,13 +481,13 @@
|
|||||||
(traces (otel/recent-traces)))
|
(traces (otel/recent-traces)))
|
||||||
(quasiquote
|
(quasiquote
|
||||||
(div :id "otel-dashboard"
|
(div :id "otel-dashboard"
|
||||||
;; The host serves single-body responses (no server-push SSE), so the
|
;; SPA-native live refresh: the SX engine polls GET /otel every 3s and
|
||||||
;; dashboard stays live by reloading itself — every 3s it re-renders the
|
;; swaps this div in place (outerHTML). The poll is a boosted request, so
|
||||||
;; latest metrics + trace. /otel/stream remains a snapshot of the newest
|
;; the route returns the text/sx fragment — no full reload, stays in the
|
||||||
;; span for any client that wants to poll it.
|
;; SPA. (No <meta refresh>, which would blow away the SPA shell.)
|
||||||
(meta :http-equiv "refresh" :content "3")
|
:sx-get "/otel" :sx-trigger "every 3s" :sx-target "#otel-dashboard" :sx-swap "outerHTML"
|
||||||
(h1 "OpenTelemetry")
|
(h1 "OpenTelemetry")
|
||||||
(p :style "font-size:0.8em;opacity:0.7" "live · auto-refreshes every 3s")
|
(p :style "font-size:0.8em;opacity:0.7" "live · refreshes every 3s in-app")
|
||||||
(h2 "latency by route")
|
(h2 "latency by route")
|
||||||
(p :style "font-size:0.75em;opacity:0.7"
|
(p :style "font-size:0.75em;opacity:0.7"
|
||||||
(span :style "color:#4c9a8f" "▉ p50") " "
|
(span :style "color:#4c9a8f" "▉ p50") " "
|
||||||
@@ -505,9 +505,16 @@
|
|||||||
(unquote (otel/-traces-list traces)))))))
|
(unquote (otel/-traces-list traces)))))))
|
||||||
|
|
||||||
;; ── routes ────────────────────────────────────────────────────────────
|
;; ── 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
|
||||||
|
;; into place; a direct/no-JS load gets the full SPA shell (host/blog--page) with
|
||||||
|
;; the dashboard in #content, so it degrades to a plain server-rendered page.
|
||||||
|
;; (Reuses the host SPA shell + content-type negotiation from lib/host/blog.sx.)
|
||||||
(define otel/dashboard-route
|
(define otel/dashboard-route
|
||||||
(dream-get "/otel"
|
(dream-get "/otel"
|
||||||
(fn (req) (dream-html (render-to-html (otel/dashboard) {})))))
|
(fn (req)
|
||||||
|
(host/blog--resp req 200
|
||||||
|
(host/blog--page req "OpenTelemetry" (otel/dashboard))))))
|
||||||
(define otel/stream-route
|
(define otel/stream-route
|
||||||
(dream-get "/otel/stream"
|
(dream-get "/otel/stream"
|
||||||
(fn (req)
|
(fn (req)
|
||||||
|
|||||||
@@ -234,7 +234,8 @@
|
|||||||
(host-ot-test "dashboard has the root id" (contains? host-ot-dash "otel-dashboard") true)
|
(host-ot-test "dashboard has the root id" (contains? host-ot-dash "otel-dashboard") true)
|
||||||
(host-ot-test "dashboard SSRs the waterfall svg" (contains? host-ot-dash "<svg") true)
|
(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 shows a route in the strip" (contains? host-ot-dash "/feed") true)
|
||||||
(host-ot-test "dashboard auto-refreshes (meta refresh, not fake SSE)" (contains? host-ot-dash "refresh") 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 shows the latency chart legend" (contains? host-ot-dash "p99 (tail)") 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
|
;; the SSE endpoint emits a span event, SSE-framed
|
||||||
@@ -252,13 +253,18 @@
|
|||||||
(define host-ot-ev (otel/latest-span-event))
|
(define host-ot-ev (otel/latest-span-event))
|
||||||
(host-ot-test "latest span event type" (str (get host-ot-ev :type)) "otel.span")
|
(host-ot-test "latest span event type" (str (get host-ot-ev :type)) "otel.span")
|
||||||
|
|
||||||
;; mounted through make-app: GET /otel serves the dashboard page
|
;; mounted through make-app: a BOOSTED GET /otel returns the text/sx fragment (the
|
||||||
|
;; SPA path — serialize, no render-page, so it's conformance-safe). The direct/
|
||||||
|
;; full-page path uses render-page (a server-env prim absent here) and is exercised
|
||||||
|
;; live, not in conformance.
|
||||||
(otel/reset!)
|
(otel/reset!)
|
||||||
(feed/reset!)
|
(feed/reset!)
|
||||||
(define host-ot-mapp (host/make-app (list host/feed-routes otel/routes)))
|
(define host-ot-mapp (host/make-app (list host/feed-routes otel/routes)))
|
||||||
(define host-ot-otelresp (host-ot-mapp (dream-request "GET" "/otel" {} "")))
|
(define host-ot-otelresp (host-ot-mapp (dream-request "GET" "/otel" {"sx-request" "true"} "")))
|
||||||
(host-ot-test "GET /otel status 200" (dream-status host-ot-otelresp) 200)
|
(host-ot-test "GET /otel (boosted) status 200" (dream-status host-ot-otelresp) 200)
|
||||||
(host-ot-test "GET /otel serves the dashboard"
|
(host-ot-test "GET /otel (boosted) is text/sx"
|
||||||
|
(contains? (str (dream-headers host-ot-otelresp)) "text/sx") true)
|
||||||
|
(host-ot-test "GET /otel (boosted) serves the dashboard fragment"
|
||||||
(contains? (dream-resp-body host-ot-otelresp) "otel-dashboard") true)
|
(contains? (dream-resp-body host-ot-otelresp) "otel-dashboard") true)
|
||||||
|
|
||||||
;; empty ring → dashboard still SSRs (a placeholder, no svg)
|
;; empty ring → dashboard still SSRs (a placeholder, no svg)
|
||||||
|
|||||||
Reference in New Issue
Block a user