logs-interceptor
Version:
High-performance, production-ready log interceptor for Node.js applications with Loki integration. Built with Clean Architecture principles. Supports Node.js, Browser, and Node-RED.
241 lines • 8.46 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.validateConfig = exports.mergeConfigs = exports.loadConfigFromEnv = void 0;
/**
* Parse labels from environment variable string format
*/
function parseLabels(labelsString) {
const labels = {};
if (!labelsString) {
return labels;
}
try {
// Support JSON format
if (labelsString.startsWith('{')) {
return JSON.parse(labelsString);
}
// Support key=value format
const pairs = labelsString.split(',');
for (const pair of pairs) {
const [key, ...valueParts] = pair.split('=');
if (key && valueParts.length > 0) {
labels[key.trim()] = valueParts.join('=').trim();
}
}
}
catch (error) {
console.warn('Failed to parse labels from environment:', error);
}
return labels;
}
/**
* Load configuration from environment variables
*/
function loadConfigFromEnv() {
const env = process.env;
const config = {};
// Transport configuration
if (env.LOGS_INTERCEPTOR_URL) {
config.transport = {
...config.transport,
url: env.LOGS_INTERCEPTOR_URL,
};
}
if (env.LOGS_INTERCEPTOR_TENANT_ID) {
config.transport = {
...config.transport,
tenantId: env.LOGS_INTERCEPTOR_TENANT_ID,
};
}
if (env.LOGS_INTERCEPTOR_AUTH_TOKEN) {
config.transport = {
...config.transport,
authToken: env.LOGS_INTERCEPTOR_AUTH_TOKEN,
};
}
// Application metadata
if (env.LOGS_INTERCEPTOR_APP_NAME) {
config.appName = env.LOGS_INTERCEPTOR_APP_NAME;
}
if (env.LOGS_INTERCEPTOR_ENVIRONMENT) {
config.environment = env.LOGS_INTERCEPTOR_ENVIRONMENT;
}
if (env.LOGS_INTERCEPTOR_VERSION) {
config.version = env.LOGS_INTERCEPTOR_VERSION;
}
// Labels
if (env.LOGS_INTERCEPTOR_LABELS) {
config.labels = parseLabels(env.LOGS_INTERCEPTOR_LABELS);
}
// Buffer configuration
if (env.LOGS_INTERCEPTOR_BUFFER_SIZE) {
const bufferSize = parseInt(env.LOGS_INTERCEPTOR_BUFFER_SIZE, 10);
if (!isNaN(bufferSize) && bufferSize > 0) {
config.buffer = {
...config.buffer,
maxSize: bufferSize,
};
}
}
if (env.LOGS_INTERCEPTOR_MAX_MEMORY_MB) {
const maxMemory = parseInt(env.LOGS_INTERCEPTOR_MAX_MEMORY_MB, 10);
if (!isNaN(maxMemory) && maxMemory > 0) {
config.buffer = {
...config.buffer,
maxMemoryMB: maxMemory,
};
}
}
if (env.LOGS_INTERCEPTOR_FLUSH_INTERVAL) {
const flushInterval = parseInt(env.LOGS_INTERCEPTOR_FLUSH_INTERVAL, 10);
if (!isNaN(flushInterval) && flushInterval > 0) {
config.buffer = {
...config.buffer,
flushInterval,
};
}
}
// Filtering
if (env.LOGS_INTERCEPTOR_LOG_LEVEL) {
const levels = env.LOGS_INTERCEPTOR_LOG_LEVEL.split(',')
.map(level => level.trim().toLowerCase())
.filter(level => ['debug', 'info', 'warn', 'error', 'fatal'].includes(level));
if (levels.length > 0) {
config.filter = {
...config.filter,
levels,
};
}
}
if (env.LOGS_INTERCEPTOR_SAMPLING_RATE) {
const samplingRate = parseFloat(env.LOGS_INTERCEPTOR_SAMPLING_RATE);
if (!isNaN(samplingRate) && samplingRate >= 0 && samplingRate <= 1) {
config.filter = {
...config.filter,
samplingRate,
};
}
}
if (env.LOGS_INTERCEPTOR_SANITIZE) {
config.filter = {
...config.filter,
sanitize: env.LOGS_INTERCEPTOR_SANITIZE.toLowerCase() === 'true',
};
}
// Circuit breaker
if (env.LOGS_INTERCEPTOR_CIRCUIT_BREAKER) {
config.circuitBreaker = {
enabled: env.LOGS_INTERCEPTOR_CIRCUIT_BREAKER.toLowerCase() === 'true',
};
}
// Feature flags
if (env.LOGS_INTERCEPTOR_ENABLED) {
const enabled = env.LOGS_INTERCEPTOR_ENABLED.toLowerCase() === 'true';
if (!enabled) {
// Return a minimal config that effectively disables logging
return {
filter: {
levels: [],
},
};
}
}
return config;
}
exports.loadConfigFromEnv = loadConfigFromEnv;
/**
* Merge configurations with precedence: user config > env config > defaults
*/
function mergeConfigs(userConfig, envConfig) {
const merged = {
...envConfig,
...userConfig,
};
// Handle transport merge carefully
if (envConfig.transport || userConfig.transport) {
merged.transport = {
...envConfig.transport,
...userConfig.transport,
};
}
// Handle other nested objects
if (envConfig.buffer || userConfig.buffer) {
merged.buffer = { ...envConfig.buffer, ...userConfig.buffer };
}
if (envConfig.filter || userConfig.filter) {
merged.filter = { ...envConfig.filter, ...userConfig.filter };
}
if (envConfig.labels || userConfig.labels) {
merged.labels = { ...envConfig.labels, ...userConfig.labels };
}
if (envConfig.dynamicLabels || userConfig.dynamicLabels) {
merged.dynamicLabels = { ...envConfig.dynamicLabels, ...userConfig.dynamicLabels };
}
if (envConfig.circuitBreaker || userConfig.circuitBreaker) {
merged.circuitBreaker = { ...envConfig.circuitBreaker, ...userConfig.circuitBreaker };
}
return merged;
}
exports.mergeConfigs = mergeConfigs;
/**
* Validate that required configuration is present
*/
function validateConfig(config) {
var _a, _b, _c, _d, _e, _f, _g, _h, _j;
const errors = [];
if (!((_a = config.transport) === null || _a === void 0 ? void 0 : _a.url)) {
errors.push('Transport URL is required (LOGS_INTERCEPTOR_URL)');
}
if (!((_b = config.transport) === null || _b === void 0 ? void 0 : _b.tenantId)) {
errors.push('Tenant ID is required (LOGS_INTERCEPTOR_TENANT_ID)');
}
if (!config.appName) {
errors.push('App name is required (LOGS_INTERCEPTOR_APP_NAME)');
}
// Validate URL format
if ((_c = config.transport) === null || _c === void 0 ? void 0 : _c.url) {
try {
new URL(config.transport.url);
}
catch {
errors.push('Transport URL must be a valid URL');
}
}
// Validate buffer size
if (((_d = config.buffer) === null || _d === void 0 ? void 0 : _d.maxSize) !== undefined && config.buffer.maxSize <= 0) {
errors.push('Buffer max size must be greater than 0');
}
// Validate flush interval
if (((_e = config.buffer) === null || _e === void 0 ? void 0 : _e.flushInterval) !== undefined && config.buffer.flushInterval <= 0) {
errors.push('Flush interval must be greater than 0');
}
// Validate sampling rate
if (((_f = config.filter) === null || _f === void 0 ? void 0 : _f.samplingRate) !== undefined) {
const rate = config.filter.samplingRate;
if (rate < 0 || rate > 1) {
errors.push('Sampling rate must be between 0 and 1');
}
}
// Validate circuit breaker
if (((_g = config.circuitBreaker) === null || _g === void 0 ? void 0 : _g.failureThreshold) !== undefined) {
if (config.circuitBreaker.failureThreshold < 1) {
errors.push('Circuit breaker failure threshold must be at least 1');
}
}
// Validate memory limit
if (((_h = config.buffer) === null || _h === void 0 ? void 0 : _h.maxMemoryMB) !== undefined) {
if (config.buffer.maxMemoryMB < 1 || config.buffer.maxMemoryMB > 1000) {
errors.push('Max memory must be between 1 and 1000 MB');
}
}
// Validate compression level
if (((_j = config.transport) === null || _j === void 0 ? void 0 : _j.compressionLevel) !== undefined) {
const level = config.transport.compressionLevel;
if (level < 0 || level > 9) {
errors.push('Compression level must be between 0 and 9');
}
}
return errors;
}
exports.validateConfig = validateConfig;
//# sourceMappingURL=ConfigLoader.js.map