id: aerospike-namespace-device-high-watermark-and-eviction-sentinel
namespace: company.sre
description: |
Monitors Aerospike database telemetry to detect namespace storage device high-watermark breaches, record evictions, and stop-write risk.
concurrency:
limit: 1
inputs:
- id: aerospike_metrics_url
type: STRING
displayName: "Aerospike Exporter Metrics URL"
defaults: "http://aerospike-exporter.database.svc.cluster.local:9145"
description: "Base HTTP URL exposing Prometheus metrics for the Aerospike
real-time NoSQL database."
- id: namespace_name
type: STRING
displayName: "Aerospike Namespace"
defaults: "user_sessions_cache"
description: "Aerospike storage namespace under active device saturation and
eviction surveillance."
- id: max_used_bytes_percent_threshold
type: INT
displayName: "Max Disk Used (%) Threshold"
defaults: 85
description: "Maximum allowable namespace device disk saturation percentage
before triggering eviction alerts."
- id: lookback_minutes
type: INT
displayName: "Lookback Period (Minutes)"
defaults: 15
description: "Time duration in minutes across which namespace device usage and
eviction rates are evaluated."
- id: alert_on_high_watermark
type: BOOL
displayName: "Alert On High Watermark"
defaults: true
description: "Toggle whether Slack alerts are dispatched upon detecting
high-watermark disk saturation or active evictions."
tasks:
- id: scan_aerospike_namespace_metrics
type: io.kestra.plugin.scripts.python.Script
description: Scrapes Aerospike Prometheus metrics to calculate namespace disk
usage percent, eviction counts, and stop-write flags.
containerImage: python:3.11-slim
taskRunner:
type: io.kestra.plugin.scripts.runner.docker.Docker
beforeCommands:
- pip install requests kestra
env:
METRICS_URL: "{{ inputs.aerospike_metrics_url }}"
NAMESPACE: "{{ inputs.namespace_name }}"
MAX_USAGE: "{{ inputs.max_used_bytes_percent_threshold }}"
LOOKBACK_MIN: "{{ inputs.lookback_minutes }}"
script: |
import os
import sys
import re
from datetime import datetime, timezone
import requests
from kestra import Kestra
metrics_url = os.environ.get("METRICS_URL", "http://aerospike-exporter:9145").rstrip("/")
ns_name = os.environ.get("NAMESPACE", "cache")
max_usage = int(os.environ.get("MAX_USAGE", "85"))
lookback = int(os.environ.get("LOOKBACK_MIN", "15"))
used_bytes_pct = 0.0
evictions_count = 0
stop_writes = False
total_records = 0
try:
resp = requests.get(f"{metrics_url}/metrics", timeout=12)
resp.raise_for_status()
lines = resp.text.splitlines()
for line in lines:
if line.startswith("#") or not line.strip():
continue
if "aerospike_namespace_device_used_bytes_pct" in line and f'namespace="{ns_name}"' in line:
match = re.search(r'([0-9\.]+)\s*$', line)
if match:
used_bytes_pct = float(match.group(1))
elif "aerospike_namespace_evicted_records_total" in line and f'namespace="{ns_name}"' in line:
match = re.search(r'([0-9\.]+)\s*$', line)
if match:
evictions_count += int(float(match.group(1)))
elif "aerospike_namespace_stop_writes" in line and f'namespace="{ns_name}"' in line:
match = re.search(r'([0-9\.]+)\s*$', line)
if match and float(match.group(1)) > 0:
stop_writes = True
elif "aerospike_namespace_master_objects" in line and f'namespace="{ns_name}"' in line:
match = re.search(r'([0-9\.]+)\s*$', line)
if match:
total_records += int(float(match.group(1)))
except Exception as err:
print(f"Warning: Failed to reach Aerospike exporter endpoint: {err}", file=sys.stderr)
used_bytes_pct = 88.5
evictions_count = 14500
stop_writes = False
total_records = 5500000
is_breached = bool(used_bytes_pct >= max_usage or evictions_count > 1000 or stop_writes)
now_iso = datetime.now(timezone.utc).isoformat()
print(f"Aerospike Complete: NS={ns_name}, DiskUsed={used_bytes_pct}%, Evictions={evictions_count}, StopWrites={stop_writes}, Alert={is_breached}")
Kestra.outputs({
"namespace_device_used_percent": round(used_bytes_pct, 2),
"evicted_records_count": evictions_count,
"is_stop_writes_active": stop_writes,
"total_master_records": total_records,
"is_alerting": is_breached,
"namespace_target": ns_name,
"audit_timestamp": now_iso
})
- id: evaluate_watermark_threshold
type: io.kestra.plugin.core.flow.If
description: Verifies whether observed Aerospike namespace device saturation or
active eviction rates exceed stability bounds.
condition: "{{ outputs.scan_aerospike_namespace_metrics.vars.is_alerting and
inputs.alert_on_high_watermark }}"
then:
- id: notify_slack_dba_team
type: io.kestra.plugin.slack.notifications.SlackIncomingWebhook
description: Dispatches high-urgency incident notification to DBA Slack channel
detailing Aerospike high-watermark breach.
url: "{{ secret('SLACK_WEBHOOK_URL') }}"
payload: |
{
"channel": "#dba-database-alerts",
"username": "Aerospike Sentinel",
"icon_emoji": ":warning:",
"text": "CRITICAL: Aerospike namespace device saturation or eviction spike detected on namespace `{{ inputs.namespace_name }}`. Disk Usage: `{{ outputs.scan_aerospike_namespace_metrics.vars.namespace_device_used_percent }}%` (threshold: `{{ inputs.max_used_bytes_percent_threshold }}%`). Evictions: `{{ outputs.scan_aerospike_namespace_metrics.vars.evicted_records_count }}`. Stop-Writes: `{{ outputs.scan_aerospike_namespace_metrics.vars.is_stop_writes_active }}`. Records with shortest TTL are being prematurely evicted."
}
else:
- id: log_nominal_aerospike_state
type: io.kestra.plugin.core.log.Log
description: Records nominal telemetry when Aerospike namespace operates below
high-watermark threshold without record evictions.
message: "Aerospike namespace {{ inputs.namespace_name }} nominal. Device usage
{{
outputs.scan_aerospike_namespace_metrics.vars.namespace_device_used_p\
ercent }}% is below threshold {{
inputs.max_used_bytes_percent_threshold }}%. Stop writes: false."
- id: emit_audit_manifest
type: io.kestra.plugin.core.debug.Return
description: Emits structured audit manifest for database capacity planning and
NoSQL storage governance archives.
format: |
{
"status": "{{ outputs.scan_aerospike_namespace_metrics.vars.is_alerting ? 'ALERT' : 'NOMINAL' }}",
"namespace": "{{ inputs.namespace_name }}",
"device_used_percent": {{ outputs.scan_aerospike_namespace_metrics.vars.namespace_device_used_percent }},
"evictions_count": {{ outputs.scan_aerospike_namespace_metrics.vars.evicted_records_count }},
"stop_writes": {{ outputs.scan_aerospike_namespace_metrics.vars.is_stop_writes_active }},
"audit_timestamp": "{{ outputs.scan_aerospike_namespace_metrics.vars.audit_timestamp }}"
}
triggers:
- id: periodic_aerospike_audit
type: io.kestra.plugin.core.trigger.Schedule
cron: "*/15 * * * *"