How to use the parse operator in KQL: step by step
The parse operator in KQL turns unstructured text — such as log lines or diagnostic messages — into tidy columns that are ready to analyze. Instead of writing complicated regular expressions, you describe the text just as it appears and KQL extracts each field for you. It is one of the fastest ways to split values like user, action, IP or duration out of a single raw column.
Prerequisites
- Access to an environment that runs KQL: a KQL Queryset in Microsoft Fabric (Real-Time Intelligence), Azure Data Explorer, Azure Monitor or Microsoft Sentinel.
- Basic knowledge of KQL queries, especially the
|pipe and theprojectoperator. - No need to load data: we will generate examples with the
datatableoperator.
Step 1: Create sample data
To practice without depending on a real table, we create a few log lines with the datatable operator. Each line is a text message in the key=value format, the classic scenario where parse shines.
datatable(RawLog: string)
[
"User=joao action=login ip=10.0.0.5 durationMs=250",
"User=maria action=logout ip=10.0.0.9 durationMs=87",
"User=rui action=login ip=10.0.0.7 durationMs=143"
]
Run the query. You should see a single column called RawLog with three text lines. That text is exactly what we are going to break into columns.
Step 2: Extract fields with the parse operator
Now we apply parse to split each message into its parts. The idea is simple: before each value you want to capture, you write the fixed literal that appears in the text (for example "User=") followed by the name of the column to create.
datatable(RawLog: string)
[
"User=joao action=login ip=10.0.0.5 durationMs=250",
"User=maria action=logout ip=10.0.0.9 durationMs=87",
"User=rui action=login ip=10.0.0.7 durationMs=143"
]
| parse RawLog with "User=" User " action=" Action " ip=" Ip " durationMs=" DurationMs: long
| project User, Action, Ip, DurationMs
Notice the pattern: the literals "User=", " action=", " ip=" and " durationMs=" act as anchors, and KQL keeps whatever sits between them. At the end we specify DurationMs: long so the duration is read as an integer rather than text. This is simple mode, the default behavior of parse.
Step 3: Skip what you don't need with *
Often the useful field comes after a prefix you don't care about, such as a timestamp. The * character means "skip everything up to the next literal". In the example below we discard the date at the start of each line:
datatable(RawLog: string)
[
"2026-07-15 09:12:03 User=joao durationMs=250",
"2026-07-15 09:12:04 User=maria durationMs=87"
]
| parse RawLog with * "User=" User " durationMs=" DurationMs: long
| project User, DurationMs
The * placed at the start tells parse to ignore everything — the date and time — until it finds "User=". This keeps the pattern short and readable. Note: * can't be used right after a string column, only before a literal.
Step 4: Filter and aggregate the extracted fields
Once extracted, the new fields are ordinary columns and can be combined with where, summarize or extend. For example, to count how many logins there are per user:
datatable(RawLog: string)
[
"User=joao action=login ip=10.0.0.5 durationMs=250",
"User=maria action=logout ip=10.0.0.9 durationMs=87",
"User=joao action=login ip=10.0.0.5 durationMs=98"
]
| parse RawLog with "User=" User " action=" Action " ip=" Ip " durationMs=" DurationMs: long
| where Action == "login"
| summarize Total = count() by User
The result shows each user with their number of logins — information that was "trapped" inside the text and is now easy to measure.
Check the result
Run each query and confirm that the expected columns appear with the correct values. If a column comes back empty (null), it almost always means a literal in the pattern doesn't match the text exactly: check for extra spaces, upper/lowercase, and the key names. When the text format varies from line to line, try parse kind=relaxed, which fills only the fields that don't fit with null instead of failing the whole line.
Conclusion
In just a few minutes you turned raw text into columns ready to analyze — an essential step for handling logs and telemetry in KQL. From here, combine parse with summarize to build metrics, or with render to create charts. One final tip: for more irregular patterns, use parse kind=regex and describe the text with regular expressions. Which fields would you like to extract from your own logs?