From f9eb013334e9a3785b5cc593649db28e6cdab18d Mon Sep 17 00:00:00 2001 From: Kristina Date: Thu, 21 Nov 2024 12:46:29 -0600 Subject: [PATCH] Transformations: Preserve base threshold when using Config from query results (#96781) * Merge in default threshold base if exists * Fix tests to not expect default threshold * Add config from query example to gdev * Add a test around the merging of thresholds * Revert "Add config from query example to gdev" This reverts commit a239224ebbd311c33fa445c9a99502262eaa0215. * update gdev * Add note about keeping the base threshold * Update public/app/features/transformers/docs/content.ts Co-authored-by: Isabel Matwawana <76437239+imatwawana@users.noreply.github.com> * Merge in generated code --------- Co-authored-by: Leon Sorokin Co-authored-by: Isabel Matwawana <76437239+imatwawana@users.noreply.github.com> --- .../transforms/config-from-query.json | 1242 ++++++++++------- .../transform-data/index.md | 2 + .../__snapshots__/fieldOverrides.test.ts.snap | 17 + .../src/field/fieldOverrides.test.ts | 27 + .../grafana-data/src/field/fieldOverrides.ts | 14 +- .../configFromQuery/configFromQuery.test.ts | 2 +- .../app/features/transformers/docs/content.ts | 5 +- .../fieldToConfigMapping.ts | 2 +- .../rowsToFields/rowsToFields.test.ts | 2 +- 9 files changed, 815 insertions(+), 498 deletions(-) create mode 100644 packages/grafana-data/src/field/__snapshots__/fieldOverrides.test.ts.snap diff --git a/devenv/dev-dashboards/transforms/config-from-query.json b/devenv/dev-dashboards/transforms/config-from-query.json index c9dd139a501..cb65f966667 100644 --- a/devenv/dev-dashboards/transforms/config-from-query.json +++ b/devenv/dev-dashboards/transforms/config-from-query.json @@ -1,552 +1,810 @@ { - "annotations": { - "list": [ - { - "builtIn": 1, - "datasource": "-- Grafana --", - "enable": true, - "hide": true, - "iconColor": "rgba(0, 211, 255, 1)", - "name": "Annotations & Alerts", - "target": { - "limit": 100, - "matchAny": false, - "tags": [], - "type": "dashboard" - }, - "type": "dashboard" - } - ] - }, - "description": "", - "editable": true, - "graphTooltip": 0, - "links": [], - "panels": [ + "annotations": { + "list": [ { - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" + "builtIn": 1, + "datasource": { + "type": "datasource", + "uid": "grafana" + }, + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations & Alerts", + "target": { + "limit": 100, + "matchAny": false, + "tags": [], + "type": "dashboard" + }, + "type": "dashboard" + } + ] + }, + "description": "", + "editable": true, + "fiscalYearStartMonth": 0, + "graphTooltip": 0, + "links": [], + "panels": [ + { + "datasource": { + "type": "grafana-testdata-datasource", + "uid": "PD8C576611E62080A" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false }, - "custom": { - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 0, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "auto", - "spanNulls": false, - "thresholdsStyle": { - "mode": "line" - } + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green" - }, - { - "color": "red", - "value": 80 - } - ] + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "line" } }, - "overrides": [] + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } }, - "gridPos": { - "h": 9, - "w": 12, - "x": 0, - "y": 0 + "overrides": [] + }, + "gridPos": { + "h": 9, + "w": 12, + "x": 0, + "y": 0 + }, + "id": 2, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true }, - "id": 2, - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom" + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "grafana-testdata-datasource", + "uid": "PD8C576611E62080A" }, - "tooltip": { - "mode": "single", - "sort": "none" - } + "hide": false, + "max": 100, + "min": 1, + "refId": "A", + "scenarioId": "random_walk", + "startValue": 50 }, - "targets": [ - { - "hide": false, - "max": 100, - "min": 1, - "refId": "A", - "scenarioId": "random_walk", - "startValue": 50 + { + "alias": "", + "csvContent": "min,max,threshold1\n1000,1000,8000\n0,100,80\n\n", + "datasource": { + "type": "grafana-testdata-datasource", + "uid": "PD8C576611E62080A" }, - { - "alias": "", - "csvContent": "min,max,threshold1\n1000,1000,8000\n0,100,80\n\n", - "refId": "config", - "scenarioId": "csv_content" + "refId": "config", + "scenarioId": "csv_content" + } + ], + "title": "Min, max, threshold from separate query", + "transformations": [ + { + "id": "configFromData", + "options": { + "configRefId": "config", + "mappings": [] } - ], - "title": "Min, max, threshold from separate query", - "transformations": [ + } + ], + "type": "timeseries" + }, + { + "datasource": { + "type": "grafana-testdata-datasource", + "uid": "PD8C576611E62080A" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "custom": { + "align": "left", + "cellOptions": { + "type": "auto" + }, + "inspect": false + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [ { - "id": "configFromData", - "options": { - "configRefId": "config", - "mappings": [] - } + "matcher": { + "id": "byName", + "options": "SensorA" + }, + "properties": [ + { + "id": "custom.cellOptions", + "value": { + "type": "color-text" + } + } + ] } - ], - "type": "timeseries" + ] }, - { - "fieldConfig": { - "defaults": { - "color": { - "mode": "thresholds" + "gridPos": { + "h": 9, + "w": 12, + "x": 12, + "y": 0 + }, + "id": 5, + "options": { + "cellHeight": "sm", + "footer": { + "countRows": false, + "fields": "", + "reducer": [ + "sum" + ], + "show": false + }, + "showHeader": true + }, + "pluginVersion": "11.4.0-pre", + "targets": [ + { + "csvContent": "Name, Value, SensorA, MyUnit, MyColor\nGoogle, 10, 50, km/h, blue\nGoogle, 100, 100,km/h, orange\n", + "datasource": { + "type": "grafana-testdata-datasource", + "uid": "PD8C576611E62080A" + }, + "hide": false, + "refId": "A", + "scenarioId": "csv_content" + } + ], + "title": "Custom mappings and apply to self", + "transformations": [ + { + "id": "configFromData", + "options": { + "applyTo": { + "id": "byName", + "options": "SensorA" }, - "custom": { - "align": "left", - "displayMode": "auto" + "applyToConfig": true, + "configRefId": "A", + "mappings": [ + { + "configProperty": "unit", + "fieldName": "MyUnit", + "handlerKey": "unit" + }, + { + "fieldName": "MyColor", + "handlerKey": "color" + } + ] + } + } + ], + "type": "table" + }, + { + "datasource": { + "type": "grafana-testdata-datasource", + "uid": "PD8C576611E62080A" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "custom": { + "align": "center", + "cellOptions": { + "type": "auto" }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green" - }, - { - "color": "red", - "value": 80 - } - ] - } + "inspect": false }, - "overrides": [ - { - "matcher": { - "id": "byName", - "options": "SensorA" + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null }, - "properties": [ - { - "id": "custom.displayMode", - "value": "color-text" - } - ] - } - ] - }, - "gridPos": { - "h": 9, - "w": 12, - "x": 12, - "y": 0 - }, - "id": 5, - "options": { - "showHeader": true + { + "color": "red", + "value": 80 + } + ] + } }, - "pluginVersion": "8.1.0-pre", - "targets": [ + "overrides": [ { - "csvContent": "Name, Value, SensorA, MyUnit, MyColor\nGoogle, 10, 50, km/h, blue\nGoogle, 100, 100,km/h, orange\n", - "hide": false, - "refId": "A", - "scenarioId": "csv_content" + "matcher": { + "id": "byName", + "options": "Value" + }, + "properties": [ + { + "id": "custom.cellOptions", + "value": { + "mode": "basic", + "type": "color-background" + } + } + ] } - ], - "title": "Custom mappings and apply to self", - "transformations": [ - { - "id": "configFromData", - "options": { - "applyTo": { - "id": "byName", - "options": "SensorA" + ] + }, + "gridPos": { + "h": 5, + "w": 12, + "x": 0, + "y": 9 + }, + "id": 7, + "options": { + "cellHeight": "sm", + "footer": { + "countRows": false, + "fields": "", + "reducer": [ + "sum" + ], + "show": false + }, + "showHeader": true + }, + "pluginVersion": "11.4.0-pre", + "targets": [ + { + "csvContent": "ID, DisplayText\n21412312312, Homer\n12421412413, Simpsons \n12321312313, Bart", + "datasource": { + "type": "grafana-testdata-datasource", + "uid": "PD8C576611E62080A" + }, + "hide": false, + "refId": "A", + "scenarioId": "csv_content" + } + ], + "title": "Mapping data", + "transformations": [ + { + "id": "configFromData", + "options": { + "applyToConfig": true, + "configRefId": "A", + "mappings": [ + { + "fieldName": "Color", + "handlerKey": "mappings.color" }, - "applyToConfig": true, - "configRefId": "A", - "mappings": [ - { - "configProperty": "unit", - "fieldName": "MyUnit", - "handlerKey": "unit" - }, - { - "fieldName": "MyColor", - "handlerKey": "color" - } - ] - } + { + "fieldName": "Value", + "handlerKey": "mappings.value" + } + ] } - ], - "type": "table" + } + ], + "type": "table" + }, + { + "datasource": { + "type": "grafana-testdata-datasource", + "uid": "PD8C576611E62080A" }, - { - "fieldConfig": { - "defaults": { - "color": { - "mode": "thresholds" - }, - "custom": { - "align": "center", - "displayMode": "auto" + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "custom": { + "align": "center", + "cellOptions": { + "type": "auto" }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green" - }, - { - "color": "red", - "value": 80 - } - ] - } + "inspect": false }, - "overrides": [ - { - "matcher": { - "id": "byName", - "options": "Value" + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null }, - "properties": [ - { - "id": "custom.displayMode", - "value": "color-background-solid" - } - ] - } - ] - }, - "gridPos": { - "h": 5, - "w": 12, - "x": 0, - "y": 9 - }, - "id": 7, - "options": { - "showHeader": true - }, - "pluginVersion": "8.1.0-pre", - "targets": [ - { - "csvContent": "ID, DisplayText\n21412312312, Homer\n12421412413, Simpsons \n12321312313, Bart", - "hide": false, - "refId": "A", - "scenarioId": "csv_content" + { + "color": "red", + "value": 80 + } + ] } - ], - "title": "Mapping data", - "transformations": [ + }, + "overrides": [ { - "id": "configFromData", - "options": { - "applyToConfig": true, - "configRefId": "A", - "mappings": [ - { - "fieldName": "Color", - "handlerKey": "mappings.color" - }, - { - "fieldName": "Value", - "handlerKey": "mappings.value" + "matcher": { + "id": "byName", + "options": "Value" + }, + "properties": [ + { + "id": "custom.cellOptions", + "value": { + "mode": "basic", + "type": "color-background" } - ] - } + } + ] } - ], - "type": "table" + ] }, - { - "fieldConfig": { - "defaults": { - "color": { - "mode": "thresholds" + "gridPos": { + "h": 10, + "w": 12, + "x": 12, + "y": 9 + }, + "id": 6, + "options": { + "cellHeight": "sm", + "footer": { + "countRows": false, + "fields": "", + "reducer": [ + "sum" + ], + "show": false + }, + "showHeader": true + }, + "pluginVersion": "11.4.0-pre", + "targets": [ + { + "csvContent": "Value, Color\nOK, blue\nPretty bad, red\nYay it's green, green\nSomething is off, orange\nNo idea, #88AA00\nAm I purple?, purple", + "datasource": { + "type": "grafana-testdata-datasource", + "uid": "PD8C576611E62080A" + }, + "hide": false, + "refId": "A", + "scenarioId": "csv_content" + } + ], + "title": "Value mappings from query result applied to itself", + "transformations": [ + { + "id": "configFromData", + "options": { + "applyTo": { + "id": "byName", + "options": "Value" }, - "custom": { - "align": "center", - "displayMode": "auto" + "applyToConfig": true, + "configRefId": "A", + "mappings": [ + { + "fieldName": "Color", + "handlerKey": "mappings.color" + }, + { + "fieldName": "Value", + "handlerKey": "mappings.value" + } + ] + } + } + ], + "type": "table" + }, + { + "datasource": { + "type": "grafana-testdata-datasource", + "uid": "PD8C576611E62080A" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "custom": { + "align": "center", + "cellOptions": { + "type": "auto" }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green" - }, - { - "color": "red", - "value": 80 - } - ] - } + "inspect": false }, - "overrides": [ - { - "matcher": { - "id": "byName", - "options": "Value" + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null }, - "properties": [ - { - "id": "custom.displayMode", - "value": "color-background-solid" - } - ] - } - ] - }, - "gridPos": { - "h": 10, - "w": 12, - "x": 12, - "y": 9 + { + "color": "red", + "value": 80 + } + ] + } }, - "id": 6, - "options": { - "showHeader": true + "overrides": [] + }, + "gridPos": { + "h": 5, + "w": 12, + "x": 0, + "y": 14 + }, + "id": 8, + "options": { + "cellHeight": "sm", + "footer": { + "countRows": false, + "fields": "", + "reducer": [ + "sum" + ], + "show": false }, - "pluginVersion": "8.1.0-pre", - "targets": [ - { - "csvContent": "Value, Color\nOK, blue\nPretty bad, red\nYay it's green, green\nSomething is off, orange\nNo idea, #88AA00\nAm I purple?, purple", - "hide": false, - "refId": "A", - "scenarioId": "csv_content" - } - ], - "title": "Value mappings from query result applied to itself", - "transformations": [ - { - "id": "configFromData", - "options": { - "applyTo": { - "id": "byName", - "options": "Value" + "showHeader": true + }, + "pluginVersion": "11.4.0-pre", + "targets": [ + { + "csvContent": "ID, Value\n21412312312, 100\n12421412413, 20\n12321312313, 10", + "datasource": { + "type": "grafana-testdata-datasource", + "uid": "PD8C576611E62080A" + }, + "hide": false, + "refId": "A", + "scenarioId": "csv_content" + } + ], + "title": "Display data", + "transformations": [ + { + "id": "configFromData", + "options": { + "applyToConfig": true, + "configRefId": "A", + "mappings": [ + { + "fieldName": "Color", + "handlerKey": "mappings.color" }, - "applyToConfig": true, - "configRefId": "A", - "mappings": [ - { - "fieldName": "Color", - "handlerKey": "mappings.color" - }, - { - "fieldName": "Value", - "handlerKey": "mappings.value" - } - ] - } + { + "fieldName": "Value", + "handlerKey": "mappings.value" + } + ] } - ], - "type": "table" + } + ], + "type": "table" + }, + { + "datasource": { + "type": "grafana-testdata-datasource", + "uid": "PD8C576611E62080A" }, - { - "fieldConfig": { - "defaults": { - "color": { - "mode": "thresholds" + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "axisSoftMin": 0, + "fillOpacity": 80, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false }, - "custom": { - "align": "center", - "displayMode": "auto" + "lineWidth": 1, + "scaleDistribution": { + "type": "linear" }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green" - }, - { - "color": "red", - "value": 80 - } - ] + "thresholdsStyle": { + "mode": "off" } }, - "overrides": [] + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } }, - "gridPos": { - "h": 5, - "w": 12, - "x": 0, - "y": 14 + "overrides": [] + }, + "gridPos": { + "h": 10, + "w": 12, + "x": 0, + "y": 19 + }, + "id": 9, + "options": { + "barRadius": 0, + "barWidth": 0.97, + "fullHighlight": false, + "groupWidth": 0.7, + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true }, - "id": 8, - "options": { - "showHeader": true + "orientation": "horizontal", + "showValue": "auto", + "stacking": "none", + "text": {}, + "tooltip": { + "mode": "single", + "sort": "none" }, - "pluginVersion": "8.1.0-pre", - "targets": [ - { - "csvContent": "ID, Value\n21412312312, 100\n12421412413, 20\n12321312313, 10", - "hide": false, - "refId": "A", - "scenarioId": "csv_content" - } - ], - "title": "Display data", - "transformations": [ - { - "id": "configFromData", - "options": { - "applyToConfig": true, - "configRefId": "A", - "mappings": [ - { - "fieldName": "Color", - "handlerKey": "mappings.color" - }, - { - "fieldName": "Value", - "handlerKey": "mappings.value" - } - ] - } - } - ], - "type": "table" + "xTickLabelRotation": 0, + "xTickLabelSpacing": 0 }, - { - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" + "pluginVersion": "8.1.0-pre", + "targets": [ + { + "csvContent": "ID, Value\nA21412312312, 100\nA12421412413, 20\nA12321312313, 10\n", + "datasource": { + "type": "grafana-testdata-datasource", + "uid": "PD8C576611E62080A" + }, + "hide": false, + "refId": "data", + "scenarioId": "csv_content" + }, + { + "csvContent": "ID, DisplayText\nA21412312312, Homer\nA12421412413, Marge \nA12321312313, Bart", + "datasource": { + "type": "grafana-testdata-datasource", + "uid": "PD8C576611E62080A" + }, + "hide": false, + "refId": "mappings", + "scenarioId": "csv_content" + } + ], + "title": "Value mapping ID -> DisplayText from separate query", + "transformations": [ + { + "id": "configFromData", + "options": { + "applyTo": { + "id": "byName", + "options": "ID" }, - "custom": { - "axisLabel": "", - "axisPlacement": "auto", - "axisSoftMin": 0, - "fillOpacity": 80, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false + "applyToConfig": false, + "configRefId": "mappings", + "mappings": [ + { + "fieldName": "ID", + "handlerKey": "mappings.value" }, - "lineWidth": 1 + { + "fieldName": "DisplayText", + "handlerKey": "mappings.text" + } + ] + } + } + ], + "type": "barchart" + }, + { + "datasource": { + "default": true, + "type": "grafana-testdata-datasource", + "uid": "PD8C576611E62080A" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green" - }, - { - "color": "red", - "value": 80 - } - ] + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "dashed+area" } }, - "overrides": [] - }, - "gridPos": { - "h": 10, - "w": 12, - "x": 0, - "y": 19 - }, - "id": 9, - "options": { - "barWidth": 0.97, - "groupWidth": 0.7, - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom" - }, - "orientation": "horizontal", - "showValue": "auto", - "text": {}, - "tooltip": { - "mode": "single", - "sort": "none" + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "blue", + "value": null + } + ] } }, - "pluginVersion": "8.1.0-pre", - "targets": [ - { - "csvContent": "ID, Value\nA21412312312, 100\nA12421412413, 20\nA12321312313, 10\n", - "hide": false, - "refId": "data", - "scenarioId": "csv_content" + "overrides": [] + }, + "gridPos": { + "h": 10, + "w": 12, + "x": 12, + "y": 19 + }, + "id": 10, + "maxDataPoints": 100, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "grafana-testdata-datasource", + "uid": "PD8C576611E62080A" }, - { - "csvContent": "ID, DisplayText\nA21412312312, Homer\nA12421412413, Marge \nA12321312313, Bart", - "hide": false, - "refId": "mappings", - "scenarioId": "csv_content" - } - ], - "title": "Value mapping ID -> DisplayText from separate query", - "transformations": [ - { - "id": "configFromData", - "options": { - "applyTo": { - "id": "byName", - "options": "ID" - }, - "applyToConfig": false, - "configRefId": "mappings", - "mappings": [ - { - "fieldName": "ID", - "handlerKey": "mappings.value" + "rawFrameContent": "[\n {\n \"schema\": {\n \"refId\": \"A\",\n \"meta\": {\n \"typeVersion\": [\n 0,\n 0\n ],\n \"custom\": {\n \"customStat\": 10\n }\n },\n \"fields\": [\n {\n \"name\": \"time\",\n \"type\": \"time\",\n \"typeInfo\": {\n \"frame\": \"time.Time\",\n \"nullable\": true\n },\n \"config\": {\n \"interval\": 300000\n }\n },\n {\n \"name\": \"A-series\",\n \"type\": \"number\",\n \"typeInfo\": {\n \"frame\": \"float64\",\n \"nullable\": true\n },\n \"labels\": {},\n \"config\": {}\n }\n ]\n },\n \"data\": {\n \"values\": [\n [\n 1732120345536,\n 1732120645536,\n 1732120945536,\n 1732121245536,\n 1732121545536,\n 1732121845536,\n 1732122145536,\n 1732122445536,\n 1732122745536,\n 1732123045536,\n 1732123345536,\n 1732123645536,\n 1732123945536,\n 1732124245536,\n 1732124545536,\n 1732124845536,\n 1732125145536,\n 1732125445536,\n 1732125745536,\n 1732126045536,\n 1732126345536,\n 1732126645536,\n 1732126945536,\n 1732127245536,\n 1732127545536,\n 1732127845536,\n 1732128145536,\n 1732128445536,\n 1732128745536,\n 1732129045536,\n 1732129345536,\n 1732129645536,\n 1732129945536,\n 1732130245536,\n 1732130545536,\n 1732130845536,\n 1732131145536,\n 1732131445536,\n 1732131745536,\n 1732132045536,\n 1732132345536,\n 1732132645536,\n 1732132945536,\n 1732133245536,\n 1732133545536,\n 1732133845536,\n 1732134145536,\n 1732134445536,\n 1732134745536,\n 1732135045536,\n 1732135345536,\n 1732135645536,\n 1732135945536,\n 1732136245536,\n 1732136545536,\n 1732136845536,\n 1732137145536,\n 1732137445536,\n 1732137745536,\n 1732138045536,\n 1732138345536,\n 1732138645536,\n 1732138945536,\n 1732139245536,\n 1732139545536,\n 1732139845536,\n 1732140145536,\n 1732140445536,\n 1732140745536,\n 1732141045536,\n 1732141345536,\n 1732141645536\n ],\n [\n 36.67835770082578,\n 35.674537924065,\n 8.339763723800829,\n 16.313291374141446,\n 66.05915891584247,\n 55.975417240601566,\n 33.75563648171818,\n 10.561077849025175,\n 20.31936089572975,\n 26.11219409670694,\n 57.542750561307564,\n 67.10954340535248,\n 82.95323961635275,\n 100.9691805551439,\n 59.829706792214644,\n 94.58723331927925,\n 89.3082374466047,\n 58.69065135820439,\n 97.144192150251,\n 139.99199318295675,\n 157.9473973408396,\n 177.94452058033198,\n 188.84065573954362,\n 154.3930906887033,\n 130.14406878049226,\n 116.65818233680316,\n 100.96041794526472,\n 144.65142921584447,\n 175.75178611497054,\n 203.55271609883386,\n 238.4931714915047,\n 253.38754249911452,\n 271.1735238723396,\n 258.54418620287515,\n 260.8463123020904,\n 216.10614084307323,\n 253.30389406688175,\n 249.37108721413884,\n 243.7226799137106,\n 216.74579233434042,\n 262.50043010512826,\n 238.71564300219498,\n 218.3552317737898,\n 195.6154411937393,\n 154.1987522722987,\n 124.00066408416897,\n 146.6474694384778,\n 101.68405646311294,\n 104.5791139459948,\n 85.39428966503652,\n 78.45166775446714,\n 56.285707917841535,\n 36.22861441808941,\n 35.098428846082555,\n 68.67835646605371,\n 101.67142528391042,\n 151.04038339587296,\n 114.77414457402928,\n 72.65341528313934,\n 113.42643748928826,\n 151.09282092262364,\n 163.24422498859587,\n 183.86606816236363,\n 230.24678524811478,\n 205.94887669562561,\n 211.24387656976373,\n 217.26738326873522,\n 214.66898480692646,\n 206.95531499977153,\n 194.19724584765092,\n 146.16071387746757,\n 188.30193538777615\n ]\n ]\n }\n }\n]", + "refId": "A", + "scenarioId": "raw_frame" + } + ], + "title": "Config from query / threshold does not overwrite Base threshold", + "transformations": [ + { + "id": "configFromData", + "options": { + "configRefId": "A", + "mappings": [ + { + "fieldName": "A-series", + "handlerArguments": { + "threshold": { + "color": "yellow" + } }, - { - "fieldName": "DisplayText", - "handlerKey": "mappings.text" - } - ] - } + "handlerKey": "threshold1" + } + ] } - ], - "type": "barchart" - } - ], - "refresh": "", - "schemaVersion": 33, - "tags": [ - "gdev", - "transform" - ], - "templating": { - "list": [] - }, - "time": { - "from": "now-6h", - "to": "now" - }, - "timepicker": {}, - "timezone": "", - "title": "Transforms - Config from query", - "uid": "Juj4_7ink", - "version": 1 - } + } + ], + "type": "timeseries" + } + ], + "refresh": "", + "schemaVersion": 40, + "tags": [ + "gdev", + "transform" + ], + "templating": { + "list": [] + }, + "time": { + "from": "2024-11-20T16:31:51.747Z", + "to": "2024-11-20T22:28:15.688Z" + }, + "timepicker": {}, + "timezone": "", + "title": "Transforms - Config from query", + "uid": "Juj4_7ink", + "version": 1, + "weekStart": "" +} diff --git a/docs/sources/panels-visualizations/query-transform-data/transform-data/index.md b/docs/sources/panels-visualizations/query-transform-data/transform-data/index.md index d0ac307a1bc..726a5da5a8b 100644 --- a/docs/sources/panels-visualizations/query-transform-data/transform-data/index.md +++ b/docs/sources/panels-visualizations/query-transform-data/transform-data/index.md @@ -286,6 +286,8 @@ In the field mapping specify: Grafana builds value mappings from your query result and applies them to the real data query results. You should see values being mapped and colored according to the config query results. +> **Note:** When you use this transformation for thresholds, the visualization continues to use the panel's base threshold. + ### Convert field type Use this transformation to modify the field type of a specified field. diff --git a/packages/grafana-data/src/field/__snapshots__/fieldOverrides.test.ts.snap b/packages/grafana-data/src/field/__snapshots__/fieldOverrides.test.ts.snap new file mode 100644 index 00000000000..aea09b13dad --- /dev/null +++ b/packages/grafana-data/src/field/__snapshots__/fieldOverrides.test.ts.snap @@ -0,0 +1,17 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`setFieldConfigDefaults applies the base threshold when one does not exist in the config 1`] = ` +{ + "mode": "absolute", + "steps": [ + { + "color": "red", + "value": -Infinity, + }, + { + "color": "green", + "value": 50, + }, + ], +} +`; diff --git a/packages/grafana-data/src/field/fieldOverrides.test.ts b/packages/grafana-data/src/field/fieldOverrides.test.ts index 0d16b66397b..0fd6e2d834e 100644 --- a/packages/grafana-data/src/field/fieldOverrides.test.ts +++ b/packages/grafana-data/src/field/fieldOverrides.test.ts @@ -730,6 +730,33 @@ describe('setFieldConfigDefaults', () => { } `); }); + + it('applies the base threshold when one does not exist in the config', () => { + const defaultConfig: FieldConfig = { + thresholds: { + mode: ThresholdsMode.Absolute, + steps: [{ value: -Infinity, color: 'red' }], + }, + }; + + const config: FieldConfig = { + thresholds: { + mode: ThresholdsMode.Absolute, + steps: [{ value: 50, color: 'green' }], + }, + }; + + const context: FieldOverrideEnv = { + data: [], + field: { type: FieldType.number } as Field, + dataFrameIndex: 0, + fieldConfigRegistry: customFieldRegistry, + }; + + setFieldConfigDefaults(config, defaultConfig, context); + + expect(config.thresholds).toMatchSnapshot(); + }); }); describe('setDynamicConfigValue', () => { diff --git a/packages/grafana-data/src/field/fieldOverrides.ts b/packages/grafana-data/src/field/fieldOverrides.ts index 479f31155c6..0924a417231 100644 --- a/packages/grafana-data/src/field/fieldOverrides.ts +++ b/packages/grafana-data/src/field/fieldOverrides.ts @@ -2,7 +2,7 @@ import { isNumber, set, unset, get, cloneDeep } from 'lodash'; import { useMemo, useRef } from 'react'; import usePrevious from 'react-use/lib/usePrevious'; -import { VariableFormatID } from '@grafana/schema'; +import { ThresholdsMode, VariableFormatID } from '@grafana/schema'; import { compareArrayValues, compareDataFrameStructures } from '../dataframe/frameComparisons'; import { guessFieldTypeForField } from '../dataframe/processDataFrame'; @@ -347,6 +347,18 @@ export function setFieldConfigDefaults(config: FieldConfig, defaults: FieldConfi // Combine the data source links and the panel default config links config.links = [...config.links, ...defaults.links]; } + + // if we have a base threshold set by default but not on the config, we need to merge it in + const defaultBaseStep = + defaults?.thresholds?.mode === ThresholdsMode.Absolute && + defaults.thresholds?.steps.find((step) => step.value === -Infinity); + if ( + config.thresholds?.mode === ThresholdsMode.Absolute && + !config.thresholds.steps.some((step) => step.value === -Infinity) && + defaultBaseStep + ) { + config.thresholds.steps = [defaultBaseStep, ...config.thresholds.steps]; + } for (const fieldConfigProperty of context.fieldConfigRegistry.list()) { if (fieldConfigProperty.isCustom && !config.custom) { config.custom = {}; diff --git a/public/app/features/transformers/configFromQuery/configFromQuery.test.ts b/public/app/features/transformers/configFromQuery/configFromQuery.test.ts index dbf6e024eb2..4dc249fc19d 100644 --- a/public/app/features/transformers/configFromQuery/configFromQuery.test.ts +++ b/public/app/features/transformers/configFromQuery/configFromQuery.test.ts @@ -93,7 +93,7 @@ describe('config from data', () => { const results = extractConfigFromQuery(options, [config, seriesA]); expect(results.length).toBe(1); - const thresholdConfig = results[0].fields[1].config.thresholds?.steps[1]; + const thresholdConfig = results[0].fields[1].config.thresholds?.steps[0]; expect(thresholdConfig).toBeDefined(); expect(thresholdConfig?.color).toBe('orange'); expect(thresholdConfig?.value).toBe(50); diff --git a/public/app/features/transformers/docs/content.ts b/public/app/features/transformers/docs/content.ts index dc91b1152b8..f303976d6bc 100644 --- a/public/app/features/transformers/docs/content.ts +++ b/public/app/features/transformers/docs/content.ts @@ -179,6 +179,9 @@ In the field mapping specify: | Color | Value mappings / Color | All values | Grafana builds value mappings from your query result and applies them to the real data query results. You should see values being mapped and colored according to the config query results. + +> **Note:** When you use this transformation for thresholds, the visualization continues to use the panel's base threshold. + `; }, }, @@ -1251,7 +1254,6 @@ Select this option to transform the time series data frame from the long format | 2023-01-01 00:00:00 | 10 | 20 | | 2023-01-01 01:00:00 | 15 | 25 | -> **Note:** This transformation is available in Grafana 7.5.10+ and Grafana 8.0.6+. `; }, links: [ @@ -1453,7 +1455,6 @@ Here is the result after applying the Series to rows transformation. This transformation facilitates the consolidation of results from multiple time series queries, providing a streamlined and unified dataset for efficient analysis and visualization in a tabular format. -> **Note:** This transformation is available in Grafana 7.1+. `; }, }, diff --git a/public/app/features/transformers/fieldToConfigMapping/fieldToConfigMapping.ts b/public/app/features/transformers/fieldToConfigMapping/fieldToConfigMapping.ts index b059f29cc20..9cd537aa190 100644 --- a/public/app/features/transformers/fieldToConfigMapping/fieldToConfigMapping.ts +++ b/public/app/features/transformers/fieldToConfigMapping/fieldToConfigMapping.ts @@ -169,7 +169,7 @@ export const configMapHandlers: FieldToConfigMapHandler[] = [ if (!config.thresholds) { config.thresholds = { mode: ThresholdsMode.Absolute, - steps: [{ value: -Infinity, color: 'green' }], + steps: [], }; } diff --git a/public/app/features/transformers/rowsToFields/rowsToFields.test.ts b/public/app/features/transformers/rowsToFields/rowsToFields.test.ts index 333fa1ae093..f6e458db2b8 100644 --- a/public/app/features/transformers/rowsToFields/rowsToFields.test.ts +++ b/public/app/features/transformers/rowsToFields/rowsToFields.test.ts @@ -111,7 +111,7 @@ describe('Rows to fields', () => { }); const result = rowsToFields({}, input); - expect(result.fields[0].config.thresholds?.steps[1].value).toBe(30); + expect(result.fields[0].config.thresholds?.steps[0].value).toBe(30); }); it('Will extract other string fields to labels', () => {