Skip to content

Create your first watch

This walkthrough uses the watch source preview, curl, and jq. Run it from the source checkout in two terminals. It sends no external notification: the destination is the daemon's console output.

Start the daemon

In the first terminal:

./ding daemon --state-dir ./ding-tutorial

Keep it running. The default address is 127.0.0.1:7676. If another daemon owns that port, stop that daemon deliberately or choose a different --listen port and update the requests below. Do not reuse an existing production state directory.

Validate and apply

In the second terminal, from the same checkout:

./ding validate ding.yaml.example --json
./ding apply ding.yaml.example --state-dir ./ding-tutorial --dry-run --json
./ding apply ding.yaml.example --state-dir ./ding-tutorial

Validation performs no I/O. Dry-run reports changes without saving them. Applying creates the watch and destination. Download the same manifest.

apiVersion: ding.ing/v1alpha1
kind: Destination
metadata: {id: console}
spec: {type: console}
---
apiVersion: ding.ing/v1alpha1
kind: Watch
metadata: {id: latency, name: Request latency}
spec:
  source: {type: push, fields: {latency_ms: latency_ms}}
  condition: {field: latency_ms, operator: gt, value: 300}
  policy: {trigger: transition, consecutive: 1, recoverAfter: 1, onUnknown: hold-incident}
  message: '{{ .Name }}: {{ .Type }} ({{ .Value }} ms)'
  destinations: [{ref: console, events: [firing, recovered, source_error, source_recovered]}]

Send a high reading

curl --fail-with-body http://127.0.0.1:7676/v1/ingest/latency \
  -H "Authorization: Bearer $(jq -r .ingest ding-tutorial/tokens.json)" \
  -H 'Content-Type: application/json' \
  -H 'Idempotency-Key: tutorial-high' \
  -d '{"latency_ms":350}'

./ding events --watch latency --state-dir ./ding-tutorial --json
./ding watch inspect latency --state-dir ./ding-tutorial --json

A successful push returns a durable receipt. The event list contains a firing event, and the first terminal prints a notification. Another high reading keeps the incident open without repeating the transition alert.

The ingest token authorizes input, not administration. Do not substitute the admin token, paste a real token into documentation, or save it in the manifest.

Record recovery

curl --fail-with-body http://127.0.0.1:7676/v1/ingest/latency \
  -H "Authorization: Bearer $(jq -r .ingest ding-tutorial/tokens.json)" \
  -H 'Content-Type: application/json' \
  -H 'Idempotency-Key: tutorial-recovery' \
  -d '{"latency_ms":100}'

./ding events --watch latency --state-dir ./ding-tutorial --json

The list now also contains recovered. The new idempotency key matters: reusing tutorial-high returns the original receipt instead of accepting a new input. Use fresh keys when repeating the walkthrough against an existing tutorial store.

Restart and inspect

Stop the daemon with Ctrl+C, then start it again with the same state directory. Read the events again: condition state, history, and pending deliveries persist.

./ding doctor --state-dir ./ding-tutorial --json
./ding watch pause latency --state-dir ./ding-tutorial

Pause stops acquisition; it does not cancel already committed delivery. Stop the daemon when finished and keep or remove only your disposable tutorial directory.

If something goes wrong

Symptom Check
Connection refused Daemon is running; port and state directory agree.
Unauthorized Request uses the ingest credential from this daemon's private directory.
No new event Use a fresh idempotency key and inspect the watch; a transition fires once until recovery.
Unknown command or invalid manifest You built the watch snapshot, not the v0.14.0 legacy binary.
Event exists but no notification Inspect delivery status and daemon output; event creation and delivery are distinct.

Next: investigate evidence, send notifications, or monitor an HTTP endpoint.