diff options
Diffstat (limited to 'app/assets/javascripts/monitoring/stores/utils.js')
-rw-r--r-- | app/assets/javascripts/monitoring/stores/utils.js | 110 |
1 files changed, 107 insertions, 3 deletions
diff --git a/app/assets/javascripts/monitoring/stores/utils.js b/app/assets/javascripts/monitoring/stores/utils.js index b6817e7279a..058fab5f4fc 100644 --- a/app/assets/javascripts/monitoring/stores/utils.js +++ b/app/assets/javascripts/monitoring/stores/utils.js @@ -2,7 +2,11 @@ import { slugify } from '~/lib/utils/text_utility'; import createGqClient, { fetchPolicies } from '~/lib/graphql'; import { SUPPORTED_FORMATS } from '~/lib/utils/unit_format'; import { getIdFromGraphQLId } from '~/graphql_shared/utils'; -import { NOT_IN_DB_PREFIX } from '../constants'; +import { parseTemplatingVariables } from './variable_mapping'; +import { NOT_IN_DB_PREFIX, linkTypes } from '../constants'; +import { DATETIME_RANGE_TYPES } from '~/lib/utils/constants'; +import { timeRangeToParams, getRangeType } from '~/lib/utils/datetime_range'; +import { isSafeURL, mergeUrlParams } from '~/lib/utils/url_utility'; export const gqClient = createGqClient( {}, @@ -138,6 +142,24 @@ const mapYAxisToViewModel = ({ }; /** + * Maps a link to its view model, expects an url and + * (optionally) a title. + * + * Unsafe URLs are ignored. + * + * @param {Object} Link + * @returns {Object} Link object with a `title`, `url` and `type` + * + */ +const mapLinksToViewModel = ({ url = null, title = '', type } = {}) => { + return { + title: title || String(url), + type, + url: url && isSafeURL(url) ? String(url) : '#', + }; +}; + +/** * Maps a metrics panel to its view model * * @param {Object} panel - Metrics panel @@ -152,6 +174,7 @@ const mapPanelToViewModel = ({ y_label, y_axis = {}, metrics = [], + links = [], max_value, }) => { // Both `x_axis.name` and `x_label` are supported for now @@ -171,7 +194,8 @@ const mapPanelToViewModel = ({ yAxis, xAxis, maxValue: max_value, - metrics: mapToMetricsViewModel(metrics, yAxis.name), + links: links.map(mapLinksToViewModel), + metrics: mapToMetricsViewModel(metrics), }; }; @@ -190,6 +214,66 @@ const mapToPanelGroupViewModel = ({ group = '', panels = [] }, i) => { }; /** + * Convert dashboard time range to Grafana + * dashboards time range. + * + * @param {Object} timeRange + * @returns {Object} + */ +export const convertToGrafanaTimeRange = timeRange => { + const timeRangeType = getRangeType(timeRange); + if (timeRangeType === DATETIME_RANGE_TYPES.fixed) { + return { + from: new Date(timeRange.start).getTime(), + to: new Date(timeRange.end).getTime(), + }; + } else if (timeRangeType === DATETIME_RANGE_TYPES.rolling) { + const { seconds } = timeRange.duration; + return { + from: `now-${seconds}s`, + to: 'now', + }; + } + // fallback to returning the time range as is + return timeRange; +}; + +/** + * Convert dashboard time ranges to other supported + * link formats. + * + * @param {Object} timeRange metrics dashboard time range + * @param {String} type type of link + * @returns {String} + */ +export const convertTimeRanges = (timeRange, type) => { + if (type === linkTypes.GRAFANA) { + return convertToGrafanaTimeRange(timeRange); + } + return timeRangeToParams(timeRange); +}; + +/** + * Adds dashboard-related metadata to the user-defined links. + * + * As of %13.1, metadata only includes timeRange but in the + * future more info will be added to the links. + * + * @param {Object} metadata + * @returns {Function} + */ +export const addDashboardMetaDataToLink = metadata => link => { + let modifiedLink = { ...link }; + if (metadata.timeRange) { + modifiedLink = { + ...modifiedLink, + url: mergeUrlParams(convertTimeRanges(metadata.timeRange, link.type), link.url), + }; + } + return modifiedLink; +}; + +/** * Maps a dashboard json object to its view model * * @param {Object} dashboard - Dashboard object @@ -197,13 +281,33 @@ const mapToPanelGroupViewModel = ({ group = '', panels = [] }, i) => { * @param {Array} dashboard.panel_groups - Panel groups array * @returns {Object} */ -export const mapToDashboardViewModel = ({ dashboard = '', panel_groups = [] }) => { +export const mapToDashboardViewModel = ({ + dashboard = '', + templating = {}, + links = [], + panel_groups = [], +}) => { return { dashboard, + variables: parseTemplatingVariables(templating), + links: links.map(mapLinksToViewModel), panelGroups: panel_groups.map(mapToPanelGroupViewModel), }; }; +/** + * Processes a single Range vector, part of the result + * of type `matrix` in the form: + * + * { + * "metric": { "<label_name>": "<label_value>", ... }, + * "values": [ [ <unix_time>, "<sample_value>" ], ... ] + * }, + * + * See https://prometheus.io/docs/prometheus/latest/querying/api/#range-vectors + * + * @param {*} timeSeries + */ export const normalizeQueryResult = timeSeries => { let normalizedResult = {}; |