observability-query

Query the project's local telemetry as a development feedback signal.

npx skills

npx skills add joshuaoliphant/claude-plugins --skill observability-query

Works for Codex, Cursor and other harnesses. Use -a <agent> to target one, e.g. -a codex.

Claude Code

/plugin marketplace add joshuaoliphant/claude-plugins
/plugin install observability-harness@oliphant-plugins

Query the Observability Harness

The harness exists so the agent can read the app's behavior instead of guessing at it. Telemetry is a feedback signal: after tests, during debugging, while verifying.

1. Detect the harness and its mode

bash .claude/harness/observability/status.sh --json
# {"installed": true, "running": true, "mode": "lite|full", "service": "...", "services": {...}}
  • File absent → no harness; this skill doesn't apply (offer the claude-code-observability-harness skill to set one up).
  • "running": false → bash .claude/harness/observability/start.sh first.
  • "mode" decides the query surface below.

If the pipeline itself is in doubt (sinks suspiciously empty), run bash .claude/harness/observability/verify.sh --py "uv run python" before concluding anything from the absence of data — no data ≠ no activity until the probe proves the transport.

2. Query

The full recipe collection lives in ../claude-code-observability-harness/references/querying.md — read it for anything beyond the essentials below.

Lite mode — jq over dated JSONL:

JSONL=.claude/harness/observability/data/jsonl
DAY=$(date +%F)

# What span names fired today (cheapest "is it running" check)
jq -r '.name // empty' "$JSONL/traces/$DAY.jsonl" | sort | uniq -c

# Recent error/warning logs
jq -c 'select((.severity_text // "") | test("ERROR|WARN")) | {sev: .severity_text, msg: (.message // .body)}' \
  "$JSONL/logs/$DAY.jsonl" | tail -20

# Did a specific instrument record? (e.g. after exercising a new feature)
jq -c 'select(.name=="<instrument.name>")' "$JSONL/metrics/$DAY.jsonl" | tail -5

Field names vary by Vector version (message vs body) — when a query returns nothing, inspect one raw line first: head -1 "$JSONL/traces/$DAY.jsonl" | jq .

Full mode — LogsQL (:9428) and PromQL (:8428); always list what's actually stored before guessing metric spellings (dots become underscores, histograms sprout _bucket/_sum/_count):

curl -s 'http://127.0.0.1:8428/api/v1/label/__name__/values' | jq .
curl -s 'http://127.0.0.1:9428/select/logsql/query?query=_msg:error&start=5m&limit=50' | jq .

3. Answer the actual question

Map the situation to the check (full table in querying.md):

Situation Check
"Did my change actually run?" Span names / counter for the touched path, after exercising it once
Debugging a failure Error logs in the failure window; the span around the failing call (trace-correlated logs carry trace_id)
Verifying new instrumentation Domain instruments fired with real labels, not just the probe's synthetic ones
Performance rate(...) during a benchmark (full mode); latency histogram points (either mode)

Report what the telemetry shows, distinguish it from what you infer, and say which window you queried. An empty result after a verified pipeline is itself evidence: the code path did not execute.

← observability-harness