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