Diagnostics Flags for Targeted Debug Logging
Learn how to enable extra logging for specific subsystems without raising the global log level. This page lists known flags and explains configuration, matching rules, and restart requirements.
Read this when
- You need targeted debug logs without raising global logging levels
- You need to capture subsystem-specific logs for support
Diagnostics flags add extra logging for a single subsystem without raising
logging.level globally. Unless a subsystem explicitly checks for a flag, that flag
has no effect.
How it works
- Flags are case-insensitive strings, sourced from
diagnostics.flagsin config and theOPENCLAW_DIAGNOSTICSenv override, with duplicates removed and lowercasing applied. name.*matches bothnameand anything nested undername.(sotelegram.*also matchestelegram.http).- Setting
*orallturns on all flags. - After modifying
diagnostics.flagsin config, restart the gateway; it does not hot-reload.
Known flags
| Flag | Enables |
|---|---|
telegram.http | Logging of Telegram Bot API HTTP errors |
brave.http | Logging of Brave Search requests, responses, and cache |
profiler | Profiler for reply stage and Codex app server (both) |
reply.profiler | Profiler for reply stage only |
codex.profiler | Profiler for Codex app server only |
health | Debug details for gateway health probe, account, binding |
ingress.timing | Timings for session load, model selection, and model catalog |
plugin.load-profile | Timings for synchronous plugin module loading |
timeline | Structured JSONL timeline artifact (details below) |
Enable via config
{
"diagnostics": {
"flags": ["telegram.http"]
}
}
Multiple flags:
{
"diagnostics": {
"flags": ["telegram.http", "brave.http", "gateway.*"]
}
}
Env override (one-off)
OPENCLAW_DIAGNOSTICS=telegram.http,brave.http
Values are split on commas or whitespace. Special values:
| Value | Effect |
|---|---|
0, false, off, none | Turn off all flags, including config |
1, true, all, * | Turn on every flag |
For a given process, OPENCLAW_DIAGNOSTICS=0 disables flags from both env and config,
which is handy for silencing a profiler flag left in config without editing
the file.
Profiler flags
Profiler flags control lightweight timing spans; when off, they add no overhead.
To enable all profiler-gated spans for a single gateway run:
OPENCLAW_DIAGNOSTICS=profiler openclaw gateway run
To enable only reply-dispatch profiler spans:
OPENCLAW_DIAGNOSTICS=reply.profiler openclaw gateway run
To enable only Codex app-server startup, tool, and thread profiler spans:
OPENCLAW_DIAGNOSTICS=codex.profiler openclaw gateway run
profiler turns on both the reply profiler and the Codex profiler; to enable
just one, use the scoped flag names.
Alternatively, set it in config:
{
"diagnostics": {
"flags": ["reply.profiler", "codex.profiler"]
}
}
After changing config flags, restart the gateway. To disable a profiler flag,
remove it from diagnostics.flags and restart, or start the process with
OPENCLAW_DIAGNOSTICS=0 to override all diagnostics flags for that run.
Timeline artifacts
The timeline flag (alias: diagnostics.timeline) emits structured startup
and runtime timing events as JSONL, intended for external QA harnesses:
OPENCLAW_DIAGNOSTICS=timeline \
OPENCLAW_DIAGNOSTICS_TIMELINE_PATH=/tmp/openclaw-timeline.jsonl \
openclaw gateway run
Or enable it in config:
{
"diagnostics": {
"flags": ["timeline"]
}
}
The output path is always taken from OPENCLAW_DIAGNOSTICS_TIMELINE_PATH, even when the
flag is set in config; no config key exists for the path.
When timeline is enabled only from config, the earliest config-loading spans
are absent because OpenClaw has not read config yet; later startup spans are
captured as usual.
OPENCLAW_DIAGNOSTICS=1, =all, and =* also activate the timeline, since they
enable all flags. When you want only the JSONL artifact and not every other
diagnostics flag, prefer the scoped timeline flag.
Event-loop delay samples in the timeline require an extra opt-in beyond
timeline: set OPENCLAW_DIAGNOSTICS_EVENT_LOOP=1 (or on/true/yes) in
addition to enabling the timeline.
Timeline records rely on the openclaw.diagnostics.v1 envelope, carrying data such as process ids, phase names, span names, durations, plugin ids, dependency counts, event-loop delay samples, provider operation names, child-process exit state, and startup error names/messages. These timeline files should be handled as local diagnostics artifacts; inspect them before distributing them beyond your own system.
Where logs go
Flags direct their output into the standard diagnostics log file. The default configuration is:
/tmp/openclaw/openclaw-YYYY-MM-DD.log
Named profiles depend on /tmp/openclaw/openclaw-<profile>-YYYY-MM-DD.log; for instance, --dev relies on openclaw-dev-YYYY-MM-DD.log.
When logging.file is configured, that path takes precedence. The logs use JSONL format, with one JSON object per line. Redaction remains active at all times. Consult Logging for the complete log-path resolution, rotation, and redaction details.
Extract logs
Access the most recent log file from the active profile:
openclaw logs --plain
# Named profile example:
openclaw --profile work logs --plain
Narrow down to Telegram HTTP diagnostics:
openclaw logs --plain --limit 5000 | rg "telegram http error"
Narrow down to Brave Search HTTP diagnostics:
openclaw logs --plain --limit 5000 | rg "brave http"
Or follow the log while reproducing the issue:
openclaw logs --follow --plain | rg "telegram http error"
For remote gateways, switch to openclaw logs --follow instead (refer to /cli/logs).
Notes
- When
logging.levelexceedswarn, flag-gated logs might be withheld. The defaultinfoworks well. brave.httpcaptures Brave Search request URLs and query parameters, response status and timing, plus cache hit, miss, and write events. It excludes the API key (delivered as a request header) and response bodies, though search queries may carry sensitive information.- Leaving flags enabled is harmless; they only increase log volume for the targeted subsystem.
- Use /logging to adjust log destinations, levels, and redaction settings.