---
title: "Diagnostics"
url: "https://nsta1.github.io/Orleans.Lattice/samples/Diagnostics/README.html"
source: "https://github.com/NSTA1/Orleans.Lattice/blob/release/9.9/samples/Diagnostics/README.md"
documents: "Orleans.Lattice 9.9.0 (release line 9.9)"
built: "2026-10-04"
all-pages: "https://nsta1.github.io/Orleans.Lattice/llms.txt"
---
# Diagnostics

Part of [Samples](../index.md).

## What it shows

`ILattice.DiagnoseAsync` returns a point-in-time health snapshot of a tree without
touching application data paths. The report exposes the shard count, total live keys,
total tombstones, recent split activity, and a per-shard breakdown (B+ tree depth,
whether the root is a leaf, live keys, tombstones, tombstone ratio, read/write
counts, current ops/second and the window it is measured over, whether a split
or a bulk load is in flight, and whether the shard could not be sampled - a shard
whose sample failed reports zero for every count because nothing was measured).
This sample writes ten keys, deletes three (leaving tombstones), then prints a deep
snapshot. Both report depths walk each shard's leaf chain: a deep report reads each
leaf's full statistics, so tombstone counts are exact, while a shallow report counts
only live keys and reports zero tombstones.

## Run it

```
dotnet run --project samples/Diagnostics
```

## Expected output

Each key is routed to its shard by a stable hash of the key, so the shard indices
below are the same on every run; the sampled timestamp and the `ops/s` values (which
depend on timing) vary between runs. The totals - 7 live keys and 3 tombstones after
10 writes and 3 deletes - are deterministic.

```
Silo starting... ready.

Writing 10 keys, then deleting 3 (leaving tombstones)...

Tree 'inventory' health snapshot (sampled 2026-07-02T18:34:14.5400810+00:00):
  Deep report:        True
  Shard count:        64 (of 4096 virtual slots)
  Total live keys:    7
  Total tombstones:   3
  Recent splits:      0

Per-shard breakdown (shards with activity only):
  shard 13: depth=1 rootIsLeaf=True live=1 tombstones=0 ratio=0.00 reads=0 writes=1 ops/s=11.4
  shard 14: depth=1 rootIsLeaf=True live=0 tombstones=1 ratio=1.00 reads=0 writes=2 ops/s=17.8
  shard 15: depth=1 rootIsLeaf=True live=1 tombstones=0 ratio=0.00 reads=0 writes=1 ops/s=12.1
  shard 19: depth=1 rootIsLeaf=True live=0 tombstones=1 ratio=1.00 reads=0 writes=2 ops/s=29.9
  shard 21: depth=1 rootIsLeaf=True live=1 tombstones=0 ratio=0.00 reads=0 writes=1 ops/s=16.0
  shard 26: depth=1 rootIsLeaf=True live=1 tombstones=0 ratio=0.00 reads=0 writes=1 ops/s=17.0
  shard 35: depth=1 rootIsLeaf=True live=0 tombstones=1 ratio=1.00 reads=0 writes=2 ops/s=25.3
  shard 43: depth=1 rootIsLeaf=True live=1 tombstones=0 ratio=0.00 reads=0 writes=1 ops/s=13.5
  shard 62: depth=1 rootIsLeaf=True live=1 tombstones=0 ratio=0.00 reads=0 writes=1 ops/s=13.1
  shard 63: depth=1 rootIsLeaf=True live=1 tombstones=0 ratio=0.00 reads=0 writes=1 ops/s=14.3
```

## When to use

- Health probes and dashboards: poll `DiagnoseAsync(deep: false, ...)` at a low rate
  to track live-key growth and per-shard hotness cheaply. A shallow report counts no
  tombstones, so tombstone counts and the tombstone ratio need `deep: true`.
- Post-mortem investigation: run `DiagnoseAsync(deep: true, ...)` to get exact
  tombstone counts and B+ tree depth when diagnosing compaction or split behaviour.

## When not to use

- Do not call `DiagnoseAsync` on the hot path or per request. It is an admin-rate
  API; every report walks each shard's leaf chain, and a deep report also reads full
  statistics from every leaf, so it is comparatively expensive.
- Do not rely on `ops/s` as a precise benchmark - it is a short-window hotness hint,
  not a load-test measurement.

## Feature doc

See [../../docs/lattice/diagnostics.md](../../docs/lattice/diagnostics.md).
