From KQL
Synopsis
Azure Sentinel ships its normalization logic as ASIM parsers — a KQL function, wrapped in a YAML file that carries it under a ParserQuery or Query field. Conversion reads that export, or a raw KQL reduction query of the form SourceTable | where ... | extend ... | project ..., and returns a native DataStream pipeline.
You can supply either the full ASIM parser YAML export, in which case the query and the parser name are extracted automatically, or the KQL text on its own.
Do not hand-translate a KQL query. Drive the conversion through an AI coding agent connected to the hosted MCP server, as described in Testing.
This Is Not Federated Search
DataStream uses KQL in two unrelated ways, and it is worth being precise about which one this page describes.
Federated Search runs KQL as a query language. You write a query, and DataStream executes it against your data at query time.
Conversion, described here, treats KQL as a source format. The query is translated once, at import, into a DataStream pipeline — and then it is gone. Nothing about KQL survives into pipeline execution; the result is ordinary YAML that runs like any other pipeline.
The two are complementary rather than overlapping. The operators conversion cannot express — summarize, join, sort, and the rest of the aggregation family — are precisely the ones Federated Search exists to run, because they describe work across a set of events rather than work on a single event.
What Converts
Pipe Operators
| KQL operator | DataStream processor | Notes |
|---|---|---|
where | Drop | The condition is negated: events that fail it are dropped. An ASIM where not(disabled) guard is recognized and skipped. |
extend | Varies | Each assignment is lowered by its value expression. See Scalar Functions. |
project | Keep | Computed columns are emitted first, then the field list is kept. |
project-keep | Keep | |
project-away | Remove | A suffix wildcard that matches no known field is kept verbatim, with a warning. |
project-rename | Rename | |
project-reorder | None | A no-op, with a warning. Field order is not significant in a per-event pipeline. |
parse | Dissect or Grok | Dissect for a pure delimiter pattern, Grok when the captures are typed. |
parse-kv | KV | |
lookup | Lookup | Each referenced datatable is registered as inline lookup_content. An unreferenced datatable is pruned. |
union | Group | Each branch becomes a group with its own condition. See the limitations below — the tail semantics differ from KQL. |
invoke | Varies | See ASIM Helpers. |
Scalar Functions
| KQL function | DataStream processor |
|---|---|
Literals, bare field references, strcat, strcat_delim, concat, column_ifexists | Set |
coalesce | Coalesce |
case, iif, iff | Case |
Arithmetic (+, -, *, /, %) | Math |
tostring, toint, tolong, todouble, toreal, todecimal, tobool, toboolean, todatetime, and the int(), long(), real(), double() literal casts | Convert |
unixtime_seconds_todatetime, unixtime_milliseconds_todatetime | Date |
toupper | Uppercase |
tolower | Lowercase |
trim, trim_start, trim_end | Trim |
replace_string, replace_regex | Gsub |
extract | Grok |
split | Split |
strcat_array | Join |
array_slice | Slice |
Array indexing, such as arr[0] | Select |
substring | Substring |
todynamic, toobject, parse_json | JSON |
bag_pack, pack, pack_dictionary | Bag Pack |
base64_encode_tostring, encode_base64, base64_encodestring | Base64 Encode |
base64_decode_tostring, decode_base64, base64_decodestring | Base64 Decode |
parse_url, parse_urlquery | URI Parts |
url_decode | URL Decode |
parse_ipv4, parse_ipv6, ipv4_is_private | IP Type |
hash_sha256, hash_md5, hash_sha1 | Fingerprint |
parse_user_agent, user_agent | User Agent |
The totimespan(F)/time(1s) duration-ratio idiom | Duration |
Any other function becomes a Comment carrying the original KQL expression, with a warning.
ASIM Helpers
| KQL construct | DataStream processor |
|---|---|
invoke _ASIM_ResolveNetworkProtocol(...) | Network Protocol |
invoke _ASIM_ResolveDvcFQDN(...) and its Src, Dst, and Target variants | FQDN |
_ASIM_GetUsernameType(...) | Username Type |
A KQL function defined in the query and then invoked — the ASIM ItemParser idiom — is inlined directly into the pipeline. Any other invoked helper becomes a comment, with a warning.
A literal EventSchema assignment is recognized: the converter prepends a Set writing the corresponding ASIM table name to _vmetric.table.
Conditions
Conditions become DataStream's native if expression language.
| KQL | Native if |
|---|---|
and, or | &&, || |
==, !=, <, <=, >, >= | Unchanged |
contains, contains_cs, icontains | contains() |
startswith, hasprefix (and their _cs forms) | startsWith() |
endswith, hassuffix (and their _cs forms) | endsWith() |
matchesregex | matches() |
in, !in | Membership test |
isempty, isnotempty, isnull, isnotnull, not() | Equivalent native forms |
=~, !~ | A case-insensitive comparison, exactly equivalent |
has, has_cs, has_any, has_all and their negations | matches() against a word-boundary regex — an approximation. See the limitations below. |
What Does Not Convert
These operators describe work across a set of events. A DataStream pipeline processes one event at a time, so they have no per-event form:
summarize, distinct, join, sort, order, top, take, limit, mv-expand, mv-apply
They do not abort the conversion. Each one becomes a Comment carrying the original KQL, a warning is added to the pipeline's description, and the remaining stages still convert. What you get back is a partial pipeline that you finish by hand — not an error.
For work that genuinely needs aggregation or joins across events, use Federated Search, which runs KQL as a query rather than converting it.
Known Limitations
A successful conversion can be silently incomplete. The KQL parser recovers from syntax it cannot handle rather than failing outright, so an unparseable construct yields a partial pipeline plus a warning — not an error. Always read the warnings in the converted pipeline's description before trusting the result.
union tail semantics differ. Events that match no union branch continue into the shared tail processors, whereas KQL's union would omit them. The converter emits a warning where this applies.
Hash values change. hash_sha256, hash_md5, and hash_sha1 become a Fingerprint, which produces a deterministic digest — but not the same value KQL produces. Do not rely on migrated hashes matching historical ones.
IP parsing is approximated. parse_ipv4, parse_ipv6, and ipv4_is_private become an IP Type, which is close but not identical.
The has family is approximated. It lowers to a case-insensitive word-boundary regex. KQL's exact term tokenization is not reproduced.
Watchlist-backed let bindings cannot be converted. An expression referencing one is skipped entirely, with a warning.
Detection rules are out of scope. This converter is for normalization parsers and reduction queries. A Sentinel analytics rule is not converted into a pipeline — it is registered, unchanged, with the Smart Engine processor, which uses it to decide what to forward to the SIEM.
Examples
A Reduction Query
A KQL query filtering, computing a field, and narrowing the output columns... | |
| |
An ASIM Helper
An ASIM parser resolving a network protocol through the standard helper... | |
The helper has a native equivalent, so it converts directly... | |
An Aggregation
A | |
The conversion continues. The operator is preserved as a comment carrying the original KQL, and a warning names it in the pipeline description... | |