docs

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 numberLevel
1 to 4trace
5 to 8debug
9 to 12info
13 to 16warn
17 to 20error
21 and abovefatal

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.

ColumnWhat it shows
TimeRecord timestamp
LevelLevel pill
ServiceSending service
MessageBody, with HTTP methods, paths, status codes and durations highlighted
TraceFirst 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.

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:

FieldAliasesReads
levelseverityLevel
severity.textSeverity text as sent
scopeInstrumentation scope name
bodymessageMessage body
serviceservice.nameService
trace_idtrace.idTrace ID
span.idSpan ID
statushttp.response.status_code attribute, as a number
pathurl.path attribute
routehttp.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=1042

Typing 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=value or field!=value token to the search. For service.name the menu also opens Exceptions for that service. Search covers only two resource attributes, service.name and service.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?"

  1. Search status>=500 or pick the Error tab.
  2. Open the record and switch to Same service to read what the process logged just before.
  3. Switch to Same trace to see only the lines of that request.
  4. Click the trace link to see which span failed in the trace view.