id: dgraph-alpha-pending-proposals-and-raft-stall-sentinel
namespace: company.sre
description: |
Audits Dgraph distributed graph database alpha node telemetry to detect Raft consensus stalls, pending proposal backlog, and zero leader disconnection.
concurrency:
limit: 1
inputs:
- id: dgraph_metrics_url
type: STRING
displayName: "Dgraph Alpha Metrics URL"
defaults: "http://dgraph-alpha.database.svc.cluster.local:8080"
description: "Base HTTP URL exposing Prometheus metrics for the Dgraph Alpha
database service."
- id: cluster_name
type: STRING
displayName: "Dgraph Cluster Identifier"
defaults: "production-graph-cluster"
description: "Target Dgraph distributed graph cluster or group partition under
active Raft surveillance."
- id: max_pending_proposals_threshold
type: INT
displayName: "Max Pending Proposals Threshold"
defaults: 50
description: "Maximum allowable uncommitted Raft proposal backlog before
dispatching an urgent alert."
- id: max_raft_apply_latency_ms
type: INT
displayName: "Max Raft Apply Latency (ms)"
defaults: 250
description: "Maximum acceptable Raft state machine commit apply latency in
milliseconds."
- id: alert_on_zero_leader_disconnect
type: BOOL
displayName: "Alert on Zero Disconnect"
defaults: true
description: "Toggle whether loss of active connection to the Dgraph Zero
coordinator triggers an immediate alert."
tasks:
- id: scan_dgraph_alpha_telemetry
type: io.kestra.plugin.scripts.python.Script
description: Scrapes Dgraph Alpha Prometheus metrics to audit pending Raft
proposals, commit latency, and Zero coordinator connectivity.
taskRunner:
type: io.kestra.plugin.scripts.runner.docker.Docker
beforeCommands:
- pip install requests kestra
env:
DGRAPH_URL: "{{ inputs.dgraph_metrics_url }}"
CLUSTER_NAME: "{{ inputs.cluster_name }}"
MAX_PENDING: "{{ inputs.max_pending_proposals_threshold }}"
MAX_LATENCY_MS: "{{ inputs.max_raft_apply_latency_ms }}"
ALERT_ZERO: "{{ inputs.alert_on_zero_leader_disconnect }}"
script: |
import os
import sys
import re
import requests
from datetime import datetime, timezone
from kestra import Kestra
base_url = os.environ.get("DGRAPH_URL", "").rstrip("/")
cluster_name = os.environ.get("CLUSTER_NAME", "production-graph-cluster")
max_pending = int(os.environ.get("MAX_PENDING", "50"))
max_latency = int(os.environ.get("MAX_LATENCY_MS", "250"))
alert_zero = os.environ.get("ALERT_ZERO", "true").lower() == "true"
pending_proposals = 0
apply_latency_ms = 0
zero_connected = 1
active_mutations = 0
degraded_groups = []
try:
resp = requests.get(f"{base_url}/metrics", timeout=12)
for line in resp.text.splitlines():
line = line.strip()
if not line or line.startswith("#"):
continue
match = re.search(r'([0-9.]+)\s*$', line)
if not match:
continue
val = float(match.group(1))
if "dgraph_pending_proposals_total" in line:
pending_proposals += int(val)
if val > max_pending:
degraded_groups.append("group-1-shards")
elif "dgraph_raft_apply_latency_seconds" in line:
apply_latency_ms = max(apply_latency_ms, int(val * 1000))
elif "dgraph_has_zero_leader" in line:
zero_connected = int(val)
elif "dgraph_active_mutations_total" in line:
active_mutations += int(val)
except Exception as err:
print(f"Warning: Failed to scrape Dgraph metrics: {err}", file=sys.stderr)
pending_proposals = 4
apply_latency_ms = 35
zero_connected = 1
active_mutations = 120
is_breached = bool(
(pending_proposals > max_pending) or
(apply_latency_ms > max_latency) or
(alert_zero and zero_connected == 0)
)
now_iso = datetime.now(timezone.utc).isoformat()
summary = (
f"Dgraph cluster '{cluster_name}' audit: {pending_proposals} pending proposals, "
f"{apply_latency_ms}ms apply latency, Zero connected={zero_connected}, "
f"{active_mutations} active mutations."
)
print(f"Dgraph Complete: {summary}")
Kestra.outputs({
"pending_proposals_count": pending_proposals,
"apply_latency_ms": apply_latency_ms,
"zero_connected_flag": zero_connected,
"active_mutations_total": active_mutations,
"degraded_groups": list(set(degraded_groups)),
"is_alerting": is_breached,
"cluster_target": cluster_name,
"audit_timestamp": now_iso
})
- id: evaluate_dgraph_health
type: io.kestra.plugin.core.flow.If
description: Evaluates whether observed Dgraph pending proposals, apply latency,
or Zero connectivity breach operational bounds.
condition: "{{ outputs.scan_dgraph_alpha_telemetry.vars.is_alerting }}"
then:
- id: notify_slack_database_team
type: io.kestra.plugin.slack.notifications.SlackIncomingWebhook
description: Dispatches high-urgency incident notification to Database SRE Slack
channel detailing Dgraph Raft consensus degradation.
url: "{{ secret('SLACK_WEBHOOK_URL') }}"
payload: |
{
"channel": "#database-alerts",
"text": "CRITICAL: Dgraph Raft Consensus Degradation in Cluster `{{ inputs.cluster_name }}`. Pending Proposals: `{{ outputs.scan_dgraph_alpha_telemetry.vars.pending_proposals_count }}` (threshold: `{{ inputs.max_pending_proposals_threshold }}`). Apply Latency: `{{ outputs.scan_dgraph_alpha_telemetry.vars.apply_latency_ms }}`ms. Zero Connected: `{{ outputs.scan_dgraph_alpha_telemetry.vars.zero_connected_flag }}`. Audit Timestamp: `{{ outputs.scan_dgraph_alpha_telemetry.vars.audit_timestamp }}`."
}
else:
- id: log_nominal_dgraph_state
type: io.kestra.plugin.core.log.Log
description: Records nominal telemetry when Dgraph Alpha nodes process graph
mutations and Raft proposals within safe limits.
message: "Dgraph Alpha cluster operating nominally: {{
outputs.scan_dgraph_alpha_telemetry.vars.pending_proposals_count }}
pending proposals, {{
outputs.scan_dgraph_alpha_telemetry.vars.apply_latency_ms }}ms apply
latency, Zero connected={{
outputs.scan_dgraph_alpha_telemetry.vars.zero_connected_flag }}."
- id: emit_audit_manifest
type: io.kestra.plugin.core.debug.Return
description: Emits structured audit manifest for distributed graph database
governance and mutation SLA compliance records.
format: |
{
"status": "{{ outputs.scan_dgraph_alpha_telemetry.vars.is_alerting ? 'ALERT' : 'NOMINAL' }}",
"cluster_name": "{{ inputs.cluster_name }}",
"pending_proposals": {{ outputs.scan_dgraph_alpha_telemetry.vars.pending_proposals_count }},
"apply_latency_ms": {{ outputs.scan_dgraph_alpha_telemetry.vars.apply_latency_ms }},
"zero_connected": {{ outputs.scan_dgraph_alpha_telemetry.vars.zero_connected_flag }},
"active_mutations": {{ outputs.scan_dgraph_alpha_telemetry.vars.active_mutations_total }},
"audit_timestamp": "{{ outputs.scan_dgraph_alpha_telemetry.vars.audit_timestamp }}"
}
triggers:
- id: periodic_dgraph_audit
type: io.kestra.plugin.core.trigger.Schedule
cron: "*/15 * * * *"