Skip to main content

Configuration Patterns - Production Ready

This page shows the complete configuration patterns used in production applications with SyntropyLog.

šŸ—ļø Standard Project Structure​

src/
ā”œā”€ā”€ config.ts # SyntropyLog configuration
ā”œā”€ā”€ boilerplate.ts # Initialization and shutdown handlers
ā”œā”€ā”€ main.ts # Application entry point
└── ...

šŸ“ Configuration File (config.ts)​

// =================================================================
// config.ts - SyntropyLog Configuration
// RESPONSIBILITY: Define configuration using official framework types
// =================================================================

import { SyntropyLogConfig, ClassicConsoleTransport } from 'syntropylog';
import { KafkaAdapter } from '@syntropylog/adapters/brokers';
import { AxiosAdapter } from '@syntropylog/adapters/http';
import { Kafka, logLevel as kafkaLogLevel } from 'kafkajs';
import axios from 'axios';

// āœ… Using official framework types
export const syntropyConfig: SyntropyLogConfig = {
logger: {
level: 'info',
serviceName: 'my-production-app',
serializerTimeoutMs: 100,
transports: [new ClassicConsoleTransport()]
},

context: {
correlationIdHeader: 'X-Correlation-ID',
},

loggingMatrix: {
default: ['correlationId', 'serviceName'],
error: ['*'], // Log everything on errors
},

http: {
instances: [
{
instanceName: 'api-client',
adapter: new AxiosAdapter(
axios.create({
baseURL: 'https://api.example.com',
timeout: 5000
})
),
},
],
},

brokers: {
instances: [
{
instanceName: 'events-bus',
adapter: new KafkaAdapter(
new Kafka({
clientId: 'my-app-client',
brokers: ['localhost:9092'],
logLevel: kafkaLogLevel.ERROR,
retry: {
initialRetryTime: 100,
retries: 8
}
}),
'my-app-group'
),
},
],
},
};

šŸ”§ Boilerplate File (boilerplate.ts)​

// =================================================================
// boilerplate.ts - Standard initialization and shutdown
// RESPONSIBILITY: Provide reusable boilerplate for SyntropyLog
// =================================================================

import { syntropyLog } from 'syntropylog';
import { syntropyConfig } from './config';

export async function initializeSyntropyLog(): Promise<void> {
console.log('šŸš€ Initializing SyntropyLog...');

try {
// āœ… Using configuration from config.ts - simple async/await pattern
await syntropyLog.init(syntropyConfig);
console.log('āœ… SyntropyLog initialized successfully!');
} catch (error) {
console.error('āŒ SyntropyLog initialization failed:', error);
throw error;
}
}

export async function gracefulShutdown(): Promise<void> {
console.log('šŸ”„ Shutting down SyntropyLog gracefully...');

try {
// āš ļø CRITICAL: This flushes all pending logs before shutdown
await syntropyLog.shutdown();
console.log('āœ… SyntropyLog shutdown completed');
} catch (error) {
console.error('āŒ Error during shutdown:', error);
}
}

// Signal handlers for graceful shutdown
process.on('SIGINT', async () => {
console.log('\nšŸ›‘ Received SIGINT, shutting down gracefully...');
await gracefulShutdown();
process.exit(0);
});

process.on('SIGTERM', async () => {
console.log('\nšŸ›‘ Received SIGTERM, shutting down gracefully...');
await gracefulShutdown();
process.exit(0);
});

šŸš€ Application Entry Point (main.ts)​

// =================================================================
// main.ts - Application Entry Point
// RESPONSIBILITY: Initialize and run the application
// =================================================================

import { syntropyLog } from 'syntropylog';
import { initializeSyntropyLog } from './boilerplate';

async function main() {
try {
// Initialize SyntropyLog with configuration
await initializeSyntropyLog();

// Get logger instance
const logger = syntropyLog.getLogger('main');
logger.info('Application started successfully');

// Get other resources (singleton instances)
const apiClient = syntropyLog.getHttp('api-client');
const eventsBroker = syntropyLog.getBroker('events-bus');

// Your application logic here
logger.info('All resources initialized, starting application...');

// Example: Make an HTTP request
const response = await apiClient.request({
method: 'GET',
url: '/health'
});

logger.info('Health check completed', { status: response.status });

} catch (error) {
console.error('āŒ Application startup failed:', error);
process.exit(1);
}
}

// Start the application
main().catch((error) => {
console.error('āŒ Unhandled error:', error);
process.exit(1);
});

šŸŽÆ Key Benefits of This Pattern​

1. Separation of Concerns​

  • config.ts: Pure configuration definition
  • boilerplate.ts: Initialization and shutdown logic
  • main.ts: Application business logic

2. Reusability​

  • Boilerplate can be copied between projects
  • Configuration is easily modifiable
  • Clear responsibility boundaries

3. Production Ready​

  • Graceful shutdown handling
  • Error handling at all levels
  • Proper resource cleanup
  • Kubernetes compatibility

4. Type Safety​

  • Uses official framework types
  • Compile-time configuration validation
  • IDE autocompletion support

šŸ“š Complete Examples​

See these patterns in action in the main repository:

āš ļø Production Checklist​

Before deploying, ensure:

  • āœ… Configuration uses official types
  • āœ… Boilerplate includes graceful shutdown
  • āœ… Error handling at all levels
  • āœ… Resource cleanup on shutdown
  • āœ… Signal handlers for SIGTERM/SIGINT