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

@lazhus/kg-central-logger

v1.0.0

Published

Central logging system with RabbitMQ support and fallback file logging

Readme

@sendeo/central-logger

Central logging system with RabbitMQ support and fallback file logging. This package is a Node.js/TypeScript implementation inspired by the .NET CentralLogging system.

Features

  • 🚀 Asynchronous logging with internal queue
  • 🐰 RabbitMQ integration with topic exchange
  • 📁 Automatic fallback to file logging on RabbitMQ failure
  • 🔄 Automatic reconnection on connection loss
  • 📊 Log levels (Trace, Debug, Information, Warning, Error, Critical)
  • 🏷️ Enrichers support
  • 🎯 Scope support with AsyncLocalStorage
  • ⚙️ Configurable channel bounds and parallelism
  • 🎨 Category-based log level filtering

Installation

npm install @sendeo/central-logger

Quick Start

import { createCentralLogger, LogLevel } from '@sendeo/central-logger';

// Create logger provider
const provider = createCentralLogger(
  'amqp://localhost:5672',
  (config) => {
    config
      .setLogKey('my-service')
      .setExchangeName('logs-exchange')
      .setDefaultLogLevel(LogLevel.Information)
      .addEnricher('Environment', 'production')
      .addEnricher('ServiceName', 'my-service');
  }
);

// Create logger instance
const logger = provider.createLogger('MyController');

// Log messages
logger.info('Application started', { version: '1.0.0' });
logger.error('Something went wrong', new Error('Test error'), { userId: '123' });

// Use scopes
const scope = logger.beginScope({ requestId: 'abc-123' });
logger.info('Processing request'); // Will include requestId in properties
scope.dispose();

// Cleanup on shutdown
await provider.dispose();

Configuration

CentralLoggerConfiguration

const config = new CentralLoggerConfiguration()
  .setLogKey('my-service')              // Required: Service identifier
  .setExchangeName('logs-exchange')     // Required: RabbitMQ exchange name
  .setConnectionKey('default')          // Optional: Connection identifier
  .setIsSpecific()                      // Optional: Use specific routing
  .setChannelBound(20000)               // Optional: Max queue size (default: 20000)
  .setMaxParallelism(20)                // Optional: Parallel processing (default: 20)
  .setFailedLogsBaseFolder('logs')      // Optional: Fallback folder (default: 'CentralFailedLogs')
  .setDefaultLogLevel(LogLevel.Info)    // Optional: Default log level
  .setMinimumLogLevel('MyController', LogLevel.Debug) // Optional: Category-specific level
  .addEnricher('key', 'value');         // Optional: Add enrichers

Usage Examples

Basic Logging

const logger = provider.createLogger('UserService');

logger.trace('Trace message');
logger.debug('Debug message');
logger.info('Info message');
logger.warn('Warning message');
logger.error('Error message', new Error('Something failed'));
logger.critical('Critical error', new Error('System failure'));

Logging with Properties

logger.info('User logged in', {
  userId: '12345',
  username: 'john.doe',
  ipAddress: '192.168.1.1'
});

Using Scopes

// Scopes add properties to all logs within the scope
const scope = logger.beginScope({
  requestId: 'req-123',
  correlationId: 'corr-456'
});

logger.info('Starting process');  // Includes requestId and correlationId
logger.info('Process completed'); // Includes requestId and correlationId

scope.dispose(); // Clean up scope

Nested Scopes

const outerScope = logger.beginScope({ requestId: 'req-123' });

logger.info('Outer scope');

const innerScope = logger.beginScope({ operationId: 'op-456' });
logger.info('Inner scope'); // Includes both requestId and operationId
innerScope.dispose();

logger.info('Back to outer'); // Only includes requestId
outerScope.dispose();

Category-based Log Levels

const provider = createCentralLogger('amqp://localhost', (config) => {
  config
    .setLogKey('my-service')
    .setExchangeName('logs')
    .setDefaultLogLevel(LogLevel.Information)
    .setMinimumLogLevel('DatabaseService', LogLevel.Debug)
    .setMinimumLogLevel('CacheService', LogLevel.Warning);
});

const dbLogger = provider.createLogger('DatabaseService');
dbLogger.debug('This will be logged'); // Debug enabled for DatabaseService

const cacheLogger = provider.createLogger('CacheService');
cacheLogger.info('This will NOT be logged'); // Only Warning+ for CacheService
cacheLogger.warn('This will be logged');

Log Entry Structure

Each log entry contains:

{
  logKey: string;              // Service identifier
  timestamp: Date;             // Log timestamp
  level: string;               // Log level (Trace, Debug, Information, etc.)
  source?: string;             // Logger category name
  eventId?: number;            // Optional event ID
  eventName?: string;          // Optional event name
  message?: string;            // Log message
  messageTemplate?: string;    // Message template with placeholders
  exception?: {                // Exception details (if any)
    type?: string;
    message?: string;
    stackTrace?: string;
    innerException?: {...};
  };
  enrichers: Record<string, string>;        // Global enrichers
  properties?: Record<string, string|null>; // Log properties + scope properties
}

RabbitMQ Integration

Routing Key Format

Logs are published to RabbitMQ with the following routing key format:

project.{logKey}.{suffix}
  • logKey: Your service identifier (lowercase)
  • suffix: Either specific or general (based on setIsSpecific())

Example: project.my-service.general

Exchange Configuration

The logger creates a topic exchange with durable flag. Make sure your RabbitMQ consumers bind to this exchange with appropriate routing key patterns.

Automatic Reconnection

The logger automatically attempts to reconnect to RabbitMQ if the connection is lost. During disconnection, logs are written to fallback files.

Fallback File Logging

When RabbitMQ is unavailable, logs are automatically written to files in the configured folder (default: CentralFailedLogs).

Files are named: failed-logs-{timestamp}.json

Each line in the file is a JSON-serialized log entry.

Performance Considerations

  • Internal Queue: Logs are queued internally and processed asynchronously
  • Bounded Channel: Queue size is limited (default: 20,000). Oldest logs are dropped when full
  • Parallel Processing: Multiple logs are published in parallel (default: 20)
  • Non-blocking: Logging operations never block the main thread

Cleanup

Always dispose the provider when shutting down your application:

process.on('SIGTERM', async () => {
  await provider.dispose();
  process.exit(0);
});

TypeScript Support

This package is written in TypeScript and includes full type definitions.

License

MIT

Credits

Inspired by the Sendeo.Core.CentralLogging .NET library.