Pino Integration
Pino integration for oRPC provides structured logging capabilities, allowing you to easily track requests, monitor errors, and gain insights into your application's behavior.
WARNING
This guide assumes familiarity with Pino. Review the official documentation if needed.
Installation
npm install @orpc/pino@beta pino@betayarn add @orpc/pino@beta pino@betapnpm add @orpc/pino@beta pino@betabun add @orpc/pino@beta pino@betadeno add npm:@orpc/pino@beta npm:pino@betaSetup
To set up Pino with oRPC, use the PinoHandlerPlugin class. This plugin automatically instruments your handler with structured logging, request tracking, and error monitoring.
import { PinoHandlerPlugin } from '@orpc/pino'
import pino from 'pino'
const logger = pino()
const handler = new RPCHandler(router, {
plugins: [
new PinoHandlerPlugin({
logger, // <- custom logger instance
generateRequestId: ({ request }) => crypto.randomUUID(), // <- custom request id generator
logLifecycle: true, // <- log information about request lifecycle (disabled by default)
logAbort: true, // <- log information when requests are aborted (disabled by default)
}),
],
})INFO
The handler can be any supported oRPC handler, such as RPCHandler, OpenAPIHandler, or a custom one.
TIP
For improved log readability during development, consider using pino-pretty to format your logs in a human-friendly way.
npm run dev | npx pino-prettyUsing the Logger in Your Code
You can access the logger from the context object using the getLogger function:
import { getLogger, LoggerContext } from '@orpc/pino'
interface ServerContext extends LoggerContext {}
const procedure = os
.$context<ServerContext>()
.handler(({ context }) => {
const logger = getLogger(context)
logger?.info('Processing request')
logger?.debug({ userId: 123 }, 'User data')
return { success: true }
})Providing Custom Logger per Request
You can provide a custom logger instance for specific requests by passing it through the context. This is especially useful when integrating with pino-http for enhanced HTTP logging:
import {
LOGGER_CONTEXT_SYMBOL,
LoggerContext,
PinoHandlerPlugin
} from '@orpc/pino'
const logger = pino()
const httpLogger = pinoHttp({ logger })
interface ServerContext extends LoggerContext {}
const router = {
ping: os.$context<ServerContext>().handler(() => 'pong')
}
const handler = new RPCHandler(router, {
plugins: [
new PinoHandlerPlugin({ logger }),
],
})
const server = createServer(async (req, res) => {
httpLogger(req, res)
const { matched } = await handler.handle(req, res, {
prefix: '/api',
context: {
[LOGGER_CONTEXT_SYMBOL]: req.log,
},
})
if (!matched) {
res.statusCode = 404
res.end('Not Found')
}
})
