Skip to main content

Logger Middleware

HTTP request/response logging middleware that logs request metadata and response details with configurable output formats.

Installation

npm i remix

Function

logger()

Creates middleware that logs various request/response information. Signature:
function logger(options?: LoggerOptions): Middleware
Parameters:
  • options - Optional logger configuration
Returns: The logger middleware.

Options

LoggerOptions

interface LoggerOptions {
  format?: string
  log?: (message: string) => void
}

format

The format to use for log messages. Supports token-based formatting.
  • Type: string
  • Default: '[%date] %method %path %status %contentLength'
Available Tokens:
  • %date - Date and time in Apache/nginx format (dd/Mon/yyyy:HH:mm:ss ±zzzz)
  • %dateISO - Date and time in ISO format
  • %duration - Request duration in milliseconds
  • %contentLength - Response Content-Length header
  • %contentType - Response Content-Type header
  • %host - Request URL host
  • %hostname - Request URL hostname
  • %method - Request method
  • %path - Request pathname + search
  • %pathname - Request pathname
  • %port - Request port
  • %query - Request query string (search)
  • %referer - Request Referer header
  • %search - Request search string
  • %status - Response status code
  • %statusText - Response status text
  • %url - Full request URL
  • %userAgent - Request User-Agent header

log

The function to use to log messages.
  • Type: (message: string) => void
  • Default: console.log

Basic Usage

import { createRouter } from 'remix/fetch-router'
import { logger } from 'remix/logger-middleware'

let router = createRouter({
  middleware: [logger()],
})

// Logs: [19/Nov/2025:14:32:10 -0800] GET /users/123 200 1234

Custom Format

import { createRouter } from 'remix/fetch-router'
import { logger } from 'remix/logger-middleware'

let router = createRouter({
  middleware: [
    logger({
      format: '%method %path - %status (%duration ms)',
    }),
  ],
})
// Logs: GET /users/123 - 200 (42 ms)

Apache Combined Log Format

import { createRouter } from 'remix/fetch-router'
import { logger } from 'remix/logger-middleware'

let router = createRouter({
  middleware: [
    logger({
      format: '%host - - [%date] "%method %path" %status %contentLength "%referer" "%userAgent"',
    }),
  ],
})

Custom Logger Function

import { createWriteStream } from 'node:fs'
import { createRouter } from 'remix/fetch-router'
import { logger } from 'remix/logger-middleware'

let logStream = createWriteStream('access.log', { flags: 'a' })

let router = createRouter({
  middleware: [
    logger({
      log(message) {
        logStream.write(message + '\n')
      },
    }),
  ],
})

Minimal Format

import { createRouter } from 'remix/fetch-router'
import { logger } from 'remix/logger-middleware'

let router = createRouter({
  middleware: [
    logger({
      format: '%method %pathname %status',
    }),
  ],
})
// Logs: GET /users/123 200

Detailed Format with Duration

import { createRouter } from 'remix/fetch-router'
import { logger } from 'remix/logger-middleware'

let router = createRouter({
  middleware: [
    logger({
      format: '[%dateISO] %method %url -> %status %statusText (%duration ms)',
    }),
  ],
})
// Logs: [2025-11-19T22:32:10.123Z] GET http://localhost:3000/users/123 -> 200 OK (42 ms)

Structured Logging

import { createRouter } from 'remix/fetch-router'
import { logger } from 'remix/logger-middleware'

let router = createRouter({
  middleware: [
    logger({
      format: '{"method":"%method","path":"%path","status":%status,"duration":%duration}',
      log(message) {
        // Parse and log as structured JSON
        console.log(JSON.parse(message))
      },
    }),
  ],
})

Conditional Logging

import { createRouter } from 'remix/fetch-router'
import { logger } from 'remix/logger-middleware'

let router = createRouter({
  middleware: [
    logger({
      format: '%method %path %status %duration',
      log(message) {
        // Only log errors and slow requests
        if (message.includes(' 5') || message.includes(' 4')) {
          console.error('Error:', message)
        } else if (parseInt(message.split(' ').pop() || '0') > 1000) {
          console.warn('Slow request:', message)
        }
      },
    }),
  ],
})

Build docs developers (and LLMs) love