Log Search Query Syntax: AND, OR, NOT, and Quoted Phrases
SimpleLogSearch speaks one small query language: AND, OR, NOT and double-quoted phrases — the entire syntax. Every rule below runs against a 24-line sample application log, so you can see exactly which lines each query returns.
The basic idea: terms and phrases
Two blocks build every query:
- Term — a single token with no whitespace:
error,MID,192.168.1.1. - Phrase — anything in double quotes, spaces included:
"status=500","MID 123456".
Both are tested per line as a case-insensitive substring — grep-style: no word boundaries, no wildcards, no field syntax.
The three operators
AND keeps lines matching every branch; OR keeps at least one; NOT removes any line its argument appears on. Six examples against the 24-line sample log:
| Operator | Example query | What it matches in the sample log |
|---|---|---|
AND | "status=500" AND payments | Lines carrying both the failed request and the payments dependency — the "what broke, and why" pair. |
error AND timeout | Any line mentioning both words; order and distance do not matter. | |
OR | "status=200" OR "status=500" | Every healthy or failed request line: 6, 11 and 15. |
"svc=api" OR "svc=db" | All API-service and database-service lines — a broad first pass. | |
NOT | NOT "192.168.1.1" | Lines not mentioning that IP — 17 of the 24 sample lines; line 10 is excluded too (its 192.168.1.10 still contains it). |
"svc=db" NOT vacuum | Database lines minus routine maintenance noise. |
Operator tokens match as whole words in any casing — and, And and AND parse identically; a bare and is therefore always an operator (mistake five).
Precedence and parentheses
Without parentheses, NOT binds tightest, then AND, then OR — so a OR b AND c means a OR (b AND c). Parentheses override completely.
The engine's canonical example, worked step by step against the 24-line sample log:
"MID 123456" and "MID 123654" not "192.168.1.1"
Step 1 — apply precedence. No parentheses: not claims only its immediate argument, and the and chain evaluates left to right:
("MID 123456" AND "MID 123654") AND NOT "192.168.1.1"
Step 2 — the inner AND. The line must contain both IDs; exactly two qualify:
- Line 7 —
… WARN svc=api MID 123456 and MID 123654 correlated by trace=t-77 - Line 20 —
… ERROR svc=db MID 123456 MID 123654 replication lag 52s host=db-2 via 192.168.1.1
Step 3 — the NOT exclusion. NOT filters whole lines, so line 20 — which ends with via 192.168.1.1 — is removed even though that IP sits outside the matched phrases. Final result: line 7, the one place both IDs appear without the noisy address.
Key takeaway: an exclusion applies to the entire line, not just to what the AND matched — appending not "noise" removes every line where it appears.
When no line contains every term
AND matches only lines carrying all of its terms. If no line does, SimpleLogSearch falls back to the lines matching any of the query's positive terms — every NOT exclusion still applies — and says so in the status row. On a web access log, GET AND POST NOT healthz has no single line with both methods, so it returns the GET and POST lines without healthz. The fallback only ever fills an empty result: when some line does contain every term, that is what you get.
Implicit AND
Two operands side by side are ANDed — whitespace is itself the operator. Unquoted MID 123456 means term MID AND term 123456: any line containing both, in either order. Quoted "MID 123456" demands the exact adjacent sequence; on messier files the two can diverge, so quote whenever you mean the literal sequence.
Case-insensitive matching — and one substring caveat
Every test is case-insensitive: mid 123456, MID 123456 and "Status=200" all match. The caveat: no word boundaries, so "192.168.1.1" also matches a line containing only 192.168.1.10 (sample line 10). The fix — quote one extra character of context, usually a trailing space: "192.168.1.1 " narrows the sample log to line 16 alone; the same trick disambiguates any prefix collision.
Twelve queries, annotated
Each row ran against the same 24-line sample log; line numbers are original, 1-based.
| # | Query | What it matches |
|---|---|---|
| 1 | "MID 123456" | The exact phrase — lines 2, 4, 7, 8, 16, 20 and 23. |
| 2 | MID 123456 | The unquoted, implicit-AND spelling of row 1 — the same seven lines here. |
| 3 | "MID 123456" and "MID 123654" | Only lines carrying both correlation IDs: 7 and 20. |
| 4 | "MID 123456" and "MID 123654" not "192.168.1.1" | The canonical query — row 3 minus the IP: line 7 alone (worked above). |
| 5 | not "192.168.1.1" | All lines without that substring: 17 of 24 (line 10's .10 address still contains it). |
| 6 | "status=200" OR "status=500" | The healthy and failed request lines: 6, 11 and 15. |
| 7 | "svc=db" AND ("deadlock" OR "replication") | Database lines about the two serious failure modes: 5 (deadlock), 20 (replication lag). |
| 8 | ("svc=api" OR "svc=db") AND error | ERROR-level lines from either service: 5, 12, 20, 23 — parentheses change the answer versus "svc=api" OR ("svc=db" AND error). |
| 9 | "192.168.1.1" | The substring trap: lines 1, 4, 8, 16, 17, 20 — plus line 10 (its .10 address still contains it). |
| 10 | "192.168.1.1 " | Same phrase with a trailing space: only line 16. |
| 11 | "svc=api" "status=200" | Implicit AND of two phrases — successful API lines: 6 and 15. |
| 12 | "and" | The quoted operator as literal text: line 7, whose message contains the word "and". |
Five common mistakes
- Missing quotes on a multi-word phrase.
timeout afterwithout quotes is two terms ANDed; only"timeout after"demands the exact sequence. - Believing operators must be typed in one case. They are whole-token matches in any casing:
and,AndandANDparse identically (same for OR/NOT). - Empty phrases.
""is a rejected query ("empty phrase"), not a zero-result search — nothing for it to match. - Dangling operators. Every
NOT,ANDandORneeds a term on each side:"svc=api" ANDandOR ORare rejected with "missing a search term". - Searching for the literal word "and" unquoted. A bare operator token is always an operator — quote it:
"and"matches the word itself (row 12).
That is the whole language: three operators, one quoting rule, one precedence chain. Load a sample log from the home page and run every query on this page — the result window keeps original line numbers. For the investigation workflow, see the How-To Guide; for privacy questions, the FAQ.