Skip to content
Logixlysia
Esc
navigateopen⌘Jpreview
On this page

Adapters Overview

Ship logs to observability platforms with built-in adapters

Send your logs to external observability platforms with built-in adapters. Each adapter is a regular transport — batched, retried, and non-blocking — so you can mix them with console and file logging or run them exclusively.

Available Adapters

Cloud Platforms

Platform Import Best for
Axiom logixlysia/axiom Schema-free log analytics — every field is queryable
Better Stack logixlysia/better-stack Logs, uptime, and alerting in one place
Datadog logixlysia/datadog Enterprise observability with facets and pipelines
Sentry logixlysia/sentry Structured logs next to your errors and traces
PostHog logixlysia/posthog Product analytics — link logs to persons and funnels

Self-Hosted & Open Standards

Platform Import Best for
OTLP logixlysia/otlp Any OpenTelemetry backend — collectors, Grafana Cloud, New Relic, Honeycomb, SigNoz
HyperDX logixlysia/hyperdx Open-source observability via OTLP
Grafana Loki logixlysia/loki Label-indexed logs for the Grafana stack
ClickHouse logixlysia/clickhouse Your own SQL log warehouse, no pipeline in between

Quick Start

Set the platform’s environment variables, create the transport, and pass it to transports:

import { Elysia } from 'elysia'
import logixlysia from 'logixlysia'
import { createAxiomTransport } from 'logixlysia/axiom'

const app = new Elysia()
  .use(
    logixlysia({
      config: {
        transports: [createAxiomTransport()]
      }
    })
  )
  .get('/', () => 'ok')
  .listen(3000)

Trigger a request and the access log appears in your platform’s log explorer.

Shared Behavior

All adapters share the same core:

  • Batching — entries buffer and flush either when maxBatchSize is reached (default 20) or after flushIntervalMs (default 2000 ms), whichever comes first.
  • Retries — network errors, 429, and 5xx responses retry with linear backoff (default 2 retries). Other 4xx responses fail immediately.
  • Timeout — each request aborts after timeout ms (default 5000).
  • Non-blocking — sends run in the background and never delay your HTTP responses. Failures are reported through onError (sink 'transport') or rate-limited to stderr.
  • Credentials — read from environment variables by default; options passed to the factory always win. Missing credentials throw at startup with an actionable message, not silently at runtime.

Every adapter accepts these options on top of its platform-specific ones:

Option Type Default Description
maxBatchSize number 20 Entries buffered before an immediate flush
flushIntervalMs number 2000 Max time an entry waits before the buffer is sent
timeout number 5000 Per-request timeout in milliseconds
retries number 2 Retry attempts on network errors, 429, and 5xx

Multiple Destinations

Adapters compose — fan the same logs out to several platforms:

import { createAxiomTransport } from 'logixlysia/axiom'
import { createSentryTransport } from 'logixlysia/sentry'

app.use(
  logixlysia({
    config: {
      transports: [createAxiomTransport(), createSentryTransport()]
    }
  })
)

Production-Only External Logging

Use useTransportsOnly to disable console and file output and send logs exclusively to your platform:

app.use(
  logixlysia({
    config: {
      transports: [createAxiomTransport()],
      useTransportsOnly: process.env.NODE_ENV === 'production'
    }
  })
)

Graceful Shutdown

Batching timers never keep the process alive, so flush pending entries before exit. beforeExit alone does not fire on SIGTERM/SIGINT, so handle those too:

const axiom = createAxiomTransport()
const FLUSH_DEADLINE_MS = 3000

const shutdown = async () => {
  await app.stop()
  await Promise.race([
    axiom.flush().catch(() => {
      /* already reported */
    }),
    new Promise(resolve => setTimeout(resolve, FLUSH_DEADLINE_MS))
  ])
  process.exit(0)
}

process.on('SIGTERM', shutdown)
process.on('SIGINT', shutdown)

What Gets Sent

Each log carries its level, message, and the full meta object: the request method and URL, the response status, durationMs, and everything merged into the request context — request IDs, trace IDs, user IDs, and your own fields. Platforms that prefer flat attributes (HyperDX, Sentry, PostHog) receive dot-notation keys like request.method and context.requestId; Axiom receives the nested structure as-is.

Redaction runs before transports, so autoRedact and redactKeys apply to everything an adapter ships off-box.

Last updated on August 22, 2026

Was this page helpful?