Initial commit: StreamFlow IPTV platform
This commit is contained in:
commit
73a8ae9ffd
1240 changed files with 278451 additions and 0 deletions
124
backend/utils/logger.js
Normal file
124
backend/utils/logger.js
Normal file
|
|
@ -0,0 +1,124 @@
|
|||
const winston = require('winston');
|
||||
const path = require('path');
|
||||
const fs = require('fs');
|
||||
|
||||
// Ensure logs directory exists
|
||||
const logsDir = path.join(__dirname, '../../logs');
|
||||
if (!fs.existsSync(logsDir)) {
|
||||
fs.mkdirSync(logsDir, { recursive: true, mode: 0o755 });
|
||||
}
|
||||
|
||||
/**
|
||||
* Custom format to sanitize sensitive data from logs
|
||||
* Removes passwords, tokens, secrets, and other sensitive information
|
||||
*/
|
||||
const sanitizeFormat = winston.format((info) => {
|
||||
// Convert info to string for pattern matching
|
||||
const infoStr = JSON.stringify(info);
|
||||
|
||||
// Patterns to redact
|
||||
const sensitivePatterns = [
|
||||
{ pattern: /"password"\s*:\s*"[^"]*"/gi, replacement: '"password":"[REDACTED]"' },
|
||||
{ pattern: /"token"\s*:\s*"[^"]*"/gi, replacement: '"token":"[REDACTED]"' },
|
||||
{ pattern: /"secret"\s*:\s*"[^"]*"/gi, replacement: '"secret":"[REDACTED]"' },
|
||||
{ pattern: /"apiKey"\s*:\s*"[^"]*"/gi, replacement: '"apiKey":"[REDACTED]"' },
|
||||
{ pattern: /"api_key"\s*:\s*"[^"]*"/gi, replacement: '"api_key":"[REDACTED]"' },
|
||||
{ pattern: /"authorization"\s*:\s*"Bearer\s+[^"]*"/gi, replacement: '"authorization":"Bearer [REDACTED]"' },
|
||||
{ pattern: /"privateKey"\s*:\s*"[^"]*"/gi, replacement: '"privateKey":"[REDACTED]"' },
|
||||
{ pattern: /"private_key"\s*:\s*"[^"]*"/gi, replacement: '"private_key":"[REDACTED]"' }
|
||||
];
|
||||
|
||||
let sanitized = infoStr;
|
||||
sensitivePatterns.forEach(({ pattern, replacement }) => {
|
||||
sanitized = sanitized.replace(pattern, replacement);
|
||||
});
|
||||
|
||||
try {
|
||||
return JSON.parse(sanitized);
|
||||
} catch (e) {
|
||||
return info; // Return original if parsing fails
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* Production format: Structured JSON logs without sensitive data
|
||||
*/
|
||||
const productionFormat = winston.format.combine(
|
||||
winston.format.timestamp({ format: 'YYYY-MM-DD HH:mm:ss' }),
|
||||
winston.format.errors({ stack: true }),
|
||||
sanitizeFormat(),
|
||||
winston.format.json()
|
||||
);
|
||||
|
||||
/**
|
||||
* Development format: Human-readable with colors
|
||||
*/
|
||||
const developmentFormat = winston.format.combine(
|
||||
winston.format.timestamp({ format: 'YYYY-MM-DD HH:mm:ss' }),
|
||||
winston.format.errors({ stack: true }),
|
||||
sanitizeFormat(),
|
||||
winston.format.colorize(),
|
||||
winston.format.printf(({ timestamp, level, message, ...meta }) => {
|
||||
let msg = `${timestamp} [${level}]: ${message}`;
|
||||
if (Object.keys(meta).length > 0) {
|
||||
msg += ` ${JSON.stringify(meta, null, 2)}`;
|
||||
}
|
||||
return msg;
|
||||
})
|
||||
);
|
||||
|
||||
const isProduction = process.env.NODE_ENV === 'production';
|
||||
|
||||
const logger = winston.createLogger({
|
||||
level: process.env.LOG_LEVEL || (isProduction ? 'info' : 'debug'),
|
||||
format: productionFormat,
|
||||
defaultMeta: { service: 'streamflow-iptv' },
|
||||
transports: [
|
||||
// Error logs - separate file for errors only
|
||||
new winston.transports.File({
|
||||
filename: path.join(logsDir, 'error.log'),
|
||||
level: 'error',
|
||||
maxsize: 5242880, // 5MB
|
||||
maxFiles: 5,
|
||||
tailable: true
|
||||
}),
|
||||
// Combined logs - all levels
|
||||
new winston.transports.File({
|
||||
filename: path.join(logsDir, 'combined.log'),
|
||||
maxsize: 5242880, // 5MB
|
||||
maxFiles: 5,
|
||||
tailable: true
|
||||
})
|
||||
],
|
||||
// Don't exit on uncaught exceptions
|
||||
exitOnError: false
|
||||
});
|
||||
|
||||
// Console transport for development
|
||||
if (!isProduction) {
|
||||
logger.add(new winston.transports.Console({
|
||||
format: developmentFormat,
|
||||
handleExceptions: true
|
||||
}));
|
||||
}
|
||||
|
||||
// Security audit log helper
|
||||
logger.security = (action, details) => {
|
||||
logger.info('SECURITY_EVENT', {
|
||||
action,
|
||||
timestamp: new Date().toISOString(),
|
||||
...details
|
||||
});
|
||||
};
|
||||
|
||||
// Performance monitoring helper
|
||||
logger.performance = (operation, duration, details = {}) => {
|
||||
logger.info('PERFORMANCE', {
|
||||
operation,
|
||||
duration_ms: duration,
|
||||
timestamp: new Date().toISOString(),
|
||||
...details
|
||||
});
|
||||
};
|
||||
|
||||
module.exports = logger;
|
||||
Loading…
Add table
Add a link
Reference in a new issue