@raypx/logger
Structured logging with Pino.
@raypx/logger provides structured JSON logging built on top of Pino. It exposes a simple API for creating loggers, attaching context, and serializing errors.
Exports
| Export | Description |
|---|---|
createLogger(options?) | Create a new logger instance with custom configuration |
getLogger() | Get or create the global default logger singleton |
setLogger(logger) | Replace the global default logger (useful in tests) |
logger | Proxy-based default logger that lazily initializes via getLogger() |
createConsoleTransport(level?) | Create a pino-pretty console transport (dev only) |
createFileTransport(destination, level?) | Create a file-based transport |
serializeError(error) | Serialize an error into a plain object |
Quick Start
import { logger } from "@raypx/logger"
logger.info("Server started", { port: 3000 })
logger.error("Database connection failed", { err: serializeError(error) })Log Levels
The logger supports six levels ordered by severity:
| Level | Priority | Default in Production |
|---|---|---|
trace | 0 | No |
debug | 1 | No |
info | 2 | Yes |
warn | 3 | Yes |
error | 4 | Yes |
fatal | 5 | Yes |
In development, the default level is debug. In production (NODE_ENV=production), it defaults to info. Override with the level option or the LOG_LEVEL environment variable.
Creating a Logger
import { createLogger } from "@raypx/logger"
const log = createLogger({
level: "debug",
service: "auth-service",
version: "1.0.0",
redact: ["password", "token"],
context: { feature: "auth" },
})
log.info("User logged in", { userId: "abc" })Context and Child Loggers
Attach context to individual log entries or create child loggers that inherit a base context:
// Per-call context
logger.info("Processing request", { feature: "rpc", endpoint: "profile" })
// Child logger with persistent context
const authLog = logger.withContext({ feature: "auth" })
authLog.info("Password reset requested", { email: "user@example.com" })
authLog.error("Reset failed", { reason: "token_expired" })Usage in RPC Interceptors
The RPC layer uses the logger to record API activity:
import { logger } from "@raypx/logger"
logger.info("rpc.call", {
feature: "rpc",
procedure: "documents.upload",
userId: session.user.id,
})Usage in Auth Callbacks
Better Auth callbacks in @raypx/auth log events with the feature: "auth" context:
import { logger } from "@raypx/logger"
logger.info("auth.password.reset", { feature: "auth", userId: user.id })Error Serialization
Use serializeError to safely convert Error objects (including nested causes) into plain objects suitable for JSON logging:
import { serializeError } from "@raypx/logger"
try {
await riskyOperation()
} catch (error) {
logger.error("Operation failed", { err: serializeError(error) })
}The serialized output includes name, message, stack, and recursively serialized cause properties.
Transports
Two transport factories are provided for advanced configurations:
import { createConsoleTransport, createFileTransport } from "@raypx/logger"
const log = createLogger({
transports: [
createConsoleTransport("debug"),
createFileTransport("/var/log/raypx.log", "info"),
],
})In development, if pino-pretty is installed and no explicit transports are configured, the logger automatically uses it for colored, single-line console output.