mrkeyoor.com_
Sat 08 Aug 17:40 UTC
npmInfraupdated 08 Aug 2026

log4js

log4js is a Node.js logging framework built around named categories, severity levels, appenders, and layouts. It can write colored console output, rolling files, date-rolled files, TCP streams, and Express access logs, with category inheritance and contextual fields. It resembles the vocabulary of Java's Log4j but is a separate implementation, and its README warns that expecting identical behavior causes confusion. This is a server-side logging system with asynchronous appender shutdown duties, not a browser package or a direct port of Log4j 2.

Verdict

log4js remains capable for category-heavy services and applications that truly need local rolling files. For a new containerized service writing JSON to stdout, install Pino instead and let the platform rotate and ship logs.

API stability4/5The 6.x configuration, category, appender, and logger APIs are mature, but migration guides remain necessary for code copied from older major versions.
Docs4/5The dedicated site documents each built-in appender, layouts, categories, clustering, shutdown, Express, and migrations, though examples and phrasing vary in age.
Maintenance4/5Version 6.9.1 is current and the repository was pushed in July 2026; 96 open issues and PRs are manageable for a mature project but not especially low.
Ecosystem4/5Built-in console, file, date-file, TCP, filters, and Express support cover many traditional Node deployments, with optional community appenders for external services.

Use it if

  • You need several appenders and different log levels for hierarchical application categories
  • You want size-based or date-based file rotation inside a traditional long-running Node service
  • You have an existing log4js configuration or plugin appender ecosystem that would be costly to replace
  • You want built-in Express request logging with status-aware levels and filtering
Skip it if

Setup reality

npm install log4js includes types and five runtime dependencies. You must configure at least one appender and a default category before expecting output, then decide category inheritance, layouts, file retention, and backpressure behavior. File and network appenders are asynchronous, so graceful shutdown must wait for log4js.shutdown. Multi-process file logging needs extra architecture and an external collector or TCP aggregation.

Patterns

Enable console loggingconfigure-console

const log4js = require('log4js')

log4js.configure({
  appenders: { out: { type: 'stdout' } },
  categories: { default: { appenders: ['out'], level: 'info' } },
})

const logger = log4js.getLogger()
logger.info('service started')

Without configure or a manual logger level, the default category is OFF and emits nothing.

Set different category levelsuse-categories

log4js.configure({
  appenders: { out: { type: 'stdout' } },
  categories: {
    default: { appenders: ['out'], level: 'info' },
    database: { appenders: ['out'], level: 'warn' },
  },
})

const dbLog = log4js.getLogger('database')
dbLog.debug('hidden query details')
dbLog.error('connection failed')

Category levels are minimum thresholds; database debug is discarded while error is emitted.

Use dotted category inheritanceinherit-category

const queryLog = log4js.getLogger('app.database.query')
queryLog.info('query complete', { durationMs: 18 })

Dotted categories inherit the closest configured parent category unless that category sets inherit: false.

Rotate a file by sizerotate-file-size

log4js.configure({
  appenders: {
    app: {
      type: 'file',
      filename: 'logs/app.log',
      maxLogSize: '10M',
      backups: 3,
      compress: true,
    },
  },
  categories: { default: { appenders: ['app'], level: 'info' } },
})

The process needs permission to create the directory and files; log4js does not replace deployment-level disk monitoring.

Roll a log file dailyrotate-file-date

log4js.configure({
  appenders: {
    audit: {
      type: 'dateFile',
      filename: 'logs/audit.log',
      pattern: 'yyyy-MM-dd',
      numBackups: 14,
      compress: true,
    },
  },
  categories: { default: { appenders: ['audit'], level: 'info' } },
})

Date rolling happens on the next log write after the date changes, not from a separate midnight timer.

Define a pattern layoutformat-pattern

log4js.configure({
  appenders: {
    out: {
      type: 'stdout',
      layout: { type: 'pattern', pattern: '%d %p %c %X{requestId} %m%n' },
    },
  },
  categories: { default: { appenders: ['out'], level: 'info' } },
})

%X reads logger context. Missing keys render empty, so add and clear request context deliberately.

Attach and clear contextual dataadd-request-context

const logger = log4js.getLogger('api')
logger.addContext('requestId', request.id)
try {
  logger.info('handling request')
  await handle(request)
} finally {
  logger.removeContext('requestId')
}

A logger is shared by category. Leaving context attached can put one request's identifier onto later logs.

Add Express access logslog-express-requests

const accessLog = log4js.getLogger('http')
app.use(log4js.connectLogger(accessLog, {
  level: 'auto',
  format: ':remote-addr :method :url :status :response-time ms',
  nolog: req => req.path === '/health',
}))

Place the middleware early enough to observe requests; level auto maps redirects to WARN and 4xx or 5xx responses to ERROR.

Skip expensive debug work when disabledavoid-expensive-log-data

if (logger.isDebugEnabled()) {
  logger.debug('cache snapshot', buildLargeDiagnosticObject())
}

Arguments are evaluated before logger.debug runs, so the guard is useful when constructing the data is costly.

Wait for appenders during shutdownflush-on-shutdown

process.once('SIGTERM', () => {
  server.close(() => {
    log4js.shutdown(error => {
      if (error) console.error(error)
      process.exit(error ? 1 : 0)
    })
  })
})

File and network appenders buffer asynchronously; exiting before the shutdown callback can lose final log messages.

Alternatives

PackageRegistryPick it when
pinonpmYou want high-throughput structured JSON logs for containers and centralized log pipelines
winstonnpmYou want a popular transport-based logger with a large third-party transport ecosystem
bunyannpmYou maintain an older JSON-logging codebase already organized around Bunyan streams