diff --git a/public/app/core/components/QueryOperationRow/QueryOperationRow.tsx b/public/app/core/components/QueryOperationRow/QueryOperationRow.tsx index 7e62b8637ef..09683f5135d 100644 --- a/public/app/core/components/QueryOperationRow/QueryOperationRow.tsx +++ b/public/app/core/components/QueryOperationRow/QueryOperationRow.tsx @@ -109,7 +109,7 @@ const getQueryOperationRowStyles = stylesFactory((theme: GrafanaTheme) => { `, content: css` margin-top: ${theme.spacing.inlineFormMargin}; - margin-left: ${theme.spacing.xl}; + margin-left: ${theme.spacing.lg}; `, }; }); diff --git a/public/app/features/dashboard/dashgrid/PanelChrome.tsx b/public/app/features/dashboard/dashgrid/PanelChrome.tsx index 72aed3a009b..b8ca99b21d7 100644 --- a/public/app/features/dashboard/dashgrid/PanelChrome.tsx +++ b/public/app/features/dashboard/dashgrid/PanelChrome.tsx @@ -200,8 +200,7 @@ export class PanelChrome extends PureComponent { timezone: this.props.dashboard.getTimezone(), timeRange: timeData.timeRange, timeInfo: timeData.timeInfo, - widthPixels: width, - maxDataPoints: panel.maxDataPoints, + maxDataPoints: panel.maxDataPoints || width, minInterval: panel.interval, scopedVars: panel.scopedVars, cacheTimeout: panel.cacheTimeout, diff --git a/public/app/features/dashboard/panel_editor/DataSourceOption.tsx b/public/app/features/dashboard/panel_editor/DataSourceOption.tsx deleted file mode 100644 index d6a726360c1..00000000000 --- a/public/app/features/dashboard/panel_editor/DataSourceOption.tsx +++ /dev/null @@ -1,33 +0,0 @@ -import React, { FC, ChangeEvent } from 'react'; -import { InlineFormLabel, LegacyForms } from '@grafana/ui'; -const { Input } = LegacyForms; - -interface Props { - label: string; - placeholder?: string; - name: string; - value: string; - onBlur: (event: ChangeEvent) => void; - onChange: (event: ChangeEvent) => void; - tooltipInfo?: any; -} - -export const DataSourceOption: FC = ({ label, placeholder, name, value, onBlur, onChange, tooltipInfo }) => { - return ( -
- - {label} - - -
- ); -}; diff --git a/public/app/features/dashboard/panel_editor/QueriesTab.tsx b/public/app/features/dashboard/panel_editor/QueriesTab.tsx index 098101928b7..bdcaa05cbd0 100644 --- a/public/app/features/dashboard/panel_editor/QueriesTab.tsx +++ b/public/app/features/dashboard/panel_editor/QueriesTab.tsx @@ -172,7 +172,15 @@ export class QueriesTab extends PureComponent {
-
+
+
-
- -
); @@ -327,6 +332,7 @@ const getStyles = stylesFactory(() => { `, dataSourceRowItemOptions: css` flex-grow: 1; + margin-right: ${theme.spacing.inlineFormMargin}; `, queriesWrapper: css` padding-bottom: 16px; diff --git a/public/app/features/dashboard/panel_editor/QueryOptions.tsx b/public/app/features/dashboard/panel_editor/QueryOptions.tsx index 8f82b5a28eb..08442f64691 100644 --- a/public/app/features/dashboard/panel_editor/QueryOptions.tsx +++ b/public/app/features/dashboard/panel_editor/QueryOptions.tsx @@ -13,8 +13,7 @@ import { InlineFormLabel, stylesFactory, } from '@grafana/ui'; -import { DataSourceOption } from './DataSourceOption'; -const { Input, Switch } = LegacyForms; +const { Switch, Input } = LegacyForms; // Types import { PanelModel } from '../state'; @@ -57,46 +56,6 @@ interface State { } export class QueryOptions extends PureComponent { - allOptions: any = { - cacheTimeout: { - label: 'Cache timeout', - placeholder: '60', - name: 'cacheTimeout', - tooltipInfo: ( - <> - If your time series store has a query cache this option can override the default cache timeout. Specify a - numeric value in seconds. - - ), - }, - maxDataPoints: { - label: 'Max data points', - placeholder: 'auto', - name: 'maxDataPoints', - tooltipInfo: ( - <> - The maximum data points the query should return. For graphs this is automatically set to one data point per - pixel. For some data sources this can also be capped in the datasource settings page. With streaming data, - this value is used for the rolling buffer. - - ), - }, - minInterval: { - label: 'Min time interval', - placeholder: '0', - name: 'minInterval', - panelKey: 'interval', - tooltipInfo: ( - <> - A lower limit for the auto group by time interval. Recommended to be set to write frequency, for example{' '} - 1m if your data is written every minute. Access auto interval via variable{' '} - $__interval for time range string and $__interval_ms for numeric variable that can - be used in math expressions. - - ), - }, - }; - constructor(props: Props) { super(props); @@ -127,6 +86,7 @@ export class QueryOptions extends PureComponent { const { value } = event.target; const { panel } = this.props; const emptyToNullValue = emptyToNull(value); + if (status === LegacyInputStatus.Valid && panel.timeFrom !== emptyToNullValue) { panel.timeFrom = emptyToNullValue; panel.refresh(); @@ -137,6 +97,7 @@ export class QueryOptions extends PureComponent { const { value } = event.target; const { panel } = this.props; const emptyToNullValue = emptyToNull(value); + if (status === LegacyInputStatus.Valid && panel.timeShift !== emptyToNullValue) { panel.timeShift = emptyToNullValue; panel.refresh(); @@ -163,35 +124,132 @@ export class QueryOptions extends PureComponent { this.setState({ ...this.state, [panelKey]: event.target.value }); }; - /** - * Show options for any value that is set, or values that the - * current datasource says it will use - */ - renderOptions = () => { + renderCacheTimeoutOption() { const { datasource } = this.props; - const queryOptions: any = datasource.meta.queryOptions || {}; + const { cacheTimeout } = this.state; + const tooltip = `If your time series store has a query cache this option can override the default cache timeout. Specify a + numeric value in seconds.`; - return Object.keys(this.allOptions).map(key => { - const options = this.allOptions[key]; - const panelKey = options.panelKey || key; + if (!datasource.meta.queryOptions?.maxDataPoints) { + return null; + } - // @ts-ignore - const value = this.state[panelKey]; - - if (queryOptions[key]) { - return ( - +
+ + Cache timeout + + - ); - } - return null; // nothing to render - }); - }; +
+ + ); + } + + renderMaxDataPointsOption() { + const { data } = this.props; + const { maxDataPoints } = this.state; + const realMd = data.request?.maxDataPoints; + const isAuto = maxDataPoints === ''; + + return ( +
+
+ + The maximum data points per series. Used directly by some data sources and used in calculation of auto + interval. With streaming data this value is used for the rolling buffer. + + } + > + Max data points + + + {isAuto && ( + <> +
=
+
Width of panel
+ + )} +
+
+ ); + } + + renderIntervalOption() { + const { data } = this.props; + const { interval } = this.state; + const realInterval = data.request?.interval; + + return ( + <> +
+
+ + A lower limit for the interval. Recommended to be set to write frequency, for example 1m{' '} + if your data is written every minute. Default value can be set in data source settings for most data + sources. + + } + > + Min interval + + +
+
+
+
+ + The evaluated Interval that is sent to data source and is used in $__interval and{' '} + $__interval_ms + + } + > + Interval + + {realInterval} +
=
+
Max data points / time range
+
+
+ + ); + } onOpenOptions = () => { this.setState({ isOpen: true }); @@ -215,8 +273,8 @@ export class QueryOptions extends PureComponent { } let intervalDesc = interval; - if (intervalDesc === '' && data.request) { - intervalDesc = `auto = ${data.request.interval}`; + if (data.request) { + intervalDesc = `${data.request.interval}`; } return ( @@ -240,7 +298,9 @@ export class QueryOptions extends PureComponent { onOpen={this.onOpenOptions} onClose={this.onCloseOptions} > - {this.renderOptions()} + {this.renderMaxDataPointsOption()} + {this.renderIntervalOption()} + {this.renderCacheTimeoutOption()}
Relative time diff --git a/public/app/features/dashboard/state/PanelQueryRunner.test.ts b/public/app/features/dashboard/state/PanelQueryRunner.test.ts index 895d51cd223..e3e0c2300e9 100644 --- a/public/app/features/dashboard/state/PanelQueryRunner.test.ts +++ b/public/app/features/dashboard/state/PanelQueryRunner.test.ts @@ -31,7 +31,6 @@ interface ScenarioContext { // Options used in setup maxDataPoints?: number | null; - widthPixels: number; dsInterval?: string; minInterval?: string; scopedVars: ScopedVars; @@ -53,7 +52,7 @@ function describeQueryRunnerScenario(description: string, scenarioFn: ScenarioFn getTransformations: () => undefined, }; const ctx: ScenarioContext = { - widthPixels: 200, + maxDataPoints: 200, scopedVars: { server: { text: 'Server1', value: 'server-1' }, }, @@ -93,12 +92,11 @@ function describeQueryRunnerScenario(description: string, scenarioFn: ScenarioFn datasource, scopedVars: ctx.scopedVars, minInterval: ctx.minInterval, - widthPixels: ctx.widthPixels, maxDataPoints: ctx.maxDataPoints, timeRange: { from: grafanaData.dateTime().subtract(1, 'days'), to: grafanaData.dateTime(), - raw: { from: '1h', to: 'now' }, + raw: { from: '1d', to: 'now' }, }, panelId: 1, queries: [{ refId: 'A', test: 1 }], @@ -137,10 +135,9 @@ describe('PanelQueryRunner', () => { }); }); - describeQueryRunnerScenario('with no maxDataPoints or minInterval', ctx => { + describeQueryRunnerScenario('with maxDataPoints', ctx => { ctx.setup(() => { - ctx.maxDataPoints = null; - ctx.widthPixels = 200; + ctx.maxDataPoints = 200; }); it('should return data', async () => { @@ -163,7 +160,7 @@ describe('PanelQueryRunner', () => { describeQueryRunnerScenario('with no panel min interval but datasource min interval', ctx => { ctx.setup(() => { - ctx.widthPixels = 20000; + ctx.maxDataPoints = 20000; ctx.dsInterval = '15s'; }); @@ -174,7 +171,7 @@ describe('PanelQueryRunner', () => { describeQueryRunnerScenario('with panel min interval and data source min interval', ctx => { ctx.setup(() => { - ctx.widthPixels = 20000; + ctx.maxDataPoints = 20000; ctx.dsInterval = '15s'; ctx.minInterval = '30s'; }); @@ -192,6 +189,10 @@ describe('PanelQueryRunner', () => { it('should pass maxDataPoints if specified', async () => { expect(ctx.queryCalledWith?.maxDataPoints).toBe(10); }); + + it('should use instead of width to calculate interval', async () => { + expect(ctx.queryCalledWith?.interval).toBe('2h'); + }); }); describeQueryRunnerScenario( diff --git a/public/app/features/dashboard/state/PanelQueryRunner.ts b/public/app/features/dashboard/state/PanelQueryRunner.ts index 441289ece5e..c673e394286 100644 --- a/public/app/features/dashboard/state/PanelQueryRunner.ts +++ b/public/app/features/dashboard/state/PanelQueryRunner.ts @@ -38,8 +38,7 @@ export interface QueryRunnerOptions< timezone?: string; timeRange: TimeRange; timeInfo?: string; // String description of time range for display - widthPixels: number; - maxDataPoints: number | undefined | null; + maxDataPoints: number; minInterval: string | undefined | null; scopedVars?: ScopedVars; cacheTimeout?: string; @@ -115,7 +114,6 @@ export class PanelQueryRunner { timeRange, timeInfo, cacheTimeout, - widthPixels, maxDataPoints, scopedVars, minInterval, @@ -139,7 +137,7 @@ export class PanelQueryRunner { interval: '', intervalMs: 0, targets: cloneDeep(queries), - maxDataPoints: maxDataPoints || widthPixels, + maxDataPoints: maxDataPoints, scopedVars: scopedVars || {}, cacheTimeout, startTime: Date.now(), @@ -160,7 +158,7 @@ export class PanelQueryRunner { }); const lowerIntervalLimit = minInterval ? templateSrv.replace(minInterval, request.scopedVars) : ds.interval; - const norm = kbn.calculateInterval(timeRange, widthPixels, lowerIntervalLimit); + const norm = kbn.calculateInterval(timeRange, maxDataPoints, lowerIntervalLimit); // make shallow copy of scoped vars, // and add built in variables interval and interval_ms diff --git a/public/app/features/panel/metrics_panel_ctrl.ts b/public/app/features/panel/metrics_panel_ctrl.ts index a2f2cb51346..c76ab907b44 100644 --- a/public/app/features/panel/metrics_panel_ctrl.ts +++ b/public/app/features/panel/metrics_panel_ctrl.ts @@ -188,8 +188,7 @@ class MetricsPanelCtrl extends PanelCtrl { timezone: this.dashboard.getTimezone(), timeInfo: this.timeInfo, timeRange: this.range, - widthPixels: this.width, - maxDataPoints: panel.maxDataPoints, + maxDataPoints: panel.maxDataPoints || this.width, minInterval: panel.interval, scopedVars: panel.scopedVars, cacheTimeout: panel.cacheTimeout, diff --git a/public/app/plugins/datasource/prometheus/configuration/PromSettings.tsx b/public/app/plugins/datasource/prometheus/configuration/PromSettings.tsx index 9849f477bdc..f0c2c222745 100644 --- a/public/app/plugins/datasource/prometheus/configuration/PromSettings.tsx +++ b/public/app/plugins/datasource/prometheus/configuration/PromSettings.tsx @@ -25,12 +25,12 @@ export const PromSettings = (props: Props) => { diff --git a/public/sass/components/_gf-form.scss b/public/sass/components/_gf-form.scss index 35282a8891c..d00ed1dd569 100644 --- a/public/sass/components/_gf-form.scss +++ b/public/sass/components/_gf-form.scss @@ -90,6 +90,10 @@ $input-border: 1px solid $input-border-color; .select-container { margin-right: $space-xs; } + + .gf-form-spacing { + margin-right: $space-xs; + } } .gf-form-button-row {