Console capture
Patch console.log / console.info / console.warn / console.error / console.debug and forward each call to AxonPush as an OpenTelemetry-shaped log event. Each captured call still passes through to the original console method, so your terminal output is unchanged.
Use this for AI agent projects where the agent (or its tools) emits free-form output via console.log instead of going through a structured logger.
[!TIP] Non-blocking by default (v0.0.2+)
Captured lines are pushed onto a bounded queue and drained by a background task. Call
handle.flush(timeoutMs?)at known checkpoints to guarantee delivery, or useflushAfterInvocation. The SDK’s own internal logger (consola) writes directly toprocess.stdout.writeand does NOT route throughconsole.log, so there is no feedback-loop risk between this capture and the SDK’s diagnostics.
Installation
Section titled “Installation”npm install @axonpush/sdkNo peer dependencies — this integration ships with the base package.
import { AxonPush } from "@axonpush/sdk";import { setupConsoleCapture } from "@axonpush/sdk/integrations/console";
const client = new AxonPush({ apiKey: process.env.AXONPUSH_API_KEY!, tenantId: process.env.AXONPUSH_TENANT_ID!,});
const handle = setupConsoleCapture({ client, channelId: 1, agentId: "my-agent", serviceName: "my-agent",});console.log("agent starting up");console.log("step 1: loaded tools = ['web_search', 'calculator']");console.error("retrying after 429");Each call is written to the original console AND shipped to AxonPush.
Source: agent vs app
Section titled “Source: agent vs app”By default, captured logs are tagged as agent.log events (for AI agent projects). Pass source: "app" to tag them as app.log instead:
setupConsoleCapture({ client, channelId: 1, source: "app" });Restoring the console
Section titled “Restoring the console”handle.unpatch(); // restore the original console.* methodsawait handle.flush(1000); // drain any pending publishesawait handle.close(); // stop the background workerAlways unpatch() in a finally: block (or before process.exit())
so that test teardown and subprocess spawning don’t inherit the patch.
The module-level beforeExit / SIGTERM / SIGINT hook closes the
publisher at normal process exit — you don’t need to call .close()
explicitly in long-running servers.
Constructor options
Section titled “Constructor options”| Option | Type | Default | Description |
|---|---|---|---|
client | AxonPush | required | The pre-built SDK client. |
channelId | number | required | Target channel for captured log events. |
source | "agent" | "app" | "agent" | Event type tag — agent.log or app.log. |
agentId | string | — | Optional agent correlation ID. |
serviceName | string | — | OTel service.name resource attribute. |
maxBodyLength | number | 4000 | Maximum characters per captured body. |
mode | "background" | "sync" | "background" | Publishing mode. |
queueSize | number | 1000 | Max records buffered before drop. |
Events
Section titled “Events”| Field | Value |
|---|---|
identifier | "console" |
eventType | agent.log (default) or app.log if source: "app" |
payload.body | The formatted argument list |
payload.severityNumber / payload.severityText | Mapped from the console method: debug→DEBUG, log/info→INFO, warn→WARN, error→ERROR |
payload.attributes | log.iostream (stdout / stderr), log.source (console) |