diff --git a/lib/handlers/prom_query.js b/lib/handlers/prom_query.js index 7a28410d..59935bef 100644 --- a/lib/handlers/prom_query.js +++ b/lib/handlers/prom_query.js @@ -39,7 +39,7 @@ async function handler (req, res) { }).send(response) } catch (err) { asyncLogError(err, req.log) - return res.send(empty) + return res.code(500).send(JSON.stringify({ status: 'error', error: err.message })) } } diff --git a/lib/handlers/prom_query_range.js b/lib/handlers/prom_query_range.js index 74a1a105..9452224c 100644 --- a/lib/handlers/prom_query_range.js +++ b/lib/handlers/prom_query_range.js @@ -17,9 +17,13 @@ async function handler (req, res) { const endMs = parseInt(req.query.end) * 1000 || Date.now() const stepMs = parseInt(req.query.step) * 1000 || 15000 const query = req.query.query - const result = await rangeQuery(query, startMs, endMs, stepMs) - console.log(JSON.stringify(result)) - return res.code(200).send(result) + try { + const result = await rangeQuery(query, startMs, endMs, stepMs) + console.log(JSON.stringify(result)) + return res.code(200).send(result) + } catch (err) { + return res.code(500).send(JSON.stringify({ status: 'error', error: err.message })) + } } module.exports = handler diff --git a/lib/handlers/prom_series.js b/lib/handlers/prom_series.js index c581fa30..d6862b7d 100644 --- a/lib/handlers/prom_series.js +++ b/lib/handlers/prom_series.js @@ -20,18 +20,22 @@ async function handler (req, res) { const startMs = req.query.start ? parseInt(req.query.start) * 1000 : Date.now() - 7 * 24 * 3600 * 1000 const endMs = req.query.end ? parseInt(req.query.end) * 1000 : Date.now() - 7 * 24 * 3600 * 1000 const result = [] - query = query.map(async (m) => { - const _result = await series(m, startMs, endMs) - result.push.apply(result, _result) - }) - await Promise.all(query) - return res.code(200).headers({ - 'Content-Type': 'application/json', - 'Access-Control-Allow-Origin': CORS - }).send(JSON.stringify({ - status: 'success', - data: result - })) + try { + query = query.map(async (m) => { + const _result = await series(m, startMs, endMs) + result.push.apply(result, _result) + }) + await Promise.all(query) + return res.code(200).headers({ + 'Content-Type': 'application/json', + 'Access-Control-Allow-Origin': CORS + }).send(JSON.stringify({ + status: 'success', + data: result + })) + } catch (err) { + return res.code(500).send(JSON.stringify({ status: 'error', error: err.message })) + } } module.exports = handler diff --git a/promql/index.js b/promql/index.js index f9fc89fd..1d9cf8aa 100644 --- a/promql/index.js +++ b/promql/index.js @@ -4,6 +4,10 @@ const { rawRequest } = require('../lib/db/clickhouse') const { DATABASE_NAME } = require('../lib/utils') const { clusterName } = require('../common') const _dist = clusterName ? '_dist' : '' + +class PSQLError extends Error {} +module.exports.PSQLError = PSQLError + /** * * @param query {string} @@ -12,35 +16,56 @@ const _dist = clusterName ? '_dist' : '' * @param stepMs {number} */ module.exports.rangeQuery = async (query, startMs, endMs, stepMs) => { - const resp = await prometheus.pqlRangeQuery(query, startMs, endMs, stepMs, module.exports.getData) - return JSON.parse(resp) + try { + const resp = await prometheus.pqlRangeQuery(query, startMs, endMs, stepMs, module.exports.getData) + return JSON.parse(resp) + } catch (e) { + if (e instanceof prometheus.WasmError) { + throw new PSQLError(e.message) + } + throw e + } } module.exports.instantQuery = async (query, timeMs) => { - const resp = await prometheus.pqlInstantQuery(query, timeMs, module.exports.getData) - return JSON.parse(resp) + try { + const resp = await prometheus.pqlInstantQuery(query, timeMs, module.exports.getData) + return JSON.parse(resp) + } catch (e) { + if (e instanceof prometheus.WasmError) { + throw new PSQLError(e.message) + } + throw e + } } module.exports.series = async (query, fromMs, toMs) => { - const fromS = Math.floor(fromMs / 1000) - const toS = Math.floor(toMs / 1000) - const matchers = prometheus.pqlMatchers(query) - const conds = getMatchersIdxCond(matchers[0]) - const idx = getIdxSubquery(conds, fromMs, toMs) - const withIdx = new Sql.With('idx', idx, !!clusterName) - const req = (new Sql.Select()) - .with(withIdx) - .select([new Sql.Raw('any(labels)'), 'labels']) - .from(`time_series${_dist}`) - .where(Sql.And( - Sql.Gte('date', new Sql.Raw(`toDate(fromUnixTimestamp(${fromS}))`)), - Sql.Lte('date', new Sql.Raw(`toDate(fromUnixTimestamp(${toS}))`)), - new Sql.In('fingerprint', 'in', new Sql.WithReference(withIdx)))) - .groupBy(new Sql.Raw('fingerprint')) - const data = await rawRequest(req.toString() + ' FORMAT JSON', - null, - DATABASE_NAME()) - return data.data.data.map(l => JSON.parse(l.labels)) + try { + const fromS = Math.floor(fromMs / 1000) + const toS = Math.floor(toMs / 1000) + const matchers = prometheus.pqlMatchers(query) + const conds = getMatchersIdxCond(matchers[0]) + const idx = getIdxSubquery(conds, fromMs, toMs) + const withIdx = new Sql.With('idx', idx, !!clusterName) + const req = (new Sql.Select()) + .with(withIdx) + .select([new Sql.Raw('any(labels)'), 'labels']) + .from(`time_series${_dist}`) + .where(Sql.And( + Sql.Gte('date', new Sql.Raw(`toDate(fromUnixTimestamp(${fromS}))`)), + Sql.Lte('date', new Sql.Raw(`toDate(fromUnixTimestamp(${toS}))`)), + new Sql.In('fingerprint', 'in', new Sql.WithReference(withIdx)))) + .groupBy(new Sql.Raw('fingerprint')) + const data = await rawRequest(req.toString() + ' FORMAT JSON', + null, + DATABASE_NAME()) + return data.data.data.map(l => JSON.parse(l.labels)) + } catch (e) { + if (e instanceof prometheus.WasmError) { + throw new PSQLError(e.message) + } + throw e + } } /** diff --git a/wasm_parts/main.go b/wasm_parts/main.go index 6d9c3fa7..a32e2ed7 100644 --- a/wasm_parts/main.go +++ b/wasm_parts/main.go @@ -150,7 +150,8 @@ func wrapError(err error) []byte { } func wrapErrorStr(err error) string { - return fmt.Sprintf(`{"status":"error", "error":%s}`, strconv.Quote(err.Error())) + //return fmt.Sprintf(`{"status":"error", "error":%s}`, strconv.Quote(err.Error())) + return err.Error() } func pql(c *ctx, query func() (promql.Query, error)) uint32 { diff --git a/wasm_parts/main.js b/wasm_parts/main.js index dc10abb3..a0d400de 100644 --- a/wasm_parts/main.js +++ b/wasm_parts/main.js @@ -4,6 +4,9 @@ const WASM_URL = join(__dirname, 'main.wasm.gz') const fs = require('fs') const { gunzipSync } = require('zlib') +class WasmError extends Error {} +module.exports.WasmError = WasmError + let counter = 0 var go var wasm @@ -66,7 +69,7 @@ module.exports.pqlMatchers = (query) => { ctx.write(query) const res1 = _wasm.exports.pqlSeries(id) if (res1 !== 0) { - throw new Error('pql failed: ', ctx.read()) + throw new WasmError(ctx.read()) } /** @type {[[[string]]]} */ const matchersObj = JSON.parse(ctx.read()) @@ -93,7 +96,7 @@ const pql = async (query, wasmCall, getData) => { ctx.write(query) const res1 = wasmCall(ctx) if (res1 !== 0) { - throw new Error('pql failed: ', ctx.read()) + throw new WasmError(ctx.read()) } const matchersObj = JSON.parse(ctx.read()) diff --git a/wasm_parts/main.wasm.gz b/wasm_parts/main.wasm.gz index 86f4f5cb..18058847 100644 Binary files a/wasm_parts/main.wasm.gz and b/wasm_parts/main.wasm.gz differ