Console capture
Mirror console.log, info, warn, error, and debug calls to axonpush without changing what your terminal prints.
setupConsoleCapture patches console.log, console.info, console.warn,
console.error, and console.debug, and forwards each call to axonpush as an
OpenTelemetry-shaped log event. The original method still runs first, so your
terminal output is unchanged.
Use it for agent projects where the agent or its tools emit free-form output
through console.log instead of a structured logger. No peer dependencies,
this one ships with the base package.
Install
npm install @axonpush/sdkPatch the console
import { AxonPush } from "@axonpush/sdk";
import { setupConsoleCapture } from "@axonpush/sdk/integrations/console";
const client = new AxonPush();
const handle = setupConsoleCapture({
client,
channelId: process.env.AXONPUSH_CHANNEL_ID!,
agentId: "research-agent",
serviceName: "research-agent",
});
console.log("agent starting up");
console.error("retrying after 429");Each call is written to the real console and published.
agent.log or app.log
Captured lines are tagged agent.log by default, which is what you want for
agent projects. Pass source: "app" for a backend service and they become
app.log instead:
setupConsoleCapture({ client, channelId, source: "app" });Non-blocking by default
Captured lines are pushed onto a bounded in-memory queue and drained by a
background loop, so console.log stays fast. Records live in memory until
drained, set mode: "bullmq" if losing them on a crash is unacceptable.
Options
| Option | Type | Default | Description |
|---|---|---|---|
client | AxonPush | required | The SDK client to publish through. |
channelId | string | required | Channel UUID for captured events. |
source | "agent" | "app" | "agent" | Chooses agent.log or app.log. |
serviceName | string | OTel service.name on the payload’s resource. | |
maxBodyLength | number | 4000 | Characters kept per captured body. |
agentId | string | Agent correlation id. | |
traceId | string | new trace | Seed an existing trace. |
mode | "background" | "sync" | "bullmq" | "background" | Publishing strategy. |
queueSize | number | 1000 | Records buffered before overflow. |
overflowPolicy | "drop-oldest" | "drop-newest" | "block" | "drop-oldest" | What a full queue does. |
shutdownTimeoutMs | number | 2000 | Drain budget on close(). |
concurrency | number | 1 | Parallel in-flight publishes. |
bullmqOptions | BullMQPublisherOptions | Required when mode: "bullmq". |
Unpatching
handle.unpatch(); // restore the original console methods
await handle.flush(1000); // drain pending publishes
await handle.close(); // restore, then stop the background loopAlways unpatch in tests and before forking
A patched console is process-global. Restore it in a finally block so test
teardown and spawned subprocesses do not inherit it.
The patch also restores itself on exit, beforeExit, and
uncaughtException, so a crashing process still prints its stack through the
real console. The uncaught-exception handler re-throws on the next tick, which
keeps Node’s default behaviour, stack printed, exit code 1, intact. Long-running
servers do not need to call close(): the module-level beforeExit /
SIGTERM / SIGINT hooks close every live publisher.
Body formatting
A single string argument is used as-is. A single non-string is JSON-stringified
with two-space indentation. Multiple arguments are stringified individually and
joined with spaces. Whatever comes out is cut at maxBodyLength with a
…[truncated] marker, then run through the client’s redactor.
Event shape
| Field | Value |
|---|---|
identifier | "console" |
eventType | agent.log, or app.log when source: "app" |
payload.timeUnixNano | capture time in nanoseconds |
payload.severityNumber / severityText | debug → DEBUG (5), log/info → INFO (9), warn → WARN (13), error → ERROR (17) |
payload.body | the formatted argument list |
payload.attributes | log.iostream (stderr for warn and error, else stdout), log.source: "console" |
payload.resource | service.name, when configured |
metadata.framework | "console-capture" |
Re-entrancy
The SDK’s own diagnostics go through consola, and records emitted while the
publisher is mid-publish are skipped, so a warning raised during a failed
publish cannot re-enter the capture and loop.
winston
A winston transport that ships log records to axonpush as OpenTelemetry-shaped app.log events, with winston's level vocabulary mapped to OTel severities.
OpenTelemetry
AxonPushSpanExporter is a SpanExporter for any OTel tracer provider, add it alongside your existing exporters and spans land in axonpush as app.span events.