Searching logs

You rarely need more than a word, a field filter and a time range. This page walks through the Logs page from top to bottom and then covers everything the search box understands.

The Logs page

From top to bottom:

  • Query editor — type LogsQL, press Enter to search (Shift+Enter for a new line). While it is empty you see Quick start examples; the ? opens a syntax popover. Clicks in the fields panel and in a row's detail edit this query.
  • Time range — presets 15m / 1h / 24h / 7d and a custom range with second precision.
  • Histogram — volume over the selected range. The status line below it shows the number of loaded lines, your retention and the volume used this month.
  • Fields panel (left) — stream fields first, then every other field seen in the current result, with values and counts. Click a value to filter.
  • Result list — newest first, virtualized, loads more as you scroll. Click a line for the detail view.
  • Toolbar — download, display settings (columns, group by, page size) and Live tail.

Words and phrases

Type a word and you get every line that contains it, in the message or in any field. Words match case-insensitively and as whole words.

  • timeoutEvery line containing the word timeout.
  • timeout paymentsBoth words, anywhere in the line (an implicit AND).
  • "upstream timeout"The exact phrase, in that order.
  • err*Prefix match: error, errno, errors …
  • *Everything in the time range.

Field filters

Every JSON key you send becomes a field. Filter on it with field:value. Note the colon — service=api is not LogsQL; the search box suggests the corrected form.

  • level:errorField level contains the word error.
  • service:=apiField service equals exactly api (case-sensitive).
  • service:="booking svc"Exact match with spaces or special characters — quote the value.
  • host:node-*Prefix match on a field.
  • path:~"^/api/v[12]/"Regular expression on a field.
  • user_id:*Lines that have the field at all, whatever its value.
  • _msg:checkoutSearch only the message, not the other fields.
  • kubernetes.namespace_name:=paymentsNested keys are dotted names.

The fields panel writes into the query

There is exactly one thing being searched: the query in the editor. The fields panel and the row detail are shortcuts that edit it, so what you see in the box is always what runs. The rules:

  • Clicking a value adds field:=value to the query. A second value of the same field turns it into field:in(a, b) — an OR. Clicking a ticked value removes it again.
  • Terms on different fields narrow each other (AND), and any free text you typed stays as it is.
  • The panel marks the values the query currently selects, so you always see what is active — and you can just as well edit or delete the terms by hand.
  • The panel computes the values of a field without that field's own terms, so the other values stay visible for widening the selection.

Excluding and combining in the query

  • -level:debugEverything except debug lines.
  • level:error OR level:warnEither one.
  • service:=api AND NOT path:/healthExplicit AND / NOT.
  • (level:error OR level:warn) team:=paymentsParentheses group conditions.
  • level:in(error, fatal, critical)One of several values.
  • _stream:{service="api",env="prod"}The fastest filter: an exact stream.

Numbers and ranges

Numeric fields (durations, sizes, status codes) can be compared and ranged.

  • duration_ms:>500Greater than.
  • status:>=500 status:<600Between — two filters combine with AND.
  • status:range(500, 599)Same, as a range.
  • bytes:>1MiBUnits are understood: KiB, MiB, GiB, and durations like 1.5s or 200ms.
  • ip:ipv4_range(10.0.0.0/8)IP ranges.

Time ranges

The presets 15m / 1h / 24h / 7d set the window relative to now. Custom rangeopens a calendar with time fields down to the second — the usual move when an alert names a moment. Your plan's retention is the outer limit. Results are always newest first.

  • _time:5mOnly the last 5 minutes, regardless of the preset.
  • _time:[2026-09-01, 2026-09-02]An explicit day range (UTC) inside the query.
Note: Paging is by offset: the list loads one page (100 lines by default, adjustable in Display) and fetches the next page as you scroll. The status line counts loaded lines and says when everything is loaded. Past a few thousand lines you are usually better off narrowing the query.

Row detail and context

Click a line to expand it. The detail shows every field of that entry with two actions per field:

  • Filter icon — appends field:=value to the query. Clicking a service name in the list does the same for service.
  • Copy JSON — the raw entry.

Context around a line

The context buttons (±1s, ±10s, ±1m, ±5m) replace the current search with the same stream — _stream:{...} of that line — and a time window around it. The anchor line stays highlighted, so you can read what happened right before and after without knowing the query for it. Use the browser's back button or the presets to return.

Live tail

Live tail streams new lines that match your query as they arrive. It runs about six seconds behind real time so batching agents can deliver in order, follows event timestamps, and keeps the newest 500 lines in view. A line whose timestamp is in the past — a backfill, a replayed file — appears in search, not in the tail.

Display, grouping, download

  • Display settings (sliders icon): page size 50/100/200/500, which columns to show, extra fields rendered as key=value next to the message, and group by a field — the list then gets a header row per value, handy for service or host.
  • These settings are yours and are remembered in the browser; they are not part of a shared link.
  • Download exports the lines currently loaded as NDJSON or CSV — narrow the query first, then load what you need.
  • Plain-text entries (from /v1/ingest/text) keep the whole original line as the message; multi-line stack traces are shown as one block.

Sharing a search

The search state lives in the URL, so a reload keeps it and a copied link reproduces it for a colleague:

ParameterMeaning
qthe free-text query
rangea preset (15m, 24h, 7d); omitted for the default 1h
from / toa custom range as ISO timestamps; used instead of range
example
https://app.uptimeeye.com/<org>/logs?q=timeout+service%3A%3Dcheckout+level%3A%3Derror&range=24h

Preset ranges stay relative (“the last 24 h” when the link is opened); a custom range is absolute — the right behaviour for incident links.

Where fields come from

There is no schema. Whatever JSON you send is stored as-is: {"_msg":"…","service":"api","env":"prod","user_id":"u_42"} gives you the fields service, env and user_id. Three fields are special:

  • _msg — the message. Agents map their message key with _msg_field.
  • _time — the event time; defaults to the time of ingestion.
  • _stream — the stream labels chosen with _stream_fields (for example service,env). Filtering on stream fields is the fastest kind of filter, so pick fields with few distinct values.

How to shape fields on the way in is covered in Ingesting logs.

Aggregations with pipes

The search box accepts the full LogsQL language, including pipes. The Logs page is built for lines, so aggregations come back as rows whose fields are the computed values — open a row to see them, or download the result.

  • level:error | stats by (service) count()Errors per service in the time range.
  • _stream:{service="api"} | stats quantile(0.99, duration_ms) p99A percentile over a numeric field.
  • * | top 10 by (path)The most frequent values of a field.
  • _msg:~"order=(?P<order>\d+)" | extract "order=<order>" | stats by (order) count()Extract a value from the message and count by it.

The complete reference is the LogsQL documentation.

Cheat sheet

QueryMeaning
wordline contains word
"exact phrase"phrase in order
field:valuefield contains word
field:=valuefield equals value
field:prefix*field starts with
-field:valueexclude
a OR beither
field:>10numeric compare
field:range(1, 9)numeric range
field:in(a, b)one of
field:*field exists
_stream:{k="v"}exact stream
_time:15mlast 15 minutes
… | stats by (f) count()aggregate

FAQ

Is the search case-sensitive?
Word search (timeout, level:error) is case-insensitive. Exact match (service:=API) and regular expressions are case-sensitive.
Why does `service=api` not work?
LogsQL uses a colon: service:api (contains the word) or service:=api (equals). The search box recognises the = form and offers the corrected query.
How far back can I search?
As far as your plan's retention — the Logs page shows it in the status line (“Your plan keeps N days of logs”). Older lines are removed automatically.
Can I search across several organizations?
No. Logs are isolated per organization; switch the organization in the sidebar to search another one.
Why do backfilled lines not appear in Live tail?
The tail follows event time (_time). A line whose timestamp is older than a few seconds when it arrives — a replayed file, a delayed batch — is searchable immediately but is not streamed into the tail.

Terms used above: a *term* is one field:=value or field:in(...) part of the query; a *stream* is the set of lines sharing the same stream-field values.