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

API Reference

Complete API reference for Logixlysia

Functions

logixlysia

Main plugin function that adds logging capabilities to your Elysia application.

function logixlysia<TFields extends object = LogFields>(
  options?: Options
): LogixlysiaPlugin<TFields>

Parameters:

  • options (optional): Configuration options for Logixlysia

Returns:

  • LogixlysiaPlugin<TFields>: the Elysia plugin instance (its store carries logger, pino and beforeTime, and every handler receives a derived log) plus wrapWs

Example:

import { Elysia } from 'elysia'
import logixlysia from 'logixlysia'

const app = new Elysia().use(
  logixlysia({
    config: {
      showStartupMessage: true
    }
  })
)

useLogger

Returns the current request’s RequestScopedLogger. Outside a request, or without useAsyncLocalStorage: true, it returns a no-op logger that writes nothing.

function useLogger<
  TFields extends object = LogFields
>(): RequestScopedLogger<TFields>

flushLogixlysia

Drains the transports in options and every file sink, and with close: true also releases them. Pass the same options object you gave the plugin; see graceful shutdown.

function flushLogixlysia(
  options: Options,
  flags?: { close?: boolean }
): Promise<void>

createLogger

Builds a Logger from Options without registering the plugin. It keeps its own request context, separate from any plugin instance’s.

function createLogger(options?: Options): Logger

resolveOptions

Applies a preset’s defaults under the explicit config and validates the result, the same way the plugin does with the options you pass it. It throws where the plugin would: an unknown preset, or an invalid rotation, sampling, threshold, logFilter or output setting.

function resolveOptions(options?: Options): Options

Also exported: createPluginLogger, createWsHandlerWrapper, getOrCreateRequestId, resolveRequestIdConfig and resolveSampling are the building blocks the plugin is assembled from. They may change between minor versions.

Types

Logixlysia

Elysia instance type with Logixlysia store.

import type { LogixlysiaSingleton } from 'logixlysia'

type Logixlysia = Elysia<'', LogixlysiaSingleton>

The plugin uses an explicit LogixlysiaSingleton: a closed store plus empty decorator / derive / resolve slots that avoid both SingletonBase’s wide Record<string, unknown> and Record<string, never> (the latter would intersect Elysia’s Context keys with never). That keeps Context and WebSocket ws.data precise after .use(logixlysia()).

Options

Configuration options for Logixlysia.

type Options = {
  preset?: 'dev' | 'prod' | 'json'
  config?: {
    showStartupMessage?: boolean
    startupMessageFormat?: 'simple' | 'banner'
    useColors?: boolean
    ip?: boolean
    autoRedact?: boolean
    redactKeys?: string[]
    logErrorPayload?: boolean
    timestamp?: {
      translateTime?: string
    }
    customLogFormat?: string
    service?: string
    slowThreshold?: number
    verySlowThreshold?: number
    showContextTree?: boolean
    contextDepth?: number
    logQueryParams?: boolean
    transports?: Transport[]
    useTransportsOnly?: boolean
    disableInternalLogger?: boolean
    disableFileLogging?: boolean
    onError?: (context: SinkErrorContext) => void
    flushTimeoutMs?: number
    enrichers?: EnricherLike[]
    requestId?: boolean | RequestIdConfig
    useAsyncLocalStorage?: boolean
    disableWebSocketLogging?: boolean
    logFilter?: LogFilter
    sampling?: SamplingConfig
    logFilePath?: string
    logDirMode?: number
    logFileMode?: number
    logRotation?: LogRotationConfig
    pino?: PinoLoggerOptions & { prettyPrint?: boolean | object }
  }
}

LogixlysiaStore

Store type available in Elysia context.

type LogixlysiaStore = {
  logger: Logger
  pino: Pino
  beforeTime?: bigint
}

Properties:

  • logger: Logger instance with helper methods
  • pino: Direct Pino logger instance
  • beforeTime: A bigint from process.hrtime.bigint(), taken at the start of the most recent request. Elysia shares the store between concurrent requests, so the value is accurate only while requests do not overlap. The plugin’s own durations do not use it.

Keep LogixlysiaStore a closed object type (no index signature). That helps merged handler and WebSocket types stay accurate.

Logger

Logger interface with logging methods.

type Logger = {
  pino: Pino
  log: (
    level: LogLevel,
    request: RequestInfo,
    data: Record<string, unknown>,
    store: StoreData
  ) => void
  handleHttpError: (
    request: RequestInfo,
    error: unknown,
    store: StoreData
  ) => void
  debug: (
    request: RequestInfo,
    message: string,
    context?: Record<string, unknown>
  ) => void
  info: (
    request: RequestInfo,
    message: string,
    context?: Record<string, unknown>
  ) => void
  warn: (
    request: RequestInfo,
    message: string,
    context?: Record<string, unknown>
  ) => void
  error: (
    request: RequestInfo,
    message: string,
    context?: Record<string, unknown>
  ) => void
  mergeContext: (
    key: RequestInfo | object,
    partial: Record<string, unknown>
  ) => void
  getContext: (key: RequestInfo | object) => Readonly<Record<string, unknown>>
  beginRequest: (request: RequestInfo) => void
  finalizeRequest: (
    request: RequestInfo,
    store: StoreData,
    status: number
  ) => void
}

RequestScopedLogger

The log every handler receives, and what useLogger() returns. It is bound to one request, so its methods take no request argument.

type RequestScopedLogger<TFields extends object = LogFields> = {
  debug: (message: string, context?: Partial<TFields>) => void
  info: (message: string, context?: Partial<TFields>) => void
  warn: (message: string, context?: Partial<TFields>) => void
  error: (message: string, context?: Partial<TFields>) => void
  mergeContext: (partial: Partial<TFields>) => void
}

LogLevel

Log level type.

type LogLevel = 'DEBUG' | 'INFO' | 'WARNING' | 'ERROR'

Transport

Custom transport interface.

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

flush drains entries the transport has queued or batched; the shutdown flush calls it when the app stops. close releases held sockets, timers and buffers, and is reached only through flushLogixlysia(options, { close: true }).

LogRotationConfig

Log rotation configuration. Importable from logixlysia.

type LogRotationConfig = {
  maxSize?: string | number
  maxFiles?: number | string
  interval?: string
  compress?: boolean
  compression?: 'gzip'
}

SinkErrorContext

The argument of config.onError, importable from logixlysia.

type SinkErrorContext = {
  sink: 'transport' | 'file' | 'rotation' | 'shutdown' | 'enricher' | 'format'
  error: unknown
}

LogFilter

The type of config.logFilter, importable from logixlysia. Only the listed levels are logged; a missing or empty list keeps every level.

type LogFilter = {
  level?: LogLevel[]
}

Pino

Pino logger type.

type Pino = PinoLogger<never, boolean>

LogixlysiaContext

Context type for request handlers.

type LogixlysiaContext = {
  request: Request
  store: LogixlysiaStore
}

Classes

HttpError

An HTTP error carrying the context that makes a failure actionable.

class HttpError extends Error {
  readonly code?: string
  readonly fix?: string
  readonly internal?: unknown
  readonly link?: string
  readonly status: number
  readonly why?: string

  constructor(status: number, message: string, init?: HttpErrorInit)

  toJSON(): HttpErrorPayload
}

interface HttpErrorInit {
  code?: string
  fix?: string
  internal?: unknown
  link?: string
  why?: string
}

Properties:

  • status — HTTP status code
  • code — stable machine-readable identifier the client can branch on, e.g. PAYMENT_DECLINED. Unlike message, it is safe to depend on: rewording the message does not break a caller
  • why — why the request failed, in plain language
  • fix — what the caller should do about it
  • link — documentation URL for this failure
  • internal — log-only diagnostics. Non-enumerable and excluded from toJSON(), so no serializer can put it in a response body

Example:

import { HttpError } from 'logixlysia'

throw new HttpError(402, 'Card declined', {
  code: 'PAYMENT_DECLINED',
  why: 'The issuing bank rejected the charge.',
  fix: 'Try a different card, or contact your bank.',
  link: 'https://docs.example.com/errors/payment-declined',
  internal: { gatewayCode: 'do_not_honor', chargeId }
})

Response body:

{
  "code": "PAYMENT_DECLINED",
  "fix": "Try a different card, or contact your bank.",
  "link": "https://docs.example.com/errors/payment-declined",
  "message": "Card declined",
  "status": 402,
  "why": "The issuing bank rejected the charge."
}

The log line carries the same fields plus internal, rendered in the context tree as error.code, error.why, error.fix, error.link, and error.internal.

An error with no client-facing fields keeps its previous behaviour exactly — throw new HttpError(404, 'User not found') still responds with the bare message, not JSON. Only an error carrying at least one of code, why, fix, or link responds as JSON.

Usage Examples

Accessing Logger in Route Handlers

app.get('/users/:id', ({ store, params, request }) => {
  const { logger, pino } = store

  // Use logger helper methods
  logger.info(request, 'User accessed', { userId: params.id })

  // Or use Pino directly
  pino.info({ userId: params.id }, 'User accessed')

  return { user: 'data' }
})

Custom Logging

app.post(
  '/users',
  ({ store, body, request }) => {
    const { logger } = store

    logger.debug(request, 'Creating user', { email: body.email })

    // ... create user logic

    logger.info(request, 'User created', { userId: newUser.id })

    return newUser
  },
  { body: t.Object({ email: t.String() }) }
)

Was this page helpful?