| name | pino |
| description | Pino fast JSON logger for Node.js. Covers log levels, child loggers, transports, and redaction. Triggers on pino, logger, log.info, log.error. |
| triggers | pino, logger, log\.info, log\.error, log\.warn, log\.debug |
MCPSearch({ query: "select:mcp__plugin_devtools_octocode__githubSearchCode" })
// Pino configuration
mcp__octocode__githubSearchCode({
keywordsToSearch: ["pino", "logger", "transport"],
owner: "pinojs",
repo: "pino",
path: "lib",
mainResearchGoal: "Understand Pino logger configuration",
researchGoal: "Find logger setup patterns",
reasoning: "Need current API for Pino setup",
});
// Transports
mcp__octocode__githubSearchCode({
keywordsToSearch: ["pino-pretty", "transport", "destination"],
owner: "pinojs",
repo: "pino",
path: "docs",
mainResearchGoal: "Understand Pino transports",
researchGoal: "Find transport configuration patterns",
reasoning: "Need current API for log transports",
});
| Template | Purpose |
|---|---|
templates/logger-setup.ts.md |
Logger configuration with redaction |
templates/request-logger.ts.md |
HTTP request middleware |
Basic usage:
import { logger } from "./logger";
logger.info("Server started");
logger.error({ err }, "Database connection failed");
With pretty printing (development):
import pino from "pino";
const logger = pino({
level: "debug",
transport: {
target: "pino-pretty",
options: {
colorize: true,
translateTime: "HH:MM:ss",
ignore: "pid,hostname",
},
},
});
Child loggers:
const requestLogger = logger.child({ requestId: req.id });
requestLogger.info("Processing request");
// Output: {"level":30,"requestId":"abc123","msg":"Processing request"}
// Good - structured data
logger.info({ userId, action: "login" }, "User logged in");
// Bad - string interpolation
logger.info(`User ${userId} logged in`);
Error logging:
try {
await riskyOperation();
} catch (error) {
// Pass error as `err` property for proper serialization
logger.error({ err: error, context: "riskyOperation" }, "Operation failed");
}
Request logging middleware:
function requestLogger(req, res, next) {
const start = Date.now();
const log = logger.child({ requestId: req.id });
res.on("finish", () => {
log.info(
{
method: req.method,
url: req.url,
status: res.statusCode,
duration: Date.now() - start,
},
"Request completed",
);
});
req.log = log;
next();
}
Redaction (hide sensitive data):
const logger = pino({
redact: ["password", "creditCard", "*.secret", "users[*].token"],
});
logger.info({ password: "secret123" }); // password: "[Redacted]"
import pino from "pino";
const logger = pino({
transport: {
targets: [
{
target: "pino-pretty",
options: { colorize: true },
level: "debug",
},
{
target: "pino/file",
options: { destination: "./app.log" },
level: "info",
},
],
},
});
Custom transport:
const logger = pino({
transport: {
target: "./my-transport.js",
options: { customOption: true },
},
});
Performance:
- Pino is async by default
- Use
pino.destination()for sync in critical paths - Avoid logging in hot paths
- Logger configured with appropriate level
- Structured logging (not string interpolation)
- Errors passed as
errproperty - Sensitive data redacted
- Pretty printing in development only