优化后端的性能
This commit is contained in:
@@ -588,6 +588,11 @@
|
|||||||
<option value="max">出入取大 (Max)</option>
|
<option value="max">出入取大 (Max)</option>
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="form-group" style="margin-top: 15px;">
|
||||||
|
<label for="prometheusCacheTtlInput">数据自动刷新/同步间隔 (秒)</label>
|
||||||
|
<input type="number" id="prometheusCacheTtlInput" placeholder="例:30" min="0" max="86400">
|
||||||
|
<p style="font-size: 0.72rem; color: var(--text-muted); margin-top: 6px;">后端将按此频率主动从 Prometheus 抓取数据并缓存。设为 0 则禁用自动同步。建议值:15-60s。</p>
|
||||||
|
</div>
|
||||||
<div class="form-group" style="margin-top: 15px;">
|
<div class="form-group" style="margin-top: 15px;">
|
||||||
<label for="psFilingInput">公安备案号 (如:京公网安备 11010102000001号)</label>
|
<label for="psFilingInput">公安备案号 (如:京公网安备 11010102000001号)</label>
|
||||||
<input type="text" id="psFilingInput" placeholder="请输入公安备案号">
|
<input type="text" id="psFilingInput" placeholder="请输入公安备案号">
|
||||||
|
|||||||
@@ -132,7 +132,8 @@
|
|||||||
btnAddCustomMetric: document.getElementById('btnAddCustomMetric'),
|
btnAddCustomMetric: document.getElementById('btnAddCustomMetric'),
|
||||||
btnSaveCustomMetrics: document.getElementById('btnSaveCustomMetrics'),
|
btnSaveCustomMetrics: document.getElementById('btnSaveCustomMetrics'),
|
||||||
customDataContainer: document.getElementById('customDataContainer'),
|
customDataContainer: document.getElementById('customDataContainer'),
|
||||||
cdnUrlInput: document.getElementById('cdnUrlInput')
|
cdnUrlInput: document.getElementById('cdnUrlInput'),
|
||||||
|
prometheusCacheTtlInput: document.getElementById('prometheusCacheTtlInput')
|
||||||
};
|
};
|
||||||
|
|
||||||
// ---- State ----
|
// ---- State ----
|
||||||
@@ -655,6 +656,7 @@
|
|||||||
if (dom.logoUrlDarkInput) dom.logoUrlDarkInput.value = window.SITE_SETTINGS.logo_url_dark || '';
|
if (dom.logoUrlDarkInput) dom.logoUrlDarkInput.value = window.SITE_SETTINGS.logo_url_dark || '';
|
||||||
if (dom.faviconUrlInput) dom.faviconUrlInput.value = window.SITE_SETTINGS.favicon_url || '';
|
if (dom.faviconUrlInput) dom.faviconUrlInput.value = window.SITE_SETTINGS.favicon_url || '';
|
||||||
if (dom.showServerIpInput) dom.showServerIpInput.value = window.SITE_SETTINGS.show_server_ip ? "1" : "0";
|
if (dom.showServerIpInput) dom.showServerIpInput.value = window.SITE_SETTINGS.show_server_ip ? "1" : "0";
|
||||||
|
if (dom.prometheusCacheTtlInput) dom.prometheusCacheTtlInput.value = window.SITE_SETTINGS.prometheus_cache_ttl !== undefined ? window.SITE_SETTINGS.prometheus_cache_ttl : 30;
|
||||||
|
|
||||||
// Apply security dependency
|
// Apply security dependency
|
||||||
updateSecurityDependency();
|
updateSecurityDependency();
|
||||||
@@ -2311,7 +2313,8 @@
|
|||||||
ip_metric_name: dom.ipMetricNameInput ? dom.ipMetricNameInput.value.trim() : null,
|
ip_metric_name: dom.ipMetricNameInput ? dom.ipMetricNameInput.value.trim() : null,
|
||||||
ip_label_name: dom.ipLabelNameInput ? dom.ipLabelNameInput.value.trim() : 'address',
|
ip_label_name: dom.ipLabelNameInput ? dom.ipLabelNameInput.value.trim() : 'address',
|
||||||
custom_metrics: getCustomMetricsFromUI(),
|
custom_metrics: getCustomMetricsFromUI(),
|
||||||
cdn_url: dom.cdnUrlInput ? dom.cdnUrlInput.value.trim() : ''
|
cdn_url: dom.cdnUrlInput ? dom.cdnUrlInput.value.trim() : '',
|
||||||
|
prometheus_cache_ttl: dom.prometheusCacheTtlInput ? parseInt(dom.prometheusCacheTtlInput.value) : 30
|
||||||
};
|
};
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
|||||||
@@ -74,14 +74,15 @@ const SCHEMA = {
|
|||||||
ip_label_name VARCHAR(100) DEFAULT 'address',
|
ip_label_name VARCHAR(100) DEFAULT 'address',
|
||||||
custom_metrics JSON DEFAULT NULL,
|
custom_metrics JSON DEFAULT NULL,
|
||||||
cdn_url VARCHAR(500) DEFAULT NULL,
|
cdn_url VARCHAR(500) DEFAULT NULL,
|
||||||
|
prometheus_cache_ttl INT DEFAULT 30,
|
||||||
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
|
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
|
||||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
|
||||||
`,
|
`,
|
||||||
seedSql: `
|
seedSql: `
|
||||||
INSERT IGNORE INTO site_settings (
|
INSERT IGNORE INTO site_settings (
|
||||||
id, page_name, show_page_name, title, default_theme, show_95_bandwidth, p95_type, require_login_for_server_details
|
id, page_name, show_page_name, title, default_theme, show_95_bandwidth, p95_type, require_login_for_server_details, prometheus_cache_ttl
|
||||||
) VALUES (
|
) VALUES (
|
||||||
1, '数据可视化展示大屏', 1, '数据可视化展示大屏', 'dark', 0, 'tx', 1
|
1, '数据可视化展示大屏', 1, '数据可视化展示大屏', 'dark', 0, 'tx', 1, 30
|
||||||
)
|
)
|
||||||
`,
|
`,
|
||||||
columns: [
|
columns: [
|
||||||
@@ -105,7 +106,8 @@ const SCHEMA = {
|
|||||||
{ name: 'ip_metric_name', sql: "ALTER TABLE site_settings ADD COLUMN ip_metric_name VARCHAR(100) DEFAULT NULL AFTER show_server_ip" },
|
{ name: 'ip_metric_name', sql: "ALTER TABLE site_settings ADD COLUMN ip_metric_name VARCHAR(100) DEFAULT NULL AFTER show_server_ip" },
|
||||||
{ name: 'ip_label_name', sql: "ALTER TABLE site_settings ADD COLUMN ip_label_name VARCHAR(100) DEFAULT 'address' AFTER ip_metric_name" },
|
{ name: 'ip_label_name', sql: "ALTER TABLE site_settings ADD COLUMN ip_label_name VARCHAR(100) DEFAULT 'address' AFTER ip_metric_name" },
|
||||||
{ name: 'custom_metrics', sql: "ALTER TABLE site_settings ADD COLUMN custom_metrics JSON DEFAULT NULL AFTER ip_label_name" },
|
{ name: 'custom_metrics', sql: "ALTER TABLE site_settings ADD COLUMN custom_metrics JSON DEFAULT NULL AFTER ip_label_name" },
|
||||||
{ name: 'cdn_url', sql: "ALTER TABLE site_settings ADD COLUMN cdn_url VARCHAR(500) DEFAULT NULL AFTER custom_metrics" }
|
{ name: 'cdn_url', sql: "ALTER TABLE site_settings ADD COLUMN cdn_url VARCHAR(500) DEFAULT NULL AFTER custom_metrics" },
|
||||||
|
{ name: 'prometheus_cache_ttl', sql: "ALTER TABLE site_settings ADD COLUMN prometheus_cache_ttl INT DEFAULT 30 AFTER cdn_url" }
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
traffic_stats: {
|
traffic_stats: {
|
||||||
|
|||||||
157
server/index.js
157
server/index.js
@@ -22,6 +22,7 @@ const fs = require('fs');
|
|||||||
const crypto = require('crypto');
|
const crypto = require('crypto');
|
||||||
|
|
||||||
let isDbInitialized = false;
|
let isDbInitialized = false;
|
||||||
|
let metricSyncTimer = null; // Background sync timer
|
||||||
const sessions = new Map(); // Fallback session store when Valkey is unavailable
|
const sessions = new Map(); // Fallback session store when Valkey is unavailable
|
||||||
const requestBuckets = new Map();
|
const requestBuckets = new Map();
|
||||||
const SESSION_TTL_SECONDS = parseInt(process.env.SESSION_TTL_SECONDS, 10) || 86400;
|
const SESSION_TTL_SECONDS = parseInt(process.env.SESSION_TTL_SECONDS, 10) || 86400;
|
||||||
@@ -152,7 +153,8 @@ function getPublicSiteSettings(settings = {}) {
|
|||||||
ip_metric_name: settings.ip_metric_name || null,
|
ip_metric_name: settings.ip_metric_name || null,
|
||||||
ip_label_name: settings.ip_label_name || 'address',
|
ip_label_name: settings.ip_label_name || 'address',
|
||||||
custom_metrics: settings.custom_metrics || [],
|
custom_metrics: settings.custom_metrics || [],
|
||||||
cdn_url: settings.cdn_url || null
|
cdn_url: settings.cdn_url || null,
|
||||||
|
prometheus_cache_ttl: settings.prometheus_cache_ttl !== undefined ? parseInt(settings.prometheus_cache_ttl) : 30
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -342,7 +344,82 @@ async function checkDb() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
checkDb();
|
checkDb().then(() => {
|
||||||
|
if (isDbInitialized) {
|
||||||
|
startMetricSync();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Background Metric Synchronization Task
|
||||||
|
*/
|
||||||
|
async function startMetricSync() {
|
||||||
|
if (metricSyncTimer) {
|
||||||
|
clearInterval(metricSyncTimer);
|
||||||
|
metricSyncTimer = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const [rows] = await db.query('SELECT prometheus_cache_ttl FROM site_settings WHERE id = 1');
|
||||||
|
const ttl = rows.length > 0 ? (parseInt(rows[0].prometheus_cache_ttl) || 0) : 30;
|
||||||
|
|
||||||
|
if (ttl <= 0) {
|
||||||
|
console.log('[MetricSync] Disabled (TTL=0)');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log(`[MetricSync] Started with interval: ${ttl}s`);
|
||||||
|
|
||||||
|
// Immediate first run
|
||||||
|
runSync();
|
||||||
|
|
||||||
|
metricSyncTimer = setInterval(runSync, ttl * 1000);
|
||||||
|
} catch (err) {
|
||||||
|
console.error('[MetricSync] Failed to start:', err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function runSync() {
|
||||||
|
try {
|
||||||
|
const [sources] = await db.query('SELECT * FROM prometheus_sources WHERE type != "blackbox"');
|
||||||
|
if (sources.length === 0) return;
|
||||||
|
|
||||||
|
console.log(`[MetricSync] Syncing ${sources.length} sources at ${new Date().toLocaleTimeString()}`);
|
||||||
|
|
||||||
|
// 1. Sync individual source metrics (Overview & Detail)
|
||||||
|
await Promise.all(sources.map(async (source) => {
|
||||||
|
try {
|
||||||
|
const metrics = await prometheusService.getOverviewMetrics(source.url, source.name);
|
||||||
|
const enrichedMetrics = {
|
||||||
|
...metrics,
|
||||||
|
sourceName: source.name,
|
||||||
|
isOverview: !!source.is_overview_source,
|
||||||
|
isDetail: !!source.is_detail_source
|
||||||
|
};
|
||||||
|
const cacheKey = `source_metrics:${source.url}:${source.name}`;
|
||||||
|
await cache.set(cacheKey, enrichedMetrics, 86400); // Store for 24h, will be overwritten
|
||||||
|
} catch (err) {
|
||||||
|
console.error(`[MetricSync] Error syncing ${source.name}:`, err.message);
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
|
||||||
|
// 2. Sync Network History (Optional but good for "real-time" feel)
|
||||||
|
const [historySources] = await db.query('SELECT * FROM prometheus_sources WHERE is_overview_source = 1 AND type != "blackbox"');
|
||||||
|
if (historySources.length > 0) {
|
||||||
|
const histories = await Promise.all(historySources.map(source =>
|
||||||
|
prometheusService.getNetworkHistory(source.url).catch(() => null)
|
||||||
|
));
|
||||||
|
const validHistories = histories.filter(h => h !== null);
|
||||||
|
if (validHistories.length > 0) {
|
||||||
|
const merged = prometheusService.mergeNetworkHistories(validHistories);
|
||||||
|
await cache.set('network_history_all', merged, 86400);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
console.error('[MetricSync] Sync loop error:', err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// --- Health API ---
|
// --- Health API ---
|
||||||
app.get('/health', async (req, res) => {
|
app.get('/health', async (req, res) => {
|
||||||
@@ -953,7 +1030,7 @@ app.post('/api/settings', requireAuth, async (req, res) => {
|
|||||||
page_name, show_page_name, title, logo_url, logo_url_dark, favicon_url,
|
page_name, show_page_name, title, logo_url, logo_url_dark, favicon_url,
|
||||||
default_theme, show_95_bandwidth, p95_type, require_login_for_server_details,
|
default_theme, show_95_bandwidth, p95_type, require_login_for_server_details,
|
||||||
icp_filing, ps_filing, show_server_ip, ip_metric_name, ip_label_name, custom_metrics,
|
icp_filing, ps_filing, show_server_ip, ip_metric_name, ip_label_name, custom_metrics,
|
||||||
cdn_url
|
cdn_url, prometheus_cache_ttl
|
||||||
} = req.body;
|
} = req.body;
|
||||||
|
|
||||||
// 3. Prepare parameters, prioritizing body but falling back to current
|
// 3. Prepare parameters, prioritizing body but falling back to current
|
||||||
@@ -980,7 +1057,10 @@ app.post('/api/settings', requireAuth, async (req, res) => {
|
|||||||
ip_metric_name: ip_metric_name !== undefined ? ip_metric_name : (current.ip_metric_name || null),
|
ip_metric_name: ip_metric_name !== undefined ? ip_metric_name : (current.ip_metric_name || null),
|
||||||
ip_label_name: ip_label_name !== undefined ? ip_label_name : (current.ip_label_name || 'address'),
|
ip_label_name: ip_label_name !== undefined ? ip_label_name : (current.ip_label_name || 'address'),
|
||||||
custom_metrics: custom_metrics !== undefined ? JSON.stringify(custom_metrics) : (current.custom_metrics || '[]'),
|
custom_metrics: custom_metrics !== undefined ? JSON.stringify(custom_metrics) : (current.custom_metrics || '[]'),
|
||||||
cdn_url: cdn_url !== undefined ? cdn_url : (current.cdn_url || null)
|
cdn_url: cdn_url !== undefined ? cdn_url : (current.cdn_url || null),
|
||||||
|
prometheus_cache_ttl: prometheus_cache_ttl !== undefined
|
||||||
|
? Math.min(86400, Math.max(0, parseInt(prometheus_cache_ttl) || 0))
|
||||||
|
: (current.prometheus_cache_ttl !== undefined ? current.prometheus_cache_ttl : 30)
|
||||||
};
|
};
|
||||||
|
|
||||||
await db.query(`
|
await db.query(`
|
||||||
@@ -989,8 +1069,8 @@ app.post('/api/settings', requireAuth, async (req, res) => {
|
|||||||
default_theme, show_95_bandwidth, p95_type, require_login_for_server_details,
|
default_theme, show_95_bandwidth, p95_type, require_login_for_server_details,
|
||||||
blackbox_source_id, latency_source, latency_dest, latency_target,
|
blackbox_source_id, latency_source, latency_dest, latency_target,
|
||||||
icp_filing, ps_filing, show_server_ip, ip_metric_name, ip_label_name,
|
icp_filing, ps_filing, show_server_ip, ip_metric_name, ip_label_name,
|
||||||
custom_metrics, cdn_url
|
custom_metrics, cdn_url, prometheus_cache_ttl
|
||||||
) VALUES (1, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
) VALUES (1, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
||||||
ON DUPLICATE KEY UPDATE
|
ON DUPLICATE KEY UPDATE
|
||||||
page_name = VALUES(page_name),
|
page_name = VALUES(page_name),
|
||||||
show_page_name = VALUES(show_page_name),
|
show_page_name = VALUES(show_page_name),
|
||||||
@@ -1012,17 +1092,19 @@ app.post('/api/settings', requireAuth, async (req, res) => {
|
|||||||
ip_metric_name = VALUES(ip_metric_name),
|
ip_metric_name = VALUES(ip_metric_name),
|
||||||
ip_label_name = VALUES(ip_label_name),
|
ip_label_name = VALUES(ip_label_name),
|
||||||
custom_metrics = VALUES(custom_metrics),
|
custom_metrics = VALUES(custom_metrics),
|
||||||
cdn_url = VALUES(cdn_url)`,
|
cdn_url = VALUES(cdn_url),
|
||||||
|
prometheus_cache_ttl = VALUES(prometheus_cache_ttl)`,
|
||||||
[
|
[
|
||||||
settings.page_name, settings.show_page_name, settings.title, settings.logo_url, settings.logo_url_dark, settings.favicon_url,
|
settings.page_name, settings.show_page_name, settings.title, settings.logo_url, settings.logo_url_dark, settings.favicon_url,
|
||||||
settings.default_theme, settings.show_95_bandwidth, settings.p95_type, settings.require_login_for_server_details,
|
settings.default_theme, settings.show_95_bandwidth, settings.p95_type, settings.require_login_for_server_details,
|
||||||
settings.blackbox_source_id, settings.latency_source, settings.latency_dest, settings.latency_target,
|
settings.blackbox_source_id, settings.latency_source, settings.latency_dest, settings.latency_target,
|
||||||
settings.icp_filing, settings.ps_filing, settings.show_server_ip,
|
settings.icp_filing, settings.ps_filing, settings.show_server_ip,
|
||||||
settings.ip_metric_name, settings.ip_label_name, settings.custom_metrics,
|
settings.ip_metric_name, settings.ip_label_name, settings.custom_metrics,
|
||||||
settings.cdn_url
|
settings.cdn_url, settings.prometheus_cache_ttl
|
||||||
]
|
]
|
||||||
);
|
);
|
||||||
|
|
||||||
|
startMetricSync();
|
||||||
res.json({ success: true, settings: getPublicSiteSettings(settings) });
|
res.json({ success: true, settings: getPublicSiteSettings(settings) });
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error('Error updating settings:', err);
|
console.error('Error updating settings:', err);
|
||||||
@@ -1049,30 +1131,17 @@ async function getOverview(force = false) {
|
|||||||
servers: []
|
servers: []
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If force is true, trigger an immediate sync run
|
||||||
|
if (force) {
|
||||||
|
await runSync();
|
||||||
|
}
|
||||||
|
|
||||||
|
// ONLY read from cache.
|
||||||
const allMetrics = await Promise.all(sources.map(async (source) => {
|
const allMetrics = await Promise.all(sources.map(async (source) => {
|
||||||
const cacheKey = `source_metrics:${source.url}:${source.name}`;
|
const cacheKey = `source_metrics:${source.url}:${source.name}`;
|
||||||
if (force) {
|
const cached = await cache.get(cacheKey);
|
||||||
await cache.del(cacheKey);
|
return cached || null;
|
||||||
} else {
|
|
||||||
const cached = await cache.get(cacheKey);
|
|
||||||
if (cached) return cached;
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
const metrics = await prometheusService.getOverviewMetrics(source.url, source.name);
|
|
||||||
const enrichedMetrics = {
|
|
||||||
...metrics,
|
|
||||||
sourceName: source.name,
|
|
||||||
isOverview: !!source.is_overview_source,
|
|
||||||
isDetail: !!source.is_detail_source
|
|
||||||
};
|
|
||||||
|
|
||||||
await cache.set(cacheKey, enrichedMetrics, 15); // Cache for 15s
|
|
||||||
return enrichedMetrics;
|
|
||||||
} catch (err) {
|
|
||||||
console.error(`Error fetching metrics from ${source.name}:`, err.message);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}));
|
}));
|
||||||
|
|
||||||
const validMetrics = allMetrics.filter(m => m !== null);
|
const validMetrics = allMetrics.filter(m => m !== null);
|
||||||
@@ -1234,31 +1303,11 @@ app.get('/api/metrics/network-history', async (req, res) => {
|
|||||||
if (force) {
|
if (force) {
|
||||||
await cache.del(cacheKey);
|
await cache.del(cacheKey);
|
||||||
} else {
|
} else {
|
||||||
const cached = await cache.get(cacheKey);
|
const cached = await cache.get(cacheKey);
|
||||||
if (cached) return res.json(cached);
|
if (cached) return res.json(cached);
|
||||||
}
|
|
||||||
|
|
||||||
const query = 'SELECT * FROM prometheus_sources WHERE is_overview_source = 1 AND type != "blackbox"';
|
// Fallback: If no cache, return empty instead of triggering Prometheus
|
||||||
const [sources] = await db.query(query);
|
return res.json({ timestamps: [], rx: [], tx: [] });
|
||||||
if (sources.length === 0) {
|
|
||||||
return res.json({ timestamps: [], rx: [], tx: [] });
|
|
||||||
}
|
|
||||||
|
|
||||||
const histories = await Promise.all(sources.map(source =>
|
|
||||||
prometheusService.getNetworkHistory(source.url).catch(err => {
|
|
||||||
console.error(`Error fetching network history from ${source.name}:`, err.message);
|
|
||||||
return null;
|
|
||||||
})
|
|
||||||
));
|
|
||||||
|
|
||||||
const validHistories = histories.filter(h => h !== null);
|
|
||||||
if (validHistories.length === 0) {
|
|
||||||
return res.json({ timestamps: [], rx: [], tx: [] });
|
|
||||||
}
|
|
||||||
|
|
||||||
const merged = prometheusService.mergeNetworkHistories(validHistories);
|
|
||||||
await cache.set(cacheKey, merged, 300); // Cache for 5 minutes
|
|
||||||
res.json(merged);
|
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error('Error fetching network history history:', err);
|
console.error('Error fetching network history history:', err);
|
||||||
res.status(500).json({ error: 'Failed to fetch network history history' });
|
res.status(500).json({ error: 'Failed to fetch network history history' });
|
||||||
|
|||||||
@@ -1,12 +1,15 @@
|
|||||||
const axios = require('axios');
|
const axios = require('axios');
|
||||||
const http = require('http');
|
const http = require('http');
|
||||||
const https = require('https');
|
const https = require('https');
|
||||||
const cache = require('./cache'); // <-- ADD
|
const cache = require('./cache');
|
||||||
|
const crypto = require('crypto');
|
||||||
|
|
||||||
const QUERY_TIMEOUT = 10000;
|
const QUERY_TIMEOUT = 10000;
|
||||||
|
|
||||||
// Reusable agents to handle potential redirect issues and protocol mismatches
|
function getCacheKey(type, baseUrl, expr, extra = '') {
|
||||||
const crypto = require('crypto');
|
return `prom_${type}:${crypto.createHash('md5').update(`${baseUrl}:${expr}:${extra}`).digest('hex')}`;
|
||||||
|
}
|
||||||
|
|
||||||
const httpAgent = new http.Agent({ keepAlive: true });
|
const httpAgent = new http.Agent({ keepAlive: true });
|
||||||
const httpsAgent = new https.Agent({ keepAlive: true });
|
const httpsAgent = new https.Agent({ keepAlive: true });
|
||||||
|
|
||||||
@@ -951,5 +954,6 @@ module.exports = {
|
|||||||
console.error(`[Prometheus] Error fetching latency for ${target}:`, err.message);
|
console.error(`[Prometheus] Error fetching latency for ${target}:`, err.message);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
|
getCacheKey
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user