Splunk → SonQL
Splunk → SonQL
Section titled “Splunk → SonQL”A translation guide for Splunk users. Every SonQL command name below was
checked against the shipped ANTLR grammars — Splv1Lexer.g4 / Splv1Parser.g4
(the search1 engine) and SplLexer.g4 / SplParser.g4 (the search2 engine) —
not carried over from a document. Where a command’s behavior is noted, it was
measured against a live instance in Searching logs with SonQL.
The short version. Most of the language is the same words. The traps worth knowing on day one:
head→limit,table→fields,sorttakes abyclause and sorts descending by default (Splunk ascends), and SonQL has two engines that disagree on a handful of commands.
Drop-in — same word, same job
Section titled “Drop-in — same word, same job”| Splunk | SonQL | note |
|---|---|---|
stats count() by service |
stats count() as n by service |
count(), avg(), sum(), min(), max() work; an unknown function errors (no match function) rather than returning an empty column |
eval duration = end - start |
eval duration = end - start |
|
where status = 500 |
where status = 500 |
|
rex field=_raw "…" |
rex field=_raw "…" |
|
fields host source |
fields host source |
also does what Splunk’s table does (below) |
rename src as dst |
rename src as dst |
|
dedup host, source |
dedup host, source |
|
bin _time span=1d |
bin _time span=1d |
spelled bin, same as Splunk |
timechart count() span=1d |
timechart count() span=1d |
|
chart avg(x) by host |
chart avg(x) by host |
same on both since 14 Aug 2026 |
eventstats avg(x) by host |
eventstats avg(x) by host |
|
transaction host maxspan=1m |
transaction host maxspan=1m |
works on both engines (15 Aug 2026); search2 carries the joined member fields as multivalue columns — the added fields are _event_count/_duration on search2, eventcount/duration_second on search1 |
lookup t a OUTPUT b |
lookup t a OUTPUT b |
needs a lookup table to exercise |
inputlookup t / outputlookup t |
same | |
makeresults |
makeresults |
|
makemv delim="," field |
makemv delim="," field |
|
replace "a" with "b" in f |
replace "a" with "b" in f |
|
convert ctime(x) |
convert ctime(x) |
|
iplocation ip |
iplocation ip |
|
accum x |
accum x |
|
addtotals |
addtotals |
|
streamstats count() by host |
streamstats count() by host |
by is required — the engine answers “expected one of ‘by’” |
Renamed, or different syntax
Section titled “Renamed, or different syntax”| Splunk | SonQL | note |
|---|---|---|
head 20 |
limit 20 |
head is not a command — it errors (unknown command [head] … did you mean 'limit'?) |
table a b |
fields a b |
there is no table |
sort -errors |
sort by errors desc |
sort takes a by; defaults to descending, Splunk ascends. A size goes first: sort 10 by errors desc |
tail 20 |
sort by _time desc | limit 20 |
no tail; this returns newest-first |
spath input=x path=y |
jsonpath input=x path=y |
|
xpath … |
xmlpath … |
|
join type=inner host [subsearch] |
join type=inner on=host [search …] |
the subsearch is a bracketed query |
append [subsearch] |
append [search …] |
|
search index=… |
search index=… or search2 index=… |
two engines (below); index= is aliased to repo= in a search predicate |
No direct command — do this instead
Section titled “No direct command — do this instead”Checked against both grammars; none of these Splunk commands exist in SonQL.
| Splunk | SonQL equivalent |
|---|---|
appendcols |
not supported |
union |
not supported |
map |
not supported |
gentimes |
makeresults (generates a row, not a time series) |
xyseries |
not supported |
untable |
not supported |
fillnull |
patch with eval |
delta |
streamstats + eval on the previous value |
trendline |
not supported |
predict |
forecast (search2), or fit / apply |
search2-only commands (no search1 equivalent)
Section titled “search2-only commands (no search1 equivalent)”mstats, msearch, logcluster, rate, fit / apply, forecast,
anomalies, outliers, unnest, topseries, show tag/metric names,
explain.
The traps that bite Splunk users
Section titled “The traps that bite Splunk users”The full detail, with the measurements, is in Searching logs with SonQL. The three worth internalizing before you migrate anything:
- A
.does not break a token by default.NullPointerExceptiondoes not match an event containingjava.lang.NullPointerException. Add.to the index’s word-breaker list (affects new data), or search*NullPointerException. sortis descending by default, the reverse of Splunk, and it is silent — a migrated query returns the reverse order, not an error.top/rareneed a count on search2.top 5 service, nottop service.mvexpandandmvcombinework on both engines.mvexpand limit=<n>works on both, and both spellings are accepted — Splunk’smvexpand <field> limit=<n>and the options-firstmvexpand limit=<n> <field>.mvcombinegroups by the searched repo’s real columns (not the per-event identity fields), so events that differ only in_time/_rawmerge. Pin the engine in anything you save, because the global Default Search Engine setting decides it otherwise.