A self-hosted monitoring & alerting engine for ClickHouse clusters. Twenty-plus collectors poll every node each minute, correlate signals across them, and fire alerts that ship with a plain-English playbook and the exact SQL to investigate.
Parts pile up. A materialized view silently falls behind. S3 latency creeps. By the time queries time out, the root cause is buried three layers deep in system.*. ch-analyzer watches all of it, continuously.
Small inserts outpace background merges, active parts climb past thresholds, and inserts start throwing TOO_MANY_PARTS before anyone notices.
A chained MV breaks or bloats. Downstream tables serve stale data for hours, and nothing in the query log looks wrong.
Absolute delay grows, a replica flips read-only, the replication queue backs up — and reads quietly start returning inconsistent results.
Standing up Prometheus + a TSDB + exporters + Grafana just to watch ClickHouse means one more fragile system to operate.
No agents on your nodes. ch-analyzer connects as a read-only monitoring user, runs every collector in parallel per instance, then reconciles alert state in a single writer.
Every instance, every collector, concurrently each cycle. A circuit breaker skips nodes that fail 5× in a row.
Std-dev baselines auto-learn per metric. Cross-collector rules catch OOM risk, merge overload, S3 contention.
Single-writer diff against DB state. Snooze, ack, inhibition, maintenance and escalation applied on top.
Slack, PagerDuty, webhook by severity. Metrics & alerts written back into ch_analyzer.* on each node.
Each collector owns a slice of ClickHouse health and knows exactly which system.* tables to read. Search or filter by domain.
Detection is the easy half. ch-analyzer is built around what you do next: triage, investigate, remediate, and communicate.
20+ categories with fire-count tracking and first-seen timestamps — plus the logic to keep noise down.
A context-aware chat that sees the view you're on and uses agentic tool calls to dig through live cluster state.
Pinned live-health message, inline Resolve / Snooze buttons, and /status · /alerts · /runcheck. No public endpoint.
Storage broken down by table and tier with monthly cost estimates — find the expensive tables before the bill does.
Patterns, live queries, users, anti-patterns, failures, S3 latency and merges in one view — plus multi-instance table search by pattern, engine, or size.
Diff DDL, settings, metrics and query patterns across instances. Per-category remediation suggestions, fully customizable via a suggestions.yaml.
No alert is a dead end. Click one and you get what it means, why it fired, and named SQL investigation queries — pre-populated with the alert's own time window. Try it:
Each ClickHouse node is the source of truth for its own observability data. ch-analyzer reads system.*, writes ch_analyzer.* right back to the same node, and fans everything out.
system.* read · ch_analyzer.* written per node. Each node owns its schema.
~20 collectors → analyzer → single-writer reconcile loop → store.
React SPA · Slack socket app · Prometheus · PagerDuty · webhook.
Create a read-only monitoring user, load the schema, point the config at your instances, and run. Binary, Docker, or Kubernetes.
# 1 · create the read-only monitoring user on each node CREATE USER IF NOT EXISTS monitoring IDENTIFIED BY '<secret>'; GRANT SELECT ON system.* TO monitoring; GRANT SELECT, INSERT ON ch_analyzer.* TO monitoring; # 2 · load the schema (tables are NOT auto-created) clickhouse-client --host your-host --secure \ --multiquery < schema.sql # 3 · configure & 4 · run as a service make build-linux sudo ./setup.sh # user + schema + binary + systemd sudo systemctl enable --now ch-analyzer
# mount your config, expose the dashboard docker run -d \ -v /etc/ch-analyzer/config.yaml:/etc/ch-analyzer/config.yaml:ro \ -p 8080:8080 \ ch-analyzer:latest # dashboard → http://localhost:8080
# edit credentials, then apply vi deploy/k8s.yaml kubectl apply -f deploy/k8s.yaml kubectl -n ch-analyzer \ port-forward svc/ch-analyzer 8080:8080 # set k8s.enabled: true in config for OOMKill + restart tracking
# terminal 1 — frontend hot reload cd web/frontend && npm run dev # terminal 2 — Go backend make build-go ./bin/ch-analyzer -config configs/ch-analyzer.yaml # dev dashboard → http://localhost:5173
Self-hosted, dependency-light, and honest about what's happening in your cluster. Clone it, load the schema, and watch your nodes light up.