All notable changes to this project are documented here. The format follows Keep a Changelog, and this project adheres to Semantic Versioning.

Watch names are the event ids consumers route on, and the event payload is versioned by its "schema" field. A change to either is a breaking change and will be called out here.

Unreleased

0.1.0

Initial release. Ships signal tiers 0 through 2; tracing is deliberately out of scope.

Added

  • use Kepler and the watch DSL: source, measure, filter, enrich, recent, severity, sink, meta, and fire.
  • Crash attribution. source crash_report: :any and source supervisor_report: :child_terminated deliver OTP crash and supervisor reports, with enrich pulling the dying process's state, last message, stacktrace, and Logger metadata into the event. One crash produces one event despite OTP emitting three reports for it.
  • A two-part event contract: a small, fully-required core (id, node, watch, timestamp, severity, state) plus a best-effort context map whose inapplicable keys are absent rather than null.
  • Named sinks with per-watch routing (sink :siem), and a guarantee: key declaring :best_effort or :at_least_once. Only :best_effort is implemented; asking for :at_least_once warns at boot and delivers best-effort.
  • An optional Kepler.Sink.format/1 callback, so a sink's wire format is replaceable without reimplementing its transport.
  • Compile-time checking of every declaration — unknown measurements, unknown identifiers in conditions, duplicate watch names, and cycles between conditions are build failures.
  • Tier 0 sources: system_monitor:, with graceful yielding when another process already holds the node's single system monitor.
  • Tier 1 sources: telemetry:, with :count, :rate, :sum, :average, and percentile: aggregates backed by lock-free counters and a log-linear histogram.
  • Tier 2 sources: process: and vm:, sampled from a declared watchlist on the tick.
  • Composite conditions across watches, evaluated in dependency order.
  • sustained: and cooldown: debouncing as part of the declaration, plus optional resolve: true notices.
  • Ring buffer capture (recent), so an event carries the observations around it.
  • Kepler.Sink.Webhook with HMAC-SHA256 signing and TLS verification, and Kepler.Sink.Callback — two implementations rather than three, so the behaviour is shaped by real use rather than guessed at in three directions.
  • Kepler.Transport for plugging in an HTTP client you already run.
  • Bounded, non-blocking emission with a configurable drop policy. An event routed to several sinks is delivered to all of them concurrently and in isolation: a sink that raises, exits, or wedges is recorded as that sink's failure and cannot stop its siblings. A sink that stops responding is killed after :delivery_timeout.
  • Kepler.Budget: self-measured overhead and automatic shedding.
  • Kepler.status/0, Kepler.watches/0, Kepler.recent/1, Kepler.tick/0, and Kepler.drain/1 for introspection and testing.