log-vista
Version:
LogVista Agent - Lightweight system monitoring and log collection for any project/language
229 lines (189 loc) • 6.34 kB
JavaScript
const cron = require('node-cron');
const logger = require('./logger');
class Scheduler {
constructor(metricsCollector, logCollector, uploader, config) {
this.metricsCollector = metricsCollector;
this.logCollector = logCollector;
this.uploader = uploader;
this.config = config;
this.tasks = new Map();
this.isRunning = false;
}
start() {
if (this.isRunning) {
logger.warn('Scheduler is already running');
return;
}
logger.info('Starting LogVista Agent Scheduler');
this.isRunning = true;
// Schedule metrics collection
const metricsInterval = this.config.agent.collection_interval || 30;
const metricsSchedule = `*/${metricsInterval} * * * * *`; // Every N seconds
const metricsTask = cron.schedule(metricsSchedule, async () => {
await this.collectAndUploadMetrics();
}, {
scheduled: false
});
this.tasks.set('metrics', metricsTask);
// Schedule log upload (every 10 seconds for more frequent log updates)
const logTask = cron.schedule('*/10 * * * * *', async () => {
await this.uploadLogs();
}, {
scheduled: false
});
this.tasks.set('logs', logTask);
// Schedule offline data retry (every 5 minutes)
const retryTask = cron.schedule('*/5 * * * *', async () => {
await this.retryOfflineData();
}, {
scheduled: false
});
this.tasks.set('retry', retryTask);
// Schedule server info update (every hour)
const serverInfoTask = cron.schedule('0 * * * *', async () => {
await this.updateServerInfo();
}, {
scheduled: false
});
this.tasks.set('serverInfo', serverInfoTask);
// Start all tasks
this.tasks.forEach((task, name) => {
task.start();
logger.info(`Started ${name} task`);
});
// Initial server info update
setTimeout(() => this.updateServerInfo(), 5000);
logger.info('All scheduled tasks started successfully');
}
stop() {
if (!this.isRunning) {
logger.warn('Scheduler is not running');
return;
}
logger.info('Stopping LogVista Agent Scheduler');
this.tasks.forEach((task, name) => {
task.stop();
logger.info(`Stopped ${name} task`);
});
this.tasks.clear();
this.isRunning = false;
logger.info('Scheduler stopped successfully');
}
async collectAndUploadMetrics() {
try {
logger.debug('Collecting system metrics...');
const metrics = [];
// Collect system-wide metrics
if (this.config.system.collect_system_metrics) {
const systemMetrics = await this.metricsCollector.collectSystemMetrics();
metrics.push({
type: 'system',
...systemMetrics
});
}
// Collect project-specific metrics
for (const project of this.config.projects) {
if (!project.enabled) continue;
try {
const projectMetrics = await this.metricsCollector.collectProjectMetrics(project);
metrics.push({
type: 'project',
...projectMetrics
});
} catch (projectError) {
logger.warn(`Failed to collect metrics for project ${project.project_name}:`, projectError.message);
}
}
if (metrics.length > 0) {
await this.uploader.withRetry(() => this.uploader.uploadMetrics(metrics));
logger.debug(`Uploaded ${metrics.length} metric records`);
}
} catch (error) {
logger.error('Error in metrics collection and upload:', error);
}
}
async uploadLogs() {
try {
const bufferedLogs = this.logCollector.getBufferedLogs();
if (bufferedLogs.length > 0) {
await this.uploader.withRetry(() => this.uploader.uploadLogs(bufferedLogs));
logger.debug(`Uploaded ${bufferedLogs.length} log records`);
}
} catch (error) {
logger.error('Error in log upload:', error);
}
}
async retryOfflineData() {
try {
logger.debug('Checking for offline data to retry...');
await this.uploader.retryOfflineData();
} catch (error) {
logger.error('Error retrying offline data:', error);
}
}
async updateServerInfo() {
try {
logger.debug('Updating server information...');
const si = require('systeminformation');
const os = require('os');
const [cpu, osInfo, system] = await Promise.all([
si.cpu(),
si.osInfo(),
si.system()
]);
const serverInfo = {
hostname: os.hostname(),
platform: os.platform(),
architecture: os.arch(),
os: {
platform: osInfo.platform,
distro: osInfo.distro,
release: osInfo.release,
kernel: osInfo.kernel,
arch: osInfo.arch
},
cpu: {
manufacturer: cpu.manufacturer,
brand: cpu.brand,
cores: cpu.cores,
physicalCores: cpu.physicalCores,
speed: cpu.speed
},
system: {
manufacturer: system.manufacturer,
model: system.model,
version: system.version,
serial: system.serial
},
memory: {
total: os.totalmem(),
free: os.freemem()
},
uptime: os.uptime(),
loadavg: os.loadavg(),
agent: {
version: require('../package.json').version,
nodeVersion: process.version,
pid: process.pid
},
projects: this.config.projects.filter(p => p.enabled).map(p => ({
name: p.project_name,
path: p.pwd_path,
logPaths: p.custom_log_paths || []
}))
};
await this.uploader.withRetry(() => this.uploader.uploadServerInfo(serverInfo));
logger.debug('Server information updated successfully');
} catch (error) {
logger.error('Error updating server information:', error);
}
}
getStatus() {
return {
isRunning: this.isRunning,
activeTasks: Array.from(this.tasks.keys()),
taskCount: this.tasks.size
};
}
}
module.exports = Scheduler;