Docs
DocumentationQuery ReferenceAPI Reference
Open Console→→
DocumentationQuery ReferenceAPI Reference

Introduction

Query reference overview

APL

IntroductionSample queriesAll features
Functions
Scalar functions
Array functions
Overview
array_concat
array_extract
array_iff
array_index_of
array_length
array_reverse
array_rotate_left
array_rotate_right
array_select_dict
array_shift_left
array_shift_right
array_slice
array_sort_asc
array_sort_desc
array_split
array_sum
bag_has_key
bag_keys
bag_pack
bag_zip
isarray
len
pack_array
pack_dictionary
strcat_array
Conditional functions
Overview
case
iff
Conversion functions
Overview
dynamic_to_json
ensure_field
isbool
toarray
tobool
todatetime
todouble, toreal
todynamic
tohex
toint, tolong
tostring
totimespan
Datetime functions
Overview
ago
datetime_add
datetime_diff
datetime_part
dayofmonth
dayofweek
dayofyear
endofday
endofmonth
endofweek
endofyear
getmonth
getyear
hourofday
monthofyear
now
startofday
startofmonth
startofweek
startofyear
unixtime_microseconds_todatetime
unixtime_milliseconds_todatetime
unixtime_nanoseconds_todatetime
unixtime_seconds_todatetime
week_of_year
GenAI functions
Overview
genai_concat_contents
genai_conversation_turns
genai_cost
genai_estimate_tokens
genai_extract_assistant_response
genai_extract_function_results
genai_extract_system_prompt
genai_extract_tool_calls
genai_extract_user_prompt
genai_get_content_by_index
genai_get_content_by_role
genai_get_pricing
genai_get_role
genai_has_tool_calls
genai_input_cost
genai_is_truncated
genai_message_roles
genai_output_cost
Hash functions
Overview
hash
hash_md5
hash_sha1
hash_sha256
hash_sha512
IP functions
Overview
format_ipv4
format_ipv4_mask
geo_info_from_ip_address
has_any_ipv4
has_any_ipv4_prefix
has_ipv4
has_ipv4_prefix
ipv4_compare
ipv4_is_in_range
ipv4_is_in_any_range
ipv4_is_match
ipv4_is_private
ipv4_netmask_suffix
ipv6_compare
ipv6_is_in_any_range
ipv6_is_in_range
ipv6_is_match
parse_ipv4
parse_ipv4_mask
Mathematical functions
Overview
abs
acos
asin
atan
atan2
cos
cot
degrees
exp
exp2
exp10
gamma
isfinite
isinf
isint
isnan
log
log2
log10
loggamma
max_of
min_of
not
pi
pow
radians
rand
range
round
set_difference
set_has_element
set_intersect
set_union
sign
sin
sqrt
tan
Metadata functions
Overview
column_ifexists
cursor_current
ingestion_time
Pair functions
Overview
find_pair
pair
parse_pair
Rounding functions
Overview
bin
bin_auto
ceiling
floor
String functions
Overview
base64_decode_toarray
base64_decode_tostring
base64_encode_fromarray
base64_encode_tostring
coalesce
countof
countof_regex
extract
extract_all
format_bytes
format_url
gettype
indexof
indexof_regex
isascii
isempty
isnotempty
isnotnull
isnull
parse_bytes
parse_csv
parse_json
parse_path
parse_url
parse_urlquery
quote
regex_quote
replace
replace_regex
replace_string
reverse
split
strcat
strcat_delim
strcmp
string_size
strlen
strrep
strip_ansi_escapes
substring
tolower
totitle
toupper
translate
trim
trim_end
trim_end_regex
trim_regex
trim_space
trim_start
trim_start_regex
unicode_codepoints_from_string
unicode_codepoints_to_string
url_decode
url_encode
SQL functions
Overview
parse_sql
format_sql
Time series functions
Overview
series_abs
series_acos
series_add
series_asin
series_atan
series_ceiling
series_cos
series_cosine_similarity
series_divide
series_dot_product
series_equals
series_exp
series_fft
series_fill_backward
series_fill_const
series_fill_forward
series_fill_linear
series_fir
series_floor
series_greater
series_greater_equals
series_ifft
series_iir
series_less
series_less_equals
series_log
series_magnitude
series_max
series_min
series_multiply
series_not_equals
series_pearson_correlation
series_pow
series_sign
series_sin
series_stats
series_stats_dynamic
series_subtract
series_sum
series_tan
Type functions
Overview
isimei
ismap
isreal
iscc
isstring
isutf8
Aggregation functions
Overview
arg_min
arg_max
avg
avgif
count
countif
dcount
dcountif
histogram
histogramif
make_list
make_list_if
make_set
make_set_if
max
maxif
min
minif
percentile
percentileif
percentiles_array
percentiles_arrayif
phrases
rate
spotlight
stdev
stdevif
sum
sumif
topk
topkif
variance
varianceif
Operators
Tabular operators
Overview
count
distinct
extend
extend-valid
externaldata
getschema
join
limit
lookup
make-series
mv-expand
order
parse
parse-kv
parse-where
project
project-away
project-keep
project-rename
project-reorder
redact
sample
search
sort
summarize
take
top
union
where
Scalar operators
Set membership operators
Overview
in
!in
in~
!in~
Logical
Numerical
String
Reference
Entity names
Map fields
Null values
Scalar data types
Set statement
Special field attributes
Migrate
Splunk SPL
SQL
Sumo Logic

MPL

Language featuresSample queriesMigrate
APL

Axiom Processing Language (APL)

Use APL to query logs, traces, and events with a text-based query language.

Axiom Processing Language (APL) is a text-based query language for logs, traces, and events stored in EventDB. It provides the flexibility to filter, manipulate, and summarize your data exactly the way you need it.

Info

You can't use APL to query metrics. To query metrics, use MPL.

Prerequisites

  • Create an Axiom account.
  • Create a dataset in Axiom where you send your data.

Build an APL query

APL queries consist of the following:

  • Data source: The most common data source is one of your Axiom datasets.
  • Operators: Operators filter, manipulate, and summarize your data.

Delimit operators with the pipe character (|).

A typical APL query has the following structure:

APL
DatasetName
| Operator ...
| Operator ...
  • DatasetName is the name of the dataset you want to query.
  • Operator is an operation you apply to the data.
Info

Apart from Axiom datasets, you can use other data sources:

  • External data sources using the externaldata operator.
  • Specify a data table in the APL query itself using the let statement.

Example query

APLRun in Playground
['github-issue-comment-event']
| extend isBot = actor contains '-bot' or actor contains '[bot]'
| where isBot == true
| summarize count() by bin_auto(_time), actor

The query above uses a dataset called github-issue-comment-event as its data source. It uses the following operators:

  • extend adds a new field isBot to the query results. It sets the values of the new field to true if the values of the actor field in the original dataset contain -bot or [bot].
  • where filters for the values of the isBot field. It only returns rows where the value is true.
  • summarize aggregates the data and produces a chart.

Each operator is separated using the pipe character (|).

Example result

As a result, the query returns a chart and a table. The table counts the different values of the actor field where isBot is true, and the chart displays the distribution of these counts over time.

actorcount_
github-actions[bot]487
sonarqubecloud[bot]208
dependabot[bot]148
vercel[bot]91
codecov[bot]63
openshift-ci[bot]52
coderabbitai[bot]43
netlify[bot]37
Info

The query results are a representation of your data based on your request. The query doesn’t change the original dataset.

Quote dataset and field names

If the name of a dataset or field contains at least one of the following special characters, quote the name in your APL query:

  • Space ( )
  • Dot (.)
  • Dash (-)

To quote the dataset or field in your APL query, enclose its name with quotation marks (' or ") and square brackets ([]). For example, ['my-field'].

For more information on rules about naming and quoting entities, see Entity names.

Common patterns

Handle nested JSON

A common scenario is dealing with fields that contain JSON objects. Use parse_json to access nested data.

APLRun in Playground
['sample-http-logs']
| extend parsed_headers = parse_json(req_duration_ms)
| where isnotempty(method)
| project _time, method, status, geo.city
  • extend parsedField = parse_json(...) converts JSON text into a structured field you can access with dot notation.
  • project _time, method, status, geo.city selects only the fields you need.

Filter and project early

A well-written query runs faster, consumes fewer resources, and gets you answers more efficiently. The two most important principles:

  1. Filter early. Reduce the amount of data as soon as possible.
  2. Project only what you need. Avoid selecting unnecessary fields.

Some datasets are wide, containing hundreds or thousands of fields. When you query these datasets with APL, use project to select only the fields you need. Without project, Axiom retrieves all fields for each event, which slows down queries.

Sub-optimal:

APL
['sample-http-logs']
| sort by _time desc
| take 10

This retrieves all fields for each of the 10 events.

Optimized:

APLRun in Playground
['sample-http-logs']
| project _time, method, status, uri, resp_body_size_bytes
| sort by _time desc
| take 10

By adding project, the query ignores all other fields, minimizing I/O and reducing data sent over the network.

Idea
  • Always use project or project-away after your where filters to reduce data volume. project keeps specified fields, project-away removes them.
  • Place your most restrictive where filters as early as possible in the query.

Virtual fields

Virtual fields let you define new fields based on an APL expression. Instead of pre-processing data before sending it to Axiom, you create these fields on the fly during a query. This provides flexibility for analysis without altering the raw data.

Example: Simple conversion

This example converts a response body size from bytes to kilobytes:

  • Name: resp_size_kb
  • Expression: resp_body_size_bytes / 1024

Example: Categorization

This example uses conditional logic to segment data. Define a virtual field to categorize HTTP responses:

  • Name: response_category
  • Expression: case(status >= 500, "Server Error", status >= 400, "Client Error", status >= 300, "Redirect", "Success")

Now you can run queries like ... | summarize count() by response_category to compare behavior across these groups.

Idea
  • Use virtual fields to avoid sending redundant data. If you can derive a value, you don't need to add it to your raw logs.
  • Use virtual fields to normalize data from different sources. If one service logs request_time and another logs duration, create a virtual field using coalesce(request_time, duration) to standardize them.
  • For very common, expensive transformations queried frequently, consider performing them at ingest time instead.

Factors impacting query performance

  • Catch-all queries: Queries that don't specify fields with project select all fields. Avoid this on high-dimensionality datasets.
  • High cardinality summarize operations: When the by field has very many unique values (like a traceId), the query may produce an enormous number of groups. Axiom has built-in limits to protect against this.
  • Mixed data types: If a field has mixed types (for example, a status code is sometimes a number 200 and sometimes a string "200"), queries can produce unexpected results. For best performance, aim for consistent typing. If you can't avoid mixed types, normalize the data at query time using typecasting functions like tostring() or toint(). For example, | where tostring(status) startswith "2" works reliably on a field with mixed types.

For more information, see Performance.

Platform limits

  • Fields per dataset: A dataset can have a maximum number of fields. While the limit is high, ingesting logs with thousands of fields can cause issues.
  • Data retention: Datasets have a configurable retention period. Data older than this period is automatically deleted.
  • Query rate limits: Axiom imposes rate limits on queries to ensure service stability.

For more information, see Limits.

What’s next

Check out the list of example queries or explore the supported operators and functions:

  • Scalar functions
  • Aggregation functions
  • Tabular operators
  • Scalar operators
Was this page helpful?
Suggest edits on GitHub
PreviousQuery reference overviewNextSample queries
On this page
Build an APL queryExample queryExample resultQuote dataset and field namesCommon patternsHandle nested JSONFilter and project earlyVirtual fieldsFactors impacting query performancePlatform limitsWhat’s next