Dashboards Architecture
This page documents Orleans.Lattice.Dashboards 9.9.0, in the documentation for Orleans.Lattice 9.9.0 (release line 9.9), built 2026-10-04. It is also published as markdown, with every table and list, at architecture.md, and llms.txt lists every page.This document describes how the dashboards package is built and kept honest. It covers behaviour and packaging, not the names of internal types - the only public surface is described in the API reference.
Embedded JSON resources
Each dashboard is authored once as a Grafana dashboard model and compiled into the assembly as an embedded resource. The public accessor maps a LatticeDashboardKind to the matching resource and returns its bytes as a UTF-8 string. Because the JSON travels inside the assembly:
- Retrieval is a synchronous in-process read - no network call, no file-system dependency, and no external service to provision before a dashboard can be fetched.
- The dashboards are version-pinned to the library. A given package version always returns dashboards whose panels reference only instruments that version emits.
The panels reference instruments by the Prometheus series name that a host exporting through .AddPrometheusExporter() derives from each instrument name (for example orleans.lattice.leaf.write.duration is read as orleans_lattice_leaf_write_duration_milliseconds_bucket), not by any internal handle, so a dashboard works against any Prometheus-compatible backend that scrapes that exposition. An exposition that names series differently - the repository-context container's own, which appends no unit suffix and publishes no histogram buckets - leaves the affected panels empty; see What these dashboards assume about the exposition.
The bidirectional drift guard
The risk with bundled dashboards is silent drift: a renamed instrument leaves a panel charting nothing, or a newly added instrument ships with no panel. A CI test closes both directions:
- Every referenced metric exists. Each metric name a panel on any bundled dashboard queries must resolve to an instrument declared in the library source, on whichever meter owns it. The
orleans_lattice_*tokens on theOverview,CommitPath,AtomicWritesandMaterialisedViewsdashboards are further confined to theorleans.latticemeter, and those onReplicationtoorleans.lattice.replicationplus the coreorleans.latticemeter, whose WAL instruments it charts. That confinement reads onlyorleans_lattice_*tokens, so it does not cover theOverviewdashboard's three exact-KNN panels, which read the repository-contextOrleans.Lattice.Api.Mcp.RepoContextmeter; a separate test requires everyrepocontext_*token a panel names to belong to an instrument documented in the metric-to-panel map, and each of that meter's rows to agree with the panels about whether it is charted. A renamed or removed instrument fails the build. - Every observable instrument is charted. Each live instrument the guard can discover on the
orleans.latticeandorleans.lattice.replicationmeters must be referenced by at least one panel, unless it is on the guard's short list of instruments deliberately left uncharted (each marked (not charted) in the metric-to-panel map). A new instrument with no panel fails the build. The add-on meters' forward direction is enforced from their owning packages' tests instead, and so is the grain-index package's: it publishes its instruments on the coreorleans.latticemeter but declares them on its own publicGrainIndexMetricstype, so its package tests assert that theGrainIndexdashboard charts every one of them.
Direction 2 carries one caveat worth knowing. The guard discovers instruments by forcing the type initialisers of LatticeMetrics and LatticeReplicationMetrics and listening for what they publish, plus the instrument-name constants those two classes declare. An instrument created in a field initialiser on some other type is not constructed at test time, so the guard cannot see it and will not demand a panel for it - the orleans.lattice.tag_index.reconcile.* family is a live example of an unpaneled instrument with a green build. Declaring a new instrument on LatticeMetrics (or LatticeReplicationMetrics) keeps it inside the guard's reach; declaring it elsewhere means its panel is yours to add by hand. Its metric-to-panel map row is still demanded: the documentation-coverage fixtures scan source for instrument-name literals rather than listening to the meter, so they fail the build until the row exists, but no fixture demands the panel.
The authoritative human-readable view of this pairing is the metric-to-panel map; the test is the enforcement. Together they keep the bundled dashboards from referencing a stale metric, and from silently omitting a new instrument the guard can observe.
No replication link dependency
The package depends on the core library only. The Replication dashboard's panels query instruments on the orleans.lattice.replication meter, but those names are embedded as plain strings in the JSON - the package does not reference the replication assembly. This keeps the dashboards installable in local-only deployments without dragging in the replication package; the replication meter simply produces no data unless that package is separately registered on the silo.
Provisioning templates
Alongside the embedded JSON, the package carries a Provisioning/ folder with a baseline Grafana data-source template and a file-provider dashboards template. These are static YAML assets meant to be copied and adjusted, not code - they let an operator stand up file-system provisioning without hand-writing the boilerplate. See Configuration for how they fit together.
Coverage at a glance
flowchart LR
meters["orleans.lattice + orleans.lattice.replication instruments"]
panels["Embedded dashboard JSON panels"]
guard["CI drift guard"]
meters -- "every instrument charted" --> guard
panels -- "every metric exists" --> guard
panels --> accessor["LatticeDashboards.GetGrafanaDashboardJson"]
accessor --> grafana["Grafana (import or provisioning)"]
See also
- API Reference - the public accessor and kinds.
- Configuration - meter registration and provisioning templates.
- Metric-to-panel map - the enforced per-instrument coverage table.