Skip to main content

Building queries

Foxglove query editor in a Grafana panel

If you've used the Foxglove Search page, the filter builder and granularity control will look familiar — they query the same engine. For Grafana queries, there are additional aggregation and grouping controls.

Selection

Selection retrieves values from Foxglove.

Message path

Select Message Path to read values out of your recordings. Enter a FoxQL path that resolves to a numeric field:

/imu.linear_acceleration.x
/battery.cells[0].voltage
/diagnostics{name=="motor"}.temperature

The Grafana plugin supports numeric queries only. Message paths must end at a numeric leaf. FoxQL functions are not supported.

Device property

Select Device Property and enter a custom property key — for example version. The value must be numeric. Device property queries always group by device; the Group By control is hidden.

Group By

Group By controls how many series the panel draws. It applies to message path selections only.

  • Device — one series per device. This is the default.
  • Device Property — one series per distinct value of the custom property key you enter. Enter the bare key (fleet). Use this to compare fleets, hardware revisions, or sites rather than individual robots.

Aggregation

Aggregation downsamples each series into fixed time bins.

MethodResult per bin
LastMost recent value
FirstEarliest value
Max / MinLargest / smallest value in the bin
SumSum of values
AverageMean of values
MedianMedian of values
P50 / P90 / P95Percentile of values

Leave Aggregation set to None to plot raw values. The Interval input appears only after you choose a method other than None.

Interval is the bin width for the values you're charting. Enter a duration such as 10s, 1m, or 1h. Leave it empty to use the dashboard time range divided by the panel's Max data points (under Query options) — roughly one bin per pixel. That default usually follows the time range as you zoom.

Granularity

Granularity sets the bin width for evaluating filter conditions, before they're applied to the selected series. Same idea as granularity on the Search page.

A filter of /accel.x > 5 with a granularity of 1m keeps selected values that fall in the same one-minute bin as a matching message.

Granularity uses the same duration format as Interval, and defaults to the dashboard time range divided by Max data points.

note

Granularity and Interval are different settings. Interval bins the values you're charting; Granularity bins the filter conditions that decide which values to keep.

Duration format

Interval and Granularity share the same duration format. Valid suffixes are ms, s, m, h, d, w, M, and y. A bare number is seconds — 30 means 30 seconds. Fractional values such as 1.5h are accepted. Compound durations such as 1h30m and spelled-out forms such as 5min or 1hr are rejected. The value must be greater than zero.

Filters

The filter builder narrows a query to the devices, messages, events, and recordings you care about.

A filter is a tree. The top level is an AND or OR group — new groups default to AND. Condition adds a predicate row; Group adds a nested group. Groups nest two levels deep.

Each condition row has a predicate type, a field or message path, an operator, and a value.

Predicate typeMatches on
DeviceDevice ID, name, and custom property values
MessageA message path and the values decoded from it
EventEvent ID, event type, device ID, and custom property values
RecordingRecording ID, key, device, path, and metadata

For Device predicates, enter the field to match:

  • name — the device's name, not its ID. Copy the name from the Devices page.
  • deviceId — the device's ID
  • properties.<key> — a custom property. For example, properties.fleet

Unlike Selection and Group By, custom properties in filters use the properties. prefix.

For Event predicates, enter:

  • eventId — the event's ID
  • eventTypeId — the event type's ID, not its name
  • deviceId — the associated device's ID
  • properties.<key> — a custom property on the event

For Recording predicates, enter:

  • recordingId — the recording's ID
  • key — the recording's key
  • deviceId / deviceName — the associated device's ID or name
  • path — the recording's path
  • metadata.<key> — a recording metadata key

For Message predicates, enter a message path — for example /battery.percentage. Message predicates can filter on strings and booleans as well as numbers.

Filter message paths are not validated as you type. Only the Selection input runs live validation. A typo in a filter path is sent as an empty topic and matches nothing.

Operators

OperatorMeaning
=Equal to
Not equal to
> < Numeric comparison
likePattern match on a string field. Same operator and pattern syntax as like on the Search page
inMatches any value in a comma-separated list, such as robot-1, robot-2

Empty conditions

The plugin drops a filter only when every condition is empty. Emptiness is judged by the value field alone — a row with a value but a blank field or message path is still sent and matches nothing.

Once any condition has a value, the whole filter is applied — including blank sibling rows. In an AND group (the default), a blank sibling matches nothing, so the query returns no data. In an OR group, a blank sibling contributes nothing and populated branches still return data. Remove unused rows with the × at the end of each row.

Example queries

Adapt the paths, property keys, and device names to your fleet.

Chart a numeric topic across the fleet

ControlValue
SelectionMessage Path → /battery.percentage
Group ByDevice
AggregationAverage, Interval 1m
Filter(none)

One series per device, averaged into one-minute bins. Leave Interval empty if you want the bin size to follow the dashboard zoom level.

Limit the chart to named devices

Keep the selection above and add a Device filter:

Predicate typeFieldOperatorValue
Devicenameinrobot-a, robot-b, robot-c

Or drive the list from a Grafana dashboard variable — see Dashboard variables.

Compare fleets instead of individual robots

ControlValue
SelectionMessage Path → /battery.percentage
Group ByDevice Property → fleet
AggregationAverage, Interval 5m

One series per distinct fleet property value. Devices must carry a fleet custom property.

Chart only while a condition holds

ControlValue
SelectionMessage Path → /imu.linear_acceleration.x
Group ByDevice
AggregationMax, Interval 10s
Granularity10s
FilterMessage → /battery.percentage < 20

Charts peak acceleration only while the battery is below 20%. Matching Granularity and Interval keeps filter evaluation and chart bins on the same width.

Chart a device property over time

ControlValue
SelectionDevice Property → version
FilterDevice → properties.fleet = warehouse

Plots the numeric version custom property for devices in the warehouse fleet. Group By is fixed to Device for property selections.

Dashboard variables

Grafana template variables work in every text input of the query editor: message paths, property keys, filter fields, filter values, interval, and granularity.

A common pattern is a device picker. Define a variable named device as a custom variable listing your device names, then use it in a filter:

Predicate typeFieldOperatorValue
Devicenamein${device:csv}

The in operator expects a comma-separated list. Grafana's csv format renders a multi-value variable as exactly that. Prefer ${device:csv} over a bare $device, whose default formatting wraps multiple values in braces.

A message path that contains a $ variable is not validated as you type — the editor skips live checks until Grafana substitutes the value — so a bad expanded path fails at query time.

The plugin can't populate variable options from Foxglove. Build device and topic lists as custom, constant, or textbox variables.

Limitations

  • Series values must be numeric. String and boolean fields can be used in filters, but not plotted.
  • FoxQL functions such as .@rpy and .@degrees are not supported.
  • Filter groups nest at most two levels deep.
  • Queries run against a single Primary Site, set on the data source. To chart data from more than one site, add a data source per site.
  • Filters cannot target sessions. The editor offers Device, Message, Event, and Recording predicates only — Session fields on the Search page are not supported here.
  • The plugin doesn't provide Grafana annotations or variable queries.