diff --git a/devenv/dev-dashboards/panel-timeseries/timeseries-yaxis-ticks.json b/devenv/dev-dashboards/panel-timeseries/timeseries-yaxis-ticks.json index 2538a59e7ae..7650a8aab56 100644 --- a/devenv/dev-dashboards/panel-timeseries/timeseries-yaxis-ticks.json +++ b/devenv/dev-dashboards/panel-timeseries/timeseries-yaxis-ticks.json @@ -1156,11 +1156,195 @@ ], "title": "Boolean On/Off", "type": "timeseries" + }, + { + "datasource": { + "type": "testdata", + "uid": "PD8C576611E62080A" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "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": { + "log": 2, + "type": "log" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "max": 150, + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 7, + "w": 8, + "x": 0, + "y": 31 + }, + "id": 16, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "testdata", + "uid": "PD8C576611E62080A" + }, + "refId": "A", + "scenarioId": "csv_metric_values", + "stringInput": "1,20,90.5,30,5,0" + } + ], + "title": "Ignore invalid min/max opts when log scale", + "type": "timeseries" + }, + { + "datasource": { + "type": "testdata", + "uid": "PD8C576611E62080A" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "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": { + "log": 2, + "type": "symlog" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "max": 200, + "min": -15, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 7, + "w": 8, + "x": 8, + "y": 31 + }, + "id": 17, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "testdata", + "uid": "PD8C576611E62080A" + }, + "refId": "A", + "scenarioId": "csv_metric_values", + "stringInput": "1,20,90.5,30,5,0" + } + ], + "title": "Neg min opt with symlog scale", + "type": "timeseries" } ], - "refresh": false, + "refresh": "", "revision": 1, - "schemaVersion": 37, + "schemaVersion": 38, "style": "dark", "tags": [ "gdev", @@ -1191,6 +1375,6 @@ "timezone": "", "title": "Panel Tests - Graph NG - Y axis ticks", "uid": "29Yjn62Gk", - "version": 1, + "version": 13, "weekStart": "" } diff --git a/packages/grafana-ui/src/components/uPlot/config/UPlotScaleBuilder.ts b/packages/grafana-ui/src/components/uPlot/config/UPlotScaleBuilder.ts index 2011ad0d147..dd7bb67e13c 100644 --- a/packages/grafana-ui/src/components/uPlot/config/UPlotScaleBuilder.ts +++ b/packages/grafana-ui/src/components/uPlot/config/UPlotScaleBuilder.ts @@ -60,6 +60,69 @@ export class UPlotScaleBuilder extends PlotConfigBuilder { } : {}; + // guard against invalid log scale limits <= 0, or snap to log boundaries + if (distr === ScaleDistribution.Log) { + let logBase = this.props.log!; + let logFn = logBase === 2 ? Math.log2 : Math.log10; + + if (hardMin != null) { + if (hardMin <= 0) { + hardMin = null; + } else { + hardMin = logBase ** Math.floor(logFn(hardMin)); + } + } + + if (hardMax != null) { + if (hardMax <= 0) { + hardMax = null; + } else { + hardMax = logBase ** Math.ceil(logFn(hardMax)); + } + } + + if (softMin != null) { + if (softMin <= 0) { + softMin = null; + } else { + softMin = logBase ** Math.floor(logFn(softMin)); + } + } + + if (softMax != null) { + if (softMax <= 0) { + softMax = null; + } else { + softMax = logBase ** Math.ceil(logFn(softMax)); + } + } + } + /* + // snap to symlog boundaries + else if (distr === ScaleDistribution.Symlog) { + let logBase = this.props.log!; + let logFn = logBase === 2 ? Math.log2 : Math.log10; + + let sign = Math.sign(hardMin); + + if (hardMin != null) { + hardMin = logBase ** Math.floor(logFn(hardMin)); + } + + if (hardMax != null) { + hardMax = logBase ** Math.ceil(logFn(hardMax)); + } + + if (softMin != null) { + softMin = logBase ** Math.floor(logFn(softMin)); + } + + if (softMax != null) { + softMax = logBase ** Math.ceil(logFn(softMax)); + } + } + */ + // uPlot's default ranging config for both min & max is {pad: 0.1, hard: null, soft: 0, mode: 3} let softMinMode: Range.SoftMode = softMin == null ? 3 : 1; let softMaxMode: Range.SoftMode = softMax == null ? 3 : 1; @@ -154,7 +217,7 @@ export class UPlotScaleBuilder extends PlotConfigBuilder { } } - if (scale.distr === 1) { + if (scale.distr === 1 || scale.distr === 4) { // if all we got were hard limits, treat them as static min/max if (hardMinOnly) { minMax[0] = hardMin!;