Query Builder

Build ad-hoc queries across all your analytics, error, trace, and log data.

Overview#

Discover is a powerful query builder that lets you run ad-hoc queries across all data types in JustAnalytics -- events, errors, spans, and logs. Build custom tables, aggregate metrics, group by dimensions, and visualize results as charts, all without writing SQL.

Data Sources#

Discover can query four data sources:

| Source | Description | Example Fields | |--------|-------------|----------------| | Events | Analytics events (pageviews, clicks, custom) | url, referrer, browser, country, eventType, properties.* | | Errors | Client and server-side errors | message, type, stack, browser, os, environment, release | | Spans | Distributed trace spans | name, serviceName, duration, statusCode, httpMethod, dbStatement | | Logs | Server-side log entries | message, level, serviceName, traceId, metadata.* |

Select a data source from the dropdown at the top of the Discover page.

Column Picker#

Choose which fields appear in your results table.

Adding Columns#

  1. Click Add Column to open the field picker
  2. Browse available fields organized by category (Basic, HTTP, User, Custom, etc.)
  3. Click a field to add it as a column
  4. Drag columns to reorder
  5. Click the X on a column header to remove it

Available Column Types#

  • Raw fields -- display the field value directly (e.g., url, browser, message)
  • Aggregated fields -- compute an aggregate across rows (e.g., count(), avg(duration))
  • Computed fields -- derived values (e.g., error_rate = errors / total)

Default Columns#

Each data source has sensible defaults:

  • Events: timestamp, eventType, url, browser, country
  • Errors: timestamp, message, type, browser, count
  • Spans: timestamp, name, serviceName, duration, statusCode
  • Logs: timestamp, level, serviceName, message

Filter Builder#

Narrow your results with powerful filter conditions.

Simple Filters#

Click Add Filter and configure:

  1. Field -- the field to filter on
  2. Operator -- comparison type
  3. Value -- the value to compare against

Supported Operators#

| Operator | Description | Example | |----------|-------------|---------| | is | Exact match | browser is Chrome | | is not | Exclude exact match | country is not US | | contains | Substring match | url contains /api | | does not contain | Exclude substring | message does not contain timeout | | starts with | Prefix match | url starts with /dashboard | | ends with | Suffix match | url ends with .json | | greater than | Numeric comparison | duration greater than 1000 | | less than | Numeric comparison | statusCode less than 400 | | in | Match any in list | level in [error, fatal] | | not in | Exclude list | serviceName not in [healthcheck] | | exists | Field is present | traceId exists | | does not exist | Field is absent | userId does not exist |

AND/OR Groups#

Build complex filter logic with nested groups:

WHERE
  (browser is "Chrome" OR browser is "Firefox")
  AND country is "US"
  AND duration greater than 500

Click the AND/OR toggle between filter groups to switch logic. Nest groups by clicking Add Group inside an existing group.

Aggregations#

Transform raw data into summary statistics.

Available Aggregations#

| Function | Description | Applicable To | |----------|-------------|---------------| | count() | Number of matching rows | All data sources | | count_unique(field) | Distinct count of field values | All fields | | avg(field) | Average of numeric field | duration, value, custom metrics | | sum(field) | Sum of numeric field | duration, value, amount | | min(field) | Minimum value | Numeric fields | | max(field) | Maximum value | Numeric fields | | p50(field) | 50th percentile (median) | duration, numeric fields | | p75(field) | 75th percentile | duration, numeric fields | | p95(field) | 95th percentile | duration, numeric fields |

Adding Aggregations#

  1. Click Add Column
  2. Select the aggregation function from the dropdown
  3. If the function takes a field argument (e.g., avg), select the field
  4. The column appears with the aggregation label (e.g., "avg(duration)")

Multiple Aggregations#

Combine multiple aggregations in a single query:

Columns: serviceName, count(), avg(duration), p95(duration), count_unique(traceId)
Group By: serviceName

Group By#

Aggregate results by one or more dimensions.

Adding Group By#

  1. Click Group By and select a field
  2. Results are grouped by unique values of that field
  3. Add multiple group-by fields for nested grouping

Examples#

Errors by browser:

Data Source: Errors
Columns: browser, count(), count_unique(message)
Group By: browser
Order By: count() DESC

Latency by endpoint:

Data Source: Spans
Columns: name, avg(duration), p95(duration), count()
Group By: name
Filter: kind is "server"
Order By: p95(duration) DESC

Pageviews by country and device:

Data Source: Events
Columns: country, deviceType, count()
Group By: country, deviceType
Order By: count() DESC

Order By#

Sort results by any column:

  1. Click a column header to sort ascending
  2. Click again to sort descending
  3. Or use the Order By control to select a column and direction

When using aggregations, you can order by any aggregated column (e.g., sort by p95(duration) descending to find slowest endpoints).

Results Display#

Table View#

The default view shows results as a sortable, paginated table. Each row is clickable to see the full detail (event detail, error detail, span waterfall, or log entry).

  • Pagination: 25, 50, or 100 rows per page
  • Export: download results as CSV or JSON

Chart View#

Toggle to chart view to visualize aggregated results:

| Chart Type | Best For | |------------|----------| | Bar | Comparing categories (errors by browser, latency by service) | | Line | Trends over time (error count per hour, p95 per day) | | Area | Stacked trends (pageviews by country over time) | | Pie | Proportions (traffic by device type) | | Heatmap | Two-dimensional comparison (hour of day vs day of week) |

Time Series Mode#

When you add a time-based group by (e.g., "Group By: timestamp (1 hour)"), results automatically switch to a time-series chart showing the aggregation over time.

Saving Queries#

Save frequently-used queries for quick access:

  1. Build your query (data source, columns, filters, aggregations)
  2. Click Save Query
  3. Enter a name and optional description
  4. The query appears in Saved Queries in the Discover sidebar

Saved queries preserve:

  • Data source selection
  • Column configuration
  • Filters and filter groups
  • Aggregations and group-by
  • Sort order
  • Chart type and visualization settings

Sharing Saved Queries#

Saved queries are scoped to the site. All users with access to the site can see and use saved queries. To share a query externally, use the Copy Link button to generate a URL with the query encoded in parameters.

Drag-and-Drop Exploration#

Discover supports an intuitive drag-and-drop mode for quick exploration:

  1. Toggle Exploration Mode at the top of the page
  2. Available fields appear in a left sidebar panel
  3. Drag fields to the Columns area to add them to the table
  4. Drag fields to the Filters area to filter by them
  5. Drag numeric fields to the Aggregations area to compute statistics
  6. Drag fields to the Group By area to group results

This mode is ideal for ad-hoc investigation when you are not sure what you are looking for.

Common Query Examples#

Top Error Messages (Last 24h)#

Data Source: Errors
Columns: message, count(), count_unique(browser)
Group By: message
Time Range: Last 24 hours
Order By: count() DESC
Limit: 20

Slowest API Endpoints#

Data Source: Spans
Columns: name, avg(duration), p50(duration), p95(duration), count()
Group By: name
Filter: kind is "server" AND duration greater than 100
Order By: p95(duration) DESC

Pageviews by Country (This Week)#

Data Source: Events
Columns: country, count(), count_unique(visitorHash)
Group By: country
Filter: eventType is "pageview"
Time Range: This week
Order By: count() DESC

Error Rate by Release#

Data Source: Errors
Columns: release, count()
Group By: release
Time Range: Last 7 days
Order By: count() DESC
Chart: Bar

Log Volume by Level#

Data Source: Logs
Columns: level, count()
Group By: level, timestamp (1 hour)
Time Range: Last 24 hours
Chart: Stacked Area