How logging works
No SDK or extra library is required:- Anything your container writes to stdout or stderr is captured.
- Each line is parsed, assigned a severity, and appears in the logs explorer within seconds.
- One line in your container is one entry in the explorer. Multi-line output is split into separate entries (see Limitations).


Structured logging
Plain text gives you logs, but structured logging makes them queryable and correctly leveled. Each line is parsed as JSON. When parsing succeeds, every key becomes a queryable field on the entry, visible in the detail panel. When it fails, the line is kept as a plain-text body.How severity is detected
Severity is read from the parsed JSON in priority order. The first matching field wins:Emit only one severity field per line. If more than one is present, the
result is undefined. Pick one logger and let it own the field.
Worked examples
Each emits a JSON line that gets parsed and leveled correctly.Library compatibility
If you use one of these libraries with JSON output enabled, severity is detected out of the box:
For any library not listed, emit JSON with a top-level
level (string or numeric) or severity_number (1 to 24) and it will be detected.
Retention
How long logs stay in the explorer depends on your plan:
Custom retention beyond 7 days is available on Enterprise. See the observability row in the plan comparison for details.
Logs older than your retention window are removed from the explorer entirely. There is no archive to recover them from.
Limitations and gotchas
console.warn and console.error are not auto-detected.
Plain text only becomes WARN or ERROR when the body contains a word-bounded match for one of: warn, warning, error, err, fatal, panic, exception, critical, crit, debug. So console.warn("user not found") shows up as info. The word boundaries keep phrases like “no errors” from being misclassified. Use a structured logger for reliable levels.
A Datadog-style status field is ignored.
Many apps log {"status": 500} for an HTTP status or {"status": "error"} for business state, so status is left alone. Use level, severity, levelname, or severity_number instead.
Multi-line output is split into one entry per line.
A bare console.error(err) in Node prints Error: ... followed by each stack frame on its own line, and every line becomes a separate entry. Log the error through a structured logger so the stack stays inside one JSON line as a field (for example logger.error({ err }, "request failed") with pino).
Emit one severity field per line.
When more than one is present, the result is undefined.