DXOS logging (@dxos/log)
SkillMonitoring & opsDXOS logging with @dxos/log (log, levels, dbg), LOG_FILTER for test stdout, and querying Composer NDJSON logs via scripts/query-logs.mjs. Use when adding or reviewing logs, debugging from app.log or tests, or explaining log levels and vite-plugin-log output.
Available today. Use it from your connected AI after setup.
No other account needed.
Connect ahel once, and every AI you use reads what you have installed.
Then ask your AI: use the DXOS logging (@dxos/log) skill
What this skill tells your AI
The instructions your AI receives, as published by dxos/dxos in .agents/skills/logging/SKILL.md and read by ahel’s review.
All application logging goes through @dxos/log (“dxlog”). Import: import { log, dbg } from '@dxos/log';
Message shape
- Static message first (lowercase phrase, no template literals in the message string).
- Structured context second (object). Do not stuff dynamic data only into the message; put it in context.
log('received queue batch', { count: items.length, spaceKey });
log.warn('plugin failed to activate', { pluginId, cause: err.message });
Levels
Use log('…', ctx) for DEBUG-level diagnostics. The callable log is log.debug (same level); prefer log(...) in new code and avoid writing log.debug so style stays consistent.
| API | Role |
|---|---|
log('…', ctx) | DEBUG — default verbose diagnostics; often not shown on the default browser console but still captured when a log sink (e.g. vite-plugin-log app.log) is attached. |
log.trace('…', ctx) | TRACE — finest granularity; usually filtered out everywhere except explicit trace filters. |
log.verbose('…', ctx) | VERBOSE — between debug and info. |
log.info('…', ctx) | INFO — user-visible / product-level events; shown on console with typical filters. |
log.warn('…', ctx) | WARN — non-fatal issues. |
log.error('…', ctx) | ERROR — hard failures. |
log.catch(err, ctx?, meta?) | Log an Error at ERROR level (stack in processors). |
Rule of thumb: log.info and above are what operators and users normally see in the console; log(...) is for deep diagnosis and file buffers.
dbg
dbg(value)(and related helpers from@dxos/log) are for local debugging only.- Remove or replace before committing (or gate behind dev-only code paths).
Composer dev: app.log
With @dxos/vite-plugin-log enabled in Composer, browser @dxos/log output is serialized to NDJSON and appended to:
packages/apps/composer-app/app.log
(from the repo root; path is relative to process cwd when the dev server runs, usually repo root → that file).
Truncate/restart behavior is owned by the plugin (file cleared on dev server start).
Tests: LOG_FILTER (stdout)
In Node / vitest runs, @dxos/log reads process.env.LOG_FILTER when building the default config (packages/common/log/src/options.ts). Set it to control which levels and paths are printed to the test process stdout (same filter string shape as query-logs -q: level name, pathFragment:level, comma-separated list, etc.).
LOG_FILTER=debug moon run functions-runtime:test -- AgentService.test.ts
Use trace for maximum noise, info for quieter runs, or a path-scoped value (e.g. AgentService:debug, functions-runtime:debug) to narrow output. This does not write app.log; it only affects the console processor during that command.
Tests: NDJSON file sink (@dxos/vite-plugin-log/vitest)
Node Vitest projects wire @dxos/vite-plugin-log/vitest via vitest.base.config.ts (global-setup truncates once; per-worker setup installs a file processor). Logs flow: @dxos/log → serializeToJsonl → JsonlFileLogStore → <package>/test.log (NDJSON, compatible with scripts/query-logs.mjs).
| Env | Role |
|---|---|
DX_TEST_LOG=0 | Disable file sink |
DX_TEST_LOG_FILE | Override path (edge: same as legacy EDGE_TEST_LOG_FILE) |
DX_TEST_LOG_FILTER / LOG_FILTER | File sink filter (default debug) |
LOG_FILTER=lifecycle:debug moon run functions-runtime:test -- AgentService.test.ts
node scripts/query-logs.mjs packages/core/compute/functions-runtime/test.log -q lifecycle:debug
Exported for reuse (e.g. edge Miniflare tail → JsonlFileLogStore.pushLines): JsonlFileLogStore, installNodeLogProcessor, resolveTestLogFilePath, truncateTestLogFile from @dxos/vite-plugin-log/vitest.
Querying logs: scripts/query-logs.mjs
From repo root:
node scripts/query-logs.mjs <file> [-q <filter>]... [-g <regexp>]...
pnpm query-logs -- <file> ...
-q: comma-separated filters inLOG_FILTERstyle (seepackages/common/logparseFilter+shouldLog).- Level only:
debug,info,warn,error,trace,verbose. - Path substring + level:
echo-db:debug— file path in the log line must containecho-db, level must be ≥debug. - Exclude:
!substring— drop lines whose file path containssubstring(after!). Use!rpc.tsto drop noisy RPC files. Bare!foois treated as exclude at trace threshold internally. - Repeat
-q: OR between groups; inside one-q, filters work like runtimeshouldLog(includes + excludes).
- Level only:
-g: RegExp (JavaScript) run on the raw JSON line. Repeat-gfor AND.
Output columns: timestamp, level letter, file:line, scope (o), message (m), context (c), error (e).
Workflow
Run narrow queries and pipe to Unix tools:
# How many debug lines mention ProcessManager?
node scripts/query-logs.mjs packages/apps/composer-app/app.log -q debug -g ProcessManager | wc -l
# Echo DB query pipeline only, exclude rpc.ts noise, first 20 lines
node scripts/query-logs.mjs packages/apps/composer-app/app.log -q 'echo-db:debug,!rpc.ts' | head -20
# Automerge-related paths at debug
node scripts/query-logs.mjs packages/apps/composer-app/app.log -q automerge:debug | less
# Invalid RPC response ids (example message grep)
node scripts/query-logs.mjs packages/apps/composer-app/app.log -q debug -g 'invalid id' | head
# OR two path groups: client package OR space proxy, debug and above
node scripts/query-logs.mjs packages/apps/composer-app/app.log -q 'sdk/client/src:debug' -q 'space-proxy:debug' | wc -l
Requires @dxos/log built: moon run log:build (script imports packages/common/log/dist/...).
Path fragments to try (Composer f field)
These substrings match typical packages/... paths in NDJSON. Counts vary per session.
| Area | Example -q fragment | Notes |
|---|---|---|
| Process / agent runtime | ProcessManager (use -g) or functions-runtime:debug | functions-runtime/src/process/ProcessManager.ts |
| ECHO queries | echo-db:debug or echo/echo-db:debug | query-result, graph, index |
| Automerge | automerge:debug | Lower volume than full echo-db |
| Client (DXOS Client) | sdk/client/src:debug or client.ts:debug | packages/sdk/client/src/client/client.ts |
| Space / ECHO proxy | space-proxy:debug | packages/sdk/client/src/echo/space-proxy.ts |
| Dedicated worker services | dedicated-worker:debug | packages/sdk/client/src/services/dedicated/ |
| Mesh RPC (noisy) | mesh/rpc:debug | Very high volume; pair with !rpc.ts or -g |
| RPC tunnel / worker port | rpc-tunnel:debug | Worker transport |
| Plugins | plugin-manager:debug | packages/sdk/app-framework/.../plugin-manager.ts |
| Edge / status RPC | edge with -g or path under client-services | Responses often QueryEdgeStatusResponse |
Add more fragments by copying a path prefix from an app.log line (f field) and using it in -q your-fragment:debug.
Related
- Log processors and filters:
packages/common/log/src/context.ts,packages/common/log/src/options.ts(parseFilter). - NDJSON capture shape:
packages/common/log/src/log-buffer.ts. - Composer wiring:
tools/vite-plugin-log,packages/apps/composer-app/vite.config.ts(vitePluginLoginsharedPlugins).
Signals
- GitHub stars
- 520
- Forks
- 49
- Last commit
- Sep 2026
Advanced
- Catalog kind
- skill
- Gateway key
logging-dxos- Source
- github.com/dxos/dxos