diff --git a/server/prometheus-service.js b/server/prometheus-service.js index 0d3af14..2701a31 100644 --- a/server/prometheus-service.js +++ b/server/prometheus-service.js @@ -68,30 +68,71 @@ async function testConnection(url) { /** * Execute a Prometheus instant query */ -async function query(url, expr) { - const client = createClient(url); - const res = await client.get('/api/v1/query', { params: { query: expr } }); - if (res.data.status !== 'success') { - throw new Error(`Prometheus query failed: ${res.data.error || 'unknown error'}`); +async function query(baseUrl, expr) { + const url = normalizeUrl(baseUrl); + try { + const params = new URLSearchParams({ query: expr }); + const controller = new AbortController(); + const timer = setTimeout(() => controller.abort(), QUERY_TIMEOUT); + + const res = await fetch(`${url}/api/v1/query?${params.toString()}`, { + signal: controller.signal + }); + + clearTimeout(timer); + + if (!res.ok) { + throw new Error(`Prometheus returned HTTP ${res.status}`); + } + + const data = await res.json(); + if (data.status !== 'success') { + throw new Error(`Prometheus query failed: ${data.error || 'unknown error'}`); + } + return data.data.result; + } catch (err) { + if (err.name === 'AbortError') { + throw new Error('Prometheus query timed out'); + } + throw err; } - return res.data.data.result; } /** * Execute a Prometheus range query */ -async function queryRange(url, expr, start, end, step) { - const client = createClient(url); - const res = await client.get('/api/v1/query_range', { - params: { query: expr, start, end, step } - }); - if (res.data.status !== 'success') { - throw new Error(`Prometheus range query failed: ${res.data.error || 'unknown error'}`); +async function queryRange(baseUrl, expr, start, end, step) { + const url = normalizeUrl(baseUrl); + try { + const params = new URLSearchParams({ query: expr, start, end, step }); + const controller = new AbortController(); + const timer = setTimeout(() => controller.abort(), QUERY_TIMEOUT); + + const res = await fetch(`${url}/api/v1/query_range?${params.toString()}`, { + signal: controller.signal + }); + + clearTimeout(timer); + + if (!res.ok) { + throw new Error(`Prometheus returned HTTP ${res.status}`); + } + + const data = await res.json(); + if (data.status !== 'success') { + throw new Error(`Prometheus range query failed: ${data.error || 'unknown error'}`); + } + return data.data.result; + } catch (err) { + if (err.name === 'AbortError') { + throw new Error('Prometheus range query timed out'); + } + throw err; } - return res.data.data.result; } + /** * Get overview metrics from a single Prometheus source */