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"
})
import pino from "pino";
const logger = pino({
level: process.env.LOG_LEVEL || "info",
});
logger.info("Server started");
logger.error({ err }, "Database connection failed");
logger.debug({ userId }, "User authenticated");
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