diff --git a/crates/dashboard/src/lib.rs b/crates/dashboard/src/lib.rs
index 26c2033..581381b 100644
--- a/crates/dashboard/src/lib.rs
+++ b/crates/dashboard/src/lib.rs
@@ -1,5 +1,6 @@
mod server;
mod store;
+mod live_explorer;
pub mod swactor;
pub mod view;
@@ -143,6 +144,7 @@ impl DashboardHandle {
/// is called.
pub fn start_dashboard(config: DashboardConfig) -> DashboardHandle {
let views = Arc::new(ViewRegistry::new());
+ views.register(Arc::new(live_explorer::LiveDatastreamExplorer));
views.register(swactor::worker_view());
let store = Arc::new(DashboardStore::new(
config.raw_frame_history,
diff --git a/crates/dashboard/src/live_explorer.rs b/crates/dashboard/src/live_explorer.rs
new file mode 100644
index 0000000..6395ae4
--- /dev/null
+++ b/crates/dashboard/src/live_explorer.rs
@@ -0,0 +1,37 @@
+use datastream::frame::{Frame, StreamId};
+use serde_json::{Value, json};
+
+use crate::FrameEvent;
+use crate::view::DashboardView;
+
+const LIVE_EXPLORER_HTML: &str = include_str!("live_explorer_page.html");
+
+#[derive(Default)]
+pub struct LiveDatastreamExplorer;
+
+impl DashboardView for LiveDatastreamExplorer {
+ fn id(&self) -> &'static str {
+ "datastream/live"
+ }
+
+ fn title(&self) -> &'static str {
+ "Datastream live explorer"
+ }
+
+ fn channels(&self) -> &'static [&'static str] {
+ &[]
+ }
+
+ fn ingest(&self, _stream: &StreamId, _frame: &Frame, _event: &FrameEvent) {}
+
+ fn snapshot_json(&self) -> Value {
+ json!({
+ "description": "Universal live explorer over /events and /api/frames",
+ "page": "/view/datastream/live"
+ })
+ }
+
+ fn html(&self) -> Option<&'static str> {
+ Some(LIVE_EXPLORER_HTML)
+ }
+}
diff --git a/crates/dashboard/src/live_explorer_page.html b/crates/dashboard/src/live_explorer_page.html
new file mode 100644
index 0000000..cbaa376
--- /dev/null
+++ b/crates/dashboard/src/live_explorer_page.html
@@ -0,0 +1,500 @@
+
+
+
+
+
+Datastream live explorer
+
+
+
+
+
+
+
+
+
+
+
+
+ Streams
+ | stream | retained frames | channels |
|---|
+
+
+ Channels
+ | stream | channel | retained | json | text | binary | latest |
|---|
+
+
+ Frames
+ Select a channel to inspect frames.
+
+
+
+
+
+
+
+
+
diff --git a/crates/mvp-system/src/bin/local_e2e_cluster.rs b/crates/mvp-system/src/bin/local_e2e_cluster.rs
index 40aa0a9..6ba5f3b 100644
--- a/crates/mvp-system/src/bin/local_e2e_cluster.rs
+++ b/crates/mvp-system/src/bin/local_e2e_cluster.rs
@@ -78,7 +78,7 @@ impl MvpDashboard {
.map_err(|e| format!("invalid MVP_DASHBOARD_PORT: {e}"))?;
config.port = port;
}
- let url = format!("http://127.0.0.1:{}/view/mvp/cluster", config.port);
+ let url = format!("http://127.0.0.1:{}/view/datastream/live", config.port);
let handle = dashboard::start_dashboard(config.clone());
handle.register_view(Arc::new(MvpClusterDashboardView::new()));
handle.start_http_standalone();