Skip to content

slash-init/pulse

Repository files navigation

Pulse

License: MIT Go Version CI

Pulse is a self-contained service health monitoring daemon written in Go. It performs scheduled HTTP, TCP, and TLS certificate expiration checks against configured targets, persisting results to an embedded SQLite database with automatic rollup aggregation and retention enforcement.


Features

  • Multi-Protocol Checking: Native support for HTTP/HTTPS (status codes and latency boundaries), TCP socket connectivity, and TLS certificate expiration auditing.
  • Single Statically Compiled Binary: Zero external runtime dependencies; embeds SQLite migrations and static dashboard assets directly inside the binary.
  • Automated Rollup Aggregation: A background aggregator summarizes raw checks into hourly and daily rollups, enabling indefinite long-term historical reporting without unbounded disk growth.
  • State-Machine Alerting & Flap Protection: Automatically manages target health states (HEALTHY, ALERTING, FLAPPING, RECOVERED) with configurable failure thresholds and flapping suppression.
  • Multi-Channel Notifications: Built-in concurrent notification dispatcher supporting structured JSON Webhooks and SMTP email alerts.
  • Embedded Dashboard & REST API: Built-in read-only web dashboard and JSON REST API served directly from the daemon on a single port.
  • Prometheus Observability: Native /metrics endpoint exposing rich operational counters, gauges, and latency histograms.

Documentation

Detailed technical guides and complete references are maintained in the docs/ directory:

Guide Audience Summary
Architecture Guide Developers & Contributors Subsystem design, startup sequence, execution lifecycle, concurrency model, SQLite WAL storage mechanics, alert FSM, and tiered rollup pipeline.
Configuration Reference Operators & SREs Complete TOML configuration reference, custom duration parsing, static validation engine rules, startup synchronization, and annotated production defaults.
REST API Reference Developers & Integrators Complete HTTP REST API specification, JSON response schemas, automatic time-based granularity routing, error formats, and cURL examples.

Architecture

graph TD
    A["config.toml"] -->|Load & Validate| B("Main Daemon")
    B -->|Initialize| C[("SQLite Database")]
    B -->|Start| D["Scheduler"]
    B -->|Start| L["Aggregator"]
    D -->|Spawn| E["Service Worker 1"]
    D -->|Spawn| F["Service Worker N"]
    E -->|Execute Check| G["Checker Registry"]
    F -->|Execute Check| G
    G -->|Dial / GET| H["Target Services"]
    G -->|Write Result| I["resultCh"]
    I -->|Drain Loop| J["Alert Evaluator"]
    J -->|Persist Result & State| C
    J -->|Dispatch Notification| K["Webhook / Email Notifiers"]
    L -->|Read raw results / hourly summaries| C
    L -->|Write hourly / daily summaries| C
    L -->|Prune aged data| C
    
    style J fill:#fff,stroke:#333
    style K fill:#fff,stroke:#333
    style L fill:#fff,stroke:#333
Loading

Pulse decouples scheduling, execution, alerting, and data retention using Go channels and interfaces. Independent worker goroutines execute checks on scheduled intervals, pushing results to a centralized alerting and storage pipeline. A dedicated background aggregator computes time-bucketed rollups and enforces data retention policies without blocking live checks.

Note

For detailed component workflows, concurrency patterns, and state transitions, see docs/architecture.md.


Quick Start

Docker Compose

Launch the complete monitoring stack (Pulse, Prometheus, and Grafana):

git clone https://github.com/slash-init/pulse.git
cd pulse
docker compose up -d

Local Build

Compile and run the single binary locally:

# Clone repository and build binary
git clone https://github.com/slash-init/pulse.git
cd pulse
make build

# Copy template configuration and launch daemon
cp config.example.toml config.toml
./bin/pulse -config config.toml

Configuration

Pulse uses a single declarative TOML configuration file. Service targets are synchronized to the local database on startup.

[server]
host        = "0.0.0.0"
port        = 8080
environment = "production"
log_level   = "info"

[database]
driver = "sqlite"
dsn    = "./pulse.db"

[retention]
raw_days                 = 7
hourly_days              = 90
aggregator_tick_interval = "15m"

[alerting]
enabled           = true
failure_threshold = 2
repeat_interval   = "4h"
flap_window       = 10

[alerting.webhook]
enabled = true
url     = "https://hooks.slack.com/services/T00/B00/XXX"

[[services]]
name     = "Production API Health"
enabled  = true
type     = "http"
url      = "https://api.example.com/health"
interval = "30s"
timeout  = "5s"

  [services.alerts]
  status_code = 200
  max_latency = "1000ms"

[[services]]
name     = "TLS Certificate Expiry"
enabled  = true
type     = "ssl"
url      = "https://api.example.com"
interval = "12h"
timeout  = "10s"

  [services.alerts]
  ssl_expiry_days = 14

Note

For complete reference on validation constraints, duration syntax, and notification integrations, see docs/configuration.md.


Dashboard (Web UI & Grafana)

Pulse includes two complementary visualization options out of the box:

  • Embedded Web Dashboard: Accessible at http://localhost:8080/. Served directly from embedded binary assets, it displays live target health, consecutive failures, latency/uptime history, and an incident timeline.
  • Grafana Integration: A production-ready dashboard is pre-provisioned in grafana/dashboards/pulse.json when running via Docker Compose, visualizing Prometheus metrics across all monitored services.

REST API

Pulse exposes read-only HTTP REST endpoints for querying target health, historical checks, and alert events:

Method Endpoint Description
GET /api/healthz Liveness probe verifying database connectivity.
GET /api/services Lists all monitored services with current health state and latest check metadata.
GET /api/services/{id} Returns details and state for a specific service.
GET /api/services/{id}/history Returns historical check results (raw, hour, or day granularity based on time range).
GET /api/services/{id}/events Returns chronological alert state transition events.

Note

For query parameters, automatic granularity routing rules, and JSON response schemas, see docs/api.md.


Prometheus Metrics

Pulse exposes operational metrics at GET /metrics for Prometheus scrapers alongside standard runtime statistics:

Metric Name Type Labels Description
pulse_checks_total Counter service, result Total health checks executed (result is pass or fail).
pulse_check_latency_ms Gauge service Latency of the latest check execution in milliseconds.
pulse_last_check_timestamp Gauge service Unix timestamp of the latest health check.
pulse_alert_state Gauge service, state Current alert state (one-hot encoded: HEALTHY, FIRING, ALERTING, FLAPPING, RECOVERED).
pulse_notifications_sent_total Counter service, event_type, channel Total alert notifications successfully dispatched.
pulse_notification_failures_total Counter channel Total notification delivery failures.
pulse_http_requests_total Counter method, path, status Total HTTP requests handled by the REST API server.
pulse_http_request_duration_seconds Histogram method, path HTTP request duration in seconds.

Design Decisions

  • SQLite Relational Storage vs. Time-Series DB: Storing check history in SQLite eliminates external database dependencies. To avoid unbounded disk growth without a specialized time-series engine, Pulse rolls up raw data into hourly and daily aggregates before pruning raw records.
  • Goroutine-per-Service vs. Worker Pool: Spawning an independent goroutine and ticker per target simplifies scheduling and isolation. Memory footprint scales linearly with service count, making it optimal for hundreds to thousands of targets.
  • Declarative Configuration Sync: Monitored targets declared in config.toml are synchronized to the database on startup. Removing a target from configuration preserves its historical records in SQLite to prevent accidental audit loss.
  • Daily Rollups Derived from Hourly Summaries: Because raw data retention (raw_days) is shorter than hourly summary retention (hourly_days), daily rollups are computed from settled hourly rows using a checks-weighted average to maintain mathematical accuracy.

Roadmap

  • PostgreSQL Storage Driver: Backend implementation of the Store interface for distributed or high-concurrency deployments.
  • Observation Coverage Tracking: Explicit tracking of expected-vs-actual check counts in rollups to distinguish target downtime from monitoring daemon gaps.

Development

make fmt         # Format codebase
make lint        # Run static analysis (golangci-lint)
make test        # Run unit tests with Go race detector (-race)
make test/cover  # Generate code coverage report

License

Pulse is open-source software licensed under the MIT License.

About

A self-contained service health monitoring daemon written in Go with HTTP/TCP/TLS checks, alerting, Prometheus metrics, and Grafana dashboards.

Topics

Resources

License

Stars

0 stars

Watchers

0 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors