Logs
Search and filter log records, read volume by level, and jump from a log line to its trace and its neighbours.
Logs holds every log record your services send over OpenTelemetry. Use it to read what the app said around a failure, or to find every line that mentions an order, a route or a status code.
The page lives at /o/:org/projects/:project/logs.
Where the data comes from
The AdonisJS agent forwards the Pino logger, so logger.info() in a controller or job becomes a record here. Records written while a request or job runs carry its trace ID and span ID and link back to the trace. Any OpenTelemetry SDK that exports logs works the same way, see Any OpenTelemetry SDK.
Two kinds of records never appear in Logs. Exceptions reported by the agent go to Issues, and analytics events go to Analytics.
Levels
Each record gets one level from its OpenTelemetry severity number:
| Severity number | Level |
|---|---|
| 1 to 4 | trace |
| 5 to 8 | debug |
| 9 to 12 | info |
| 13 to 16 | warn |
| 17 to 20 | error |
| 21 and above | fatal |
When the severity number is missing, the severity text decides: information counts as info, warning as warn and critical as fatal. Unknown text becomes info.
The level tabs group these into All, Error (error and fatal), Warn, Info and Debug (debug and trace), each with its count for the current search.
Volume chart
The chart stacks record counts per bucket, coloured by level. Without a search it reads a per-minute volume rollup, so it stays fast on long ranges. Drag across it to zoom the time range. The Volume button collapses the chart, and the page remembers that choice.
The log table
Rows are sorted newest first and load 100 at a time as you scroll. Records that share a timestamp keep a stable order, so paging never skips or repeats one. A page reads back from the end of the range in growing windows (15 minutes, 1 hour, 6 hours, 24 hours, then the rest) and stops once it is full.
| Column | What it shows |
|---|---|
| Time | Record timestamp |
| Level | Level pill |
| Service | Sending service |
| Message | Body, with HTTP methods, paths, status codes and durations highlighted |
| Trace | First 8 characters of the trace ID, linking to the trace at this span |
The list carries the first 2,000 characters of each message. Opening a record loads its full body.
Columns adds any attribute of the loaded records as a column, and the density toggle switches to compact rows. Copy link copies the current view, including search, level and columns. Its menu also copies a link to the exact window, which pins the start and end.
Top values, the rail on the left of wide screens, lists the most frequent values of common fields. Its counts cover the time range, not the search. Click a value to filter on it.
Live streams new records into the top of the list, the same way as live tail on Traces.
Patterns
The View switch next to the level tabs turns the list into Patterns. Unhandled masks the variable parts of each message (quoted strings, UUIDs, IP addresses, long hex strings and numbers) and groups records whose masked text matches. Each pattern shows its count, its mix of levels, a trend over the range and the template with its variable parts highlighted. Filter adds a search for the pattern's fixed text and switches back to the list.
Patterns read the newest 100,000 matching records at most. When the range holds more, the header says the patterns come from the newest ones.
Search
The search bar uses the same grammar as Traces: space-separated tokens that all must match, field<op>value filters with =, :, !=, ~, ^, >, >=, < and <=, comma lists for is any of, and double quotes around values with spaces. A bare word matches the message body, case-insensitively.
These log fields map to stored columns:
| Field | Aliases | Reads |
|---|---|---|
level | severity | Level |
severity.text | Severity text as sent | |
scope | Instrumentation scope name | |
body | message | Message body |
service | service.name | Service |
trace_id | trace.id | Trace ID |
span.id | Span ID | |
status | http.response.status_code attribute, as a number | |
path | url.path attribute | |
route | http.route attribute |
Any other field reads the record attribute of that name. Some examples:
level=error path^/checkout
status>=500 service.name!=worker
"payment declined" order.id=1042Typing a field suggests values with counts, Tab cycles the operator, Backspace on an empty input removes the last filter, and / focuses the bar.
Log details
Clicking a row opens a resizable panel. Up and Down move to the neighbouring record and Escape closes it. f toggles full screen, which shows Overview and JSON side by side.
- Overview shows the message, level, severity, service, source scope, trace and span, then every attribute and resource attribute. The menu on a value offers Filter in, Filter out, Copy value and Open in Traces. Filter in and Filter out add a
field=valueorfield!=valuetoken to the search. Forservice.namethe menu also opens Exceptions for that service. Search covers only two resource attributes,service.nameandservice.version, so other resource attributes can only be copied. - Same trace lists up to 200 records of the same trace within an hour either side, in order.
- Same service shows the 10 records before and the 10 after this one from the same service and environment, within 6 hours either side.
- JSON shows the raw record.
Records older than your plan's retention are hidden everywhere, including Same trace and Same service. See Retention.
Answering "what happened before the 500?"
- Search
status>=500or pick the Error tab. - Open the record and switch to Same service to read what the process logged just before.
- Switch to Same trace to see only the lines of that request.
- Click the trace link to see which span failed in the trace view.