Observability

Every op is instrumented — for free.

Every source, sink, transform, and state operation emits Prometheus metrics and OpenTelemetry tracing spans automatically — no per-connector code, no wrappers. Scrape it, ship spans over OTLP, and point Grafana at it.

Prometheus metrics OTLP tracing spans labels: pipeline · row · connector zero per-connector code
The metric catalog

Counters, gauges, and histograms across the whole path.

Over 120 metrics across the runtime — a representative set per subsystem below; the full list, histogram buckets, and label values are in the reference.

Source

faucet_source_records_total counter Records read
faucet_source_errors_total counter Read errors, by kind
faucet_source_page_duration_seconds histogram Time per page
faucet_source_in_flight gauge Pages being read
faucet_source_lag_seconds gauge How far a CDC or streaming source is behind its head (also _bytes, _events)
faucet_source_throttled_total counter Rate-limit responses from the source API (429s)
faucet_source_throttle_wait_seconds histogram Time spent backing off after each one
faucet_source_retries_total counter Source-side retries, by class

Sink

faucet_sink_records_total counter Records written
faucet_sink_writes_total counter Write calls
faucet_sink_errors_total counter Write errors
faucet_sink_write_duration_seconds histogram Time per write
faucet_sink_flush_duration_seconds histogram Time per flush

Transform

faucet_transform_records_in_total counter Records in
faucet_transform_records_out_total counter Records out
faucet_transform_duration_seconds histogram Time per page
faucet_transform_errors_total counter Errors, by kind

State

faucet_state_get_total counter Bookmark reads (hit/miss)
faucet_state_put_total counter Bookmark writes
faucet_state_errors_total counter State errors, by op
faucet_state_*_duration_seconds histogram Time per op

Pipeline

faucet_pipeline_runs_total counter Runs, by status
faucet_pipeline_run_duration_seconds histogram Run wall-clock
faucet_pipeline_in_flight gauge Runs in progress
faucet_pipeline_seconds_since_last_bookmark gauge Freshness
faucet_build_info gauge Version label (group_left)

Dead-letter queue

faucet_sink_dlq_records_total counter Rows routed to the DLQ
faucet_sink_dlq_pages_total counter DLQ pages written
faucet_sink_dlq_write_duration_seconds histogram Time per DLQ write
faucet_sink_dlq_budget_exceeded_total counter DLQ budget exceeded

Governance

faucet_quality_checks_total counter Quality checks run
faucet_contract_violations_total counter Contract breaches
faucet_schema_drift_total counter Drift events, by kind
faucet_masking_fields_total counter Fields masked
faucet_lineage_events_total counter OpenLineage events emitted
faucet_pipeline_sla_violations_total counter SLA violations, by kind

Resilience

faucet_resilience_retries_total counter Retries, by connector
faucet_resilience_circuit_state gauge Circuit-breaker state
faucet_resilience_giveup_total counter Give-ups after retries
faucet_resilience_poison_rows_total counter Poison rows quarantined

Topology & scale

faucet_tee_records_total counter Records fanned out (tee)
faucet_merge_records_total counter Records merged (fan-in)
faucet_join_matches_total counter Join matches
faucet_pipeline_adaptive_batch_size gauge Adaptive batch size

Plus metrics for backfill, scheduling, serve/cluster, notifications, and cleanup — see all 120+ in the reference →

Wire it up

Scrape it in two minutes.

faucet serve exposes a Prometheus /metrics endpoint on its listener, and a one-shot faucet run serves one wherever the config's observability.prometheus.listen says. The endpoint is unauthenticated, so bind it locally. Tracing spans export over OTLP to any collector. faucet_build_info carries the running version — group_left it onto any metric to annotate dashboards.

  • Common labels: pipeline, row, connector.
  • run_id is a span attribute only — never a high-cardinality label.
  • Drop-guard timers sample even on cancellation; panics surface as a typed error kind.
Observability reference →
# faucet serve: /metrics on its HTTP listener
faucet serve --listen 127.0.0.1:8080

# faucet run / schedule: in the pipeline file
observability:
  prometheus:
    listen: "127.0.0.1:9090"

# prometheus.yml
scrape_configs:
  - job_name: faucet
    static_configs:
      - targets: ["localhost:9090"]

# annotate any panel with the running version
rate(faucet_sink_records_total[5m])
  * on() group_left(version) faucet_build_info
Status and state

One screen per pipeline.

faucet status answers the questions an operator actually asks: when did this last succeed, where does the next run resume, how far behind is the source, what's waiting in the DLQ, and are the SLA and profiling checks passing. Its exit code (0 healthy, 1 degraded, 2 failed) makes it a cron or Nagios check.

  • faucet state show / set / reset / export / import moves, resets or backs up a bookmark, and refuses while a run holds the row.
  • State is versioned: after an upgrade, faucet migrates an older bookmark or refuses one it can't read, never guesses.
  • Also served over HTTP at /v1/status and /v1/state.
State and status guide →
# health check, for cron or Nagios
faucet status orders.yaml
faucet status orders.yaml --json

# back up, move or reset a bookmark
faucet state show orders.yaml
faucet state export orders.yaml -o orders-state.json
faucet state reset orders.yaml --row refunds --yes
Get started

Your first pipeline runs in five minutes.

Install the CLI, scaffold a config, and move real data — nothing external to stand up.

curl -LsSf https://github.com/faucet-hq/faucet-stream/releases/latest/download/faucet-cli-installer.sh | sh
brew install faucet-hq/faucet-stream/faucet-cli