UNPKG

@netdata/charts

Version:

Netdata frontend SDK and chart utilities

323 lines (322 loc) 17.8 kB
"use strict"; function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); } Object.defineProperty(exports, "__esModule", { value: true }); exports.sparklineRequestLimits = exports.normalizeSparklinePayload = exports.getSparklineRequestKey = exports.getSparklineDataFetcher = exports.getSparklineBatchDimensions = exports.getSparklineBatchAttributes = void 0; var _units = require("../../../helpers/units"); var _getPointValue = require("../../../sdk/makeChart/getPointValue"); var _excluded = ["signal"]; function _objectWithoutProperties(e, t) { if (null == e) return {}; var o, r, i = _objectWithoutPropertiesLoose(e, t); if (Object.getOwnPropertySymbols) { var n = Object.getOwnPropertySymbols(e); for (r = 0; r < n.length; r++) o = n[r], -1 === t.indexOf(o) && {}.propertyIsEnumerable.call(e, o) && (i[o] = e[o]); } return i; } function _objectWithoutPropertiesLoose(r, e) { if (null == r) return {}; var t = {}; for (var n in r) if ({}.hasOwnProperty.call(r, n)) { if (-1 !== e.indexOf(n)) continue; t[n] = r[n]; } return t; } function _createForOfIteratorHelper(r, e) { var t = "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (!t) { if (Array.isArray(r) || (t = _unsupportedIterableToArray(r)) || e && r && "number" == typeof r.length) { t && (r = t); var _n = 0, F = function F() {}; return { s: F, n: function n() { return _n >= r.length ? { done: !0 } : { done: !1, value: r[_n++] }; }, e: function e(r) { throw r; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var o, a = !0, u = !1; return { s: function s() { t = t.call(r); }, n: function n() { var r = t.next(); return a = r.done, r; }, e: function e(r) { u = !0, o = r; }, f: function f() { try { a || null == t["return"] || t["return"](); } finally { if (u) throw o; } } }; } function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; } function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; } function _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; } function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : i + ""; } function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); } function _slicedToArray(r, e) { return _arrayWithHoles(r) || _iterableToArrayLimit(r, e) || _unsupportedIterableToArray(r, e) || _nonIterableRest(); } function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } function _iterableToArrayLimit(r, l) { var t = null == r ? null : "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (null != t) { var e, n, i, u, a = [], f = !0, o = !1; try { if (i = (t = t.call(r)).next, 0 === l) { if (Object(t) !== t) return; f = !1; } else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0); } catch (r) { o = !0, n = r; } finally { try { if (!f && null != t["return"] && (u = t["return"](), Object(u) !== u)) return; } finally { if (o) throw n; } } return a; } } function _arrayWithHoles(r) { if (Array.isArray(r)) return r; } function _toConsumableArray(r) { return _arrayWithoutHoles(r) || _iterableToArray(r) || _unsupportedIterableToArray(r) || _nonIterableSpread(); } function _nonIterableSpread() { throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } function _unsupportedIterableToArray(r, a) { if (r) { if ("string" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } } function _iterableToArray(r) { if ("undefined" != typeof Symbol && null != r[Symbol.iterator] || null != r["@@iterator"]) return Array.from(r); } function _arrayWithoutHoles(r) { if (Array.isArray(r)) return _arrayLikeToArray(r); } function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; } var maxConcurrentRequests = 4; var maxCachedResponses = 100; var maxBatchDimensions = 50; var maxSparklinePoints = 120; var requestAttributeKeys = ["after", "agent", "aggregationMethod", "before", "context", "contextScope", "eliminateZeroDimensions", "groupBy", "groupByLabel", "groupingMethod", "groupingTime", "host", "liveAnchor", "nodesScope", "points", "postGroupBy", "postGroupByLabel", "renderedAt", "selectedContexts", "selectedDimensions", "selectedInstances", "selectedLabels", "selectedNodes", "showPostAggregations"]; var states = new WeakMap(); var batchesByDimensions = new WeakMap(); var hasOwn = function hasOwn(object, key) { return Object.prototype.hasOwnProperty.call(object, key); }; var uniqueSorted = function uniqueSorted(values) { return _toConsumableArray(new Set(values)).sort(); }; var makeAbortError = function makeAbortError() { var error = new Error("The sparkline request was aborted"); error.name = "AbortError"; return error; }; var getSparklineRequestKey = exports.getSparklineRequestKey = function getSparklineRequestKey(attrs) { return JSON.stringify(requestAttributeKeys.reduce(function (result, key) { result[key] = attrs[key]; return result; }, {})); }; var makeDimensionBatches = function makeDimensionBatches(dimensions) { var groups = new Map(); var batchesByRowId = new Map(); dimensions.forEach(function (item) { var groupKey = JSON.stringify([item.context, item.nodeId]); var group = groups.get(groupKey) || []; group.push(item); groups.set(groupKey, group); }); groups.forEach(function (group) { var _loop = function _loop() { var batch = group.slice(index, index + maxBatchDimensions); batch.forEach(function (item) { return batchesByRowId.set(item.rowId, batch); }); }; for (var index = 0; index < group.length; index += maxBatchDimensions) { _loop(); } }); return batchesByRowId; }; var getSparklineBatchDimensions = exports.getSparklineBatchDimensions = function getSparklineBatchDimensions(target, dimensions) { if (!Array.isArray(dimensions)) return [target]; var batches = batchesByDimensions.get(dimensions); if (!batches) { batches = makeDimensionBatches(dimensions); batchesByDimensions.set(dimensions, batches); } return batches.get(target.rowId) || [target]; }; var getSparklineBatchAttributes = exports.getSparklineBatchAttributes = function getSparklineBatchAttributes(chart, dimensions) { var _ref, _overrides$points, _overrides$after, _overrides$aggregatio, _overrides$before, _overrides$liveAnchor, _overrides$renderedAt; var overrides = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {}; var _dimensions = _slicedToArray(dimensions, 1), first = _dimensions[0]; if (!first) return null; var points = (_ref = (_overrides$points = overrides.points) !== null && _overrides$points !== void 0 ? _overrides$points : chart.getAttribute("points")) !== null && _ref !== void 0 ? _ref : maxSparklinePoints; return { after: (_overrides$after = overrides.after) !== null && _overrides$after !== void 0 ? _overrides$after : chart.getAttribute("after"), agent: chart.getAttribute("agent"), aggregationMethod: (_overrides$aggregatio = overrides.aggregationMethod) !== null && _overrides$aggregatio !== void 0 ? _overrides$aggregatio : chart.getAttribute("correlate.aggregation", "average"), before: (_overrides$before = overrides.before) !== null && _overrides$before !== void 0 ? _overrides$before : chart.getAttribute("before"), context: null, contextScope: [first.context], eliminateZeroDimensions: false, groupBy: ["dimension"], groupByLabel: [], groupingMethod: chart.getAttribute("groupingMethod"), groupingTime: chart.getAttribute("groupingTime"), host: chart.getAttribute("host"), liveAnchor: (_overrides$liveAnchor = overrides.liveAnchor) !== null && _overrides$liveAnchor !== void 0 ? _overrides$liveAnchor : chart.getAttribute("liveAnchor"), nodesScope: [first.nodeId], points: Math.min(points || maxSparklinePoints, maxSparklinePoints), postGroupBy: [], postGroupByLabel: [], renderedAt: (_overrides$renderedAt = overrides.renderedAt) !== null && _overrides$renderedAt !== void 0 ? _overrides$renderedAt : chart.getAttribute("renderedAt"), selectedContexts: [], selectedDimensions: uniqueSorted(dimensions.map(function (item) { return item.dimension; })), selectedInstances: [], selectedLabels: [], selectedNodes: [], showPostAggregations: false }; }; var normalizeSparklinePayload = exports.normalizeSparklinePayload = function normalizeSparklinePayload(rawPayload) { var _rawPayload$view, _rawPayload$view2, _rawPayload$db; var result = rawPayload === null || rawPayload === void 0 ? void 0 : rawPayload.result; if (!result || !Array.isArray(result.labels) || !Array.isArray(result.data)) throw new Error("Invalid sparkline response"); var dimensionUnits = ((_rawPayload$view = rawPayload.view) === null || _rawPayload$view === void 0 || (_rawPayload$view = _rawPayload$view.dimensions) === null || _rawPayload$view === void 0 ? void 0 : _rawPayload$view.units) || []; var defaultUnit = ((_rawPayload$view2 = rawPayload.view) === null || _rawPayload$view2 === void 0 ? void 0 : _rawPayload$view2.units) || ((_rawPayload$db = rawPayload.db) === null || _rawPayload$db === void 0 ? void 0 : _rawPayload$db.units) || ""; var seriesByDimension = new Map(); for (var column = 1; column < result.labels.length; column++) { var _values, _dimensionUnits; var values = new Array(result.data.length); var min = Infinity; var max = -Infinity; for (var rowIndex = 0; rowIndex < result.data.length; rowIndex++) { var row = result.data[rowIndex]; var value = Array.isArray(row) ? (0, _getPointValue.getPointValue)(row[column], result.point, "value") : undefined; var normalizedValue = Number.isFinite(value) ? value : null; values[rowIndex] = normalizedValue; if (normalizedValue === null) continue; if (normalizedValue < min) min = normalizedValue; if (normalizedValue > max) max = normalizedValue; } seriesByDimension.set(result.labels[column], { values: values, min: min === Infinity ? null : min, max: max === -Infinity ? null : max, latest: (_values = values[values.length - 1]) !== null && _values !== void 0 ? _values : null, unit: (0, _units.getAlias)((_dimensionUnits = dimensionUnits[column - 1]) !== null && _dimensionUnits !== void 0 ? _dimensionUnits : defaultUnit) }); } return seriesByDimension; }; var makeRequestChart = function makeRequestChart(ownerChart, attrs) { return _objectSpread(_objectSpread({}, ownerChart), {}, { getAttributes: function getAttributes() { return _objectSpread(_objectSpread({}, ownerChart.getAttributes()), attrs); }, getAttribute: function getAttribute(key, defaultValue) { return hasOwn(attrs, key) ? attrs[key] : ownerChart.getAttribute(key, defaultValue); }, getFilteredNodeIds: function getFilteredNodeIds() { return attrs.selectedNodes; } }); }; var touchEntry = function touchEntry(state, entry) { if (state.entries.get(entry.key) !== entry) return; state.entries["delete"](entry.key); state.entries.set(entry.key, entry); }; var pruneCache = function pruneCache(state) { if (state.entries.size <= maxCachedResponses) return; var _iterator = _createForOfIteratorHelper(state.entries), _step; try { for (_iterator.s(); !(_step = _iterator.n()).done;) { var _step$value = _slicedToArray(_step.value, 2), key = _step$value[0], entry = _step$value[1]; if (state.entries.size <= maxCachedResponses) break; if (entry.status !== "fulfilled" || entry.consumers) continue; state.entries["delete"](key); } } catch (err) { _iterator.e(err); } finally { _iterator.f(); } }; var removeEntry = function removeEntry(state, entry) { if (state.entries.get(entry.key) === entry) state.entries["delete"](entry.key); }; var _drainQueue = function drainQueue(state) { var _loop2 = function _loop2() { var entry = state.queue.shift(); if (entry.status !== "queued") return 0; // continue if (!entry.consumers) { entry.status = "cancelled"; removeEntry(state, entry); entry.reject(makeAbortError()); return 0; // continue } entry.status = "active"; state.active++; state.ownerChart.getChart(entry.requestChart, _objectSpread(_objectSpread({}, entry.options), {}, { attrs: entry.attrs, signal: entry.controller.signal })).then(normalizeSparklinePayload).then(function (value) { entry.status = "fulfilled"; entry.resolve(value); touchEntry(state, entry); })["catch"](function (error) { entry.status = "rejected"; removeEntry(state, entry); entry.reject(error); })["finally"](function () { state.active--; pruneCache(state); _drainQueue(state); }); }, _ret; while (state.active < maxConcurrentRequests && state.queue.length) { _ret = _loop2(); if (_ret === 0) continue; } }; var releaseConsumer = function releaseConsumer(state, entry) { entry.consumers--; if (entry.consumers || entry.status === "fulfilled") return; if (entry.status === "queued") { entry.status = "cancelled"; removeEntry(state, entry); entry.reject(makeAbortError()); } else if (entry.status === "active") { removeEntry(state, entry); entry.controller.abort(); } }; var consumeEntry = function consumeEntry(state, entry, signal) { entry.consumers++; touchEntry(state, entry); return new Promise(function (resolve, reject) { var settled = false; var finish = function finish(callback) { return function (value) { if (settled) return; settled = true; signal === null || signal === void 0 || signal.removeEventListener("abort", onAbort); releaseConsumer(state, entry); callback(value); }; }; var onResolve = finish(resolve); var onReject = finish(reject); var onAbort = function onAbort() { return onReject(makeAbortError()); }; if (signal !== null && signal !== void 0 && signal.aborted) { onAbort(); return; } signal === null || signal === void 0 || signal.addEventListener("abort", onAbort, { once: true }); entry.promise.then(onResolve, onReject); }); }; var makeEntry = function makeEntry(state, attrs, options, key) { var resolve; var reject; var promise = new Promise(function (resolvePromise, rejectPromise) { resolve = resolvePromise; reject = rejectPromise; }); var entry = { key: key, attrs: attrs, options: options, requestChart: makeRequestChart(state.ownerChart, attrs), promise: promise, resolve: resolve, reject: reject, controller: new AbortController(), consumers: 0, status: "queued" }; state.entries.set(key, entry); state.queue.push(entry); return entry; }; var makeState = function makeState(ownerChart) { var state = { ownerChart: ownerChart, entries: new Map(), queue: [], active: 0, getData: null }; state.getData = function (attrs) { var _ref2 = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}, signal = _ref2.signal, options = _objectWithoutProperties(_ref2, _excluded); var key = getSparklineRequestKey(attrs); var entry = state.entries.get(key) || makeEntry(state, attrs, options, key); var result = consumeEntry(state, entry, signal); _drainQueue(state); return result; }; return state; }; var getSparklineDataFetcher = exports.getSparklineDataFetcher = function getSparklineDataFetcher(ownerChart) { var state = states.get(ownerChart); if (!state) { state = makeState(ownerChart); states.set(ownerChart, state); } return state.getData; }; var sparklineRequestLimits = exports.sparklineRequestLimits = { batchDimensions: maxBatchDimensions, cache: maxCachedResponses, concurrency: maxConcurrentRequests, points: maxSparklinePoints };