Skip to main content
In Axiom, you can use two query languages:
  • Axiom Processing Language (APL) lets you query datasets with events, OTel logs, and OTel traces. For more information, see Introduction to APL.
  • AxQL lets you query OTel metrics. This page explains how to use AxQL.
AxQL is a metric-focused query language that combines the simplicity of APL with the expressive power of PromQL. It enables effective querying, transformation, and aggregation of metric data, supporting diverse observability use cases. It addresses the shortcomings of existing metric query languages, which are either overly complex or too rigidly tied to specific storage formats. If you use PromQL, your existing expressions can be translated to AxQL for quick onboarding and greater flexibility. For more information, see Migrate metrics to Axiom.
Support for OTel metrics is currently in public preview. For more information, see Feature states.

Limitations

The current implementation of AxQL comes with the following limitations:
  • You can only query one dataset in a query.

Concepts

  • Dataset: A group of related metrics.
  • Metric: One-dimensional time series data.
  • Tag: Key-value pair identifying a series.
  • Series: A unique combination of a metric and tag set.

Query structure

A typical AxQL query contains the following:
  1. Source: Defines dataset, metric, and optional time range
  2. Filter: Applies conditions to series via tags
  3. Transformation can be the following:
    • Mapping: Maps the data to a new value.
    • Aggregation: Aggregates the data over a given time to a single value.
    • Grouping: Groups the data by a set of tags, combining overlapping values.
    • Bucketing: A two-dimensional transformation that combines the time and tag dimension.
Example:
k8s:cpu_usage[1h..]
| where namespace == "prod"
| align to 5m using avg
This example queries the k8s dataset’s cpu_usage metric one hour before the current time. It filters results to events where namespace is prod and aggregates events over 5-minute time windows into their average value.

Elements of queries

The following explains each element of an AxQL query. To learn more about the language features of AxQL, see Language features.

Source

Specify the dataset, the metric, and optional time bounds. Syntax:
<dataset>:<metric>[<time range>][ as <alias>]
  • dataset: Name of the dataset.
  • metric: Name of the metric.
  • time range: Optional: The time range of the query. For more information, see Time ranges.
  • alias: Optional: Renames the metric for later use.
Examples:
k8s:cpu_usage[1h..]
k8s:cpu_usage[2h..5m]
k8s:cpu_usage["2025-03-01T13:00:00Z"..+1h] as usage

Filter

Use where or filter to filter series based on tag values. where and filter are identical. Syntax:
| where <tag> <operator> <value>
Available operators:
  • Equality: ==, !=
  • Comparisons: <, <=, >, >=
The value must be one of the supported data types. Example:
| where project == /.*metrics.*/ and code >= 200 and code < 300

Mapping

Transform individual values or series. Available functions:
FunctionDescription
rateComputes the per-second rate of change for a metric.
min(arg)Returns the minimum between the argument and the value.
max(arg)Returns the maximum between the argument and the value.
absReturns the absolute value of each data point.
fill::prevFills missing values using the previous non-null value.
fill::const(arg)Fills missing values with a constant.
interpolate::linearLinear interpolation of missing values.
+, -, *, /Performs the respective mathematical calculation on each value.
>, <, >=, <=Sets the value to 1.0 if the condition is true, 0 otherwise.
Examples for data mappings:
// Calculate rate per second for the metric
| map rate

// Add 5 to each value
| map  + 5

// Fill empty values with the latest value
| map fill::prev

// Fill empty values with zeros
| map fill::const(0)

// Set existing values to 0 if the value is < 0.4. Else set to 1.
| map < 0.4

Aggregation

Use align to aggregate over time windows. Syntax:
| align to <time_window> using <aggregation_function>
Available aggregation functions:
FunctionDescription
avgAverages values in each interval.
sumSums values in each interval.
minTakes the minimum value per interval.
maxTakes the maximum value per interval.
countCounts non-null values per interval.
prom::ratePrometheus style rate
Examples:
// Calculate the average over 5-minute time windows
| align to 5m using avg

// Count the data points in the last hour
| align to 1h using count

Grouping

Use group by to combine series by tags. Syntax:
| group [by <tag1>, <tag2>] using <aggregation_function>
If you don’t specify tags, Axiom aggregates all series into one group. Available aggregation functions:
FunctionDescription
avgAverages values in each interval.
sumSums values in each interval.
minTakes the minimum value per interval.
maxTakes the maximum value per interval.
countCounts non-null values per interval.
Examples:
// Calculate the number of series
| group using count

// Calculate the total number of nodes
| group using sum

// Group data by the `project` and `namespace` tags using the `sum` aggregation
| group by project, namespace using sum

Bucketing

Bucketing is a special case of grouping that combines the time and tag dimensions. Syntax:
| bucket [by <tags>] to <window> using <function>
Available functions:
FunctionDescription
histogramCalculates a histogram over all values in the bucket.
interpolate_histogramInterpolates a histogram from a histogram-type set of series.
Examples:
// Bucket over the `project` and `namespace` tags using the histogram aggregation
| bucket by project, namespace to 5m using histogram

Other operations

Compute

Combine multiple metrics in one query block. Syntax:
{
  <subquery1>;
  <subquery2>;
}
| compute <name> using <operator>
Available operators:
OperatorDescription
+Adds subquery results.
-Subtracts one subquery from another.
*Multiplies subquery results.
/Divides one subquery by another.
minMinimum across result series.
maxMaximum across result series.
avgAverage across result series.
Example:
// Return the average error rate over the past 5 minutes
{
 k8s-metrics-dev:http_requests_total
 | where code >= 400
 | group by method, path using sum;
 k8s-metrics-dev:http_requests_total
 | group by method, path using sum;
}
| compute error_rate using /
| align to 5m using avg

Language features

Data types

  • Strings: "string"
  • Integers: 42
  • Floats: 3.14
  • Booleans: true, false
  • Regex: /.*metrics.*/

Identifier naming rules

Valid identifier names in AxQL follow these rules:
  • Between 1 and 1024 characters long.
  • Allowed characters:
    • Alphanumeric characters (letters and digits)
    • Underscore (_)
    • Dot (.)
Identifier names are case-sensitive.

Quote identifiers

Quote an identifier in your AxQL query if any of the following is true:
  • The identifier name contains an unsupported character.
  • The identifier name is identical to one of the reserved keywords of the APL query language. For example, by or where.
If any of the above is true, you must quote the identifier by enclosing it in backticks (```). For example, my-field. If none of the above is true, you don’t need to quote the identifier in your AxQL query. For example, myfield. In this case, quoting the identifier name is optional.

Time ranges

Syntax:
[<start>..<end>?]
Define time ranges with the following:
  • Start time:: Inclusive beginning of the time range.
  • End time: Optional, exclusive end of the time range. If you don’t specify the end time, Axiom uses the current time.
Separate the start and the end times with ... Time can be defined in one of the following ways:
  • Relative time. The time unit can be one of the following:
    • ms for milliseconds (will be rounded to seconds)
    • s for seconds
    • m for minutes
    • h for hours
    • d for days
    • w for weeks
    • M for months
    • y for years Examples: -1h, +5m
  • Unix epoch timestamp in seconds. For example: 1723982394
  • An RFC3339 timestamp. For example: 2025-03-01T13:00:00Z
Examples:
// One hour ago until the current time
[1h..]

// One hour after a Unix timestamp
[1747077736092..+1h]

// One hour before a Unix timestamp
[-1h..1747077736092]

// One hour before an RFC3339 date
[-1h..2025-03-01T13:00:00Z]
I