Package Exports
- syntropylog
- syntropylog/brokers
- syntropylog/doctor
- syntropylog/http
- syntropylog/testing
- syntropylog/testing/mock
Readme
SyntropyLog
From Chaos to Clarity
The Observability Framework for High-Performance Teams
๐ Quick Start
Get started with SyntropyLog usage in 30 seconds (after initialization):
npm install syntropylog@0.6.14import { 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
- Configuration Errors โ Application fails to start (as expected)
- Pipeline Errors โ Error reported to transports, application continues
- Serializer Errors โ Error reported to transports, application continues
- 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
- Getting Started - Complete setup guide (in progress)
- API Reference - Full API documentation (in progress)
- Examples - 30 production-ready examples (in progress)
- Configuration Guide - Advanced configuration (in progress)
๐ฏ 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
๐ฆ Ecosystem
- syntropylog - Core framework
- @syntropylog/adapters - HTTP and broker adapters
- @syntropylog/types - TypeScript types
- syntropylog-examples - 30 complete examples
๐ 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
๐ค 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
- ๐ Documentation (in progress)
- ๐ Issues
- ๐ฌ Discussions
From Chaos to Clarity - Ship resilient, secure, and cost-effective Node.js applications with confidence.