npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

motifer

v26.1.1

Published

Production-ready structured logging for Node.js & Express with automatic request ID tracking, log rotation, and Logstash compatibility

Readme

🚀 Motifer

The Ultimate Structured Logging Solution for Node.js & Express

npm version npm downloads GitHub stars License Node.js Version CI Security Scan CodeQL

✨ Production-Ready | 🔍 Request Tracing | 📊 Logstash Compatible | 🎯 Zero Configuration

FeaturesQuick StartDocumentationExamplesContributing


🌟 Why Motifer?

Tired of scattered, inconsistent logs that make debugging a nightmare? Motifer transforms your logging experience with:

  • 🎯 Automatic Request ID Tracking - Every request gets a unique UUID v4, making it trivial to trace requests across microservices
  • 📋 Structured Log Patterns - Consistent, parseable logs that work seamlessly with Logstash, Elasticsearch, and CloudTrail
  • 🚀 Zero Boilerplate - Set up in 30 seconds, works out of the box
  • 🔄 Smart File Rotation - Automatic log rotation with compression and archival
  • 🎨 Express.js Native - Built specifically for Express with automatic request/response logging
  • 🔍 Microservice-Ready - Request ID chaining across service boundaries
  • 📊 Elastic APM Integration - Built-in support for application performance monitoring

✨ Features

🎯 Core Capabilities

  • Pattern Validation - Enforce consistent log patterns across your entire application
  • Request/Response Logging - Automatic HTTP request and response logging with full context
  • Unique Request IDs - UUID v4 tracking for complete request lifecycle visibility
  • Multi-Level Logging - Support for info, debug, warn, error, and custom log levels
  • File Rotation - Time-based and size-based log rotation with compression
  • Multiple Appenders - Configure different log files for different log levels
  • Logstash Compatible - Pre-configured patterns for seamless Logstash integration
  • CloudTrail Support - Ready for AWS CloudTrail logging
  • Elastic APM - Built-in integration for application performance monitoring
  • Express Middleware - Automatic Express.js integration with zero configuration

🚀 Quick Start

Installation

npm install motifer

Basic Usage (Express)

const express = require('express');
const bodyParser = require('body-parser');
const { ExpressLoggerFactory } = require('motifer');

const app = express();
app.use(bodyParser.json());

// Initialize Motifer (do this before your routes!)
const Logger = new ExpressLoggerFactory('my-app', 'debug', app);

// Use in your routes
const logger = Logger.getLogger(__filename);

app.get('/api/users', (req, res) => {
  logger.info('Fetching users');
  logger.debug('Query params:', req.query);
  
  // Your business logic here
  res.json({ users: [] });
});

Basic Usage (Non-Express)

const { LoggerFactory } = require('motifer');

const Logger = new LoggerFactory('my-service', 'info');
const logger = Logger.getLogger(__filename);

logger.info('Service started successfully');
logger.error('Something went wrong', error);

That's it! Your logs are now structured, traceable, and production-ready. 🎉


📅 Versioning

Motifer uses date-based versioning in the format YY.M.S:

  • YY: Last two digits of the year (e.g., 25 for 2025)
  • M: Month (1-12, no leading zeros)
  • S: Sequence number for releases in that month (1, 2, 3, ...)

Examples:

  • 26.1.1 - First release in January 2026
  • 26.1.2 - Second release in January 2026
  • 26.2.1 - First release in February 2026

This makes it easy to identify when a version was released and ensures chronological ordering. For detailed version history, see CHANGELOG.md.


📖 Documentation

Table of Contents


🎯 Express Setup

Step 1: Install Dependencies

npm install motifer express body-parser

Step 2: Initialize Motifer

Important: Initialize Motifer after body-parser but before your routes.

const express = require('express');
const bodyParser = require('body-parser');
const { ExpressLoggerFactory } = require('motifer');

const app = express();

// 1. Configure body parser first
app.use(bodyParser.json());

// 2. Initialize Motifer
const Logger = new ExpressLoggerFactory(
  'my-awesome-app',  // Service name
  'debug',           // Log level
  app,                // Express instance
  [/* options */]     // Optional: file appenders
);

// 3. Use logger in your routes
const logger = Logger.getLogger(__filename);

app.get('/api/status', (req, res) => {
  logger.info('Status check requested');
  res.json({ status: 'ok' });
});

app.listen(3000, () => {
  logger.info('Server started on port 3000');
});

Request ID Chaining (Microservices)

Motifer automatically handles request ID propagation across microservices:

// Service A - Generates request ID
app.get('/api/users', (req, res) => {
  // Request ID: 47de6d41-6dbd-44fc-9732-e28823755b58
  logger.info('Fetching users');
  
  // Forward to Service B with same request ID
  axios.get('http://service-b/api/data', {
    headers: { 'request-id': req.id }
  });
});

// Service B - Receives and uses the same request ID
// All logs will have the same request ID, making tracing effortless!

🔧 Non-Express Setup

For non-Express applications or background services:

const { LoggerFactory } = require('motifer');

// Simple setup
const Logger = new LoggerFactory('background-worker', 'info');
const logger = Logger.getLogger(__filename);

// With file logging
const options = [{
  rotate: true,
  filename: 'worker-%DATE%.log',
  datePattern: 'YYYY-MM-DD',
  dirname: './logs',
  maxSize: '20m',
  maxFiles: '14d'
}];

const Logger = new LoggerFactory('background-worker', 'info', options);
const logger = Logger.getLogger(__filename);

logger.info('Worker started');
logger.error('Processing failed', error);

⚙️ Configuration Options

File Appender Options

const options = [{
  // Basic options
  filename: 'app-%DATE%.log',        // Log filename (supports %DATE% placeholder)
  dirname: './logs',                  // Directory for log files
  level: 'info',                      // Log level for this appender
  
  // Rotation options
  rotate: true,                       // Enable file rotation
  datePattern: 'YYYY-MM-DD',         // Date pattern (moment.js format)
  frequency: '1d',                    // Rotation frequency (e.g., '5m', '2h', '1d')
  
  // Size and retention
  maxSize: '20m',                     // Max file size (supports: b, kb, mb, gb)
  maxFiles: '14d',                    // Retention period (e.g., '14d', '30', '100')
  archived: true                      // Compress archived files
}];

Multiple File Appenders

const options = [
  {
    level: 'error',
    filename: 'errors.log',
    dirname: './logs'
  },
  {
    level: 'warn',
    filename: 'warnings.log',
    dirname: './logs'
  },
  {
    rotate: true,
    filename: 'app-%DATE%.log',
    datePattern: 'YYYY-MM-DD',
    dirname: './logs',
    maxSize: '50m',
    maxFiles: '30d'
  }
];

const Logger = new ExpressLoggerFactory('my-app', 'debug', app, options);

Date Pattern Examples

| Pattern | Description | Example Output | |---------|-------------|----------------| | YYYY-MM-DD | Daily rotation | 2024-01-15 | | YYYY-MM-DD-HH | Hourly rotation | 2024-01-15-14 | | YYYY-MM-DD-HHmm | Every 5 minutes | 2024-01-15-1430 | | YYYY-MM | Monthly rotation | 2024-01 |


📋 Log Patterns

Motifer uses structured log patterns that are easy to parse and search.

Request Logs

TIMESTAMP [request] [REQUEST_ID] [APP_NAME] [LOG_LEVEL] [METHOD] [IP] [PATH] [BODY]

Examples:

# GET request (no body)
2024-01-15T10:30:45.123Z [request] [47de6d41-6dbd-44fc-9732-e28823755b58] [my-app] [INFO] [GET] [::1] [/api/users?page=1] [{}]

# POST request with JSON body
2024-01-15T10:30:46.234Z [request] [a1b2c3d4-e5f6-7890-abcd-ef1234567890] [my-app] [INFO] [POST] [192.168.1.100] [/api/users] [{"name":"John Doe","email":"[email protected]","age":30}]

# PUT request with body
2024-01-15T10:30:47.345Z [request] [b2c3d4e5-f6a7-8901-bcde-f12345678901] [my-app] [INFO] [PUT] [10.0.0.1] [/api/users/123] [{"email":"[email protected]"}]

Service Logs

TIMESTAMP [service] [REQUEST_ID] [APP_NAME] [LOG_LEVEL] [FILENAME] MESSAGE

Example:

2024-01-15T10:30:45.125Z [service] [47de6d41-6dbd-44fc-9732-e28823755b58] [my-app] [INFO] [users.controller.js] Fetching users from database

Response Logs

TIMESTAMP [response] [REQUEST_ID] [APP_NAME] [LOG_LEVEL] [METHOD] [IP] [PATH] [STATUS] [SIZE] [TIME] [USER_AGENT]

Example:

2024-01-15T10:30:45.250Z [response] [47de6d41-6dbd-44fc-9732-e28823755b58] [my-app] [INFO] [GET] [::1] [/api/users?page=1] [200] [1024] [125.5 ms] [Mozilla/5.0...]

🎨 Advanced Features

Elastic APM Integration

const { ApmFactory } = require('motifer');

// Initialize APM (do this at the very start of your app)
ApmFactory({
  serviceName: 'my-awesome-app',
  apmServerUrl: 'https://apm-server.example.com',
  secretToken: 'your-secret-token',
  environment: 'production',
  logLevel: 'error'
});

// Errors are automatically captured
logger.error('Something went wrong', error); // Automatically sent to APM

Standard Log Levels

const logger = Logger.getLogger(__filename);

// Standard levels
logger.info('Information message');
logger.debug('Debug message');
logger.warn('Warning message');
logger.error('Error message');

Logging with Context

// Simple message
logger.info('User created');

// Message with formatted arguments
logger.debug('Processing user:', { id: 123, name: 'John' });

// Error with stack trace
logger.error(error); // Automatically includes stack trace

// Multiple arguments
logger.info('User', user.id, 'performed action', action.type);

📚 Examples

Complete Express Application

const express = require('express');
const bodyParser = require('body-parser');
const { ExpressLoggerFactory } = require('motifer');

const app = express();
app.use(bodyParser.json());

// Configure logger with file rotation
const logOptions = [{
  rotate: true,
  filename: 'app-%DATE%.log',
  datePattern: 'YYYY-MM-DD',
  dirname: './logs',
  maxSize: '20m',
  maxFiles: '14d',
  level: 'info'
}, {
  level: 'error',
  filename: 'errors.log',
  dirname: './logs'
}];

const Logger = new ExpressLoggerFactory('ecommerce-api', 'debug', app, logOptions);
const logger = Logger.getLogger(__filename);

// Routes
app.get('/api/products', async (req, res) => {
  logger.info('Fetching products');
  logger.debug('Query parameters:', req.query);
  
  try {
    const products = await fetchProducts(req.query);
    logger.info(`Found ${products.length} products`);
    res.json(products);
  } catch (error) {
    logger.error('Failed to fetch products', error);
    res.status(500).json({ error: 'Internal server error' });
  }
});

app.listen(3000, () => {
  logger.info('Server started on port 3000');
});

Background Service

const { LoggerFactory } = require('motifer');

const Logger = new LoggerFactory('email-worker', 'info', [{
  rotate: true,
  filename: 'worker-%DATE%.log',
  datePattern: 'YYYY-MM-DD-HH',
  dirname: './logs'
}]);

const logger = Logger.getLogger(__filename);

async function processEmails() {
  logger.info('Starting email processing');
  
  try {
    const emails = await fetchEmails();
    logger.debug(`Processing ${emails.length} emails`);
    
    for (const email of emails) {
      await sendEmail(email);
      logger.info(`Email sent to ${email.to}`);
    }
    
    logger.info('Email processing completed');
  } catch (error) {
    logger.error('Email processing failed', error);
  }
}

processEmails();

📖 API Reference

ExpressLoggerFactory(service, level, express, options)

Creates a logger factory for Express.js applications.

Parameters:

  • service (string, required) - Application/service name
  • level (string, required) - Log level (info, debug, warn, error, etc.)
  • express (object, required) - Express application instance
  • options (array, optional) - File appender configuration

Returns: Logger factory object with getLogger(filename) method

LoggerFactory(service, level, options)

Creates a logger factory for non-Express applications.

Parameters:

  • service (string, required) - Application/service name
  • level (string, optional) - Log level (default: 'info')
  • options (array, optional) - File appender configuration

Returns: Logger factory object with getLogger(filename) method

ApmFactory(configObject)

Initializes Elastic APM integration.

Parameters:

  • configObject.serviceName (string, required) - Service name
  • configObject.apmServerUrl (string, required) - APM server URL
  • configObject.secretToken (string, required) - APM secret token
  • configObject.environment (string, optional) - Environment (default: 'production')
  • configObject.logLevel (string, optional) - APM log level (default: 'error')

Logger Methods

logger.info(...args)      // Log info message
logger.debug(...args)     // Log debug message
logger.warn(...args)      // Log warning message
logger.error(...args)     // Log error message

🎯 Best Practices

1. Initialize Early

// ✅ Good: Initialize at the start
const app = express();
app.use(bodyParser.json());
const Logger = new ExpressLoggerFactory('app', 'info', app);

// ❌ Bad: Initialize after routes
app.use('/api', routes);
const Logger = new ExpressLoggerFactory('app', 'info', app); // Too late!

2. Use Appropriate Log Levels

// ✅ Good
logger.error('Database connection failed', error); // For errors
logger.warn('Rate limit approaching');           // For warnings
logger.info('User logged in');                    // For important events
logger.debug('Processing request', data);        // For debugging

// ❌ Bad
logger.info('Database connection failed', error); // Should be error
logger.error('User logged in');                   // Should be info

3. Include Context

// ✅ Good
logger.info('Order created', { orderId: order.id, userId: user.id });
logger.error('Payment failed', { orderId: order.id, error: error.message });

// ❌ Bad
logger.info('Order created'); // Missing context

4. Use Request IDs

// ✅ Good: Request ID is automatically included in Express apps
app.get('/api/users', (req, res) => {
  logger.info('Fetching users'); // Request ID automatically included
});

// For non-Express, you can manually track context

5. Configure File Rotation

// ✅ Good: Proper rotation configuration
const options = [{
  rotate: true,
  filename: 'app-%DATE%.log',
  datePattern: 'YYYY-MM-DD',
  maxSize: '20m',
  maxFiles: '14d'
}];

// ❌ Bad: No rotation (files will grow indefinitely)
const options = [{
  filename: 'app.log' // No rotation!
}];

🔍 Troubleshooting

Request ID is undefined

Problem: Request ID shows as null in logs.

Solution: Make sure you initialize ExpressLoggerFactory before your routes:

// ✅ Correct order
app.use(bodyParser.json());
const Logger = new ExpressLoggerFactory('app', 'info', app);
app.use('/api', routes);

Logs not appearing in files

Problem: Console logs work but file logs don't appear.

Solution: Check file permissions and directory existence:

const options = [{
  filename: 'app.log',
  dirname: './logs' // Make sure this directory exists and is writable
}];

Request body is empty in logs

Problem: Request body shows as {} in request logs.

Solution: Initialize body-parser before Motifer:

// ✅ Correct
app.use(bodyParser.json());
const Logger = new ExpressLoggerFactory('app', 'info', app);

// ❌ Wrong
const Logger = new ExpressLoggerFactory('app', 'info', app);
app.use(bodyParser.json());

🤝 Contributing

We love contributions! See CONTRIBUTING.md for guidelines.

Quick start:

  1. Fork the repository
  2. Create a feature branch (git checkout -b feature/amazing-feature)
  3. Commit your changes (git commit -m 'Add amazing feature')
  4. Push to the branch (git push origin feature/amazing-feature)
  5. Open a Pull Request

📄 License

This project is licensed under the Apache License 2.0 - see the LICENSE file for details.


🙏 Acknowledgments

  • Inspired by the need for better structured logging in Node.js applications
  • Built for developers who value clean, traceable, and production-ready logging

📊 Project Status

GitHub last commit GitHub issues GitHub pull requests

Active DevelopmentProduction ReadyWell Maintained


🌟 Star History

Star History Chart


💬 Community


Made with ❤️ by Ankur Mahajan

⭐ Star this repo if you find it helpful!

⬆ Back to Top