Node.js
Send logs, console output and uncaught errors from Node.js with @dlogify/node.
By the end of this page your Node.js service sends its logs and uncaught errors to dlogify. @dlogify/node requires Node.js 20.19 or later and has no runtime dependencies.
Install
npm install @dlogify/nodeWithout code changes
Load the package when Node starts, with your API key in the environment:
export LOGIFY_API_KEY=lgf_live_…
node --import @dlogify/node/register dist/server.js
# or, without touching the start command:
NODE_OPTIONS="--import @dlogify/node/register" npm startregister captures console.*, uncaught exceptions and unhandled rejections. CommonJS applications can use node -r @dlogify/node/register. Without LOGIFY_API_KEY it prints one warning and does nothing else, so a Docker image can keep the flag and receive the key at run time:
ENV NODE_OPTIONS="--import @dlogify/node/register"
# pass LOGIFY_API_KEY at run timeWith the SDK
Call init() once at startup, then log with levels and attributes:
import * as logify from "@dlogify/node";
logify.init({ service: "checkout" });
export async function placeOrder(orderId: string, charge: () => Promise<void>) {
logify.info("order placed", { attributes: { orderId } });
try {
await charge();
} catch (err) {
logify.error("charge failed", { error: err, attributes: { orderId } });
}
}
// Before process.exit(), send what is still queued.
await logify.flush();init()capturesconsole.*and uncaught errors too; passcaptureConsole: falseorcaptureUncaught: falseto turn them off.logify.captureException(err)records an error you caught.- Calls before
init()are dropped, and a secondinit()is ignored. Do not combineregisterwith aninit()that has options. new logify.Client(options)creates an independent client.
pino
import pino from "pino";
export const logger = pino({ transport: { target: "@dlogify/node/pino" } });winston
import winston from "winston";
import { LogifyTransport } from "@dlogify/node/winston";
export const logger = winston.createLogger({
transports: [new winston.transports.Console(), new LogifyTransport()],
});The winston transport needs winston-transport, which comes with winston. It sends through the init() client when there is one, otherwise through its own client configured from its options and the environment.
Any process: logify run
logify run sends the output of any command, in any language:
LOGIFY_API_KEY=lgf_live_… npx @dlogify/node run -- ./my-server --port 3000The output still appears in your terminal exactly as before, and the exit code is the command's. Lines are grouped into events (stack traces, Python tracebacks and Go panics stay together), and JSON lines are read as structured records. A non-zero exit or a death by signal is reported as one more error, except a SIGPIPE after the reader of the output went away, as in | head.
Configuration
Options passed to init() win over environment variables, which win over the defaults.
| Variable | Option | Default |
|---|---|---|
LOGIFY_API_KEY | apiKey | Required; without it the client is disabled. |
LOGIFY_ENDPOINT | endpoint | https://api.dlogify.com |
LOGIFY_SERVICE | service | OTEL_SERVICE_NAME, then the name of the nearest package.json from the working directory, then unknown_service |
LOGIFY_ENVIRONMENT | environment | NODE_ENV, then default |
LOGIFY_RELEASE | release | empty |
LOGIFY_MIN_LEVEL | minLevel | info (trace, debug, info, warn, error, fatal) |
LOGIFY_DISABLED | disabled | off (1 or true turns the client into a no-op) |
LOGIFY_DEBUG | debug | off (1 or true prints the client's diagnostics to stderr) |
LOGIFY_REDACT_DEFAULTS | redactDefaults | off (1 or true applies dlogify's redaction in your process; see Redaction) |
LOGIFY_REDACT_KEYS | redactKeys | empty (comma-separated attribute keys replaced by <redacted>) |
| — | redactPatterns, beforeSend | none; see Redaction |
Also attributes (added to every record) and maxQueueSize (default 2000).
Guarantees
- No call throws, nothing blocks the event loop, and nothing keeps the process alive.
- The client's own diagnostics go to stderr, never through
console. - Records are sent in the background in compressed batches, with retries for up to 5 minutes. If the key is rejected, the client stops for the rest of the process with one warning. Redirects are not followed: if the endpoint redirects, one warning names the URL to put in
LOGIFY_ENDPOINT. - At normal exit and after an uncaught exception, the client flushes for at most 2 seconds.
process.exit()skips that flush, so callawait logify.flush()first. - After an uncaught exception with no handler of your own, the error is printed like Node does and the process exits with code 1. If you have your own
uncaughtExceptionhandler, dlogify only records the error.
What is sent
Only log records: message, level, time, the attributes you pass, the error's type, message and stack, and the service name, environment, release, host name and SDK version. The SDK makes no other network calls and opens no ports. See What is sent.