diff options
Diffstat (limited to 'app/assets/javascripts/monitoring/stores/variable_mapping.js')
-rw-r--r-- | app/assets/javascripts/monitoring/stores/variable_mapping.js | 113 |
1 files changed, 98 insertions, 15 deletions
diff --git a/app/assets/javascripts/monitoring/stores/variable_mapping.js b/app/assets/javascripts/monitoring/stores/variable_mapping.js index c0a8150063b..0b268402992 100644 --- a/app/assets/javascripts/monitoring/stores/variable_mapping.js +++ b/app/assets/javascripts/monitoring/stores/variable_mapping.js @@ -46,7 +46,7 @@ const textAdvancedVariableParser = advTextVar => ({ * @param {Object} custom variable option * @returns {Object} normalized custom variable options */ -const normalizeCustomVariableOptions = ({ default: defaultOpt = false, text, value }) => ({ +const normalizeVariableValues = ({ default: defaultOpt = false, text, value }) => ({ default: defaultOpt, text: text || value, value, @@ -59,17 +59,19 @@ const normalizeCustomVariableOptions = ({ default: defaultOpt = false, text, val * The default value is the option with default set to true or the first option * if none of the options have default prop true. * - * @param {Object} advVariable advance custom variable + * @param {Object} advVariable advanced custom variable * @returns {Object} */ const customAdvancedVariableParser = advVariable => { - const options = (advVariable?.options?.values ?? []).map(normalizeCustomVariableOptions); - const defaultOpt = options.find(opt => opt.default === true) || options[0]; + const values = (advVariable?.options?.values ?? []).map(normalizeVariableValues); + const defaultValue = values.find(opt => opt.default === true) || values[0]; return { type: VARIABLE_TYPES.custom, label: advVariable.label, - value: defaultOpt?.value, - options, + value: defaultValue?.value, + options: { + values, + }, }; }; @@ -80,7 +82,7 @@ const customAdvancedVariableParser = advVariable => { * @param {String} opt option from simple custom variable * @returns {Object} */ -const parseSimpleCustomOptions = opt => ({ text: opt, value: opt }); +export const parseSimpleCustomValues = opt => ({ text: opt, value: opt }); /** * Custom simple variables are rendered as dropdown elements in the dashboard @@ -95,12 +97,28 @@ const parseSimpleCustomOptions = opt => ({ text: opt, value: opt }); * @returns {Object} */ const customSimpleVariableParser = simpleVar => { - const options = (simpleVar || []).map(parseSimpleCustomOptions); + const values = (simpleVar || []).map(parseSimpleCustomValues); return { type: VARIABLE_TYPES.custom, - value: options[0].value, + value: values[0].value, label: null, - options: options.map(normalizeCustomVariableOptions), + options: { + values: values.map(normalizeVariableValues), + }, + }; +}; + +const metricLabelValuesVariableParser = variable => { + const { label, options = {} } = variable; + return { + type: VARIABLE_TYPES.metric_label_values, + value: null, + label, + options: { + prometheusEndpointPath: options.prometheus_endpoint_path || '', + label: options.label || null, + values: [], // values are initially empty + }, }; }; @@ -123,14 +141,16 @@ const isSimpleCustomVariable = customVar => Array.isArray(customVar); * @return {Function} parser method */ const getVariableParser = variable => { - if (isSimpleCustomVariable(variable)) { + if (isString(variable)) { + return textSimpleVariableParser; + } else if (isSimpleCustomVariable(variable)) { return customSimpleVariableParser; - } else if (variable.type === VARIABLE_TYPES.custom) { - return customAdvancedVariableParser; } else if (variable.type === VARIABLE_TYPES.text) { return textAdvancedVariableParser; - } else if (isString(variable)) { - return textSimpleVariableParser; + } else if (variable.type === VARIABLE_TYPES.custom) { + return customAdvancedVariableParser; + } else if (variable.type === VARIABLE_TYPES.metric_label_values) { + return metricLabelValuesVariableParser; } return () => null; }; @@ -200,4 +220,67 @@ export const mergeURLVariables = (varsFromYML = {}) => { return variables; }; +/** + * Converts series data to options that can be added to a + * variable. Series data is returned from the Prometheus API + * `/api/v1/series`. + * + * Finds a `label` in the series data, so it can be used as + * a filter. + * + * For example, for the arguments: + * + * { + * "label": "job" + * "data" : [ + * { + * "__name__" : "up", + * "job" : "prometheus", + * "instance" : "localhost:9090" + * }, + * { + * "__name__" : "up", + * "job" : "node", + * "instance" : "localhost:9091" + * }, + * { + * "__name__" : "process_start_time_seconds", + * "job" : "prometheus", + * "instance" : "localhost:9090" + * } + * ] + * } + * + * It returns all the different "job" values: + * + * [ + * { + * "label": "node", + * "value": "node" + * }, + * { + * "label": "prometheus", + * "value": "prometheus" + * } + * ] + * + * @param {options} options object + * @param {options.seriesLabel} name of the searched series label + * @param {options.data} series data from the series API + * @return {array} Options objects with the shape `{ label, value }` + * + * @see https://prometheus.io/docs/prometheus/latest/querying/api/#finding-series-by-label-matchers + */ +export const optionsFromSeriesData = ({ label, data = [] }) => { + const optionsSet = data.reduce((set, seriesObject) => { + // Use `new Set` to deduplicate options + if (seriesObject[label]) { + set.add(seriesObject[label]); + } + return set; + }, new Set()); + + return [...optionsSet].map(parseSimpleCustomValues); +}; + export default {}; |