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 🙏

© 2025 – Pkg Stats / Ryan Hefner

onprem-logger

v1.0.3

Published

A powerful, flexible logging utility for on-premise Node.js servers with automatic file rotation, module-specific logs, colored console output, and JSON formatting.

Readme

onprem-logger

A powerful, flexible logging utility designed for on-premise Node.js servers. Features automatic file rotation, module-specific logs, colored console output, JSON formatting, and full TypeScript support.

npm version License: MIT

Why Use This Logger?

  • Zero Dependencies - Built entirely with Node.js built-in modules
  • Production Ready - Designed for on-premise enterprise server deployments
  • Smart Defaults - Works out of the box with sensible defaults
  • Highly Configurable - Customize everything via options or environment variables
  • Module Isolation - Create separate log files for different parts of your application
  • Auto Rotation - Never worry about disk space with automatic log rotation
  • Express Ready - Built-in middleware support for API logging

Features

| Feature | Description | |---------|-------------| | 📁 File Logging | Separate error and combined log files | | 🔄 Auto Rotation | Rotate logs when they reach configurable size | | 🎨 Colored Output | Color-coded console logs for easy debugging | | 📊 JSON Format | Structured logs for parsing and analysis | | 🧩 Module-Specific | Separate logs for database, api, scheduler, etc. | | ⚡ Performance Tracking | Built-in duration logging for operations | | 🔧 Express Integration | Middleware-ready request/response logging | | 📝 TypeScript | Full type definitions included |

Installation

npm install onprem-logger

Quick Start

const { createLogger } = require('onprem-logger');

// Create a logger instance
const logger = createLogger({
  serverName: 'MyServer'
});

// Start logging!
logger.info('Server started successfully');
logger.warn('Memory usage is high', { usage: '85%' });
logger.error('Database connection failed', { host: 'localhost' });
logger.debug('Processing request...'); // Only in non-production

Configuration

Environment Variables

Configure the logger using environment variables (perfect for Docker/Kubernetes):

| Variable | Description | Default | |----------|-------------|---------| | LOG_DIR | Directory for log files | ./logs | | SERVER_NAME | Server identifier in logs | server | | NODE_ENV | Environment (affects debug logging) | development |

Example .env File

LOG_DIR=/var/logs/myapp
SERVER_NAME=Production_API_Server
NODE_ENV=production

Constructor Options

const logger = createLogger({
  // Identification
  serverName: 'MyServer',        // Server name in logs (overrides SERVER_NAME)
  moduleName: 'database',        // Module name (creates separate log files)

  // Paths
  logDir: '/var/logs/myapp',     // Log directory (overrides LOG_DIR)

  // Behavior
  environment: 'production',     // Environment (overrides NODE_ENV)
  consoleOutput: true,           // Enable/disable console output

  // Rotation Settings
  maxLogSize: 10 * 1024 * 1024,  // 10MB max file size
  maxBackups: 10,                // Keep 10 backup files
  rotationInterval: 1800000,     // Check every 30 minutes
  autoRotate: true               // Enable auto-rotation
});

Log File Naming Convention

Log files are automatically named based on your serverName and moduleName:

| serverName | moduleName | Error Log | Combined Log | |------------|------------|-----------|--------------| | MyServer | (default) | MyServer_error.log | MyServer_combined.log | | MyServer | database | MyServer_database_error.log | MyServer_database_combined.log | | MyServer | api | MyServer_api_error.log | MyServer_api_combined.log | | MyServer | scheduler | MyServer_scheduler_error.log | MyServer_scheduler_combined.log |

Usage Examples

Basic Logging

const { createLogger } = require('onprem-logger');

const logger = createLogger({ serverName: 'MyApp' });

// Simple messages
logger.info('Application started');
logger.warn('Cache miss detected');
logger.error('Failed to process request');
logger.debug('Variable value: 42'); // Only in non-production

// With metadata (additional context)
logger.info('User logged in', { 
  userId: 123, 
  email: '[email protected]',
  loginMethod: 'oauth'
});

logger.error('Payment failed', { 
  orderId: 'ORD-456',
  amount: 99.99,
  currency: 'USD',
  errorCode: 'INSUFFICIENT_FUNDS'
});

Module-Specific Loggers

Create separate log files for different parts of your application:

const { createLogger } = require('onprem-logger');

// Main application logger
const appLogger = createLogger({ 
  serverName: 'MyApp' 
});

// Database logger → MyApp_database_error.log, MyApp_database_combined.log
const dbLogger = createLogger({
  serverName: 'MyApp',
  moduleName: 'database'
});

// API logger → MyApp_api_error.log, MyApp_api_combined.log
const apiLogger = createLogger({
  serverName: 'MyApp',
  moduleName: 'api'
});

// Scheduler logger → MyApp_scheduler_error.log, MyApp_scheduler_combined.log
const schedulerLogger = createLogger({
  serverName: 'MyApp',
  moduleName: 'scheduler'
});

// Each logger writes to its own files
dbLogger.info('Connected to PostgreSQL');
apiLogger.info('API server listening on port 3000');
schedulerLogger.info('Daily backup job started');

Express Middleware Integration

const express = require('express');
const { createLogger } = require('onprem-logger');

const app = express();
const logger = createLogger({ 
  serverName: 'API', 
  moduleName: 'http' 
});

// Request/Response logging middleware
app.use((req, res, next) => {
  const startTime = Date.now();

  // Log incoming request
  logger.logApiRequest(req, { requestId: req.headers['x-request-id'] });

  // Log response when finished
  res.on('finish', () => {
    const duration = Date.now() - startTime;
    logger.logApiResponse(req, res, null, { 
      duration,
      requestId: req.headers['x-request-id']
    });
  });

  next();
});

// Error handling middleware
app.use((err, req, res, next) => {
  logger.logHttpError(req, err, { 
    requestId: req.headers['x-request-id'] 
  });
  res.status(err.statusCode || 500).json({ 
    error: 'Internal Server Error' 
  });
});

Error Logging with Stack Traces

const { createLogger } = require('onprem-logger');

const logger = createLogger({ serverName: 'MyApp' });

async function processOrder(orderId) {
  try {
    // Some operation that might fail
    await chargeCustomer(orderId);
  } catch (error) {
    // Log full error with stack trace and context
    logger.logError(error, {
      context: 'order-processing',
      orderId,
      customerId: 'CUST-123'
    });
    throw error; // Re-throw if needed
  }
}

Performance Monitoring

const { createLogger } = require('onprem-logger');

const logger = createLogger({ serverName: 'MyApp' });

async function fetchDataFromAPI() {
  const startTime = Date.now();

  try {
    const data = await externalAPICall();
    
    // Log successful operation with timing
    logger.logPerformance('external-api-call', Date.now() - startTime, {
      endpoint: 'https://api.example.com/data',
      recordCount: data.length,
      status: 'success'
    });

    return data;
  } catch (error) {
    // Log failed operation with timing
    logger.logPerformance('external-api-call', Date.now() - startTime, {
      endpoint: 'https://api.example.com/data',
      status: 'failed',
      error: error.message
    });
    throw error;
  }
}

Database Module Example

// src/config/database.js
const { createLogger } = require('onprem-logger');
const { Pool } = require('pg');

const logger = createLogger({
  serverName: process.env.SERVER_NAME || 'MyApp',
  moduleName: 'database'
});

const pool = new Pool({
  host: process.env.DB_HOST,
  database: process.env.DB_NAME
});

async function connectDatabase() {
  const startTime = Date.now();
  
  try {
    logger.info('Attempting database connection...', {
      host: process.env.DB_HOST,
      database: process.env.DB_NAME
    });

    await pool.connect();
    
    logger.info('Database connected successfully');
    logger.logPerformance('database-connect', Date.now() - startTime);
    
    return pool;
  } catch (error) {
    logger.logError(error, { 
      operation: 'database-connect',
      host: process.env.DB_HOST
    });
    throw error;
  }
}

// Log slow queries
pool.on('query', (query) => {
  const start = Date.now();
  query.on('end', () => {
    const duration = Date.now() - start;
    if (duration > 1000) { // Log queries taking more than 1 second
      logger.warn('Slow query detected', {
        query: query.text?.substring(0, 100),
        duration,
        threshold: 1000
      });
    }
  });
});

module.exports = { connectDatabase, pool, logger };

Log Output Formats

Console Output (Development)

[2024-01-15T10:30:45.123Z] [MyServer:database] INFO: Connected to database
  { host: 'localhost', database: 'myapp' }
[2024-01-15T10:30:45.456Z] [MyServer:api] ERROR: Request failed
  { statusCode: 500, endpoint: '/api/users', error: 'Connection timeout' }

File Output (JSON - for log aggregators)

{"timestamp":"2024-01-15T10:30:45.123Z","level":"info","server":"MyServer","module":"database","message":"Connected to database","environment":"production","host":"localhost","database":"myapp"}
{"timestamp":"2024-01-15T10:30:45.456Z","level":"error","server":"MyServer","module":"api","message":"Request failed","environment":"production","statusCode":500,"endpoint":"/api/users","error":"Connection timeout"}

API Reference

createLogger(options)

Create a new logger instance.

const logger = createLogger({
  serverName: 'MyServer',      // Server identifier
  moduleName: 'api',           // Module identifier
  logDir: '/var/logs',         // Log directory
  environment: 'production',   // Environment name
  consoleOutput: false,        // Disable console in production
  maxLogSize: 10485760,        // 10MB
  maxBackups: 5,               // Keep 5 backups
  rotationInterval: 3600000,   // Check every hour
  autoRotate: true             // Enable auto-rotation
});

Logging Methods

| Method | Description | Example | |--------|-------------|---------| | info(message, metadata?) | Log informational message | logger.info('Started', { port: 3000 }) | | warn(message, metadata?) | Log warning message | logger.warn('High memory', { usage: '90%' }) | | error(message, metadata?) | Log error message | logger.error('Failed', { code: 500 }) | | debug(message, metadata?) | Log debug message (non-prod only) | logger.debug('Value:', { x: 42 }) |

Specialized Logging Methods

| Method | Description | |--------|-------------| | logApiRequest(req, metadata?) | Log Express request details | | logApiResponse(req, res, body?, metadata?) | Log Express response details | | logError(error, metadata?) | Log Error object with stack trace | | logPerformance(operation, duration, metadata?) | Log operation timing | | logHttpError(req, error, metadata?) | Log HTTP error with CORS info |

Utility Methods

| Method | Description | |--------|-------------| | clearLogs() | Clear all log files | | getLogSizes() | Get current log file sizes | | rotateLog(path, maxSize?) | Manually rotate a log file | | stopAutoRotation() | Stop automatic rotation timer | | setConsoleOutput(enabled) | Enable/disable console output | | setEnvironment(env) | Change environment at runtime | | getLoggerInfo() | Get logger configuration |

Log Rotation

Logs are automatically rotated when they exceed maxLogSize (default: 5MB).

How It Works

  1. When a log file exceeds the size limit, it's renamed with a timestamp
  2. A new empty log file is created
  3. Old backups beyond maxBackups are automatically deleted

Backup File Naming

MyServer_combined.log.2024-01-15T10-30-45.123Z.backup
MyServer_combined.log.2024-01-14T08-15-30.456Z.backup

Manual Rotation

// Force rotation regardless of size
await logger.rotateLog(logger.combinedLogPath, 0);

TypeScript Support

Full TypeScript definitions are included:

import { createLogger, LoggerHelper, LoggerOptions, LogSizes } from 'onprem-logger';

const options: LoggerOptions = {
  serverName: 'TypedServer',
  moduleName: 'api',
  maxLogSize: 10 * 1024 * 1024
};

const logger: LoggerHelper = createLogger(options);

// Full IntelliSense support
logger.info('TypeScript is awesome!');

// Get typed log sizes
const sizes: LogSizes | null = await logger.getLogSizes();
if (sizes) {
  console.log(`Combined log: ${sizes.combinedLog.sizeInMB} MB`);
}

Best Practices

1. Use Module-Specific Loggers

// ✅ Good - Separate loggers for different concerns
const dbLogger = createLogger({ serverName: 'App', moduleName: 'database' });
const apiLogger = createLogger({ serverName: 'App', moduleName: 'api' });
const authLogger = createLogger({ serverName: 'App', moduleName: 'auth' });

// ❌ Avoid - Single logger for everything
const logger = createLogger({ serverName: 'App' });

2. Include Contextual Metadata

// ✅ Good - Rich context for debugging
logger.error('Payment failed', {
  userId: user.id,
  orderId: order.id,
  amount: order.total,
  paymentMethod: 'credit_card',
  errorCode: error.code
});

// ❌ Avoid - No context
logger.error('Payment failed');

3. Use Appropriate Log Levels

logger.debug('Entering function X');       // Development only
logger.info('User registered');            // Normal operations
logger.warn('Rate limit approaching');     // Potential issues
logger.error('Database connection lost');  // Errors requiring attention

4. Disable Console in Production

const logger = createLogger({
  serverName: 'ProdServer',
  consoleOutput: process.env.NODE_ENV !== 'production'
});

License

MIT © miryasha

Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

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

Related Packages