Adapters

Better Stack Adapter

Send wide events to Better Stack (formerly Logtail) for log management, alerting, and dashboards. Zero-config setup with environment variables.

Better Stack is a DX-first log management platform with powerful search, alerting, and dashboards. The evlog Better Stack adapter sends your wide events to the Better Stack HTTP ingestion API.

Installation

The Better Stack adapter comes bundled with evlog:

import { createBetterStackDrain } from 'evlog/better-stack'

Quick Start

1. Get your source token

  1. Create a Better Stack account
  2. Go to Telemetry > Sources and create a new source
  3. Copy the Source Token

2. Set environment variables

.env
BETTER_STACK_SOURCE_TOKEN=your-source-token-here

3. Wire the drain to your framework

// server/plugins/evlog-drain.ts
import { createBetterStackDrain } from 'evlog/better-stack'

export default defineNitroPlugin((nitroApp) => {
  nitroApp.hooks.hook('evlog:drain', createBetterStackDrain())
})

That's it! Your logs will now appear in Better Stack.

Configuration

The adapter reads configuration from multiple sources (highest priority first):

  1. Overrides passed to createBetterStackDrain()
  2. Runtime config at runtimeConfig.betterStack (Nuxt/Nitro only)
  3. Environment variables (BETTER_STACK_* or NUXT_BETTER_STACK_*)

Environment Variables

VariableNuxt aliasDescription
BETTER_STACK_SOURCE_TOKENNUXT_BETTER_STACK_SOURCE_TOKENBetter Stack source token (required)
BETTER_STACK_ENDPOINTNUXT_BETTER_STACK_ENDPOINTCustom ingestion endpoint

Runtime Config (Nuxt only)

Configure via nuxt.config.ts for type-safe configuration:

nuxt.config.ts
export default defineNuxtConfig({
  runtimeConfig: {
    betterStack: {
      sourceToken: '', // Set via NUXT_BETTER_STACK_SOURCE_TOKEN
    },
  },
})

Override Options

Pass options directly to override any configuration:

const drain = createBetterStackDrain({
  sourceToken: 'my-token',
  timeout: 10000,
})

Full Configuration Reference

OptionTypeDefaultDescription
sourceTokenstring-Better Stack source token (required)
endpointstringhttps://in.logs.betterstack.comIngestion endpoint
timeoutnumber5000Request timeout in milliseconds

Log Transformation

evlog wide events are transformed using toBetterStackEvent():

  • Timestamp: timestamp is mapped to dt (Better Stack's expected ISO-8601 timestamp field)
  • All other fields: Spread as-is into the event body

Better Stack accepts arbitrary JSON fields, so all your wide event context (level, service, action, user data, etc.) is automatically searchable.

Querying Logs in Better Stack

Better Stack provides a powerful log search interface:

  • Live tail: Stream logs in real time
  • Full-text search: Search across all fields
  • Structured queries: Filter by level:error, service:my-app, or any wide event field
  • Dashboards: Create custom dashboards from your wide event data
  • Alerts: Set up alerts based on log patterns or thresholds

Troubleshooting

Missing source token error

[evlog/better-stack] Missing source token. Set BETTER_STACK_SOURCE_TOKEN env var or pass to createBetterStackDrain()

Make sure your environment variable is set and the server was restarted after adding it.

401 Unauthorized

Your source token may be invalid or revoked. Generate a new source token in Telemetry > Sources in the Better Stack dashboard.

403 Forbidden

The source may be archived or deleted. Create a new source in Better Stack.

Direct API Usage

For advanced use cases, you can use the lower-level functions:

server/utils/better-stack.ts
import { sendToBetterStack, sendBatchToBetterStack } from 'evlog/better-stack'

// Send a single event
await sendToBetterStack(event, {
  sourceToken: process.env.BETTER_STACK_SOURCE_TOKEN!,
})

// Send multiple events in one request
await sendBatchToBetterStack(events, {
  sourceToken: process.env.BETTER_STACK_SOURCE_TOKEN!,
})

Next Steps