|
|
|
@@ -1,8 +1,48 @@
|
|
|
|
|
const fs = require('fs');
|
|
|
|
|
const path = require('path');
|
|
|
|
|
const { trackRequestWithTiming, trackRequest } = require('../../../maintenance/metrics');
|
|
|
|
|
const { logError } = require('../../../infrastructure/logger');
|
|
|
|
|
const { createErrorResponse } = require('../../../infrastructure/error_handler');
|
|
|
|
|
const { collectAdminStats, collectHistoricalMinutes } = require('../stats-collector');
|
|
|
|
|
|
|
|
|
|
const statsUIPrefsFile = './cache/statsUIPreferences.json';
|
|
|
|
|
const VALID_STATS_MINUTES = [1, 5, 15, 30, 60, 360, 1440, 2880];
|
|
|
|
|
const VALID_STATS_INTERVALS = [1000, 2000, 5000, 10000, 30000];
|
|
|
|
|
const DEFAULT_STATS_UI_PREFS = {
|
|
|
|
|
minutes: 5,
|
|
|
|
|
intervalMs: 2000,
|
|
|
|
|
autoRefresh: true
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
function normalizeStatsUIPrefs(input) {
|
|
|
|
|
const prefs = {
|
|
|
|
|
...DEFAULT_STATS_UI_PREFS,
|
|
|
|
|
...(input && typeof input === 'object' ? input : {})
|
|
|
|
|
};
|
|
|
|
|
const minutes = Number(prefs.minutes);
|
|
|
|
|
const intervalMs = Number(prefs.intervalMs);
|
|
|
|
|
prefs.minutes = VALID_STATS_MINUTES.includes(minutes) ? minutes : DEFAULT_STATS_UI_PREFS.minutes;
|
|
|
|
|
prefs.intervalMs = VALID_STATS_INTERVALS.includes(intervalMs) ? intervalMs : DEFAULT_STATS_UI_PREFS.intervalMs;
|
|
|
|
|
prefs.autoRefresh = prefs.autoRefresh !== false;
|
|
|
|
|
return prefs;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function readStatsUIPrefsFromDisk() {
|
|
|
|
|
if (!fs.existsSync(statsUIPrefsFile)) {
|
|
|
|
|
return { ...DEFAULT_STATS_UI_PREFS };
|
|
|
|
|
}
|
|
|
|
|
const data = fs.readFileSync(statsUIPrefsFile, 'utf8');
|
|
|
|
|
return normalizeStatsUIPrefs(JSON.parse(data));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function writeStatsUIPrefsToDisk(prefs) {
|
|
|
|
|
const cacheDir = path.dirname(statsUIPrefsFile);
|
|
|
|
|
if (!fs.existsSync(cacheDir)) {
|
|
|
|
|
fs.mkdirSync(cacheDir, { recursive: true });
|
|
|
|
|
}
|
|
|
|
|
fs.writeFileSync(statsUIPrefsFile, JSON.stringify(normalizeStatsUIPrefs(prefs), null, 2));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
async function handleStatsRoutes(req, res) {
|
|
|
|
|
const urlPath = req.urlPath || new URL(req.url, `https://${req.headers.host}`).pathname;
|
|
|
|
|
const method = req.method;
|
|
|
|
@@ -27,7 +67,7 @@ async function handleStatsRoutes(req, res) {
|
|
|
|
|
|
|
|
|
|
if (method === 'GET' && urlPath === '/api/stats/historical') {
|
|
|
|
|
try {
|
|
|
|
|
let minutes = 60;
|
|
|
|
|
let minutes = 5;
|
|
|
|
|
if (req.url.includes('?')) {
|
|
|
|
|
const queryString = req.url.split('?')[1];
|
|
|
|
|
const params = new URLSearchParams(queryString);
|
|
|
|
@@ -52,6 +92,42 @@ async function handleStatsRoutes(req, res) {
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (method === 'GET' && urlPath === '/api/stats-ui-preferences') {
|
|
|
|
|
try {
|
|
|
|
|
const prefs = readStatsUIPrefsFromDisk();
|
|
|
|
|
trackRequest('/api/stats-ui-preferences', true);
|
|
|
|
|
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
|
|
|
res.end(JSON.stringify(prefs));
|
|
|
|
|
} catch (err) {
|
|
|
|
|
logError('Admin', `Error in /api/stats-ui-preferences: ${err.message}`, err);
|
|
|
|
|
trackRequest('/api/stats-ui-preferences', false);
|
|
|
|
|
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
|
|
|
res.end(JSON.stringify(DEFAULT_STATS_UI_PREFS));
|
|
|
|
|
}
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (method === 'POST' && urlPath === '/api/save-stats-ui-preferences') {
|
|
|
|
|
let body = '';
|
|
|
|
|
req.on('data', (chunk) => { body += chunk; });
|
|
|
|
|
req.on('end', () => {
|
|
|
|
|
try {
|
|
|
|
|
const prefs = normalizeStatsUIPrefs(JSON.parse(body || '{}'));
|
|
|
|
|
writeStatsUIPrefsToDisk(prefs);
|
|
|
|
|
trackRequest('/api/save-stats-ui-preferences', true);
|
|
|
|
|
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
|
|
|
res.end(JSON.stringify(prefs));
|
|
|
|
|
} catch (err) {
|
|
|
|
|
logError('Admin', `Error in /api/save-stats-ui-preferences: ${err.message}`, err);
|
|
|
|
|
trackRequest('/api/save-stats-ui-preferences', false);
|
|
|
|
|
const errorResponse = createErrorResponse(err, 500);
|
|
|
|
|
res.writeHead(errorResponse.statusCode, errorResponse.headers);
|
|
|
|
|
res.end(errorResponse.body);
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|