diff --git a/server/prometheus-service.js b/server/prometheus-service.js index 0f3dd07..5f6c3e7 100644 --- a/server/prometheus-service.js +++ b/server/prometheus-service.js @@ -1,18 +1,35 @@ const axios = require('axios'); +const http = require('http'); +const https = require('https'); const QUERY_TIMEOUT = 10000; +// Reusable agents to handle potential redirect issues and protocol mismatches +const httpAgent = new http.Agent({ keepAlive: true }); +const httpsAgent = new https.Agent({ keepAlive: true, rejectUnauthorized: false }); + +/** + * Normalize URL and ensure protocol + */ +function normalizeUrl(baseUrl) { + let url = baseUrl.trim().replace(/\/+$/, ''); + if (!/^https?:\/\//i.test(url)) { + url = 'http://' + url; + } + return url; +} + /** * Create an axios instance for a given Prometheus URL */ function createClient(baseUrl) { - let url = baseUrl.replace(/\/+$/, ''); - if (!/^https?:\/\//i.test(url)) { - url = 'http://' + url; - } + const url = normalizeUrl(baseUrl); return axios.create({ baseURL: url, - timeout: QUERY_TIMEOUT + timeout: QUERY_TIMEOUT, + httpAgent, + httpsAgent, + maxRedirects: 5 }); } @@ -20,9 +37,18 @@ function createClient(baseUrl) { * Test Prometheus connection */ async function testConnection(url) { - const client = createClient(url); - const res = await client.get('/api/v1/status/buildinfo'); - return res.data?.data?.version || 'unknown'; + const normalized = normalizeUrl(url); + try { + const res = await axios.get(`${normalized}/api/v1/status/buildinfo`, { + timeout: QUERY_TIMEOUT, + httpAgent, + httpsAgent + }); + return res.data?.data?.version || 'unknown'; + } catch (err) { + console.error(`[Prometheus] Connection test failed for ${normalized}:`, err.message); + throw err; + } } /** @@ -51,6 +77,7 @@ async function queryRange(url, expr, start, end, step) { return res.data.data.result; } + /** * Get overview metrics from a single Prometheus source */