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







✨ Production-Ready | 🔍 Request Tracing | 📊 Logstash Compatible | 🎯 Zero Configuration
Features • Quick Start • Documentation • Examples • Contributing
---
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
---
- ✅ 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
---
``bash`
npm install motifer
`javascript
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: [] });
});
`
`javascript
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. 🎉
---
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 202626.1.2
- - Second release in January 202626.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.
---
- Installation
- Express Setup
- Non-Express Setup
- Configuration Options
- Log Patterns
- Advanced Features
- Examples
- API Reference
- Best Practices
- Troubleshooting
---
`bash`
npm install motifer express body-parser
Important: Initialize Motifer after body-parser but before your routes.
`javascript
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');
});
`
Motifer automatically handles request ID propagation across microservices:
`javascript
// 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!
`
---
For non-Express applications or background services:
`javascript
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);
`
---
`javascript`
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
}];
`javascript
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);
`
| 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 |
---
Motifer uses structured log patterns that are easy to parse and search.
``
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] [{}]
$3
`
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
`$3
`
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
$3
`javascript
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
`$3
`javascript
const logger = Logger.getLogger(__filename);// Standard levels
logger.info('Information message');
logger.debug('Debug message');
logger.warn('Warning message');
logger.error('Error message');
`$3
`javascript
// 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
$3
`javascript
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');
});
`$3
`javascript
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
$3
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 configurationReturns: Logger factory object with
getLogger(filename) method$3
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 configurationReturns: Logger factory object with
getLogger(filename) method$3
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')$3
`javascript
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
$3
`javascript
// ✅ 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!
`$3
`javascript
// ✅ 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
`javascript
// ✅ 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
`$3
`javascript
// ✅ 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
`$3
`javascript
// ✅ 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
$3
Problem: Request ID shows as
null in logs.Solution: Make sure you initialize
ExpressLoggerFactory before your routes:`javascript
// ✅ Correct order
app.use(bodyParser.json());
const Logger = new ExpressLoggerFactory('app', 'info', app);
app.use('/api', routes);
`$3
Problem: Console logs work but file logs don't appear.
Solution: Check file permissions and directory existence:
`javascript
const options = [{
filename: 'app.log',
dirname: './logs' // Make sure this directory exists and is writable
}];
`$3
Problem: Request body shows as
{} in request logs.Solution: Initialize
body-parser before Motifer:`javascript
// ✅ 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`)---
This project is licensed under the Apache License 2.0 - see the LICENSE file for details.
---
- Inspired by the need for better structured logging in Node.js applications
- Built for developers who value clean, traceable, and production-ready logging
---
!GitHub last commit
!GitHub issues
!GitHub pull requests
Active Development • Production Ready • Well Maintained
---

---
- 🐛 Found a bug? Open an issue
- 💡 Have a feature request? Open an issue
- 📖 Need help? Check the documentation or open a discussion
- 💬 Want to chat? Join our Discussions
---