Skip to content

Evlog Integration

Evlog integration for oRPC adds structured logging so you can trace requests, monitor errors, and inspect application behavior.

WARNING

This guide assumes familiarity with Evlog. Review the official documentation if needed.

Installation

sh
npm install @orpc/evlog@beta evlog@beta
sh
yarn add @orpc/evlog@beta evlog@beta
sh
pnpm add @orpc/evlog@beta evlog@beta
sh
bun add @orpc/evlog@beta evlog@beta
sh
deno add npm:@orpc/evlog@beta npm:evlog@beta

Setup

Use EvlogHandlerPlugin to instrument your handler with structured logs, request tracking, and error monitoring.

ts
import { 
EvlogHandlerPlugin
} from '@orpc/evlog'
const
handler
= new
RPCHandler
(
router
, {
plugins
: [
new
EvlogHandlerPlugin
({
drain
:
undefined
, // <- custom Evlog drain (optional)
plugins
: [], // <- additional Evlog plugins (optional)
logAbort
: true, // <- log when requests are aborted (disabled by default)
}), ], })

INFO

The handler can be any supported oRPC handler, such as RPCHandler, OpenAPIHandler, or a custom one.

Using the Logger in Your Code

This plugin supports using AsyncLocalStorage to access the logger throughout a request and enrich the final wide event. It is the most convenient way to use Evlog's full feature set. If your runtime does not support AsyncLocalStorage, you can still access the logger from the context.

ts
import { createLoggerStorage } from '@orpc/evlog/node'

/**
 * Pass `storage` to the plugin configuration.
 * Call `useLogger` inside a procedure to access the request logger.
 */
export const { storage, useLogger } = createLoggerStorage()

const procedure = os
  .handler(async () => {
    const logger = useLogger() 

    logger?.set({ user: { id: 123, name: 'John Doe' } }) 

    await logger.fork('child-procedure', () => {
      const logger = useLogger() 
    })

    return { success: true }
  })
ts
const handler = new RPCHandler(router, {
  plugins: [
    new EvlogHandlerPlugin({
      storage, // <- pass the storage to the plugin
    }),
  ],
})

Without AsyncLocalStorage

If you do not want to use AsyncLocalStorage, or your runtime does not support it, you can still read the logger from the context.

ts
import { getLogger, LoggerContext } from '@orpc/evlog'

interface ServerContext extends LoggerContext {} 

const procedure = os
  .$context<ServerContext>()
  .handler(({ context }) => {
    const logger = getLogger(context) 

    logger?.set({ user: { id: 123, name: 'John Doe' } }) 

    return { success: true }
  })

Released under the MIT License.