Dashboards Configuration
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 configuration.md, and llms.txt lists every page.The dashboards package has no options type of its own - it is a delivery vehicle for JSON. "Configuring" the dashboards means three things: registering the meters whose instruments the panels query, choosing which dashboards to surface, and wiring the JSON into Grafana (by import or by provisioning template).
1. Register the meters
A dashboard only charts data if the matching meter is exported to the backend Grafana reads from. Register the meters with OpenTelemetry on the silo:
builder.Services.AddOpenTelemetry()
.WithMetrics(b => b
.AddMeter("orleans.lattice") // Overview, CommitPath, AtomicWrites, MaterialisedViews, GrainIndex, and Replication's WAL panels
.AddMeter("orleans.lattice.replication") // Replication (only if the replication package is registered)
.AddMeter("orleans.lattice.replication.grpc") // ReplicationGrpc (only if the gRPC replication transport is registered)
.AddMeter("orleans.lattice.auth") // Authorization (only if the auth package is registered)
.AddMeter("orleans.lattice.membership") // Authorization (only if the membership package is registered)
.AddMeter("orleans.lattice.backup") // Backup (only if the backup package is registered)
.AddMeter("orleans.lattice.scaling") // Scaling (only if the scaling package is registered)
.AddMeter("orleans.lattice.tenancy") // Tenancy (only if the tenancy package is registered)
.AddMeter("Orleans.Lattice.Api.Mcp.RepoContext") // Overview's exact-KNN panels (only if the repository-context package is hosted)
.AddMeter("Microsoft.Orleans") // Orleans runtime: activations, activation latency, directory, messaging
.AddMeter("System.Runtime") // .NET runtime: GC heap, allocation, pause time, working set, thread pool
.AddPrometheusExporter());
AddMeter matches a meter name exactly and does not cascade to child
namespaces, so each name above has to be registered in its own right. A silo
that registers only orleans.lattice exports none of its siblings, and one that
registers only the orleans.lattice family exports no runtime telemetry at all.
| Meter | Emitted by | Dashboards that need it |
|---|---|---|
orleans.lattice |
the core library, always (the grain-index package publishes onto it too) | Overview, CommitPath, AtomicWrites, MaterialisedViews, GrainIndex, and the WAL, WAL-compaction and WAL GC panels on Replication |
orleans.lattice.replication |
the replication package, only when registered on the silo | Replication |
orleans.lattice.replication.grpc |
the gRPC replication transport, only when registered on the silo | ReplicationGrpc |
orleans.lattice.auth, orleans.lattice.membership |
the auth / membership packages, only when registered on the silo | Authorization |
orleans.lattice.backup |
the backup package, only when registered on the silo | Backup |
orleans.lattice.scaling |
the scaling package, only when registered on the silo | Scaling |
orleans.lattice.tenancy |
the tenancy package, only when registered on the silo | Tenancy |
Orleans.Lattice.Api.Mcp.RepoContext |
the repository-context MCP package, only where it is hosted | the three exact-KNN panels on Overview |
orleans.lattice.api.mcp |
the MCP server host package, only where it is hosted | none of the bundled dashboards; deliberately left uncharted (see its metric-to-panel map section) |
Microsoft.Orleans |
the Orleans runtime, always | none of the bundled dashboards; registered for operational diagnosis |
System.Runtime |
the .NET runtime, always | none of the bundled dashboards; registered for operational diagnosis |
If you do not register the replication package, omit the replication meter. Its panels on the Replication dashboard would resolve to no data; the WAL, WAL-compaction and WAL GC panels on the same dashboard read the core meter and still populate.
Why register the two runtime meters
Neither runtime meter backs a bundled dashboard panel, so it is tempting to leave both out. Do not. They are what turns an unexplained restart into a diagnosable one, and their absence is indistinguishable on the endpoint from an instrument that was never declared:
| Meter | Exact name | What it carries |
|---|---|---|
| Orleans runtime | Microsoft.Orleans |
grain activation counts and activation latency (orleans-catalog-activation-latency), activation collection, grain directory, scheduler, messaging |
| .NET runtime | System.Runtime |
GC heap size and total allocation, GC pause time, process working set, thread-pool depth and queue length, lock contention |
Without System.Runtime the endpoint carries no heap or process-memory series
whatsoever, so a silo in an out-of-memory restart loop has to be diagnosed by
inferring heap composition from activation counts. Without Microsoft.Orleans
there is no direct measure of activation cost, only a grain-call-duration proxy
that cannot separate activation from call.
Two details are worth getting right rather than assuming:
System.Runtimeis built into .NET from .NET 9 and needs no package reference. The olderOpenTelemetry.Instrumentation.Runtimepackage and itsAddRuntimeInstrumentation()call publish an equivalent, differently-namedprocess.runtime.dotnet.*series set; on a modern target framework prefer the built-in meter and skip the dependency.Microsoft.Orleans.Runtime,Microsoft.Orleans.Applicationand their siblings areActivitySourcenames for tracing, not meter names. Passing one of those toAddMetermatches nothing, throws nothing, and leaves the endpoint looking exactly as it did before. The meter name is the bareMicrosoft.Orleans. Re-verify it on an Orleans major upgrade.
Cardinality cost
Measured on a single silo rather than estimated: Microsoft.Orleans produced 54
distinct series and System.Runtime 29.
Every System.Runtime dimension is a fixed enumeration (GC generation, CPU
mode), so its cost does not grow with load at all. The only Orleans dimension
that grows is the type tag on orleans-grains and orleans-system-targets,
which is bounded by the number of grain types in the image - a compile-time
constant - not by the number of grain activations. Neither meter carries a
per-key, per-tree, or per-activation tag, so neither is a cardinality risk on a
large keyspace.
2. Choose which dashboards to surface
Retrieve only the kinds relevant to a deployment. A local-only silo typically imports Overview, CommitPath, and AtomicWrites (and MaterialisedViews if it registers any views); a multi-cluster deployment adds Replication.
using System.IO;
using Orleans.Lattice.Dashboards;
public static class DashboardProvisioning
{
public static void WriteSelectedDashboards(string directory)
{
var kinds = new[]
{
LatticeDashboardKind.Overview,
LatticeDashboardKind.CommitPath,
LatticeDashboardKind.AtomicWrites,
LatticeDashboardKind.MaterialisedViews, // add when materialised views are registered
// LatticeDashboardKind.Replication, // add when replication is registered
// LatticeDashboardKind.ReplicationGrpc, // add when the gRPC replication transport is registered
// LatticeDashboardKind.Authorization, // add when the auth / membership packages are registered
// LatticeDashboardKind.Backup, // add when the backup package is registered
// LatticeDashboardKind.Scaling, // add when the scaling package is registered
// LatticeDashboardKind.Tenancy, // add when the tenancy package is registered
// LatticeDashboardKind.GrainIndex, // add when the grain-index package is registered
};
foreach (var kind in kinds)
{
string json = LatticeDashboards.GetGrafanaDashboardJson(kind);
File.WriteAllText(Path.Combine(directory, $"{kind}.json"), json);
}
}
}
3. Wire the JSON into Grafana
Manual import
In Grafana, open Dashboards -> New -> Import, paste a JSON string returned by GetGrafanaDashboardJson, and select your Prometheus data source.
File-system provisioning
Write the JSON files to a directory and point Grafana at it with a provisioning template. A matching pair of templates ships in the package's Provisioning/ folder:
# Provisioning/datasources.yaml
apiVersion: 1
datasources:
- name: Prometheus
type: prometheus
access: proxy
uid: prometheus
url: http://prometheus:9090
isDefault: true
editable: false
# Provisioning/dashboards.yaml
apiVersion: 1
providers:
- name: orleans-lattice
orgId: 1
folder: Orleans.Lattice
type: file
disableDeletion: true
editable: false
updateIntervalSeconds: 30
allowUiUpdates: false
options:
path: /var/lib/grafana/dashboards/orleans-lattice
foldersFromFilesStructure: false
Mount the rendered JSON files at the path above and Grafana loads them at startup. The templates are a convenience baseline - adjust the data-source URL, folder, and provider name to match your environment.
See also
- API Reference - the accessor and kinds you call to fetch the JSON.
- Architecture - how the JSON and provisioning templates are packaged.
- Metric-to-panel map - which instruments each panel queries, so you can confirm your meter registration is complete.