Monitoring Teranode¶
This guide covers the dashboards Teranode ships out of the box, the metrics that distinguish a healthy node from a degraded one, and how to get started with alerting. It applies to both the Docker quickstart and Kubernetes operator deployments — the metrics and the dashboard files are the same; what differs is how you reach Grafana/Prometheus and which dashboards are provisioned for you.
Dashboards¶
Teranode ships pre-built Grafana dashboards. Not all of them are provisioned by
every stack — the Provisioned by column says which one mounts each file:
| Dashboard | File | Provisioned by | What it shows |
|---|---|---|---|
| Teranode Service Overview | deploy/docker/base/grafana_dashboards/teranode/teranode-overview-dashboard.json |
Operator Docker stacks (deploy/docker/mainnet, deploy/docker/testnet, deploy/docker/monitoring) |
Top-level health across all services: throughput, latencies, error rates |
| Aerospike Batch Index Bottleneck Diagnostic | deploy/docker/base/grafana_dashboards/teranode/teranode-batch-index-dashboard.json |
Operator Docker stacks | Aerospike batch index buffer pressure, a common scaling bottleneck |
| Aerospike Namespace | deploy/docker/base/grafana_dashboards/aerospike/aerospike-namespace.json |
Operator Docker stacks | Namespace-level memory, disk, and object counts |
| Aerospike Latency | deploy/docker/base/grafana_dashboards/aerospike/aerospike-latency.json |
Operator Docker stacks | Read/write/batch latency buckets for the UTXO store |
| BlockAssembler State Monitoring | compose/grafana/dashboards/blockassembly-state.json |
Nothing on the operator paths — import by hand (only the developer multi-node stacks compose/docker-compose-ss.yml and test/docker-compose-host.yml mount it) |
Block assembler state timeline (running, reorging, movingUp, ...), state durations, and transition rates — see dashboard notes |
The Grafana service in the Docker stacks mounts a single dashboards directory,
deploy/docker/base/grafana_dashboards, so the four dashboards in that directory
— and only those — are provisioned automatically. On the quickstart, Grafana and
Prometheus come up with the monitoring compose profile, which is part of the
default COMPOSE_PROFILES (legacy,p2p,monitoring). Grafana is then reachable
at http://localhost:3005 and Prometheus at http://localhost:9090 (both
loopback-only by default). See Installing with
Docker and its Troubleshooting
guide if Grafana shows no data.
The BlockAssembler State Monitoring dashboard is not provisioned on either
operator path. To use it, import
compose/grafana/dashboards/blockassembly-state.json manually (Grafana →
Dashboards → Import → Upload JSON file), or drop the file into
deploy/docker/base/grafana_dashboards/teranode/ before starting the stack so
the existing provisioning picks it up.
On Kubernetes, Prometheus and Grafana are not deployed by the Teranode operator itself — point your cluster's existing Prometheus at the Teranode services' metrics endpoints and import all of the dashboards above manually (Grafana → Dashboards → Import).
Metrics: Healthy vs. Degraded¶
The full metric catalogue is in the Prometheus Metrics Reference. The signals below are the ones worth watching first — most are visible directly on the Service Overview dashboard.
FSM and sync state¶
teranode_blockchain_fsm_current_state is a numeric gauge, not a string — it
carries the enum ordinal of the blockchain FSM state:
| Value | State |
|---|---|
| 0 | IDLE |
| 1 | RUNNING |
| 2 | CATCHINGBLOCKS |
A healthy node sits on 1 (RUNNING) once initial sync completes. Stuck on 2
(CATCHINGBLOCKS) or oscillating indicates a sync problem; see Syncing the
Node. The gauge is written on FSM transitions
only, so the series is absent until the node makes its first transition — use
absent(...) if you want to alert on that case as well.
Also watch:
teranode_blockvalidation_catchup_activeandteranode_blockvalidation_processing_blocks_stuck— non-zero for extended periods means the node has fallen behind or a block is wedged.
Block assembly¶
teranode_blockassembly_current_state is a numeric gauge too:
| Value | State |
|---|---|
| 0 | starting |
| 1 | running |
| 2 | resetting |
| 4 | blockchainSubscription |
| 5 | reorging |
| 6 | movingUp |
| 7 | reconciling |
Value 3 is unused — that state was removed. A healthy node spends almost all of
its time on 1 (running).
teranode_blockassembly_state_duration_seconds (histogram) and
teranode_blockassembly_state_transitions_total (counter) carry the state in a
state / from / to label. The label values are the lower-camelCase names in
the table above — running, movingUp, blockchainSubscription, and so on —
not the capitalised names the dashboard panels display, so a selector such as
{state="Running"} matches nothing. Long dwell time in reorging or movingUp
is worth investigating.
Also watch:
teranode_blockassembly_best_block_heightvs. your own chain tip — a gap that doesn't close means block assembly is falling behind validation.
Validation and propagation errors¶
teranode_validator_invalid_transactionsandteranode_propagation_invalid_transactions— a sustained non-zero rate (rather than occasional spikes from normal network traffic) suggests policy misconfiguration or an upstream data problem.teranode_aerospike_utxo_errors,teranode_aerospike_txmeta_errors, and the SQL-store equivalents (teranode_sql_utxo_errors) — any sustained rate here points at store-level trouble (disk, memory pressure, connectivity), not the chain itself.
Fork and reorg activity¶
teranode_blockvalidation_fork_countandteranode_blockvalidation_fork_orphaned_total— occasional forks are normal; a rapidly growing fork count or frequent orphaning suggests network or peering issues.
Cache and store pressure¶
teranode_tx_meta_cache_hitsvs.teranode_tx_meta_cache_misses— a degrading hit ratio under steady load usually precedes increased UTXO store latency.teranode_aerospike_utxo_create_batch/_spend_batch(histograms) — rising batch durations are an early indicator of Aerospike contention, before it shows up as user-visible slowdown.
Starter Alerting¶
Teranode does not ship Prometheus alerting rules — alert thresholds depend on your hardware, network, and risk tolerance, so this is left to the operator.
Both state metrics are numeric gauges, so state alerts must be written as
numeric comparisons; a string comparison such as
teranode_blockchain_fsm_current_state != "RUNNING" is not valid PromQL and
will be rejected. As a starting point, consider:
groups:
- name: teranode-starter
rules:
# Blockchain FSM not RUNNING (1) for 5 minutes.
- alert: TeranodeFSMNotRunning
expr: teranode_blockchain_fsm_current_state != 1
for: 5m
annotations:
summary: "Blockchain FSM is not RUNNING"
# Block assembly stuck outside running (1) for 5 minutes. Tune the window
# to the block time you expect on your network.
- alert: TeranodeBlockAssemblyNotRunning
expr: teranode_blockassembly_current_state != 1
for: 5m
annotations:
summary: "Block assembly is not in the running state"
# A block is wedged in validation.
- alert: TeranodeBlockProcessingStuck
expr: teranode_blockvalidation_processing_blocks_stuck > 0
for: 2m
annotations:
summary: "Block validation reports stuck blocks"
# Sustained store or validation errors.
- alert: TeranodeErrorRate
expr: |
rate(teranode_validator_invalid_transactions[5m]) > 0
or rate(teranode_aerospike_utxo_errors[5m]) > 0
or rate(teranode_sql_utxo_errors[5m]) > 0
for: 10m
annotations:
summary: "Sustained validation or UTXO store errors"
# Reorgs happening more than once every 10 seconds.
- alert: TeranodeFrequentReorgs
expr: sum(rate(teranode_blockassembly_state_transitions_total{to="reorging"}[5m])) > 0.1
for: 5m
annotations:
summary: "Frequent block assembly reorgs"
Note the to="reorging" label value: the state, from, and to labels carry
the lower-camelCase state names listed above, so capitalised selectors return an
empty series and the alert silently never fires.
The BlockAssembler State Monitoring dashboard notes carry further examples in the same style.