Query SignalDB with SQL¶
In this tutorial you run SQL queries against your stored traces, logs, and
metrics using the signaldb-cli command-line tool. Queries travel over
Arrow Flight to the router (port 50053 by default), which forwards them to
a querier where DataFusion executes them against the Iceberg tables.
Prerequisites¶
- A running SignalDB deployment (
./scripts/run-dev.shis enough locally). - The
signaldb-clibinary (cargo build -p signaldb-cliin the repo). - An API key and tenant ID, and some ingested data — see Sending OTLP data and Authentication.
1. Run your first query¶
signaldb-cli query --sql "SELECT trace_id, span_name, service_name FROM traces LIMIT 10" \
--api-key sk-acme-prod-key-123 \
--tenant-id acme
query takes exactly one language flag; --sql runs Arrow-Flight SQL. (The
other flags — --promql, --logql, --traceql, --ir — run the
corresponding query language and return its native JSON; --trace-id
fetches one trace by ID instead of running a query. --start/--end
switch --promql/--logql from an instant query to a range query, with
--step as the resolution.) You get a pretty-printed table and a
10 row(s) returned. summary on stderr. All flags can also come from the
environment: SIGNALDB_FLIGHT_URL (default http://localhost:50053),
SIGNALDB_API_KEY, SIGNALDB_TENANT_ID, SIGNALDB_DATASET_ID.
2. Understand table naming¶
Your data is organized as catalog.schema.table:
- catalog = your tenant slug
- schema = your dataset slug
- tables =
traces,logs,metrics,metric_exemplars
When you authenticate, the session's default catalog and schema are pinned to your tenant and dataset, so unqualified names work:
SELECT count(*) FROM traces
Fully qualified names work too (quote slugs that contain hyphens):
SELECT count(*) FROM "acme"."production"."traces"
Authenticated sessions default to your own tenant's catalog and dataset schema, and trace-lookup and trace-search requests that name another tenant are rejected. Always qualify (or leave unqualified) names within your own tenant's catalog.
3. Try some useful queries¶
Services that reported spans:
signaldb-cli query --sql "SELECT DISTINCT service_name FROM traces"
Slowest spans:
signaldb-cli query --sql "SELECT trace_id, span_name, duration_nano FROM traces ORDER BY duration_nano DESC LIMIT 20"
Recent log records:
signaldb-cli query --sql "SELECT * FROM logs LIMIT 20"
4. Change the output format¶
--format selects table (default), json (newline-delimited, one
object per row, pipe-friendly), or csv (with header row):
signaldb-cli query --sql "SELECT DISTINCT service_name FROM traces" --format json | jq -r .service_name
Limits to know¶
- Row cap: the querier truncates raw SQL results at the server-side
max_sql_rowslimit (default 1,000,000). UseLIMIT/aggregation rather than relying on unbounded selects. - Concurrency: operators can cap concurrent queries per tenant; excess queries fail with a resource-exhausted error.
Where to go next¶
- SQL is for ad-hoc exploration; to query metrics with PromQL over the Prometheus-compatible HTTP API, see Query metrics with PromQL.
signaldb-cli tuistarts an interactive terminal UI over the same endpoints.- The Tempo-compatible HTTP API serves Grafana trace views — see the Tempo API reference.
- Grafana datasource options for dashboards.