Skip to content
Logixlysia
Esc
↑↓navigate↵open⌘Jpreview
On this page

Custom Transports

Send logs to external services

Send logs to external services using custom transports. Transports work alongside built-in console and file logging.

Looking for Axiom, Better Stack, ClickHouse, Datadog, HyperDX, Loki, OTLP, PostHog, or Sentry? Built-in adapters cover those — with batching, retries, and credential handling included. Custom transports are for everything else.

Output Behavior

Logixlysia supports three types of logging outputs:

  1. Console Logging - Built-in console output
  2. File Logging - Built-in file output
  3. Transport Logging - Custom external services

Controlling Outputs

  • Default: Console + File (if logFilePath is set) + Transports
  • disableInternalLogger: true: Disables console logging only
  • disableFileLogging: true: Disables file logging only
  • useTransportsOnly: true: Disables both console and file, uses only transports

Basic Transport

type Transport = {
  log: (
    level: LogLevel,
    message: string,
    meta?: Record<string, unknown>
  ) => void | Promise<void>
  flush?: () => void | Promise<void>
  close?: () => void | Promise<void>
}

const consoleTransport: Transport = {
  log: (level, message, meta) => {
    console.log(`[${level}] ${message}`, meta)
  }
}

app.use(
  logixlysia({
    config: {
      transports: [consoleTransport]
    }
  })
)

log is the only required member. Implement flush when your transport batches or queues entries — the plugin calls it on shutdown so the last lines before an exit still arrive. Implement close when you hold a socket, timer, or buffer that must be released; it is never called automatically, only through flushLogixlysia(options, { close: true }), and it must be idempotent.

meta always carries request.method, request.url and durationMs, plus the merged context when there is one. An access line adds status, and its message argument is the empty string. An error line adds status, message and error, a plain object with message, name, status, code, why, fix, link and internal when the error carried them.

External Services

Elasticsearch

const elasticsearchTransport = {
  log: async (level, message, meta) => {
    try {
      await fetch('http://elasticsearch:9200/logs/_doc', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({
          level,
          message,
          ...meta,
          timestamp: new Date().toISOString()
        })
      })
    } catch (err) {
      console.error('Elasticsearch transport error', err)
    }
  }
}

MongoDB

const mongodbTransport = {
  log: async (level, message, meta) => {
    try {
      await db.collection('logs').insertOne({
        level,
        message,
        ...meta,
        timestamp: new Date()
      })
    } catch (err) {
      console.error('MongoDB transport error', err)
    }
  }
}

Slack

const slackTransport = {
  log: async (level, message, meta) => {
    if (level.toLowerCase() === 'error') {
      const webhook = process.env.SLACK_WEBHOOK_URL
      if (!webhook) return

      try {
        await fetch(webhook, {
          method: 'POST',
          headers: { 'Content-Type': 'application/json' },
          body: JSON.stringify({
            text: `[${level}] ${message}\n${JSON.stringify(meta, null, 2)}`
          })
        })
      } catch (err) {
        console.error('Slack transport error', err)
      }
    }
  }
}

Multiple Transports

app.use(
  logixlysia({
    config: {
      transports: [elasticsearchTransport, slackTransport]
    }
  })
)

Transport-Only Logging

app.use(
  logixlysia({
    config: {
      useTransportsOnly: true,
      transports: [elasticsearchTransport, slackTransport]
    }
  })
)

Best Practices

  • Handle transport errors gracefully
  • Implement retry logic for critical transports
  • Use async transports for better performance
  • Secure transport credentials
  • Avoid logging secrets or PII
  • Use useTransportsOnly for production environments where you only want external logging

Was this page helpful?