Aerospike Monitoring Dashboards¶
Monitoring dashboards for Aerospike NoSQL database using OpenTelemetry metrics with ES|QL queries.
Overview¶
These dashboards provide comprehensive monitoring for Aerospike clusters, including cluster-level health metrics, per-node performance, and namespace-level storage and query statistics.
Dashboards¶
| Dashboard | File | Description |
|---|---|---|
| Overview | overview.yaml |
Cluster-level metrics and node health monitoring |
| Node Metrics | node-metrics.yaml |
Detailed per-node performance monitoring |
| Namespace Metrics | namespace-metrics.yaml |
Namespace-level storage and query statistics |
All dashboards include navigation links for easy switching between views.
Dashboard Definitions¶
Overview (overview.yaml)
---
# Aerospike Overview Dashboard
# Provides cluster-level metrics and node health monitoring
dashboards:
- id: 4d5b8a67-c5d9-478c-8128-e09cccc7f8ef
name: '[Metrics Aerospike] Overview'
description: Aerospike cluster overview with node health and performance metrics using ES|QL
filters:
- field: data_stream.dataset
equals: aerospikereceiver.otel
controls:
- type: options
id: node-filter
label: Node
data_view: metrics-*
field: aerospike.node.name
- type: options
id: namespace-filter
label: Namespace
data_view: metrics-*
field: aerospike.namespace
panels:
# Navigation Links
- size: {w: 48, h: 2}
links:
layout: horizontal
items:
- label: Overview
dashboard: 4d5b8a67-c5d9-478c-8128-e09cccc7f8ef
- label: Node Metrics
dashboard: 36bd5b4a-9c5b-4377-827d-f2e64d860f60
- label: Namespace Metrics
dashboard: c9484395-aa2b-43c4-84ad-12a7feb8c7d1
# KPI Metrics Row
- title: Aerospike Nodes
size: {w: 12, h: 5}
esql:
type: metric
query: |
FROM metrics-*
| WHERE data_stream.dataset == "aerospikereceiver.otel"
| WHERE aerospike.node.name IS NOT NULL
| STATS node_count = COUNT_DISTINCT(aerospike.node.name)
primary:
field: node_count
label: Nodes
format:
type: number
decimals: 0
- title: Unique Namespaces
size: {w: 12, h: 5}
esql:
type: metric
query: |
FROM metrics-*
| WHERE data_stream.dataset == "aerospikereceiver.otel"
| WHERE aerospike.namespace IS NOT NULL
| STATS namespace_count = COUNT_DISTINCT(aerospike.namespace)
primary:
field: namespace_count
label: Namespaces
format:
type: number
decimals: 0
- title: Avg Connections
size: {w: 12, h: 5}
esql:
type: metric
query: |
FROM metrics-*
| WHERE data_stream.dataset == "aerospikereceiver.otel"
| WHERE aerospike.node.connection.open IS NOT NULL
| STATS avg_connections = AVG(aerospike.node.connection.open)
primary:
field: avg_connections
label: Connections
format:
type: number
- title: Avg Memory Free
size: {w: 12, h: 5}
esql:
type: metric
query: |
FROM metrics-*
| WHERE data_stream.dataset == "aerospikereceiver.otel"
| WHERE aerospike.node.memory.free IS NOT NULL
| STATS memory_free = AVG(aerospike.node.memory.free)
primary:
field: memory_free
label: Memory Free %
format:
type: number
suffix: '%'
# Cluster Summary DataTable
- title: Cluster Node Summary
size: {w: 48, h: 15}
description: Summary of node-level metrics across the cluster
esql:
type: datatable
query:
- FROM metrics-*
- WHERE data_stream.dataset == "aerospikereceiver.otel"
- WHERE aerospike.node.name IS NOT NULL
- STATS memory_free = AVG(aerospike.node.memory.free), connections = AVG(aerospike.node.connection.open), namespaces = COUNT_DISTINCT(aerospike.namespace)
BY node = aerospike.node.name
- KEEP node, namespaces, memory_free, connections
- SORT node ASC
- LIMIT 100
breakdowns:
- field: node
label: Node
- field: namespaces
label: Namespaces
- field: memory_free
label: Memory Free %
- field: connections
label: Connections
# Memory Free Over Time
- title: Memory Free Over Time
size: {w: 48, h: 10}
esql:
type: line
query: |
TS metrics-*
| WHERE data_stream.dataset == "aerospikereceiver.otel"
| WHERE aerospike.node.memory.free IS NOT NULL
| STATS memory_free = AVG(AVG_OVER_TIME(aerospike.node.memory.free)) BY time_bucket = BUCKET(@timestamp, 20, ?_tstart, ?_tend), node = aerospike.node.name
| SORT time_bucket ASC
legend:
visible: show
position: right
dimension:
field: time_bucket
label: Time
data_type: date
metrics:
- field: memory_free
label: Memory Free %
format:
type: number
suffix: '%'
breakdown:
field: node
# Connections Over Time
- title: Open Connections Over Time
size: {w: 48, h: 10}
esql:
type: line
query: |
TS metrics-*
| WHERE data_stream.dataset == "aerospikereceiver.otel"
| WHERE aerospike.node.connection.open IS NOT NULL
| STATS connections = AVG(AVG_OVER_TIME(aerospike.node.connection.open)) BY time_bucket = BUCKET(@timestamp, 20, ?_tstart, ?_tend), node = aerospike.node.name
| SORT time_bucket ASC
legend:
visible: show
position: right
dimension:
field: time_bucket
label: Time
data_type: date
metrics:
- field: connections
label: Open Connections
format:
type: number
breakdown:
field: node
# Distribution Charts
- title: Memory Free by Node
size: {w: 24, h: 10}
esql:
type: pie
query: |
FROM metrics-*
| WHERE data_stream.dataset == "aerospikereceiver.otel"
| WHERE aerospike.node.memory.free IS NOT NULL
| STATS memory_free = AVG(aerospike.node.memory.free) BY node = aerospike.node.name
| SORT memory_free DESC
| LIMIT 20
metrics:
- field: memory_free
label: Memory Free %
format:
type: number
suffix: '%'
breakdowns:
- field: node
label: Node
appearance:
donut: medium
- title: Connections by Node
size: {w: 24, h: 10}
esql:
type: pie
query: |
FROM metrics-*
| WHERE data_stream.dataset == "aerospikereceiver.otel"
| WHERE aerospike.node.connection.open IS NOT NULL
| STATS connections = AVG(aerospike.node.connection.open) BY node = aerospike.node.name
| SORT connections DESC
| LIMIT 20
metrics:
- field: connections
label: Connections
format:
type: number
breakdowns:
- field: node
label: Node
appearance:
donut: medium
Node Metrics (node-metrics.yaml)
---
# Aerospike Node Metrics Dashboard
# Provides detailed per-node performance monitoring
dashboards:
- id: 36bd5b4a-9c5b-4377-827d-f2e64d860f60
name: '[Metrics Aerospike] Node Metrics'
description: Detailed per-node performance monitoring for Aerospike using ES|QL
filters:
- field: data_stream.dataset
equals: aerospikereceiver.otel
controls:
- type: options
id: node-filter
label: Node
data_view: metrics-*
field: aerospike.node.name
panels:
# Navigation Links
- size: {w: 48, h: 2}
position: {x: 0, y: 0}
links:
layout: horizontal
items:
- label: Overview
dashboard: 4d5b8a67-c5d9-478c-8128-e09cccc7f8ef
- label: Node Metrics
dashboard: 36bd5b4a-9c5b-4377-827d-f2e64d860f60
- label: Namespace Metrics
dashboard: c9484395-aa2b-43c4-84ad-12a7feb8c7d1
# Context Note
- size: {w: 48, h: 2}
position: {x: 0, y: 2}
markdown:
content: |
Detailed per-node performance metrics for Aerospike. Use the Node filter to focus on specific nodes.
# KPI Metrics Row
- title: Selected Nodes
size: {w: 8, h: 5}
position: {x: 0, y: 4}
esql:
type: metric
query: |
FROM metrics-*
| WHERE data_stream.dataset == "aerospikereceiver.otel"
| WHERE aerospike.node.name IS NOT NULL
| STATS node_count = COUNT_DISTINCT(aerospike.node.name)
primary:
field: node_count
label: Nodes
format:
type: number
decimals: 0
- title: Aerospike Namespaces
size: {w: 8, h: 5}
position: {x: 8, y: 4}
esql:
type: metric
query: |
FROM metrics-*
| WHERE data_stream.dataset == "aerospikereceiver.otel"
| WHERE aerospike.namespace IS NOT NULL
| STATS namespace_count = COUNT_DISTINCT(aerospike.namespace)
primary:
field: namespace_count
label: Namespaces
format:
type: number
decimals: 0
- title: Memory Free
size: {w: 16, h: 5}
position: {x: 16, y: 4}
esql:
type: metric
query: |
FROM metrics-*
| WHERE data_stream.dataset == "aerospikereceiver.otel"
| WHERE aerospike.node.memory.free IS NOT NULL
| STATS memory_free = AVG(aerospike.node.memory.free)
primary:
field: memory_free
label: Memory Free %
format:
type: number
suffix: '%'
- title: Open Connections
size: {w: 16, h: 5}
position: {x: 32, y: 4}
esql:
type: metric
query: |
FROM metrics-*
| WHERE data_stream.dataset == "aerospikereceiver.otel"
| WHERE aerospike.node.connection.open IS NOT NULL
| STATS connections = AVG(aerospike.node.connection.open)
primary:
field: connections
label: Connections
format:
type: number
# Memory Section Header
- size: {w: 48, h: 2}
position: {x: 0, y: 9}
markdown:
content: '# Memory Metrics'
# Memory Charts
- title: Memory Free Over Time
size: {w: 48, h: 10}
position: {x: 0, y: 11}
esql:
type: line
query: |
TS metrics-*
| WHERE data_stream.dataset == "aerospikereceiver.otel"
| WHERE aerospike.node.memory.free IS NOT NULL
| STATS memory_free = AVG(AVG_OVER_TIME(aerospike.node.memory.free)) BY time_bucket = BUCKET(@timestamp, 20, ?_tstart, ?_tend), node = aerospike.node.name
| SORT time_bucket ASC
legend:
visible: show
position: right
dimension:
field: time_bucket
label: Time
data_type: date
metrics:
- field: memory_free
label: Memory Free %
format:
type: number
suffix: '%'
breakdown:
field: node
# Connection Section Header
- size: {w: 48, h: 2}
position: {x: 0, y: 21}
markdown:
content: '# Connection Metrics'
# Connection Charts
- title: Open Connections Over Time
size: {w: 48, h: 10}
position: {x: 0, y: 23}
esql:
type: line
query: |
TS metrics-*
| WHERE data_stream.dataset == "aerospikereceiver.otel"
| WHERE aerospike.node.connection.open IS NOT NULL
| STATS connections = AVG(AVG_OVER_TIME(aerospike.node.connection.open)) BY time_bucket = BUCKET(@timestamp, 20, ?_tstart, ?_tend), node = aerospike.node.name
| SORT time_bucket ASC
legend:
visible: show
position: right
dimension:
field: time_bucket
label: Time
data_type: date
metrics:
- field: connections
label: Open Connections
format:
type: number
breakdown:
field: node
# Connections by Type
- title: Connections by Type
size: {w: 48, h: 10}
position: {x: 0, y: 33}
esql:
type: line
query: |
TS metrics-*
| WHERE data_stream.dataset == "aerospikereceiver.otel"
| WHERE aerospike.node.connection.open IS NOT NULL
| WHERE attributes.type IS NOT NULL
| STATS connections = AVG(AVG_OVER_TIME(aerospike.node.connection.open)) BY time_bucket = BUCKET(@timestamp, 20, ?_tstart, ?_tend), connection_type = attributes.type
| SORT time_bucket ASC
legend:
visible: show
position: right
dimension:
field: time_bucket
label: Time
data_type: date
metrics:
- field: connections
label: Connections
format:
type: number
breakdown:
field: connection_type
# Node Details Table
- title: Node Details
size: {w: 48, h: 12}
position: {x: 0, y: 44}
description: Detailed node-level metrics
esql:
type: datatable
query:
- FROM metrics-*
- WHERE data_stream.dataset == "aerospikereceiver.otel"
- WHERE aerospike.node.name IS NOT NULL
- STATS memory_free = AVG(aerospike.node.memory.free), connections_open = AVG(aerospike.node.connection.open) BY node = aerospike.node.name
- KEEP node, memory_free, connections_open
- SORT node ASC
- LIMIT 100
breakdowns:
- field: node
label: Node
- field: memory_free
label: Memory Free %
- field: connections_open
label: Open Connections
Namespace Metrics (namespace-metrics.yaml)
---
# Aerospike Namespace Metrics Dashboard
# Provides namespace-level storage and query statistics
dashboards:
- id: c9484395-aa2b-43c4-84ad-12a7feb8c7d1
name: '[Metrics Aerospike] Namespace Metrics'
description: Namespace-level storage and query statistics for Aerospike using ES|QL
filters:
- field: data_stream.dataset
equals: aerospikereceiver.otel
controls:
- type: options
id: node-filter
label: Node
data_view: metrics-*
field: aerospike.node.name
- type: options
id: namespace-filter
label: Namespace
data_view: metrics-*
field: aerospike.namespace
panels:
# Navigation Links
- size: {w: 48, h: 2}
position: {x: 0, y: 0}
links:
layout: horizontal
items:
- label: Overview
dashboard: 4d5b8a67-c5d9-478c-8128-e09cccc7f8ef
- label: Node Metrics
dashboard: 36bd5b4a-9c5b-4377-827d-f2e64d860f60
- label: Namespace Metrics
dashboard: c9484395-aa2b-43c4-84ad-12a7feb8c7d1
# Context Note
- size: {w: 48, h: 2}
position: {x: 0, y: 2}
markdown:
content: |
Namespace-level storage and query statistics for Aerospike. Use the Node and Namespace filters to focus on specific resources.
# KPI Metrics Row
- title: Selected Namespaces
size: {w: 12, h: 5}
position: {x: 0, y: 4}
esql:
type: metric
query: |
FROM metrics-*
| WHERE data_stream.dataset == "aerospikereceiver.otel"
| WHERE aerospike.namespace IS NOT NULL
| STATS namespace_count = COUNT_DISTINCT(aerospike.namespace)
primary:
field: namespace_count
label: Namespaces
format:
type: number
decimals: 0
- title: Memory Usage
size: {w: 12, h: 5}
position: {x: 12, y: 4}
esql:
type: metric
query: |
FROM metrics-*
| WHERE data_stream.dataset == "aerospikereceiver.otel"
| WHERE aerospike.namespace.memory.usage IS NOT NULL
| STATS memory_usage = AVG(aerospike.namespace.memory.usage)
primary:
field: memory_usage
label: Memory Usage
format:
type: bytes
- title: Disk Available
size: {w: 12, h: 5}
position: {x: 24, y: 4}
esql:
type: metric
query: |
FROM metrics-*
| WHERE data_stream.dataset == "aerospikereceiver.otel"
| WHERE aerospike.namespace.disk.available IS NOT NULL
| STATS disk_available = AVG(aerospike.namespace.disk.available)
primary:
field: disk_available
label: Disk Available %
format:
type: number
suffix: '%'
- title: Memory Free
size: {w: 12, h: 5}
position: {x: 36, y: 4}
esql:
type: metric
query: |
FROM metrics-*
| WHERE data_stream.dataset == "aerospikereceiver.otel"
| WHERE aerospike.namespace.memory.free IS NOT NULL
| STATS memory_free = AVG(aerospike.namespace.memory.free)
primary:
field: memory_free
label: Memory Free %
format:
type: number
suffix: '%'
# Query Information Section
- size: {w: 48, h: 2}
position: {x: 0, y: 9}
markdown:
content: '# Query Information'
# Query Charts - Primary Index
- title: Primary Index Queries Over Time
size: {w: 24, h: 10}
position: {x: 0, y: 11}
esql:
type: line
query: |
TS metrics-*
| WHERE data_stream.dataset == "aerospikereceiver.otel"
| WHERE aerospike.namespace.query.count IS NOT NULL
| WHERE attributes.index == "primary"
| STATS query_rate = SUM(RATE(aerospike.namespace.query.count)) BY time_bucket = BUCKET(@timestamp, 20, ?_tstart, ?_tend), namespace = aerospike.namespace
| SORT time_bucket ASC
legend:
visible: show
position: right
dimension:
field: time_bucket
label: Time
data_type: date
metrics:
- field: query_rate
label: Queries/sec
format:
type: number
decimals: 2
breakdown:
field: namespace
# Query Charts - Secondary Index
- title: Secondary Index Queries Over Time
size: {w: 24, h: 10}
position: {x: 24, y: 11}
esql:
type: line
query: |
TS metrics-*
| WHERE data_stream.dataset == "aerospikereceiver.otel"
| WHERE aerospike.namespace.query.count IS NOT NULL
| WHERE attributes.index == "secondary"
| STATS query_rate = SUM(RATE(aerospike.namespace.query.count)) BY time_bucket = BUCKET(@timestamp, 20, ?_tstart, ?_tend), namespace = aerospike.namespace
| SORT time_bucket ASC
legend:
visible: show
position: right
dimension:
field: time_bucket
label: Time
data_type: date
metrics:
- field: query_rate
label: Queries/sec
format:
type: number
decimals: 2
breakdown:
field: namespace
# Transaction Information Section
- size: {w: 48, h: 2}
position: {x: 0, y: 21}
markdown:
content: '# Transaction Information'
# Transaction Charts
- title: Transaction Rate Over Time
size: {w: 48, h: 10}
position: {x: 0, y: 23}
esql:
type: line
query: |
TS metrics-*
| WHERE data_stream.dataset == "aerospikereceiver.otel"
| WHERE aerospike.namespace.transaction.count IS NOT NULL
| WHERE attributes.type IS NOT NULL
| STATS transaction_rate = SUM(RATE(aerospike.namespace.transaction.count)) BY time_bucket = BUCKET(@timestamp, 20, ?_tstart, ?_tend), transaction_type = attributes.type
| SORT time_bucket ASC
legend:
visible: show
position: right
dimension:
field: time_bucket
label: Time
data_type: date
metrics:
- field: transaction_rate
label: Transactions/sec
format:
type: number
decimals: 2
breakdown:
field: transaction_type
# Storage Metrics Section
- size: {w: 48, h: 2}
position: {x: 0, y: 34}
markdown:
content: '# Storage Metrics'
# Storage Charts
- title: Memory Usage Over Time
size: {w: 24, h: 10}
position: {x: 0, y: 36}
esql:
type: line
query: |
TS metrics-*
| WHERE data_stream.dataset == "aerospikereceiver.otel"
| WHERE aerospike.namespace.memory.usage IS NOT NULL
| STATS memory_usage = AVG(AVG_OVER_TIME(aerospike.namespace.memory.usage)) BY time_bucket = BUCKET(@timestamp, 20, ?_tstart, ?_tend), namespace = aerospike.namespace
| SORT time_bucket ASC
legend:
visible: show
position: right
dimension:
field: time_bucket
label: Time
data_type: date
metrics:
- field: memory_usage
label: Memory Usage
format:
type: bytes
breakdown:
field: namespace
- title: Disk Available Over Time
size: {w: 24, h: 10}
position: {x: 24, y: 36}
esql:
type: line
query: |
TS metrics-*
| WHERE data_stream.dataset == "aerospikereceiver.otel"
| WHERE aerospike.namespace.disk.available IS NOT NULL
| STATS disk_available = AVG(AVG_OVER_TIME(aerospike.namespace.disk.available)) BY time_bucket = BUCKET(@timestamp, 20, ?_tstart, ?_tend), namespace = aerospike.namespace
| SORT time_bucket ASC
legend:
visible: show
position: right
dimension:
field: time_bucket
label: Time
data_type: date
metrics:
- field: disk_available
label: Disk Available %
format:
type: number
suffix: '%'
breakdown:
field: namespace
# Distribution Charts
- title: Memory Usage by Namespace
size: {w: 24, h: 10}
position: {x: 0, y: 46}
esql:
type: pie
query: |
FROM metrics-*
| WHERE data_stream.dataset == "aerospikereceiver.otel"
| WHERE aerospike.namespace.memory.usage IS NOT NULL
| STATS memory_usage = AVG(aerospike.namespace.memory.usage) BY namespace = aerospike.namespace
| SORT memory_usage DESC
| LIMIT 20
metrics:
- field: memory_usage
label: Memory Usage
format:
type: bytes
breakdowns:
- field: namespace
label: Namespace
appearance:
donut: medium
- title: Memory Free by Namespace
size: {w: 24, h: 10}
position: {x: 24, y: 46}
esql:
type: pie
query: |
FROM metrics-*
| WHERE data_stream.dataset == "aerospikereceiver.otel"
| WHERE aerospike.namespace.memory.free IS NOT NULL
| STATS memory_free = AVG(aerospike.namespace.memory.free) BY namespace = aerospike.namespace
| SORT memory_free DESC
| LIMIT 20
metrics:
- field: memory_free
label: Memory Free %
format:
type: number
suffix: '%'
breakdowns:
- field: namespace
label: Namespace
appearance:
donut: medium
# Namespace Summary Table
- title: Namespace Summary
size: {w: 48, h: 12}
position: {x: 0, y: 56}
description: Summary of namespace-level metrics
esql:
type: datatable
query:
- FROM metrics-*
- WHERE data_stream.dataset == "aerospikereceiver.otel"
- WHERE aerospike.namespace IS NOT NULL
- STATS memory_usage = AVG(aerospike.namespace.memory.usage), memory_free = AVG(aerospike.namespace.memory.free), disk_available =
AVG(aerospike.namespace.disk.available) BY namespace = aerospike.namespace, node = aerospike.node.name
- KEEP namespace, node, memory_usage, memory_free, disk_available
- SORT namespace ASC, node ASC
- LIMIT 100
breakdowns:
- field: namespace
label: Namespace
- field: node
label: Node
- field: memory_usage
label: Memory Usage
- field: memory_free
label: Memory Free %
- field: disk_available
label: Disk Available %
Prerequisites¶
- Aerospike: Aerospike database cluster
- OpenTelemetry Collector: Collector with Aerospike receiver configured
- Kibana: Version 9.2.0 or later (required for TS/BUCKET/RATE/AVG_OVER_TIME)
Data Requirements¶
- Data stream dataset:
aerospikereceiver.otel - Data view:
metrics-*
OpenTelemetry Collector Configuration¶
receivers:
aerospike:
endpoint: localhost:3000
collection_interval: 60s
metrics:
aerospike.node.memory.free:
enabled: true
aerospike.node.connection.open:
enabled: true
aerospike.namespace.memory.usage:
enabled: true
aerospike.namespace.memory.free:
enabled: true
aerospike.namespace.disk.available:
enabled: true
aerospike.namespace.query.count:
enabled: true
aerospike.namespace.transaction.count:
enabled: true
Metrics Reference¶
Core Metrics (enabled by default)¶
| Metric | Type | Unit | Description |
|---|---|---|---|
aerospike.node.name |
Resource | - | Node identifier |
aerospike.node.memory.free |
Gauge | % (0-100) | Percentage of free memory on the node |
aerospike.node.connection.open |
Sum | connections | Current open connections (by type) |
aerospike.namespace |
Resource | - | Namespace identifier |
aerospike.namespace.memory.usage |
Sum | bytes | Memory usage per namespace (by component) |
aerospike.namespace.memory.free |
Gauge | % (0-100) | Percentage of free memory per namespace |
aerospike.namespace.disk.available |
Gauge | % (0-100) | Percentage of available disk per namespace |
Counter Metrics (use RATE() for time-series)¶
| Metric | Unit | Description |
|---|---|---|
aerospike.namespace.query.count |
queries | Query count (by type, index, result) |
aerospike.namespace.transaction.count |
transactions | Transaction count (by type, result) |
Extended Metrics (optional)¶
| Metric | Unit | Description |
|---|---|---|
aerospike.node.connection.count |
connections | Connection count (by type, operation) |
aerospike.node.query.tracked |
queries | Queries exceeding tracking threshold |
aerospike.namespace.scan.count |
scans | Scan count (by type, result) |
Key Attributes¶
| Attribute | Description |
|---|---|
aerospike.node.name |
Node name |
aerospike.namespace |
Namespace name |
attributes.type |
Connection or transaction type |
attributes.index |
Index type (primary/secondary) |