Skip to main content
Wildo.ai Coming soon

Observability

Keep local output readable and inspectable

Local development labels and captures each service’s output while presenting it in the terminal. Choose structured output when diagnostic tools need to read individual log fields.

The same process output produces raw machine records and readable terminal output.

Keep local output readable and inspectable

Local development labels and captures each service’s output while presenting it in the terminal. Choose structured output when diagnostic tools need to read individual log fields.

Keep console formatting disabled for machine-oriented checks. Use the process label to locate the same event in the terminal and capture.

Example — Inspect a validation failure

With structured process output enabled, a validation error keeps its fields in the captured record. A diagnostic tool removes the process label, parses the JSON and examines the issues without extracting them from prose.

For engineers

Choose presentation in the environment

Wonder Todos authors this logging block in its local infrastructure configuration:

logging: {
  level: 'debug',
  formattedConsoleErrors: false,
},

false keeps the process logger’s JSON output and the terminal’s raw presentation. true also enables pretty formatting inside the process logger, before the CLI receives stdout. The capture then contains those received text lines, not the original JSON record.

SettingProcess outputCaptured form
formattedConsoleErrors: falseStructured logger recordsProcess-prefixed, ANSI-free JSON lines
formattedConsoleErrors: truePretty logger outputProcess-prefixed text, potentially several lines per event

Use the first setting for tools that require structured fields. The CLI’s recognition of a JSON record cannot recover fields already turned into prose upstream.

Follow one line to both destinations

LocalDevOutputBoundary.emitLine() performs the split. This selected implementation excerpt keeps the decision visible:

const pressure = new Set<LocalDevOutputSink>();
if (this.options.writeCapture(`[${this.options.label}] ${stripAnsi(line)}\n`) === false) {
  pressure.add(LocalDevOutputSink.CAPTURE);
}

const consoleLines = this.options.consoleRendering === LocalDevConsoleRendering.RAW
  ? [line]
  : formatLocalDevConsoleLine(line);

for (const consoleLine of consoleLines) {
  if (this.options.writeConsole(`${this.options.consolePrefix}${consoleLine}\n`) === false) {
    pressure.add(LocalDevOutputSink.CONSOLE);
  }
}

The capture is process-prefixed and ANSI-free, not an unchanged byte-for-byte copy of the pipe. A tool reading JSON must account for that label. The human renderer recognizes structured log records; unrelated text passes through rather than being guessed into a record.

Keep framing and flow together

Separate UTF-8 framers own stdout and stderr. A chunk split through a character or a line is held until it can be emitted correctly; one stream cannot finish the other’s partial record. LocalDevOutputFlowController pauses both streams when either destination applies back-pressure and resumes after the pressured sinks drain.

This is the local stack’s output handling. Production collection, retention and log access are operator concerns. When investigating a formatting discrepancy, compare the capture with the terminal rather than assuming the decoded view is the stored record.

Building a B2B product or an internal tool?

Wildo is not self-service yet. Tell us what you have in mind and we will say plainly whether it fits, and what happens next.