Berserk Docs

Running Queries

Inspect what the cluster is executing right now with bzrk ps, tell a slow query from a stuck one, see where each query came from, and stop one

bzrk ps lists the queries a cluster is executing, and bzrk kill stops one.

The listing is cluster-wide. A query runs on one query pod; the gateway asks every pod and merges the answers. A pod that cannot be reached is left out of the result and is missing from the POD column.

Reading a row

bzrk ps
QUERY ID                               POD                      ELAPSED   QUEUED      IDLE    SPAN  SEGMENTS      CHUNKS READ           ROWS
0199f3a2-7c41-7db3-9f0e-2a1b4c6d8e10   berserk-query-1            1m2s        -     200ms      7d     42.0%        1200/3000        1204331
  who:    alice@example.com (session) from 203.0.113.7
  claims: bzrk-cli 1.0.19 · cli
  window: 7d  2026-08-27T09:12:00Z → 2026-09-03T09:12:00Z
  search "error" | summarize count() by bin(timestamp, 1m)
ColumnMeaning
QUERY IDServer-side id, and the handle bzrk kill takes
PODWhich query pod is running it: its pod name, or its address when the pod does not know its name
ELAPSEDHow long since the query arrived
QUEUEDHow long it waited for an execution slot; - when it never waited
IDLESince the last frame reached the client; - before the first one
SPANHow much time the query covers; see The window a query scans
SEGMENTSShare of the segments the query overlaps that it has finished, the progress bzrk search shows; - while still planning
CHUNKS READChunks read against chunks that must be read after pruning
ROWSRows processed so far

SEGMENTS and CHUNKS READ measure different things: many small segments finish while a few large ones are still being read, so SEGMENTS can be near 100% while CHUNKS READ is low.

ELAPSED, QUEUED and IDLE are durations of the execution; SPAN is the time range the query asks about.

IDLE tells a slow query from a stuck one: a query four minutes in whose last frame was 200 ms ago is working, and one whose last frame was three minutes ago is not. QUEUED does the same at the start: a query a minute old that has not started is waiting for a slot, and shows no progress because it has not been planned yet.

Buffered surfaces show no idle time

IDLE reads - for the whole life of a query on a buffered surface (the Kusto REST endpoints), which delivers its result once, at the end.

The window a query scans

SPAN is how much time the query covers. Nothing else in the row tells a ten-minute lookback from a thirty-day one: both can show the same elapsed time, progress and chunk counts for a while.

The window: line under the row gives the bounds of the span. A query that bounds ingest time gets an ingest: line of the same shape, and the column marks an ingest-only span as i30d, so it is not read as an event window.

The window is the server's resolution of the request: relative bounds like 24h ago are resolved against the now captured when the request arrived. It is not a client claim.

A self-bounded query reports no span

SPAN reads - when the request had no window and the query bounds itself in KQL (| where timestamp > ago(1h)). The coordinator derives that window while planning, after the listing entry is made, so the pod answering bzrk ps does not know it. Pass --since, or your surface's equivalent, to make the span visible.

--full adds every execution statistic the engine reports (slices, chunk coverage, skip reasons by kind, bytes scanned and skipped, fetch and snapshot time, state-cache reuse), the set bzrk search --stats prints for a finished query.

Where a query came from

Under each row are up to three lines: who asked, what the client says it is, and the query.

  who:    grafana-dev (service_token) from 203.0.113.7
  claims: grafana-plugin 1.4.0 · dashboard · Ingest health › p99 latency · user alice
  search "error" | summarize count() by bin(timestamp, 1m)

who: is what the server established. The gateway authenticated the caller, resolved the credential and passed the result to the query pod. A client cannot set any of it: the gateway strips the headers these travel in from every inbound request.

Field
principalEmail for a user, principal name for a service
authn methodsession, cli_token, service_token or trusted_proxy
client addressLeft-most X-Forwarded-For from the trusted edge proxy, else the TCP peer

claims: is what the client says about itself. Nothing verifies it, so the listing keeps it on its own line.

Field
app + versionThe program that issued the query
surfacecli, dashboard, explore, alerting, …
dashboard › panelTitle when the client sent one, uid or panel number otherwise
userThe person behind a shared credential
agentThe agent driving the client, when there is one

The Berserk Grafana datasource plugin authenticates the whole organization with one service principal, so who: names the same principal for every panel, and claims: … user alice names the person. The plugin takes the login from Grafana, not from anything the browser sets, but it is still the plugin's claim.

A line with nothing to say is omitted: a client that reports nothing about itself has no claims:.

The listing is not private

Any authenticated caller sees every running query, with its full text and the identity that submitted it.

Structured output

--json keeps the verified and the claimed fields in separate objects:

{
  "query_id": "0199f3a2-7c41-7db3-9f0e-2a1b4c6d8e10",
  "pod": "10.0.1.5:9510",
  "query": "search \"error\" | summarize count() by bin(timestamp, 1m)",
  "attested": {
    "principal_type": "service",
    "principal_name": "grafana-dev",
    "authn_method": "service_token",
    "client_ip": "203.0.113.7"
  },
  "claimed": {
    "app": "grafana-plugin",
    "app_version": "1.4.0",
    "surface": "dashboard",
    "end_user": "alice",
    "dashboard_uid": "abc123",
    "dashboard_title": "Ingest health",
    "panel_title": "p99 latency"
  },
  "window": {
    "span_ms": 604800000,
    "since": "2026-08-27T09:12:00Z",
    "until": "2026-09-03T09:12:00Z",
    "ingest_span_ms": null,
    "ingest_since": null,
    "ingest_until": null,
    "now": "2026-09-03T09:12:00Z",
    "bypass_state_cache": false
  },
  "elapsed_ms": 62000,
  "idle_ms": 200
}

--csv and --tsv carry the same fields, flattened with the prefix kept: attested.principal_name, claimed.dashboard_title.

The query text is stored truncated, with a trailing …, and the table shows it on one line. --json gives the stored text.

Attributing your own client

Every field under claims: comes from one optional message on the query request. The CLI reports itself, its version and its driving agent; the Grafana plugin reports the dashboard, panel and Grafana login, on both its streaming and its one-shot paths.

  • It travels on the request, not in a header. The gateway drops every inbound x-bzrk-* header, so a header cannot carry it. The Kusto-compatible HTTP endpoints are the exception: a stock Grafana datasource pointed at them is attributed from the dashboard headers Grafana sends.
  • Nothing acts on it. Claims are display strings, capped in length and stripped of control characters on arrival. No planning, routing or authorization decision reads them.

Stopping a query

bzrk kill 0199f3a2-7c41-7db3-9f0e-2a1b4c6d8e10
Asked query 0199f3a2-7c41-7db3-9f0e-2a1b4c6d8e10 to stop. It stops at its next work boundary.

Cancellation is cooperative. The command returns once the signal is delivered (--json reports signalled, not "stopped"), and the query stops at its next work boundary, not mid-chunk. The client running it sees its stream end with who stopped it:

warning: incomplete result — the query was killed by alice@example.com via `bzrk kill` before it finished, so these rows are a partial answer.

"No pod is running query …" (not_found in --json) usually means the query finished between bzrk ps and bzrk kill.

After the fact

bzrk ps sees only queries in flight. The same provenance is recorded on each query's completion event, so the dashboards and principals behind past load can be queried; see Observability for where those events land. The anonymized usage record carries none of it.

On this page