JSPM

  • Created
  • Published
  • Downloads 21
  • Score
    100M100P100Q71622F
  • License Apache-2.0

A modern, composable observability framework for Node.js

Package Exports

  • syntropylog
  • syntropylog/brokers
  • syntropylog/doctor
  • syntropylog/http
  • syntropylog/testing
  • syntropylog/testing/mock

Readme

SyntropyLog Logo

SyntropyLog

From Chaos to Clarity
The Observability Framework for High-Performance Teams

NPM Version License Test Coverage Beta


๐Ÿš€ Quick Start

Get started with SyntropyLog usage in 30 seconds (after initialization):

npm install syntropylog@0.6.14
import { syntropyLog } from 'syntropylog';

// Initialize with minimal configuration
await syntropyLog.init({
  logger: {
    serviceName: 'my-app',
    level: 'info',
  },
});

// Use it immediately
const logger = syntropyLog.getLogger();
logger.info('Hello, SyntropyLog!');

// Note: This shows the "zero boilerplate" usage pattern. // Initialization and shutdown require the boilerplate shown in the documentation.

โš ๏ธ CRITICAL REQUIREMENT: You MUST include the graceful shutdown boilerplate in ALL applications. This ensures logs are flushed and resources are cleaned up when:

  • Development: You press Ctrl+C to stop the application
  • Production: Kubernetes sends SIGTERM to terminate your pod

โœจ Key Features

  • ๐Ÿ”„ Zero Boilerplate - Get started in 30 seconds with automatic context propagation (usage only - initialization/shutdown boilerplate required)
  • ๐Ÿ”— Automatic Correlation - Distributed tracing across services, HTTP calls, and message brokers
  • ๐ŸŽฏ Framework Agnostic - Works with Express, Fastify, Koa, NestJS, and any Node.js app
  • ๐Ÿ›ก๏ธ Security First - Built-in data masking and compliance-ready logging
  • โšก High Performance - 45,000+ ops/sec with less than 1ms latency
  • ๐Ÿ—๏ธ Singleton Pattern - Prevents pod crashes by managing resource instances efficiently

๐ŸŽญ Core Philosophy: Silent Observer

SyntropyLog follows the "Silent Observer" principle - we report what happened and nothing more.

๐Ÿšซ Never Interrupts Your Application

// โœ… Your application continues running, even if logging fails
try {
  const result = await database.query('SELECT * FROM users');
  logger.info('Query successful', { count: result.length });
} catch (error) {
  // Your error handling continues normally
  logger.error('Database error', { error: error.message });
  // Application logic continues...
}

๐Ÿ” What Happens When Logging Fails

  1. Configuration Errors โ†’ Application fails to start (as expected)
  2. Pipeline Errors โ†’ Error reported to transports, application continues
  3. Serializer Errors โ†’ Error reported to transports, application continues
  4. Transport Errors โ†’ Error reported to console, application continues

๐Ÿ“ก Error Reporting Strategy

// Any error in the logging pipeline:
// 1. Reports to configured transports (console, file, etc.)
// 2. Application continues running normally
// 3. No exceptions thrown to your code
// 4. No application interruption

logger.info('This will work even if serialization fails');
logger.error('This will work even if transport fails');

Think of SyntropyLog as a journalist - we observe, report, and never interfere with the main story.

๐Ÿ“š Documentation

๐ŸŽฏ Production Ready

SyntropyLog is BETA (0.6.14) and ready for production use:

๐Ÿ“ Version Notes

v0.6.15 - Silent Observer Release

  • ๐ŸŽญ Silent Observer Philosophy - Documented core principle: "report what happened and nothing more"
  • ๐Ÿ›ก๏ธ IMPROVED: TimeoutStep Robustness - Eliminated non-null assertions, added defensive fallback
  • ๐Ÿงช ENHANCED: Testing Patterns - Comprehensive test coverage for edge cases and error scenarios
  • ๐Ÿ“š NEW: 5 Comprehensive Testing Examples - Vitest patterns, Jest patterns, Redis context, Serializers, and Transport spies
  • ๐Ÿ”ง FIXED: TimeoutStep Validation - Now handles missing strategies gracefully without throwing errors
  • ๐Ÿ“š UPDATED: Core Philosophy Documentation - Clear explanation of error handling strategy
  • โšก IMPROVED: Error Resilience - Pipeline errors never interrupt application flow
  • ๐ŸŽฏ FOCUS: Zero Application Interruption - Logging failures are reported, not propagated

v0.6.14 - Testing Revolution Release

  • ๐Ÿงช NEW: SyntropyLogMock - Eliminates all connection boilerplate in tests
  • ๐Ÿงช NEW: BeaconRedisMock - In-memory Redis simulation for testing
  • ๐Ÿงช NEW: Test Helpers - Simplified setup and teardown for all test frameworks
  • ๐Ÿงช NEW: Framework Agnostic Mocks - Works with Vitest, Jest, and Jasmine
  • ๐Ÿงช NEW: Boilerplate Testing Patterns - Test initialization and shutdown functions
  • ๐Ÿ“š NEW: 4 Comprehensive Testing Examples - Vitest, Jest, Redis context, and Serializers
  • ๐Ÿ“š NEW: Docusaurus Documentation - Complete testing guides with AI-friendly instructions
  • ๐ŸŽฏ Focus on Declarative Testing - Test behavior, not implementation details
  • โšก Zero External Dependencies - No Redis, brokers, or HTTP servers needed for testing
  • ๐Ÿ”„ Framework Agnostic Testing - Works with Vitest, Jest, and any test runner

v0.6.13 - Documentation Release

  • ๐Ÿ“š Enhanced README with detailed Singleton pattern explanation

  • ๐ŸŒ New GitHub Pages documentation site

  • ๐Ÿ”— Updated documentation links

  • ๐Ÿ“– Improved technical documentation for developers

  • No framework changes - documentation improvements only

  • โœ… 94.1% test coverage across 616+ tests

  • โœ… Core features stable - Logger, context, HTTP, Redis, brokers

  • โœ… API stable - Backward compatible

  • โœ… 17 examples complete - Core features and message brokers tested

  • โœ… Real integration - Examples work with actual services (Redis, Kafka, etc.)

๐Ÿ”ง Standard Configuration

For most applications, you'll want HTTP instrumentation and context management:

import { syntropyLog, PrettyConsoleTransport } from 'syntropylog';
import { AxiosAdapter } from '@syntropylog/adapters';
import axios from 'axios';

await syntropyLog.init({
  logger: {
    level: 'info',
    serviceName: 'my-app',
    transports: [new PrettyConsoleTransport()],
  },
  loggingMatrix: {
    default: ['correlationId'],
    error: ['*'], // Log everything on errors
  },
  http: {
    instances: [
      {
        instanceName: 'myApi',
        adapter: new AxiosAdapter(axios.create({ baseURL: 'https://api.example.com' })),
      },
    ],
  },
});

// Use the instrumented client (singleton instances)
const apiClient = syntropyLog.getHttp('myApi');
const logger = syntropyLog.getLogger();

// Automatic correlation and logging
await apiClient.request({ method: 'GET', url: '/users' });

// Multiple instances with different configurations
const userLogger = syntropyLog.getLogger('user-service');
const paymentLogger = syntropyLog.getLogger('payment-service');
const cacheRedis = syntropyLog.getRedis('cache');
const sessionRedis = syntropyLog.getRedis('session');
const eventsBroker = syntropyLog.getBroker('events');
const notificationsBroker = syntropyLog.getBroker('notifications');

// All instances are singletons - efficient resource usage

๐Ÿ—๏ธ Singleton Pattern - Intelligent Resource Management

SyntropyLog implements a Singleton pattern across all resource types, providing automatic instance management and preventing common production issues:

๐ŸŽฏ Named Instance Management

SyntropyLog uses different patterns for different resource types:

๐Ÿ“ Loggers - On-Demand Creation with Singleton Management

Loggers are the only resources created on-demand and managed as singletons:

// Loggers - Created on-demand with automatic singleton management
const userLogger = syntropyLog.getLogger('user-service');     // Creates new instance
const paymentLogger = syntropyLog.getLogger('payment-service'); // Creates new instance
const userLogger2 = syntropyLog.getLogger('user-service');    // Returns existing instance

// Logger derivatives - Create specialized loggers from templates
const userErrorLogger = syntropyLog.getLogger('user-service:errors'); // New instance
const userDebugLogger = syntropyLog.getLogger('user-service:debug');  // New instance

// Memory efficient - Only creates what you request
// If you create 200 loggers, you get exactly 200 logger instances
// No more, no less - controlled resource allocation

๐Ÿ”— Infrastructure Resources - Pre-configured Singletons

Redis, brokers, and HTTP clients are pre-configured in init() and reused:

// These instances are created during init() and reused
const cacheRedis = syntropyLog.getRedis('cache');             // Returns pre-configured instance
const sessionRedis = syntropyLog.getRedis('session');         // Returns pre-configured instance
const eventsBroker = syntropyLog.getBroker('events');         // Returns pre-configured instance
const apiClient = syntropyLog.getHttp('myApi');               // Returns pre-configured instance

// All calls return the SAME pre-configured instances
console.log(userLogger === userLogger2);      // true โœ… (on-demand singleton)
console.log(cacheRedis === cacheRedis);       // true โœ… (pre-configured singleton)
console.log(eventsBroker === eventsBroker);   // true โœ… (pre-configured singleton)
console.log(apiClient === apiClient);         // true โœ… (pre-configured singleton)

๐Ÿ”„ Automatic Resource Lifecycle

The framework manages resources differently based on their type:

๐Ÿ“ Logger Lifecycle (On-Demand)

  • First call: Creates new logger instance and stores it internally
  • Subsequent calls: Returns the existing logger instance (singleton)
  • Controlled allocation: Only creates loggers you explicitly request
  • Memory efficient: If you create 200 loggers, you get exactly 200 instances

๐Ÿ”— Infrastructure Lifecycle (Pre-configured)

  • During init(): Creates Redis, broker, and HTTP instances based on configuration
  • Runtime calls: Returns pre-configured instances (no new creation)
  • Connection pooling: Reuses existing connections efficiently
  • Consistent state: Same instances across your entire application

โšก Production Benefits

This pattern provides critical advantages in production environments:

  • ๐Ÿ›ก๏ธ Pod Stability: Prevents OOM (Out of Memory) crashes from multiple instances
  • ๐Ÿ”— Connection Efficiency: Reuses existing connections instead of creating new ones
  • ๐Ÿ“Š Consistent Observability: Same logger instance ensures consistent correlation IDs
  • โšก Performance: Eliminates overhead of creating duplicate resources
  • ๐Ÿ—๏ธ Resource Management: Automatic cleanup and connection pooling
  • ๐Ÿš€ Kubernetes Ready: Essential for containerized environments where memory is limited

๐Ÿงช Testing Revolution

๐ŸŽฏ Zero Boilerplate Testing with SyntropyLogMock

Testing SyntropyLog applications is now dramatically simplified with our new testing framework:

import { describe, it, expect, beforeEach } from 'vitest';
import { UserService } from './UserService';
const { createTestHelper } = require('syntropylog/testing');

// No initialization, no shutdown, no external dependencies
const testHelper = createTestHelper();

describe('UserService', () => {
  let userService: UserService;

  beforeEach(() => {
    testHelper.beforeEach(); // Reset mocks
    userService = new UserService(testHelper.mockSyntropyLog); // Inject mock
  });

  it('should create user successfully', async () => {
    const result = await userService.createUser({ name: 'John', email: 'john@example.com' });
    expect(result).toHaveProperty('userId');
    expect(result.name).toBe('John');
  });
});

๐Ÿš€ What's New in v0.6.14

  • ๐Ÿงช SyntropyLogMock - Complete framework simulation in memory
  • ๐Ÿงช BeaconRedisMock - Full Redis simulation without external dependencies
  • ๐Ÿงช Test Helpers - One-line setup for any test framework
  • ๐Ÿ“š 3 Testing Examples - Example 28 (Vitest), Example 29 (Jest), Example 30 (Redis context)
  • ๐ŸŽฏ Declarative Testing - Focus on behavior, not implementation
  • โšก Zero External Dependencies - No Redis, brokers, or HTTP servers needed

โœ… Benefits

  • ๐Ÿšซ No Connection Boilerplate - No init/shutdown in tests
  • โšก Lightning Fast - Everything runs in memory
  • ๐Ÿ”’ Reliable - No network issues or state conflicts
  • ๐ŸŽฏ Focused - Test business logic, not framework internals
  • ๐Ÿ”„ Framework Agnostic - Works with Vitest, Jest, and any test runner

View Testing Examples โ†’

๐Ÿ“ฆ Ecosystem

๐Ÿš€ Examples

Complete examples demonstrating SyntropyLog features:

โœ… Complete & Tested (00-13, 20-24, 28-30)

  • 00-09: Core Framework Features - Basic setup, context, configuration
  • 10-13: HTTP & Redis Integration - Framework agnosticism (Express, Fastify)
  • 20-24: Message Brokers - Kafka, RabbitMQ, NATS with correlation
  • 28-30: Testing Patterns - Vitest, Jest, and Redis context testing with SyntropyLogMock

๐Ÿšง In Development (14-19, 25-27)

  • 14-19: Advanced Framework Features - NestJS, Koa, Hapi, custom serializers
  • 25-27: Enterprise Patterns - Production configuration, advanced context

View all examples โ†’

๐Ÿค Contributing

We welcome contributions! Please see our Contributing Guide for details.

๐Ÿ“„ License

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

๐Ÿ“ž Support


From Chaos to Clarity - Ship resilient, secure, and cost-effective Node.js applications with confidence.