added working config lib

This commit is contained in:
Bojan Kucera 2025-06-03 14:09:31 -04:00
parent f8576c0d93
commit def9bce8dc
33 changed files with 2896 additions and 1485 deletions

View file

@ -1,102 +1,81 @@
/**
* Loki logging configuration for Stock Bot platform
* Logging configuration using envalid
* Application logging settings without Loki (Loki config is in monitoring.ts)
*/
import { z } from 'zod';
import { getEnvVar, getNumericEnvVar, getBooleanEnvVar, createConfigLoader, validateConfig } from './core';
import { cleanEnv, str, bool, num } from 'envalid';
/**
* Loki configuration schema
* Logging configuration with validation and defaults
*/
export const lokiConfigSchema = z.object({
host: z.string().default('localhost'),
port: z.number().default(3100),
username: z.string().optional(),
password: z.string().optional(),
retentionDays: z.number().default(30),
labels: z.record(z.string()).default({}),
batchSize: z.number().default(100),
flushIntervalMs: z.number().default(5000)
export const loggingConfig = cleanEnv(process.env, {
// Basic Logging Settings
LOG_LEVEL: str({
default: 'info',
choices: ['error', 'warn', 'info', 'http', 'verbose', 'debug', 'silly'],
desc: 'Logging level'
}),
LOG_FORMAT: str({
default: 'json',
choices: ['json', 'simple', 'combined'],
desc: 'Log output format'
}),
LOG_CONSOLE: bool({ default: true, desc: 'Enable console logging' }),
LOG_FILE: bool({ default: false, desc: 'Enable file logging' }),
// File Logging Settings
LOG_FILE_PATH: str({ default: 'logs', desc: 'Log file directory path' }),
LOG_FILE_MAX_SIZE: str({ default: '20m', desc: 'Maximum log file size' }),
LOG_FILE_MAX_FILES: num({ default: 14, desc: 'Maximum number of log files to keep' }),
LOG_FILE_DATE_PATTERN: str({ default: 'YYYY-MM-DD', desc: 'Log file date pattern' }),
// Error Logging
LOG_ERROR_FILE: bool({ default: true, desc: 'Enable separate error log file' }),
LOG_ERROR_STACK: bool({ default: true, desc: 'Include stack traces in error logs' }),
// Performance Logging
LOG_PERFORMANCE: bool({ default: false, desc: 'Enable performance logging' }),
LOG_SQL_QUERIES: bool({ default: false, desc: 'Log SQL queries' }),
LOG_HTTP_REQUESTS: bool({ default: true, desc: 'Log HTTP requests' }),
// Structured Logging
LOG_STRUCTURED: bool({ default: true, desc: 'Use structured logging format' }),
LOG_TIMESTAMP: bool({ default: true, desc: 'Include timestamps in logs' }),
LOG_CALLER_INFO: bool({ default: false, desc: 'Include caller information in logs' }),
// Log Filtering
LOG_SILENT_MODULES: str({ default: '', desc: 'Comma-separated list of modules to silence' }),
LOG_VERBOSE_MODULES: str({ default: '', desc: 'Comma-separated list of modules for verbose logging' }),
// Application Context
LOG_SERVICE_NAME: str({ default: 'stock-bot', desc: 'Service name for log context' }),
LOG_SERVICE_VERSION: str({ default: '1.0.0', desc: 'Service version for log context' }),
LOG_ENVIRONMENT: str({ default: 'development', desc: 'Environment for log context' }),
});
export type LokiConfig = z.infer<typeof lokiConfigSchema>;
// Export typed configuration object
export type LoggingConfig = typeof loggingConfig;
/**
* Logging configuration schema
*/
export const loggingConfigSchema = z.object({
level: z.enum(['debug', 'info', 'warn', 'error']).default('info'),
console: z.boolean().default(true),
loki: lokiConfigSchema
});
export type LoggingConfig = z.infer<typeof loggingConfigSchema>;
/**
* Parse labels from environment variable string
* Format: key1=value1,key2=value2
*/
function parseLabels(labelsStr?: string): Record<string, string> {
if (!labelsStr) return {};
const labels: Record<string, string> = {};
labelsStr.split(',').forEach(labelPair => {
const [key, value] = labelPair.trim().split('=');
if (key && value) {
labels[key] = value;
}
});
return labels;
}
/**
* Default logging configuration
*/
const defaultLoggingConfig: LoggingConfig = {
level: 'info',
console: true,
loki: {
host: 'localhost',
port: 3100,
retentionDays: 30,
labels: {},
batchSize: 100,
flushIntervalMs: 5000
}
};
/**
* Load logging configuration from environment variables
*/
export function loadLoggingConfig(): LoggingConfig {
const config = {
level: (getEnvVar('LOG_LEVEL') || 'info') as 'debug' | 'info' | 'warn' | 'error',
console: getBooleanEnvVar('LOG_CONSOLE', true),
loki: {
host: getEnvVar('LOKI_HOST') || 'localhost',
port: getNumericEnvVar('LOKI_PORT', 3100),
username: getEnvVar('LOKI_USERNAME'),
password: getEnvVar('LOKI_PASSWORD'),
retentionDays: getNumericEnvVar('LOKI_RETENTION_DAYS', 30),
labels: parseLabels(getEnvVar('LOKI_LABELS')),
batchSize: getNumericEnvVar('LOKI_BATCH_SIZE', 100),
flushIntervalMs: getNumericEnvVar('LOKI_FLUSH_INTERVAL_MS', 5000)
}
};
return validateConfig(config, loggingConfigSchema);
}
/**
* Creates a dynamic configuration loader for logging
*/
export const createLoggingConfig = createConfigLoader<typeof defaultLoggingConfig>(
'logging',
loggingConfigSchema,
defaultLoggingConfig
);
/**
* Singleton logging configuration
*/
export const loggingConfig = loadLoggingConfig();
// Export individual config values for convenience
export const {
LOG_LEVEL,
LOG_FORMAT,
LOG_CONSOLE,
LOG_FILE,
LOG_FILE_PATH,
LOG_FILE_MAX_SIZE,
LOG_FILE_MAX_FILES,
LOG_FILE_DATE_PATTERN,
LOG_ERROR_FILE,
LOG_ERROR_STACK,
LOG_PERFORMANCE,
LOG_SQL_QUERIES,
LOG_HTTP_REQUESTS,
LOG_STRUCTURED,
LOG_TIMESTAMP,
LOG_CALLER_INFO,
LOG_SILENT_MODULES,
LOG_VERBOSE_MODULES,
LOG_SERVICE_NAME,
LOG_SERVICE_VERSION,
LOG_ENVIRONMENT,
} = loggingConfig;