Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 34 additions & 0 deletions .changeset/orpc-integration.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
---
'evlog': minor
---

Add oRPC integration (`evlog/orpc`) with automatic wide-event logging. Two complementary primitives:

- `withEvlog(handler)` β€” wraps `RPCHandler` / `OpenAPIHandler` from `@orpc/server/fetch`. Each matched request becomes one wide event with full pipeline support (drain, enrich, `include`/`exclude`, route-based service overrides, tail sampling). Excluded routes still receive a no-op `context.log` so procedures never crash on missing fields.
- `evlog()` β€” procedure-level middleware (`os.use(evlog())`). Tags the wide event with `operation` (procedure path joined with `.`), forwards the request logger as `context.log`, and promotes the level to `error` when a procedure throws.

```ts
import { os } from '@orpc/server'
import { RPCHandler } from '@orpc/server/fetch'
import { evlog, withEvlog, type EvlogOrpcContext } from 'evlog/orpc'

const base = os.$context<EvlogOrpcContext>().use(evlog())

const router = {
ping: base.handler(({ context }) => {
context.log.set({ pinged: true })
return { ok: true }
}),
}

const handler = withEvlog(new RPCHandler(router))

export default async function fetch(request: Request) {
const { matched, response } = await handler.handle(request, { prefix: '/rpc' })
return matched ? response : new Response('Not Found', { status: 404 })
}
```

`useLogger()` is exposed for off-context access (utility modules / deep service functions). `EvlogOrpcContext` is the type to plug into `os.$context()` for typed access.

Closes [#297](https://github.com/HugoRCD/evlog/issues/297).
1 change: 1 addition & 0 deletions .github/pull_request_template.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ scope.
- next (Next.js integration)
- nitro (Nitro plugin)
- nuxt (Nuxt module)
- orpc (oRPC integration)
- otlp (OTLP drain adapter)
- playground (the playground app)
- posthog (PostHog drain adapter)
Expand Down
1 change: 1 addition & 0 deletions .github/workflows/semantic-pull-request.yml
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ jobs:
next
nitro
nuxt
orpc
otlp
playground
posthog
Expand Down
4 changes: 4 additions & 0 deletions apps/docs/app/components/features/FeatureFrameworks.vue
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ const frameworkRows = [
{ name: 'Hono', icon: 'i-simple-icons-hono', tab: 8 },
{ name: 'Fastify', icon: 'i-simple-icons-fastify', tab: 9 },
{ name: 'Elysia', icon: 'i-custom-elysia', tab: 10 },
{ name: 'oRPC', icon: 'i-lucide-network', tab: 13 },
{ name: 'Cloudflare', icon: 'i-simple-icons-cloudflare', tab: 11 },
{ name: 'Vite', icon: 'i-custom-vite', link: '/reference/vite-plugin' },
],
Expand Down Expand Up @@ -153,6 +154,9 @@ const frameworkRows = [
<div v-show="activeTab === 12" class="landing-code">
<slot name="bun" />
</div>
<div v-show="activeTab === 13" class="landing-code">
<slot name="orpc" />
</div>
</Motion>
</section>
</template>
26 changes: 26 additions & 0 deletions apps/docs/content/0.landing.md
Original file line number Diff line number Diff line change
Expand Up @@ -425,6 +425,32 @@ A modern TypeScript logger built for everything you ship. Simple logs, wide even
})
```

#orpc
```ts [server/orpc.ts]
import { os } from '@orpc/server'
import { RPCHandler } from '@orpc/server/fetch'
import { evlog, withEvlog, type EvlogOrpcContext } from 'evlog/orpc'
import { createAxiomDrain } from 'evlog/axiom'

const base = os.$context<EvlogOrpcContext>().use(evlog())

const router = {
checkout: base
.input(z.object({ cartId: z.string() }))
.handler(async ({ input, context }) => {
const cart = await db.findCart(input.cartId)
context.log.set({ cart: { items: cart.items.length, total: cart.total } })

const charge = await stripe.charge(cart.total)
context.log.set({ stripe: { chargeId: charge.id } })

return { orderId: charge.id }
}),
}

const handler = withEvlog(new RPCHandler(router), { drain: createAxiomDrain() })
```

#cloudflare
```ts [src/worker.ts]
import { defineWorkerFetch, initWorkersLogger } from 'evlog/workers'
Expand Down
9 changes: 9 additions & 0 deletions apps/docs/content/1.start/3.installation.md
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,15 @@ After installing the package, follow the setup guide for your framework:
:::
:::card
---
icon: i-lucide-network
title: oRPC
to: /integrate/frameworks/orpc
color: neutral
---
`withEvlog()` handler wrapper + `evlog()` procedure middleware.
:::
:::card
---
icon: i-simple-icons-cloudflare
title: Cloudflare Workers
to: /integrate/frameworks/cloudflare-workers
Expand Down
10 changes: 10 additions & 0 deletions apps/docs/content/3.integrate/frameworks/00.overview.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ No HTTP framework? Use [Standalone TypeScript](/integrate/frameworks/standalone)
| [Hono](/integrate/frameworks/hono) | `evlog/hono` | Middleware | `c.get('log')` | Stable |
| [Fastify](/integrate/frameworks/fastify) | `evlog/fastify` | Plugin | `request.log` / `useLogger()` | Stable |
| [Elysia](/integrate/frameworks/elysia) | `evlog/elysia` | Plugin | `log` (context) / `useLogger()` | Stable |
| [oRPC](/integrate/frameworks/orpc) | `evlog/orpc` | Handler wrapper + middleware | `context.log` / `useLogger()` | Stable |
| [Cloudflare Workers](/integrate/frameworks/cloudflare-workers) | `evlog/workers` | Factory | `createWorkersLogger()` | Stable |
| [AWS Lambda](/integrate/frameworks/aws-lambda) | `evlog` | Manual | `createLogger()` / `createRequestLogger()` | Guide |
| [Standalone](/integrate/frameworks/standalone) | `evlog` | Manual | `createLogger()` / `createRequestLogger()` | Stable |
Expand Down Expand Up @@ -143,6 +144,15 @@ No HTTP framework? Use [Standalone TypeScript](/integrate/frameworks/standalone)
:::
:::card
---
icon: i-lucide-network
title: oRPC
to: /integrate/frameworks/orpc
color: neutral
---
Handler wrapper + procedure middleware exposing `context.log` and per-procedure `operation`.
:::
:::card
---
icon: i-simple-icons-cloudflare
title: Cloudflare Workers
to: /integrate/frameworks/cloudflare-workers
Expand Down
Loading
Loading