slatepipe operational

Status › Configuration

Configuration

Two files and a handful of flags. Every key has a default that works; the ones below are the ones people actually change.

collector.yml

listen:
  ingest: "0.0.0.0:7180"
  ui: "127.0.0.1:7181"

database:
  dsn_env: SLATEPIPE_DSN     # read from the environment, never inline
  max_open: 12
  statement_timeout: 20s

ingest:
  token_env: SLATEPIPE_INGEST_TOKEN
  max_body: 1MiB
  stderr_tail: 64KiB
  accept_clock_skew: 5m

retention:
  events_days: 90
  runs_days: 1095
  prune_at: "04:17"

baseline:
  window_runs: 30
  min_runs: 8

alerts:
  from: "slatepipe@example.internal"
  smtp: "mail.example.internal:587"
  rules: /etc/slatepipe/rules.yml

Keys worth a second look

ingest.accept_clock_skew
Records whose start time is further from the collector's clock than this are rejected with 422 rather than quietly stored. Loosen it only if you know a host has no time sync; a drifting clock makes every duration a lie.
baseline.window_runs / min_runs
The trailing median that ratio rules compare against. Below min_runs a pipeline has no baseline and ratio rules do not fire for it at all, which is why a brand-new pipeline is quiet for its first week.
retention.events_days
Governs the raw jsonb payloads and stderr tails only. Aggregated run and step rows live for runs_days, so your year-over-year chart survives a short event retention.
retention.prune_at
Local wall-clock time for the nightly delete. Pick a minute that is not on the hour: every pipeline in the building starts on the hour and prune takes a few table locks.
database.statement_timeout
Applied to the interface's own queries, not to yours. If a dashboard over a year of history starts timing out, this is the knob, and the answer after that is a smaller date range.

Agent flags

FlagDefaultWhat it does
--wrapoff Everything after -- is the command to run and watch.
--pipeline NAMErequired Stable identifier. Changing it starts a new history; the old one does not merge.
--collector URL$SLATEPIPE_COLLECTOR Base URL of the ingest listener. Scheme is required.
--spool DIR/var/lib/slatepipe/spool Where events wait when the collector is unreachable.
--spool-max256MiB Oldest files are dropped first once reached, and the loss is reported.
--onceoff Flush the spool and exit. Pair it with a timer on hosts that run jobs rarely.
--dry-runoff Print the JSON that would be posted and send nothing. Useful in review.
--tag k=vnone Repeatable label stored with the run. Teams use it for environment and owner.
--timeout0 Kill the wrapped command after this long and record a timeout. Zero means never.

Any flag can be given as an environment variable with the SLATEPIPE_ prefix and underscores, so --spool-max is SLATEPIPE_SPOOL_MAX. Flags win over the environment, and the environment wins over the file.

rules.yml

- name: non-zero exit
  when: exit_code != 0
  notify: [etl-oncall@example.internal]

- name: much slower than usual
  when: duration > 2.5 * median_duration
  for_pipelines: ["nightly-*", "billing-rollup"]
  notify: [data-team@example.internal]

- name: suspiciously empty
  when: rows_out < 0.2 * median_rows_out
  min_median_rows: 1000
  notify: [data-team@example.internal]

- name: did not run
  when: missed_schedule
  schedule: "0 2 * * *"
  grace: 45m
  notify: [etl-oncall@example.internal]

Rules are evaluated in order and a run matches at most one, so put the specific rule above the general one. missed_schedule is the single place where you have to tell Slatepipe what you expect, and it is also the only rule that can fire without a run existing.

De-duplication is per rule and per pipeline with a four-hour window: a pipeline failing every ten minutes sends one message, then a second one when it recovers. There is no way to make it page you repeatedly, on purpose.

Webhooks instead of mail

Replace notify with post and the collector sends a flat JSON object: rule name, pipeline, run id, exit code, duration, median duration, and a path to the run in the interface. Non-2xx responses are retried three times over ninety seconds and then dropped with a log line. We do not queue webhook deliveries, because an alert that arrives forty minutes late is noise pretending to be signal.