Skip to main content
If you already use Pino for logging, the @squasher/pino transport sends your logs directly to Squasher with zero code changes to your existing log calls. Errors are automatically enriched with stack traces, and all log levels flow into your Squasher dashboard alongside SDK-captured errors.

Installation

npm install @squasher/pino pino

Setup

Add the Squasher transport to your Pino logger:
src/logger.ts
import pino from "pino";

const logger = pino(
  { level: "info" },
  pino.transport({
    target: "@squasher/pino",
    options: {
      apiKey: process.env.SQUASHER_API_KEY,
      projectId: process.env.SQUASHER_PROJECT_ID,
    },
  }),
);

export default logger;
Add the environment variables to your .env:
.env
SQUASHER_API_KEY=sq_pk_your_key_here
SQUASHER_PROJECT_ID=your_project_id
That’s it. Every log call now sends to Squasher automatically.

Usage

Use your Pino logger exactly as you normally would:
logger.info("Server started on port 3000");
logger.warn({ userId: "usr-42" }, "Rate limit approaching");
logger.error({ err: new Error("Connection refused") }, "Database unavailable");
logger.fatal({ err: new Error("Out of memory") }, "Process crashing");
When you pass an err object (Pino’s standard error serialization), Squasher automatically extracts the error type, message, and stack trace.

Multiple Transports

Send logs to both stdout and Squasher at the same time:
src/logger.ts
import pino from "pino";

const logger = pino({
  level: "info",
  transport: {
    targets: [
      {
        target: "pino/file",
        options: { destination: 1 }, // stdout
      },
      {
        target: "@squasher/pino",
        options: {
          apiKey: process.env.SQUASHER_API_KEY,
          projectId: process.env.SQUASHER_PROJECT_ID,
          environment: process.env.NODE_ENV,
          release: process.env.GIT_COMMIT_SHA,
        },
      },
    ],
  },
});

export default logger;
This is the recommended setup for production — you get local log output for debugging and Squasher for monitoring in a single logger.

Framework Examples

src/app.ts
import express from "express";
import logger from "./logger";

const app = express();

app.get("/api/users", async (req, res) => {
  try {
    const users = await db.getUsers();
    logger.info({ count: users.length }, "Fetched users");
    res.json(users);
  } catch (error) {
    logger.error({ err: error, url: req.originalUrl }, "Request failed");
    res.status(500).json({ error: "Internal server error" });
  }
});

app.listen(3000, () => {
  logger.info({ port: 3000 }, "Server started");
});

Error Enrichment

When a Pino log includes an err object, Squasher extracts structured error data:
// This log call:
logger.error({ err: new Error("ECONNREFUSED") }, "Database connection failed");

// Sends an event with:
// - message: "ECONNREFUSED"
// - type: "Error"
// - stack: full stack trace
// - frames: parsed stack frames with file, line, and column
// - level: "error"
// - extra.pino_msg: "Database connection failed"
Standard Pino fields like pid and hostname are stored as tags. Any additional properties you bind are stored as extra data, fully searchable in the dashboard.

Log Level Mapping

Pino log levels map to Squasher levels automatically:
Pino LevelSquasher Level
trace (10)debug
debug (20)debug
info (30)info
warn (40)warning
error (50)error
fatal (60)fatal

Configuration

OptionTypeDefaultDescription
apiKeystringRequiredYour project API key (sq_pk_...)
projectIdstringRequiredYour project ID
endpointstringhttps://ingest.squasher.aiIngestion endpoint URL
environmentstringundefinedEnvironment tag (production, staging, etc.)
releasestringundefinedRelease/version tag
debugbooleanfalseLog transport activity to console
batchSizenumber25Flush when this many events are buffered
flushIntervalMsnumber5000Max milliseconds between automatic flushes
maxRetriesnumber3Retry attempts on transient failures

Combining with the Node.js SDK

The Pino transport can be used alongside @squasher/node if you want both structured logging and explicit error capture with breadcrumbs and user context:
import { init, captureError, getClient } from "@squasher/node";
import logger from "./logger"; // Pino with @squasher/pino transport

// SDK for explicit error capture with rich context
init({
  apiKey: process.env.SQUASHER_API_KEY!,
  projectId: process.env.SQUASHER_PROJECT_ID!,
});

// Set user context (only available via the SDK)
getClient().setUser({ id: "usr-42", email: "user@example.com" });

// Use pino for logging — all logs flow to Squasher automatically
logger.info("Request started");

// Use the SDK for errors that need breadcrumbs or user context
try {
  await processOrder(order);
} catch (error) {
  await captureError(error as Error, { orderId: order.id });
}
If you only need log-based monitoring without breadcrumbs or user context, the Pino transport alone is sufficient. You don’t need @squasher/node.

Requirements

  • Node.js 18 or higher
  • Pino 8 or higher