Transport Adapters

All 10 built-in transport adapters — Logger, HTTP, OTLP, Sentry, Slack, Discord, Telegram, Memory, Mock, and Store. Compare features, see configuration, and build custom adapters.

Transport Adapters

Transport adapters are pluggable destinations for telemetry events. Each adapter receives the event envelope and routes it to its target — a log file, a monitoring service, a chat platform, or your own backend.


Adapter Comparison

AdapterUse CaseDependenciesImport Path
LoggerConsole/file loggingNone@igniter-js/telemetry/adapters
HTTPWebhook POST to any URLNone@igniter-js/telemetry/adapters
OTLPOpenTelemetry collectorNone@igniter-js/telemetry/adapters
SentryError monitoring@sentry/node@igniter-js/telemetry/adapters
SlackTeam notificationsNone@igniter-js/telemetry/adapters
DiscordTeam notificationsNone@igniter-js/telemetry/adapters
TelegramTeam notificationsNone@igniter-js/telemetry/adapters
MemoryTesting/debuggingNone@igniter-js/telemetry/adapters
MockUnit testingNone@igniter-js/telemetry/adapters
StoreRedis Streams persistence@igniter-js/store@igniter-js/telemetry/adapters

Logger Adapter

Outputs events to any logger with info(), warn(), error(), and debug() methods.

import { LoggerTransportAdapter } from "@igniter-js/telemetry/adapters";

const logger = LoggerTransportAdapter.create({
  logger: console,
  format: "json",           // "json" | "pretty"
  minLevel: "info",         // Minimum level to log
  includeTimestamp: true,   // Include ISO timestamp
});
OptionTypeDefaultDescription
loggerobjectrequiredAny object with info/warn/error/debug methods
format"json" | "pretty""pretty"Output format
minLevelstring"debug"Minimum level to log
includeTimestampbooleantrueInclude ISO 8601 timestamp
// JSON format output
const jsonLogger = LoggerTransportAdapter.create({
  logger: console,
  format: "json",
});

// Filter to errors only
const errorLogger = LoggerTransportAdapter.create({
  logger: console,
  format: "pretty",
  minLevel: "error",
});

HTTP Adapter

Sends events as JSON via HTTP POST to any URL.

import { HttpTransportAdapter } from "@igniter-js/telemetry/adapters";

const http = HttpTransportAdapter.create({
  url: "https://webhook.example.com/telemetry",
  headers: {
    Authorization: `Bearer ${process.env.TELEMETRY_TOKEN}`,
    "X-Service-Name": "billing-api",
  },
  timeout: 4000,    // Request timeout in ms
  retries: 2,       // Number of retries on failure
});
OptionTypeDefaultDescription
urlstringrequiredTarget webhook URL
headersRecord<string, string>{}Custom HTTP headers
timeoutnumber5000Request timeout in ms
retriesnumber0Number of retries on failure

OTLP Adapter

Sends events to an OpenTelemetry collector via OTLP HTTP.

import { OtlpTransportAdapter } from "@igniter-js/telemetry/adapters";

const otlp = OtlpTransportAdapter.create({
  url: "http://localhost:4318/v1/logs",
  headers: {
    "x-api-key": process.env.OTEL_API_KEY ?? "",
  },
});
OptionTypeDefaultDescription
urlstringrequiredOTLP HTTP endpoint
headersRecord<string, string>{}Custom headers

The OTLP adapter sends events as OTLP Logs over HTTP. Point it at any OTEL collector (Jaeger, Grafana Tempo, Datadog Agent with OTLP ingest).


Sentry Adapter

Forwards error-level events to Sentry for error monitoring.

import * as Sentry from "@sentry/node";
import { SentryTransportAdapter } from "@igniter-js/telemetry/adapters";

Sentry.init({ dsn: process.env.SENTRY_DSN });

const sentry = SentryTransportAdapter.create({
  sentry: Sentry,
});
OptionTypeDefaultDescription
sentrytypeof SentryrequiredInitialized Sentry SDK instance

The Sentry adapter only forwards error-level events. Info, debug, and warn events are ignored. Initialize Sentry with Sentry.init() before creating the adapter.


Slack Adapter

Posts events to a Slack channel via webhook.

import { SlackTransportAdapter } from "@igniter-js/telemetry/adapters";

const slack = SlackTransportAdapter.create({
  webhookUrl: process.env.SLACK_WEBHOOK_URL ?? "",
  minLevel: "error",                    // Only error+ events
  username: "Igniter Bot",
  iconEmoji: ":rotating_light:",
});
OptionTypeDefaultDescription
webhookUrlstringrequiredSlack incoming webhook URL
minLevelstring"warn"Minimum event level to post
usernamestring"Igniter Telemetry"Bot display name
iconEmojistring":bar_chart:"Bot icon emoji

Discord Adapter

Posts events to a Discord channel via webhook.

import { DiscordTransportAdapter } from "@igniter-js/telemetry/adapters";

const discord = DiscordTransportAdapter.create({
  webhookUrl: process.env.DISCORD_WEBHOOK_URL ?? "",
  minLevel: "warn",
  username: "Igniter Bot",
  avatarUrl: "https://example.com/bot-avatar.png",
});
OptionTypeDefaultDescription
webhookUrlstringrequiredDiscord webhook URL
minLevelstring"warn"Minimum event level
usernamestring"Igniter Telemetry"Bot display name
avatarUrlstringBot avatar URL

Telegram Adapter

Sends events to a Telegram chat via bot API.

import { TelegramTransportAdapter } from "@igniter-js/telemetry/adapters";

const telegram = TelegramTransportAdapter.create({
  botToken: process.env.TELEGRAM_BOT_TOKEN ?? "",
  chatId: process.env.TELEGRAM_CHAT_ID ?? "",
  minLevel: "error",
});
OptionTypeDefaultDescription
botTokenstringrequiredTelegram bot token from @BotFather
chatIdstringrequiredTarget chat ID
minLevelstring"error"Minimum event level

In-Memory Adapter

Stores events in memory. Ideal for testing and debugging.

import { InMemoryTransportAdapter } from "@igniter-js/telemetry/adapters";

const memory = InMemoryTransportAdapter.create();

const telemetry = IgniterTelemetry.create()
  .withService("test")
  .addTransport(memory)
  .build();

telemetry.emit("test.event.one", {
  attributes: { "ctx.value": 1 },
});
telemetry.emit("test.event.two", {
  attributes: { "ctx.value": 2 },
});

// Inspect captured events
const events = memory.getEvents();
console.log(events.length);       // 2
console.log(events[0].name);      // "test.event.one"
console.log(events[0].attributes); // { "ctx.value": 1 }

// Clear events
memory.clear();
MethodDescription
.getEvents()Returns all captured events
.clear()Clears all captured events

Mock Adapter

Records events and provides assertion helpers. Designed for unit tests.

import { MockTelemetryAdapter } from "@igniter-js/telemetry/adapters";

const mock = MockTelemetryAdapter.create();

const telemetry = IgniterTelemetry.create()
  .withService("test")
  .addTransport(mock)
  .build();

telemetry.emit("user.created", {
  attributes: { "ctx.user.id": "usr_001" },
});

// Assertions
expect(mock.getLastEvent()?.name).toBe("user.created");
expect(mock.getLastEvent()?.attributes).toEqual({
  "ctx.user.id": "usr_001",
});
MethodDescription
.getLastEvent()Returns the most recent event
.getEvents()Returns all captured events
.clear()Clears captured events

Store Stream Adapter

Persists events to Redis Streams via @igniter-js/store. Best for durable event storage and replay.

import { IgniterStore } from "@igniter-js/store";
import { StoreStreamTransportAdapter } from "@igniter-js/telemetry/adapters";

const store = IgniterStore.create()
  .withAdapter(redisAdapter)
  .withNamespace("telemetry")
  .build();

const storeTransport = StoreStreamTransportAdapter.create({
  store,
  stream: "telemetry:events",
  maxLen: 10000,   // Max stream length (capped)
});
OptionTypeDefaultDescription
storeIgniterStorerequiredInitialized store instance
streamstring"telemetry:events"Redis Stream key
maxLennumber10000Maximum stream length (capped)

The Store adapter requires @igniter-js/store as a peer dependency. Install it separately: npm install @igniter-js/store.


Multiple Transports

Add as many transports as you need — events fan out to all of them:

const telemetry = IgniterTelemetry.create()
  .withService("api")
  .addTransport(LoggerTransportAdapter.create({ logger: console }))
  .addTransport(HttpTransportAdapter.create({ url: "https://..." }))
  .addTransport(SentryTransportAdapter.create({ sentry: Sentry }))
  .addTransport(SlackTransportAdapter.create({ webhookUrl: "..." }))
  .build();

// All four transports receive every event
telemetry.emit("payment.failed", {
  level: "error",
  error: { name: "PaymentError", message: "..." },
});

If all transports fail for a given event, telemetry throws TELEMETRY_TRANSPORT_FAILED. Individual transport failures are silently logged but do not prevent other transports from receiving the event.


Custom Transport Adapter

Implement the IgniterTelemetryTransportAdapter interface to create your own adapter:

import type {
  IgniterTelemetryTransportAdapter,
  IgniterTelemetryEnvelope,
  IgniterTelemetryTransportMeta,
} from "@igniter-js/telemetry";

class DatadogTransport implements IgniterTelemetryTransportAdapter {
  readonly type = "datadog" as const;

  async init(meta: IgniterTelemetryTransportMeta): Promise<void> {
    // Optional: validate API key, open connection
    console.log(`Datadog transport initialized for ${meta.service}`);
  }

  async handle(envelope: IgniterTelemetryEnvelope): Promise<void> {
    await fetch("https://http-intake.logs.datadoghq.com/api/v2/logs", {
      method: "POST",
      headers: {
        "Content-Type": "application/json",
        "DD-API-KEY": process.env.DD_API_KEY!,
      },
      body: JSON.stringify({
        ddsource: envelope.service,
        ddtags: `env:${envelope.environment}`,
        service: envelope.service,
        message: envelope.name,
        ...envelope,
      }),
    });
  }

  async flush(): Promise<void> {
    // Optional: flush any buffered events
  }

  async shutdown(): Promise<void> {
    // Optional: close connections, cleanup
  }
}

// Use it
const telemetry = IgniterTelemetry.create()
  .withService("api")
  .addTransport(new DatadogTransport())
  .build();

Adapter Interface

MethodRequiredDescription
typeYesUnique adapter identifier string
init(meta)NoCalled during .build() — validate/set up
handle(envelope)YesProcess a telemetry event
flush()NoFlush buffered events
shutdown()NoGraceful cleanup

Next Steps