Test grok patterns against your log lines, get fix suggestions when they fail to match, and convert grok to regex or Logstash config. Free, in-browser.
Writing a Grok pattern is a tight loop: change one token, see whether the line still parses, change it back. Doing that loop inside Logstash means restarting a pipeline for every attempt. This tool runs the loop in the browser — paste real log lines, type a pattern, and the matched fields, the failure position and the fix suggestions all update as you type. Nothing is uploaded; the pattern is compiled to a JavaScript regular expression and executed on the page, so you can paste production log excerpts without them leaving your machine.
When the pattern is right, the output panel hands you the same expression as a Logstash filter block, an Elasticsearch or OpenSearch ingest pipeline, or a plain regular expression in JavaScript or PCRE form.
| Form | Meaning |
|---|---|
%{PATTERN} | Match this pattern, do not capture it into a field |
%{PATTERN:field} | Match and capture into a field of that name |
%{PATTERN:field:int} | Capture and convert to an integer |
%{PATTERN:field:float} | Capture and convert to a floating-point number |
Everything outside a %{…} token is literal — and literal here means regex, not plain text. That single fact causes most first-attempt failures. A log line containing [ERROR] needs \[%{LOGLEVEL:level}\] in the pattern, because unescaped square brackets are a character class. The same applies to ( ) { } . * + ? | ^ $. When a literal fails to match, the debugger checks specifically for unescaped brackets and parentheses and offers the escaped version as a one-click fix.
The type suffix is worth using consistently. %{NUMBER:status} stores 200 as the string “200”; %{NUMBER:status:int} stores it as a number you can aggregate, range-query and graph. The tool applies the same coercion when it displays extracted fields, so a value shown without quotes in the results table is one your log platform will index as numeric.
Two shortcuts get you most of the way before you type a token.
The preset selector loads a pattern and a matching sample log together. There are twelve, covering the formats people actually parse: nginx access, Apache combined (using the built-in %{COMBINEDAPACHELOG}), BSD syslog (RFC 3164), SSH authentication failures from auth.log, Cisco ASA connection messages, a generic ISO-8601 application log, Java Log4j/Logback lines, AWS ELB access logs, HAProxy HTTP logs, PostgreSQL server logs, IIS W3C extended logs, and the Docker/containerd line prefix. Loading a preset and then editing it against your own line is usually faster than starting clean, because the hard part — the timestamp — is already correct.
The suggest button takes the first non-empty line of your log box and generates a pattern for it, walking the line left to right and emitting a token wherever it recognises a known structure. It tries the most specific recognisers first — ISO-8601 timestamps, Apache dates, syslog timestamps, URIs, email addresses, UUIDs, MACs, IP addresses, quoted strings, log levels, paths, then numbers and words — and escapes everything else as a literal. If the tail of the result degenerates into a long run of %{WORD} and %{NUMBER} tokens, it collapses that tail into %{GREEDYDATA:message}. Treat the output as a draft: it names fields generically (word2, num3) and it will happily match a value that is only coincidentally shaped like a number.
Seventy-two named patterns ship with the tool, taken from the standard logstash-patterns-core dictionary and adapted to compile under a JavaScript regex engine. They are grouped and searchable in the side panel, and clicking one appends it to your pattern. The distribution tells you where the complexity lives:
| Category | Count | Examples |
|---|---|---|
| Dates & times | 23 | TIMESTAMP_ISO8601, SYSLOGTIMESTAMP, HTTPDATE, DATESTAMP_RFC2822, UNIXTIMESTAMP |
| Basic | 13 | WORD, NOTSPACE, DATA, GREEDYDATA, QUOTEDSTRING, LOGLEVEL, UUID |
| Network | 10 | IP, IPV4, IPV6, HOSTNAME, IPORHOST, HOSTPORT, MAC |
| Paths & URLs | 10 | UNIXPATH, WINPATH, URI, URIPATH, URIPARAM |
| Syslog | 7 | SYSLOGBASE, SYSLOGPROG, SYSLOGHOST, SYSLOG5424PRI |
| Numbers | 6 | INT, NUMBER, BASE10NUM, BASE16NUM, POSINT |
| HTTP / web | 3 | COMMONAPACHELOG, COMBINEDAPACHELOG, HTTPDUSER |
Patterns compose: %{IP} is defined as %{IPV6}|%{IPV4}, and %{COMBINEDAPACHELOG} is %{COMMONAPACHELOG} plus a referrer and user agent. The compiler expands these references recursively, so using a high-level pattern costs you nothing and reads far better than the expansion.
The tool opens with this pattern:
%{TIMESTAMP_ISO8601:timestamp} \[%{LOGLEVEL:level}\] %{NOTSPACE:logger} - %{GREEDYDATA:message}
and this line:
2026-01-15T10:30:45.123Z [ERROR] com.example.PaymentService - Failed to process payment for order 12345: connection timeout
Reading it token by token: TIMESTAMP_ISO8601 takes the leading timestamp including the fractional seconds and the Z; the escaped brackets consume the literal [ and ] around ERROR, which LOGLEVEL matches (it accepts ERROR, ERR, Error and the rest of the usual spellings, in several cases); NOTSPACE takes the dotted logger name because it runs to the next space; the literal - separates; and GREEDYDATA takes the remainder of the line. Four fields, and the results table shows each captured value with its position highlighted in the source line.
Now the useful part: break it. Change %{LOGLEVEL:level} to %{WORD:level} and it still matches — WORD is looser but wide enough. Change it to %{NUMBER:level} and the line fails; the debugger reports that %{NUMBER} does not match ERROR] com.example… at that position, names the patterns that would match there, and offers each as a one-click replacement.
%{GREEDYDATA} is .* and %{DATA} is .*? — greedy and lazy. That difference is the single most common cause of a pattern that “works” but captures the wrong text.
Put GREEDYDATA anywhere but the end and it first swallows the entire line, then backtracks only as far as it must to let the rest of the pattern match. Because it gives back as little as possible, every field after it gets the last candidate on the line rather than the first. A pattern like %{GREEDYDATA:prefix} %{NUMBER:id} against a line containing several numbers captures the final one, silently, with no error to tell you. Two consequences follow:
%{DATA} between known anchors, and %{GREEDYDATA} only at the end. Lazy matching between two literals you can actually see in the line does what you meant.The other side of the same coin: a Grok pattern is not anchored. If your pattern matches starting at character 40, the tool tells you so and says how many leading characters were skipped, because an unanchored pattern that quietly matches part of a line is worse than one that fails loudly. It also tells you when a match leaves trailing characters uncaptured, and offers to append %{GREEDYDATA:rest} — the correct trailing use.
When a line does not match, the tool does not just say “no match”. It recompiles your pattern one segment at a time and finds the longest prefix that still matches, which pinpoints the exact character where parsing stopped. From there it produces targeted suggestions:
\s+.%{DATA:value} (lazy) or %{NOTSPACE:value} (to the next space).%{TIMSTAMP_ISO8601} gets a “did you mean” list computed by edit distance against the dictionary, each with a one-click fix.The panel analyses the first few problem lines rather than all of them, which is the right trade: log lines that fail usually fail the same way, and fixing the first fixes the rest.
The custom patterns box takes the same format as a Logstash patterns file — one definition per line, name then a space then the regex source, with # for comments:
ORDERID ORD-\d{6}
Definitions may reference other patterns with %{…}, and a custom name overrides a built-in of the same name. When you export, custom definitions travel with the pattern: the Logstash output emits them as a pattern_definitions block and the ingest-pipeline output as a pattern_definitions object inside the grok processor, so what you copy is complete.
Five output formats are available: the raw Grok pattern; a JavaScript regular expression; a PCRE-style expression with named groups for Python, grep -P or Go; a complete Logstash filter { grok { … } } block with quoting and backslashes escaped for the config file; and an Elasticsearch/OpenSearch ingest pipeline as JSON. The pattern itself is also shareable — pattern and log are encoded into the page URL (the log only up to a couple of thousand characters), so a link reproduces the exact state you were debugging.
The caveat: this tool compiles to JavaScript’s regex engine, and Logstash uses Oniguruma. The dictionary here has atomic groups rewritten as ordinary non-capturing groups to compile at all. Matching semantics are the same for every pattern in normal use — what differs is backtracking behaviour on pathological input, so a pattern that is merely slow here can be slower in production, and a catastrophic-backtracking risk is not something this tool will surface for you. Validate the fields, then load-test the pipeline separately. The other structural difference is that Grok in Logstash tries a list of patterns and applies further filters afterwards; here you test one pattern against many lines, which is the right granularity for getting a single pattern correct but is not a substitute for testing the whole pipeline.
Grok is the de facto standard language for parsing unstructured logs into structured, searchable data. Originally built for Logstash, it's now supported by Elasticsearch ingest pipelines, OpenSearch, Graylog, Fluentd, and most SIEM platforms.
A grok expression combines pattern names and field names: %{IP:client_ip} means "match an IP address here, and store it in a field called client_ip." Under the hood, every grok pattern expands into a regular expression — grok just makes those expressions reusable, readable, and named.
The power comes from composition. The built-in %{COMBINEDAPACHELOG} pattern expands into a regex over 400 characters long, built from smaller patterns like %{IPORHOST}, %{HTTPDATE}, and %{QUOTEDSTRING}. You write one token; grok handles the complexity.
Grok and regular expressions are not competitors — grok is regex, with a naming and reuse layer on top.
Use grok when:
%{TIMESTAMP_ISO8601:time} vs. 60 characters of date regex)Use plain regex when:
Performance note: because grok compiles to regex, all regex performance rules apply. Anchor patterns at the start of the line, avoid %{GREEDYDATA} mid-pattern, and prefer specific patterns (%{IP}) over generic ones (%{NOTSPACE}) — failed matches on generic patterns cause expensive backtracking.
Grok failures are frustrating because the error is always the same — _grokparsefailure — with no hint about where the pattern broke. The systematic approach:
Start with the timestamp. Most patterns fail in the first 30 characters because the timestamp format doesn't match. %{TIMESTAMP_ISO8601} will not match Jan 15 10:30:45 (that's %{SYSLOGTIMESTAMP}).
Build incrementally. Match the first element, append %{GREEDYDATA:rest}, and verify. Then move one element from rest into your pattern at a time. The moment matching breaks, you've found the problem element.
Watch the whitespace. A single literal space in your pattern requires exactly one space in the log. Logs aligned with multiple spaces or tabs need \s+ instead.
Escape special characters. Square brackets, parentheses, and pipes are regex syntax. To match [ERROR] literally, write \[%{LOGLEVEL:level}\].
This tool's debugger automates all four steps: it shows exactly where matching stopped and proposes one-click fixes for the failing element.
A grok pattern is a named, reusable regular expression used to parse unstructured log lines into structured fields. Instead of writing raw regex like (?:[+-]?(?:[0-9]+)), you write %{INT:status_code} — the pattern name (INT) describes what to match and the field name (status_code) describes where to store it. Grok is the standard parsing language in Logstash, Elasticsearch ingest pipelines, OpenSearch, Graylog, and Fluentd.
Grok is a layer on top of regex, not a replacement. Every grok pattern compiles down to a regular expression. The differences: 1) Grok gives you 100+ pre-built, tested patterns (%{IP}, %{TIMESTAMP_ISO8601}) so you don't reinvent them. 2) Grok pairs each match with a named output field, so parsing and field mapping happen in one step. 3) Grok patterns are far more readable — %{COMBINEDAPACHELOG} vs. a 400-character regex. Use plain regex for one-off matching in code; use grok when parsing logs into structured data for a SIEM or log platform.
Work left to right: grok fails at the first non-matching element, and everything after it never gets evaluated. This tool's debugger automates that process — it matches your pattern segment by segment, shows exactly where matching stopped (green = matched, red = unmatched), and suggests replacements for the failing element. The most common causes are: timestamp format mismatches, single literal spaces where the log has multiple spaces or tabs, and unescaped special characters like [ ] ( ).
GREEDYDATA matches everything to the end of the line (regex .*). It's perfect as the last element of a pattern to capture "the rest of the message." Avoid using it in the middle of patterns — the regex engine will match to the end of the line, then backtrack character by character to satisfy the rest of your pattern. On non-matching lines this causes catastrophic backtracking that can spike Logstash CPU. Use %{DATA} (non-greedy) between known anchors instead.
Paste or build your grok pattern in this tool, then open the Export panel and choose "Regex (JavaScript)" or "Regex (PCRE)". The tool recursively expands every %{PATTERN:field} reference into its underlying regular expression with named capture groups. This is useful when you need the same parsing logic in application code, grep -P, or a tool that doesn't support grok.
Yes. Open "Custom Patterns" below the pattern input and define them one per line, exactly like a Logstash patterns_dir file: ORDERID ORD-[0-9]{6}. You can then reference %{ORDERID:order_id} in your main pattern. The Logstash and ingest pipeline exports automatically include your custom definitions in the generated config.
For the standard combined format, use the built-in %{COMBINEDAPACHELOG} pattern (works for both Apache and nginx default formats). It extracts clientip, timestamp, verb, request, response, bytes, referrer, and agent fields. This tool includes presets for nginx, Apache, HAProxy, and IIS — click one to load the pattern with a sample log line.
Start with %{SYSLOGTIMESTAMP:timestamp} %{SYSLOGHOST:hostname} %{PROG:program}(?:[%{POSINT:pid:int}])?: %{GREEDYDATA:message} for traditional RFC 3164 syslog. This extracts the timestamp, host, program name, optional PID, and message. For specific applications (sshd, CRON, kernel), parse the message field with a second grok pattern. The Syslog and SSH presets in this tool give you working starting points.
Dissect splits strings by fixed delimiters with no regex involved, making it roughly 4x faster than grok. Use dissect when your log format is rigid (every line has identical structure, like CSV or tab-separated). Use grok when the format varies — optional fields, variable whitespace, or different message types in the same stream. A common production pattern is dissect first for the fixed prefix (timestamp, host), then grok only the variable message part.
Add :int or :float as a third component: %{NUMBER:response_time:float} or %{INT:status_code:int}. Without this, every captured field is a string — which means your log platform can't do range queries, sums, or averages on it. This matters for response times, byte counts, and status codes you'll want to aggregate in dashboards.
Test regular expressions online with live matching, pattern explanations, and a built-in regex library. Supports JavaScript, Python, and Go.
Build detection queries for Splunk SPL, Elastic KQL, and Microsoft Sentinel. Includes presets for authentication, network, malware, and threat hunting with MITRE ATT&CK mappings.
Extract indicators of compromise (IOCs) like IPs, domains, URLs, hashes, and emails from text for threat intelligence