Skip to content


Uptrace provides a powerful querying language that supports filters (WHERE), grouping (GROUP BY), and aggregates (sum(amount)).


To write useful and fast queries you have to clean and structure your data. To record contextual information in spans you should use semantic attributes. For logs to achieve the same you should use structured logging.


Filtering allows to filter spans and events by their attributes. The following span attribute types are supported:

Attribute type Supported comparison operators
string =, like, contains, exists.
int64 and float64 =, <, <=, >, >=, exists.
array of the types above contains, exists.

For example:

Uptrace filter Note
span.status.code = "error" Filters spans with error status code. Case-sensitive. like "hello%" Filters span names that start with "hello". Case-insensitive. like "%hello" Filters span names that end with "hello". Case-insensitive. contains "hello" Filters span names that contain "hello". Case-insensitive.
span.duration > 1ms Same as span.duration > 1000. Uptrace supports μs, ms, and s.
http.request_content_length > 1kb Same as http.request_content_length > 1024. Uptrace supports kb, mb, gb, and tb.
span.event.count > 0 Filters spans with events.
span.event.error_count > 0 Filters spans with error events.
span.event.log_count > 0 Filters spans with log events. exists Filters span events (spans that have attribute).


Grouping works like SQL GROUP BY, but in addition it also selects the grouping expression.

Uptrace grouping Note
span.group_id Groups similar spans together.
span.start_of_minute Groups spans by the minute they were created. Uptrace also supports grouping by hour, day, and week. Groups spans by the hostname.
lower( Groups spans by the lower-cased hostname.


Aggregate functions perform a calculation on a set of values, and return a single value. You often use them together with grouping.

Aggregate function Note
any( Any (random) span name.
avg(span.duration) The average span duration.
max(span.duration) The maximum span duration.
min(span.duration) The minimum span duration.
p50(span.duration) The span duration percentile.
sum(http.request_content_length) The total number of processed bytes.
top3(code.function) The top 3 most popular function names.
uniq(http.client_ip) The number of unique IP addresses.

There is also a number of common pre-calculated columns:

Virtual column Note
span.count The equivalent of SQL count(*).
span.error_count The number of spans with span.status.code = 'error'.
span.error_pct The result of span.error_count / span.count.
span.rate The average number of spans per minute.

Combining all together

You can write powerful queries combining filtering, grouping, and aggregates together. For example, to select the number of unique visitors (excluding bots) for each day:

filters: not exists
aggregates: uniq(http.client_ip)
grouping:   span.start_of_day