Skip to content
Merged
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
4 changes: 4 additions & 0 deletions apps/docs/content/3.cli/1.init.md
Original file line number Diff line number Diff line change
Expand Up @@ -216,6 +216,8 @@ export const { register, onRequestError } = createInstrumentation({
export const { withEvlog, useLogger, log, createError } = createEvlog(config)
```

`init` writes the config import relative to the file it creates, so `src/lib/evlog.ts` imports `../../evlog.config`.

Wrapping handlers stays yours: Next has no ambient request logger, so each route opts in with `withEvlog()`. `init` prints the snippet.

### TanStack Start
Expand All @@ -241,6 +243,8 @@ initLogger(toLoggerConfig(config))
export const evlogMiddleware = evlog(toMiddlewareOptions(config))
```

The config import is relative to the file `init` creates, so a root-level `evlog.ts` imports `./evlog.config`.

### Express

Same shape as Hono: `src/evlog.ts` starts the logger from the config and exports an `evlogMiddleware` built from `evlog/express`, and the `app.use(evlogMiddleware)` line is left for you to paste before your routes.
Expand Down
26 changes: 26 additions & 0 deletions apps/docs/content/4.integrate/frameworks/02.nextjs.md
Original file line number Diff line number Diff line change
Expand Up @@ -421,6 +421,32 @@ The `createEvlog()` factory accepts the following options:
| `drain` | `DrainFunction` | `undefined` | Drain adapter for external services |
| `enrich` | `(ctx: EnrichContext) => void` | `undefined` | Event enrichment callback |

### Keep the options in evlog.config.ts

The options can live in an [`evlog.config.ts`](/cli/config) at the root of the app, the file the CLI reads too. Read it in `lib/evlog.ts` for both the instrumentation and `createEvlog()`:

```typescript [lib/evlog.ts]
import { toLoggerConfig } from 'evlog'
import { createEvlog } from 'evlog/next'
import { createInstrumentation } from 'evlog/next/instrumentation/create'
import config from '../evlog.config'

export const { register, onRequestError } = createInstrumentation({
...toLoggerConfig(config),
captureOutput: true,
})

export const { withEvlog, useLogger, log, createError } = createEvlog(config)
```

```typescript [instrumentation.ts]
import { defineNodeInstrumentation } from 'evlog/next/instrumentation'

export const { register, onRequestError } = defineNodeInstrumentation(() => import('./lib/evlog'))
```

`defineNodeInstrumentation` loads `lib/evlog.ts` on Node.js only, so the drains the config imports stay out of the Edge bundle. `register()` starts the logger from the file before any route runs, and `createEvlog()` takes the route filters, `enrich` and `keep` from it. [`evlog init`](/cli/init#nextjs) writes both files for you.

## Tail Sampling

Combine rule-based and custom tail sampling to always capture what matters, even when head sampling drops most logs:
Expand Down
16 changes: 16 additions & 0 deletions apps/docs/content/4.integrate/frameworks/03.sveltekit.md
Original file line number Diff line number Diff line change
Expand Up @@ -214,6 +214,22 @@ The error is captured and logged with both the custom context and structured err

See the [Configuration reference](/reference/configuration) for all available options (`initLogger`, middleware options, sampling, silent mode, etc.).

### Keep the options in evlog.config.ts

The options can live in an [`evlog.config.ts`](/cli/config) at the root of the app, the file the CLI reads too. Import it in the server hooks:

```typescript [src/hooks.server.ts]
import { initLogger, toLoggerConfig, toMiddlewareOptions } from 'evlog'
import { createEvlogHooks } from 'evlog/sveltekit'
import config from '../evlog.config'

initLogger(toLoggerConfig(config))

export const { handle, handleError } = createEvlogHooks(toMiddlewareOptions(config))
```

`toLoggerConfig` keeps the options `initLogger` takes and `toMiddlewareOptions` the ones the hooks take, so the sampling, drain, `enrich` and route filters of the file all apply. The [Vite plugin](/reference/vite-plugin) does not read the file. Keep it for stripping and source locations: the `initLogger` call replaces its auto-initialization, so the service and sampling come from the file.

## Drain & Enrichers

Configure drain adapters and enrichers directly in the hooks options:
Expand Down
4 changes: 4 additions & 0 deletions apps/docs/content/4.integrate/frameworks/05.tanstack-start.md
Original file line number Diff line number Diff line change
Expand Up @@ -227,6 +227,10 @@ try {

See the [Configuration reference](/reference/configuration) for all available options (`initLogger`, middleware options, sampling, silent mode, etc.).

### Keep the options in evlog.config.ts

The options can live in an [`evlog.config.ts`](/cli/config) at the root of the app, the file the CLI reads too. The `evlog/nitro/v3` module finds it and bundles it into the server, with nothing to import. Options passed to the module in `nitro.config.ts` override the file. See [Nuxt and Nitro load it for you](/cli/config#nuxt-and-nitro-load-it-for-you).

## Route Filtering

Control which routes are logged with `include` and `exclude` in the module options:
Expand Down
33 changes: 33 additions & 0 deletions apps/docs/content/4.integrate/frameworks/06.nestjs.md
Original file line number Diff line number Diff line change
Expand Up @@ -242,6 +242,39 @@ The error is captured and logged with both the custom context and structured err

See the [Configuration reference](/reference/configuration) for all available options (`initLogger`, middleware options, sampling, silent mode, etc.).

### Keep the options in evlog.config.ts

The options can live in an [`evlog.config.ts`](/cli/config) at the root of the app, the file the CLI reads too. Import it where you call `initLogger` and where you register the module:

```typescript [src/main.ts]
import 'reflect-metadata'
import { NestFactory } from '@nestjs/core'
import { initLogger, toLoggerConfig } from 'evlog'
import config from '../evlog.config'
import { AppModule } from './app.module'

initLogger(toLoggerConfig(config))

const app = await NestFactory.create(AppModule)
await app.listen(3000)
```

```typescript [src/app.module.ts]
import { Module } from '@nestjs/common'
import { toMiddlewareOptions } from 'evlog'
import { EvlogModule } from 'evlog/nestjs'
import config from '../evlog.config'

@Module({
imports: [
EvlogModule.forRoot(toMiddlewareOptions(config)),
],
})
export class AppModule {}
```

`toLoggerConfig` keeps the options `initLogger` takes and `toMiddlewareOptions` the ones `forRoot()` takes, so the sampling, drain, `enrich` and route filters of the file all apply.

## Drain & Enrichers

Configure drain adapters and enrichers in `EvlogModule.forRoot()`:
Expand Down
18 changes: 18 additions & 0 deletions apps/docs/content/4.integrate/frameworks/07.express.md
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,24 @@ The error is captured and logged with both the custom context and structured err

See the [Configuration reference](/reference/configuration) for all available options (`initLogger`, middleware options, sampling, silent mode, etc.).

### Keep the options in evlog.config.ts

The options can live in an [`evlog.config.ts`](/cli/config) at the root of the app, the file the CLI reads too. Import it where you call `initLogger` and where you register the middleware:

```typescript [src/index.ts]
import express from 'express'
import { initLogger, toLoggerConfig, toMiddlewareOptions } from 'evlog'
import { evlog } from 'evlog/express'
import config from '../evlog.config'

initLogger(toLoggerConfig(config))

const app = express()
app.use(evlog(toMiddlewareOptions(config)))
```

`toLoggerConfig` keeps the options `initLogger` takes and `toMiddlewareOptions` the ones `evlog()` takes, so the sampling, drain, `enrich` and route filters of the file all apply. [`evlog init`](/cli/init#per-framework) writes this wiring for you.

## Drain & Enrichers

Configure drain adapters and enrichers directly in the middleware options:
Expand Down
18 changes: 18 additions & 0 deletions apps/docs/content/4.integrate/frameworks/08.hono.md
Original file line number Diff line number Diff line change
Expand Up @@ -217,6 +217,24 @@ The error is captured and logged with both the custom context and structured err

See the [Configuration reference](/reference/configuration) for all available options (`initLogger`, middleware options, sampling, silent mode, etc.).

### Keep the options in evlog.config.ts

The options can live in an [`evlog.config.ts`](/cli/config) at the root of the app, the file the CLI reads too. Import it where you call `initLogger` and where you register the middleware:

```typescript [src/index.ts]
import { Hono } from 'hono'
import { initLogger, toLoggerConfig, toMiddlewareOptions } from 'evlog'
import { evlog, type EvlogVariables } from 'evlog/hono'
import config from '../evlog.config'

initLogger(toLoggerConfig(config))

const app = new Hono<EvlogVariables>()
app.use(evlog(toMiddlewareOptions(config)))
```

`toLoggerConfig` keeps the options `initLogger` takes and `toMiddlewareOptions` the ones `evlog()` takes, so the sampling, drain, `enrich` and route filters of the file all apply. [`evlog init`](/cli/init#per-framework) writes this wiring for you.

## Drain & Enrichers

Configure drain adapters and enrichers directly in the middleware options:
Expand Down
18 changes: 18 additions & 0 deletions apps/docs/content/4.integrate/frameworks/09.fastify.md
Original file line number Diff line number Diff line change
Expand Up @@ -202,6 +202,24 @@ The error is captured and logged with both the custom context and structured err

See the [Configuration reference](/reference/configuration) for all available options (`initLogger`, middleware options, sampling, silent mode, etc.).

### Keep the options in evlog.config.ts

The options can live in an [`evlog.config.ts`](/cli/config) at the root of the app, the file the CLI reads too. Import it where you call `initLogger` and where you register the plugin:

```typescript [src/index.ts]
import Fastify from 'fastify'
import { initLogger, toLoggerConfig, toMiddlewareOptions } from 'evlog'
import { evlog } from 'evlog/fastify'
import config from '../evlog.config'

initLogger(toLoggerConfig(config))

const app = Fastify({ logger: false })
await app.register(evlog, toMiddlewareOptions(config))
```

`toLoggerConfig` keeps the options `initLogger` takes and `toMiddlewareOptions` the ones the plugin takes, so the sampling, drain, `enrich` and route filters of the file all apply. [`evlog init`](/cli/init#per-framework) writes this wiring for you.

## Drain & Enrichers

Configure drain adapters and enrichers directly in the plugin options:
Expand Down
19 changes: 19 additions & 0 deletions apps/docs/content/4.integrate/frameworks/10.elysia.md
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,25 @@ The error is captured and logged with both the custom context and structured err

See the [Configuration reference](/reference/configuration) for all available options (`initLogger`, middleware options, sampling, silent mode, etc.).

### Keep the options in evlog.config.ts

The options can live in an [`evlog.config.ts`](/cli/config) at the root of the app, the file the CLI reads too. Import it where you call `initLogger` and where you register the plugin:

```typescript [src/index.ts]
import { Elysia } from 'elysia'
import { initLogger, toLoggerConfig, toMiddlewareOptions } from 'evlog'
import { evlog } from 'evlog/elysia'
import config from '../evlog.config'

initLogger(toLoggerConfig(config))

const app = new Elysia()
.use(evlog(toMiddlewareOptions(config)))
.listen(3000)
```

`toLoggerConfig` keeps the options `initLogger` takes and `toMiddlewareOptions` the ones `evlog()` takes, so the sampling, drain, `enrich` and route filters of the file all apply.

## Drain & Enrichers

Configure drain adapters and enrichers directly in the plugin options:
Expand Down
24 changes: 24 additions & 0 deletions apps/docs/content/4.integrate/frameworks/11.react-router.md
Original file line number Diff line number Diff line change
Expand Up @@ -241,6 +241,30 @@ The error is captured and logged with both the custom context and structured err

See the [Configuration reference](/reference/configuration) for all available options (`initLogger`, middleware options, sampling, silent mode, etc.).

### Keep the options in evlog.config.ts

The options can live in an [`evlog.config.ts`](/cli/config) at the root of the app, the file the CLI reads too. Read it in a `.server` module, which React Router keeps out of the browser bundle along with the drains the file imports:

```typescript [app/evlog.server.ts]
import { initLogger, toLoggerConfig, toMiddlewareOptions } from 'evlog'
import { evlog } from 'evlog/react-router'
import config from '../evlog.config'

initLogger(toLoggerConfig(config))

export const evlogMiddleware = evlog(toMiddlewareOptions(config))
```

```typescript [app/root.tsx]
import { evlogMiddleware } from './evlog.server'

export const middleware: Route.MiddlewareFunction[] = [
evlogMiddleware,
]
```

`toLoggerConfig` keeps the options `initLogger` takes and `toMiddlewareOptions` the ones `evlog()` takes, so the sampling, drain, `enrich` and route filters of the file all apply.

## Drain & Enrichers

Configure drain adapters and enrichers directly in the middleware options:
Expand Down
29 changes: 27 additions & 2 deletions apps/docs/content/4.integrate/frameworks/12.cloudflare-workers.md
Original file line number Diff line number Diff line change
Expand Up @@ -206,12 +206,31 @@ export default defineWorkerFetch(async (request, env, _ctx, log) => {

See the [Configuration reference](/reference/configuration) for all available options (`initLogger`, middleware options, sampling, silent mode, etc.).

### Keep the options in evlog.config.ts

The options can live in an [`evlog.config.ts`](/cli/config) at the root of the Worker, the file the CLI reads too. Import it where you call `initWorkersLogger` and where you wrap the handler:

```typescript [src/worker.ts]
import { toLoggerConfig, toMiddlewareOptions } from 'evlog'
import { initWorkersLogger, withEvlog } from 'evlog/workers'
import config from '../evlog.config'

initWorkersLogger(toLoggerConfig(config))

export default withEvlog(async (request, _env, _ctx, log) => {
log.set({ action: 'handle_request' })
return Response.json({ ok: true })
}, toMiddlewareOptions(config))
```

`toLoggerConfig` keeps the options `initWorkersLogger` takes and `toMiddlewareOptions` the ones `withEvlog()` takes, so the sampling, drain, `enrich` and route filters of the file all apply. `initWorkersLogger` always sets `pretty` and `stringify` to `false`, whatever the file says.

## Drain & Enrichers

Configure drain and enrichers via `initWorkersLogger` options:
The drain goes to `initWorkersLogger`, and the enrichers to the `withEvlog` options, which run them on every request event:

```typescript [src/worker.ts]
import { initWorkersLogger, createWorkersLogger } from 'evlog/workers'
import { initWorkersLogger, withEvlog } from 'evlog/workers'
import { createAxiomDrain } from 'evlog/axiom'
import { createUserAgentEnricher } from 'evlog/enrichers'
import { createDrainPipeline } from 'evlog/pipeline'
Expand All @@ -226,6 +245,12 @@ const userAgent = createUserAgentEnricher()
initWorkersLogger({
env: { service: 'my-worker' },
drain,
})

export default withEvlog(async (request, _env, _ctx, log) => {
log.set({ action: 'handle_request' })
return Response.json({ ok: true })
}, {
enrich: (ctx) => {
userAgent(ctx)
},
Expand Down
13 changes: 13 additions & 0 deletions apps/docs/content/4.integrate/frameworks/13.standalone.md
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,19 @@ try {

See the [Configuration reference](/reference/configuration) for all available options (`initLogger`, middleware options, sampling, silent mode, etc.).

### Keep the options in evlog.config.ts

The options can live in an [`evlog.config.ts`](/cli/config) next to the `package.json`, the file the CLI reads too. Pass it to `initLogger`:

```typescript [src/index.ts]
import { initLogger, toLoggerConfig } from 'evlog'
import config from '../evlog.config'

initLogger(toLoggerConfig(config))
```

`toLoggerConfig` keeps every option `initLogger` takes, such as the service, sampling, `minLevel`, `redact`, the drain and the plugins. The file's `enrich`, `keep`, `include`, `exclude` and `routes` are framework middleware options, so they do not apply to a script.

## Drain & Enrichers

Configure drain in `initLogger`:
Expand Down
18 changes: 18 additions & 0 deletions apps/docs/content/4.integrate/frameworks/14.astro.md
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,24 @@ export const POST: APIRoute = async ({ request, locals }) => {

See the [Configuration reference](/reference/configuration) for all available options (`initLogger`, middleware options, sampling, silent mode, etc.).

### Keep the options in evlog.config.ts

The options can live in an [`evlog.config.ts`](/cli/config) at the root of the app, the file the CLI reads too. Pass it to `initLogger` in the middleware:

```typescript [src/middleware.ts]
import { defineMiddleware } from 'astro:middleware'
import { initLogger, createRequestLogger, toLoggerConfig } from 'evlog'
import config from '../evlog.config'

initLogger(toLoggerConfig(config))

export const onRequest = defineMiddleware(async ({ request, locals }, next) => {
// ... same as above
})
```

`toLoggerConfig` keeps every option `initLogger` takes, such as the service, sampling, `minLevel`, `redact`, the drain and the plugins. This guide builds the request logger with `createRequestLogger`, not an evlog middleware, so the file's `enrich`, `keep`, `include`, `exclude` and `routes` do not apply.

## Drain

Configure drain in `initLogger` inside your middleware:
Expand Down
17 changes: 17 additions & 0 deletions apps/docs/content/4.integrate/frameworks/15.orpc.md
Original file line number Diff line number Diff line change
Expand Up @@ -233,6 +233,23 @@ oRPC's error envelope is `{ defined, code, status, message, data }`. Clients des

See the [Configuration reference](/reference/configuration) for all available options (`initLogger`, middleware options, sampling, silent mode, etc.).

### Keep the options in evlog.config.ts

The options can live in an [`evlog.config.ts`](/cli/config) at the root of the app, the file the CLI reads too. Import it where you call `initLogger` and where you wrap the handler:

```typescript [server/orpc.ts]
import { RPCHandler } from '@orpc/server/fetch'
import { initLogger, toLoggerConfig, toMiddlewareOptions } from 'evlog'
import { withEvlog } from 'evlog/orpc'
import config from '../evlog.config'

initLogger(toLoggerConfig(config))

const handler = withEvlog(new RPCHandler(router), toMiddlewareOptions(config))
```

`toLoggerConfig` keeps the options `initLogger` takes and `toMiddlewareOptions` the ones `withEvlog()` takes, so the sampling, drain, `enrich` and route filters of the file all apply. The `evlog()` middleware on your procedures takes no options and stays as it is.

## Drain & Enrichers

Configure drain adapters and enrichers directly in the `withEvlog()` options:
Expand Down
15 changes: 14 additions & 1 deletion apps/docs/content/4.integrate/frameworks/16.aws-lambda.md
Original file line number Diff line number Diff line change
Expand Up @@ -108,9 +108,22 @@ initLogger({
```

::callout{icon="i-lucide-alert-triangle" color="warning"}
If `silent` is enabled without a `drain`, events may not be visible anywhere. See the configuration docs for details.
If `silent` is enabled without a `drain`, events are built but never written anywhere. [Silence the terminal](/reference/configuration#silence-the-terminal) covers when to use it.
::

## Keep the options in evlog.config.ts

The options can live in an [`evlog.config.ts`](/cli/config) next to the `package.json`, the file the CLI reads too. Your bundler includes it with the handler, so the drain and `process.env` reads in it work at cold start:

```typescript [src/handler.ts]
import { initLogger, toLoggerConfig } from 'evlog'
import config from '../evlog.config'

initLogger(toLoggerConfig(config))
```

`toLoggerConfig` keeps every option `initLogger` takes, such as the service, sampling, `minLevel`, `redact`, the drain and the plugins. The file's `enrich`, `keep`, `include`, `exclude` and `routes` are framework middleware options, so they do not apply to a handler.

## Error handling

Use `createError` where you want structured fields (`why`, `fix`, `link`). Map failures to your Lambda return or rethrow so SQS retry/DLQ behavior stays correct. evlog does not replace AWS error semantics.
Expand Down
Loading