Skip to content

StroomQL and Data Sources

Write searches as text with the Stroom Query Language, and choose what they run against, from indexes and views to Stroom's own internal data.

The Stroom Query Language (StroomQL) describes a search as plain text: which data source to read, which events to keep, what to calculate, and how to group, sort and show the result. It is the language of the Query document, and of analytic rules, which are StroomQL queries that Stroom keeps running for you.

The full syntax, with every keyword and its options, is in Stroom Query Language. This page is about what the pieces are for.

A first query

from "Authentication Events"
where Outcome = "Failure"
and EventTime > now() - 1d
select EventTime, UserId, SourceHost

This reads the data source called Authentication Events, keeps the failed log-ons from the last day, and returns three columns.

A query that counts and groups:

// Accounts with the most failed log-ons today
from "Authentication Events"
where Outcome = "Failure"
and EventTime > day()
eval failures = count()
eval hosts = countUnique(SourceHost)
group by UserId
sort by failures desc
having failures > 10
limit 20
select UserId, failures, hosts

Keywords

Every query starts with from. Keywords are not case-sensitive. Field names are.

KeywordWhat it does
fromThe one data source to query. Required, and always first.
whereConditions applied by the data source itself, such as an index. This is the fast way to narrow a search.
evalAssigns the result of an expression to a named variable, for example eval failures = count().
windowGroups rows by a time field and a window size, for example window EventTime by 1d. Add advance to slide the window by a different step.
filterConditions applied after the data has been retrieved. It works on fields the index doesn't hold, but it is slower than where.
group byCollapses rows by one or more columns. A second group by line makes a nested group.
sort bySorts by one or more columns, asc (the default) or desc.
havingConditions applied after grouping, on aggregated values.
limitThe maximum number of rows to return.
selectThe columns to return. as gives a column a display name: select UserId as "User".
showDraws the result with a visualisation, passing columns to its controls.

Stroom checks the order of the keywords. Write them in this order: from, where, eval, window, filter, group by, sort by, having, limit, select, show. You can repeat eval and group by. Put select after limit, and show after select.

Conditions

where, filter and having take conditions joined with and, or and not, with brackets to group them:

where UserId = "jbloggs"
and (Feed = "VPN-EVENTS" or Feed = "PROXY-EVENTS")

The conditions are =, !=, >, >=, <, <=, is null, is not null, between ... and ..., in (...) with a comma-separated list, and in dictionary, which matches the values held in a Dictionary:

where UserId in dictionary "Privileged Accounts"

Fields, quoting and comments

  • A field name with spaces goes inside ${...}, for example ${Event Time}. Without spaces, the braces are optional.
  • A data source name with spaces is quoted: from "Authentication Events".
  • // starts a comment that runs to the end of the line, and /* ... */ comments out a block. Commenting out a line is a quick way to try a query with and without it.

Expressions and functions

eval and select take expressions built from Stroom's expression functions, the same functions dashboard table columns use. They are grouped as aggregate, AI, cast, date, link, logic, lookup, mathematics, parameter, selection, string, type checking, URI and value functions. A few examples:

ExpressionResult
count()The number of rows in the group.
countUnique(SourceHost)The number of distinct values in the group.
floorDay(EventTime)The time rounded down to the start of its day.
upperCase(UserId)The value in upper case.
substringBefore(UserId, '.')The part of the value before the first ..
concat(FirstName, ' ', LastName)The values joined together.
askAi('My Model', concat('Summarise: ', Message))The answer from the named OpenAI Model document. It asks once per value, so use it on a small or grouped set of rows.

Functions nest, and a variable can be reused in a later eval. Every field in the data source is available as a variable without declaring it.

Data sources

A query reads from one data source. What it can return depends on the kind of source:

  • Index: a Lucene index built by an indexing pipeline. This is where most event searches run. Elasticsearch and Solr indexes are queried the same way.
  • View: a document that pairs a data source with an extraction pipeline (see below).
  • Plan B: a Plan B state store.
  • SQL Temporal Store: a SQL Temporal Store, from Stroom 7.14.
  • FloorMap Event Store: the events behind a floor map, from Stroom 7.14.
  • Statistics: a statistics store.
  • Internal data sources: Stroom's own records, which appear at the root of the data source picker rather than in the explorer tree.

The internal data sources are:

Data sourceEach row is
Stream StoreA stream, with its feed, type, status, sizes and processing counts.
Processor TasksA processing task, with its status, node and timings.
AnnotationsAn annotation.
Index ShardsA Lucene index shard, with its size, document count and status.
Plan B ShardsA Plan B shard.
Task ManagerA background task running somewhere in the cluster.
Reference Data Store (This Node Only)Reference data loaded on the node you are connected to.
DualA single row with one field, Dummy. Useful for trying out functions.

Some of these appear only if you have the matching application permission, for example Annotations for the Annotations data source.

Stored and extracted fields

An index can hold a field in two ways. A stored field keeps its value in the index, so a query returns it straight away. A field that is indexed but not stored can be searched with where, but its value has to be fetched from the original event.

Fetching it is called search extraction. For each matching event, Stroom uses the StreamId and EventId held in the index to read the event from the stream store, runs it through an extraction pipeline, and takes the field values from the output. The pipeline usually ends in a SearchResultOutputFilter, or a DynamicSearchResultOutputFilter for dynamic indexes.

Extraction is slower than reading stored fields, but it keeps the index small and means the data is not held twice. A field that isn't indexed at all can still be returned by extraction and narrowed with filter. See Lucene Index for how to choose which fields to store, and the index's default extraction pipeline.

Views

A View document gives a data source a name of its own and fixes the extraction pipeline that goes with it. It has three settings:

  • Data source: the index or other source it reads from.
  • Pipeline: the extraction pipeline used for search extraction.
  • Meta filter: an expression on stream properties, such as feed and stream type.

Querying a view is the same as querying its data source, with its pipeline used for extraction. Views matter most for analytic rules: streaming and table builder rules must read from a view, and the view's meta filter becomes the rule's default processing filter. See Analytic rules.

The query document

A Query document holds one StroomQL query. Its Query tab has:

  • the editor, with code completion: press Ctrl+Space for a list of fields, functions, keywords, dictionaries and data sources that fit where the cursor is;
  • a help pane listing Data Sources, Structure (the keywords), Fields, Annotation Fields, Functions, Visualisations and Dictionaries. Click an item to read about it, and double-click to insert it;
  • a time range, and buttons to run and stop the query;
  • the results, on a Table tab and, when the query uses show, a Visualisation tab.

From the results table you can annotate events, as on a dashboard. From the toolbar, Create Rule turns the query into an analytic rule.

A Dashboard runs the same kind of search, built from components rather than written as text. Use a Query document to explore and to write rules, and a dashboard to put several linked views of the data in front of people.

All documentation