Querying Traces

While the span query language operates on individual spans and logs, trace queries allow you to select entire traces based on the spans, logs, and events they contain. This is useful for finding traces that match complex criteria across multiple services and operations.

For example, you can find all traces that contain a slow database query, have an error in a specific service, or involve a particular combination of microservices.

Querying Traces UI

Query Structure

A trace query consists of multiple rows, where each row targets a different part of the trace. The first row is always the root row, and subsequent rows define conditions on child spans, logs, or events.

text
root: <query for the root span>
<system> as <alias>: <query for matching spans>

Each row accepts the full span query language including filters, aggregations, and groupings. A typical root row query looks like:

text
root: perMin(count()) | quantiles(_dur_ms) | group by _group_id
ComponentDescription
rootSelects the root span of the trace. Use <empty> to match all root spans.
<system>A span system like db:postgresql, rpc:all, or log:error.
as <alias>An optional alias for readability.
<query>Full query with where, group by, and aggregate clauses.

Filtering by System

Each non-root row targets spans belonging to a specific system. You can use exact systems or wildcard systems with :all:

SystemMatches
db:postgresqlPostgreSQL database spans only
db:mysqlMySQL database spans only
db:allAll database spans (PostgreSQL, MySQL, etc)
rpc:grpcgRPC spans only
rpc:allAll RPC spans
http:service1HTTP spans for service1
httpserver:allAll HTTP server spans
messaging:kafkaKafka messaging spans only
messaging:allAll messaging spans
log:errorError-level logs
log:warnWarning-level logs

Examples

Traces with Multiple Database Queries

Find traces that contain at least 2 PostgreSQL queries:

text
root: <empty>
db:postgresql as pg: having count() >= 2

This is useful for identifying N+1 query problems or traces with excessive database calls.

Traces with Slow Service Calls

Find traces where a specific service takes longer than 1 second to respond:

text
root: <empty>
rpc:all as rpc: where service_name = "foo" | where _kind = "server" | where _dur_ms >= 1000

Traces with Error Logs

Find traces that contain error logs mentioning "timeout":

text
root: <empty>
log:error as err: _display_name contains "timeout"

Traces with Errors in a Specific Service

Find traces where a particular service returned an error:

text
root: <empty>
rpc:all as rpc: where service_name = "payment-service" | where _status_code = "error"

Traces with Slow Root Spans

Find traces where the root span exceeds 5 seconds:

text
root: where _dur_ms >= 5000

Combining Multiple Conditions

Find traces that are slow and contain database errors:

text
root: where _dur_ms >= 3000
db:all as db: where _status_code = "error"

This selects traces where the overall duration exceeds 3 seconds and at least one database span has an error status.

Available Clauses

Each row — both root and child — supports the full span query language including filters, aggregations, and groupings:

ClauseExampleDescription
wherewhere service_name = "foo"Filter spans by attribute values
wherewhere _dur_ms >= 1000Filter by span duration
wherewhere _status_code = "error"Filter by status code
wherewhere _kind = "server"Filter by span kind
wherewhere _display_name contains "text"Filter by display name
group bygroup by _group_idGroup spans by attribute
group bygroup by service_nameGroup by service
Aggregatescount(), perMin(count())Count and rate aggregations
Aggregatesp50(_dur_ms), quantiles(_dur_ms)Duration percentiles
havinghaving count() >= 2Filter by aggregated span count
havinghaving p99(_dur_ms) >= 500Filter by percentile duration

Multiple clauses can be chained with the pipe | operator:

text
rpc:all as rpc: where service_name = "foo" | where _kind = "server" | where _dur_ms >= 1000

See Also