polaris_dashboard 0.1.3

Opinionated read-only dashboard for Polaris sessions.
Documentation

polaris_dashboard

Read-only HTTP dashboard for Polaris sessions, runs, and spans. The crate ships a precompiled SvelteKit SPA embedded via rust-embed; register DashboardPlugin on a Polaris Server and the dashboard is served at a configurable base path on the same HTTP origin as the rest of your Polaris APIs.

The SPA itself is not built by this crate. It must be compiled and built in its own repository; its build output is placed in assets/ and embedded at compile time. When assets/ is empty, the crate still compiles and every dashboard route returns a "bundle missing" notice instead of the UI.

Usage

[dependencies]
polaris-ai = { version = "0.4", features = ["file-store", "sessions-http", "dashboard"] }
polaris_dashboard = "0.1"
use std::sync::Arc;
use polaris_ai::app::{AppConfig, AppPlugin};
use polaris_ai::models::ModelsPlugin;
use polaris_ai::plugins::{PersistencePlugin, ServerInfoPlugin, TracingPlugin};
use polaris_ai::sessions::{HttpPlugin, InMemoryStore, SessionsPlugin};
use polaris_ai::system::server::Server;
use polaris_ai::tools::ToolsPlugin;
use polaris_dashboard::DashboardPlugin;

#[tokio::main]
async fn main() {
    let mut server = Server::new();
    server
        .add_plugins(ServerInfoPlugin)
        .add_plugins(PersistencePlugin)
        .add_plugins(ModelsPlugin)
        .add_plugins(ToolsPlugin)
        .add_plugins(AppPlugin::new(AppConfig::new().with_port(8080)))
        .add_plugins(TracingPlugin::new())
        .add_plugins(SessionsPlugin::new(Arc::new(InMemoryStore::new())))
        .add_plugins(HttpPlugin::new())
        .add_plugins(DashboardPlugin::default()); // serves at /dashboard

    server.run().await.expect("server build failed");
    let _ = tokio::signal::ctrl_c().await;
    server.cleanup().await;
}

See examples/serve.rs for the minimum plugin stack required to drive the runs and sessions panes.

OTLP viewer mode

To point the runs pane at arbitrary OpenTelemetry sources (a microservice, or Polaris exporting OTLP) instead of native Polaris tracing, register OtelTracingPlugin as the trace surface. It mounts an OTLP/HTTP JSON ingest endpoint (POST /v1/traces) plus the same /v1/tracing/* read routes the SPA consumes, backed by its own in-memory TraceStore:

[dependencies]
# Drop `native-tracing` so the upstream TracingPlugin doesn't also claim
# `/v1/tracing/runs` — the two surfaces conflict on that route.
polaris_dashboard = { version = "0.1", default-features = false }
use std::time::Duration;
use polaris_dashboard::{DashboardPlugin, OtelTracingPlugin};

// Configure retention from the plugin surface, then `build()` to mount.
// (Use OtelTracingPlugin::new() for an in-memory collector with defaults.)
server
    .add_plugins(
        OtelTracingPlugin::builder()
            .with_capacity(1_000)                  // cap distinct traces in memory
            .with_ttl(Duration::from_secs(3_600))  // age out traces idle > 1h
            .with_persistence("./trace-history")   // restart-safe NDJSON history
            .build(),
    )
    .add_plugins(DashboardPlugin::default());

The builder's knobs compose in any order and apply together — the TraceStore is constructed once, in build(). The builder returns an OtelTracingPlugin<Configuring>, which is deliberately not mountable, so forgetting build() is a compile error rather than a silently-default collector. For a pre-built or shared store, use OtelTracingPlugin::with_store.

OtelTracingPlugin and the default native-tracing surface are mutually exclusive — pick one. TraceStore::list_runs / run_tree return the same RunSummary / SpanTree shapes the SPA renders, so the OTLP collector is a drop-in source for the existing panes.

Note: POST /v1/traces is an unauthenticated write endpoint unless the host installs an AuthProvider (see below); keep it on a trusted network.

Replacing the SPA

The crate is framework-agnostic — it embeds whatever static bundle is in assets/ and serves it (index.html at the base path, embedded files for matching sub-paths, index.html fallback for everything else). It does no templating and injects no config, so any framework (React, Vue, Solid, plain HTML) can replace the bundled SvelteKit SPA as long as the bundle:

  1. is client-routed and rooted at index.html (no SSR);
  2. emits asset URLs under the mount base — the SPA's build-time base must match DashboardPlugin's base_path (the shipped SPA is built for /dashboard; a mismatch 404s every asset and build() logs a warning);
  3. calls the documented contracts at the same origin: /v1/sessions/* (from HttpPlugin) and /v1/tracing/* (from TracingPlugin or OtelTracingPlugin), consuming the RunSummary / SpanTree JSON shapes;
  4. self-configures — the host injects no settings.

Auth

The dashboard plugin does not register an AuthProvider. Whatever provider you set on polaris_ai::app::HttpRouter covers the dashboard routes too — same-origin, same middleware.

License

Apache-2.0