mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
MaxDataPoints: Now used in interval calculation for all data sources (#23915)
* MaxDataPoints: Now enabled for all * Updates to code and test * Moved the panel query inspector * PaneQueryRunner: Simplify logic and only take in maxDataPoints not width
This commit is contained in:
parent
32492dd650
commit
0742dbc9be
@ -109,7 +109,7 @@ const getQueryOperationRowStyles = stylesFactory((theme: GrafanaTheme) => {
|
|||||||
`,
|
`,
|
||||||
content: css`
|
content: css`
|
||||||
margin-top: ${theme.spacing.inlineFormMargin};
|
margin-top: ${theme.spacing.inlineFormMargin};
|
||||||
margin-left: ${theme.spacing.xl};
|
margin-left: ${theme.spacing.lg};
|
||||||
`,
|
`,
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
@ -200,8 +200,7 @@ export class PanelChrome extends PureComponent<Props, State> {
|
|||||||
timezone: this.props.dashboard.getTimezone(),
|
timezone: this.props.dashboard.getTimezone(),
|
||||||
timeRange: timeData.timeRange,
|
timeRange: timeData.timeRange,
|
||||||
timeInfo: timeData.timeInfo,
|
timeInfo: timeData.timeInfo,
|
||||||
widthPixels: width,
|
maxDataPoints: panel.maxDataPoints || width,
|
||||||
maxDataPoints: panel.maxDataPoints,
|
|
||||||
minInterval: panel.interval,
|
minInterval: panel.interval,
|
||||||
scopedVars: panel.scopedVars,
|
scopedVars: panel.scopedVars,
|
||||||
cacheTimeout: panel.cacheTimeout,
|
cacheTimeout: panel.cacheTimeout,
|
||||||
|
@ -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<HTMLInputElement>) => void;
|
|
||||||
onChange: (event: ChangeEvent<HTMLInputElement>) => void;
|
|
||||||
tooltipInfo?: any;
|
|
||||||
}
|
|
||||||
|
|
||||||
export const DataSourceOption: FC<Props> = ({ label, placeholder, name, value, onBlur, onChange, tooltipInfo }) => {
|
|
||||||
return (
|
|
||||||
<div className="gf-form gf-form--flex-end">
|
|
||||||
<InlineFormLabel width={9} tooltip={tooltipInfo}>
|
|
||||||
{label}
|
|
||||||
</InlineFormLabel>
|
|
||||||
<Input
|
|
||||||
type="text"
|
|
||||||
className="gf-form-input width-6"
|
|
||||||
placeholder={placeholder}
|
|
||||||
name={name}
|
|
||||||
spellCheck={false}
|
|
||||||
onBlur={onBlur}
|
|
||||||
onChange={onChange}
|
|
||||||
value={value}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
};
|
|
@ -172,7 +172,15 @@ export class QueriesTab extends PureComponent<Props, State> {
|
|||||||
<DataSourcePicker datasources={this.datasources} onChange={this.onChangeDataSource} current={currentDS} />
|
<DataSourcePicker datasources={this.datasources} onChange={this.onChangeDataSource} current={currentDS} />
|
||||||
</div>
|
</div>
|
||||||
<div className={styles.dataSourceRowItem}>
|
<div className={styles.dataSourceRowItem}>
|
||||||
<Button variant="secondary" icon="info-circle" title="Open data source help" onClick={this.onOpenHelp} />
|
<Button
|
||||||
|
variant="secondary"
|
||||||
|
icon="question-circle"
|
||||||
|
title="Open data source help"
|
||||||
|
onClick={this.onOpenHelp}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div className={styles.dataSourceRowItemOptions}>
|
||||||
|
<QueryOptions panel={panel} datasource={currentDS} data={data} />
|
||||||
</div>
|
</div>
|
||||||
<div className={styles.dataSourceRowItem}>
|
<div className={styles.dataSourceRowItem}>
|
||||||
<Button
|
<Button
|
||||||
@ -183,9 +191,6 @@ export class QueriesTab extends PureComponent<Props, State> {
|
|||||||
Query inspector
|
Query inspector
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
<div className={styles.dataSourceRowItemOptions}>
|
|
||||||
<QueryOptions panel={panel} datasource={currentDS} data={data} />
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
@ -327,6 +332,7 @@ const getStyles = stylesFactory(() => {
|
|||||||
`,
|
`,
|
||||||
dataSourceRowItemOptions: css`
|
dataSourceRowItemOptions: css`
|
||||||
flex-grow: 1;
|
flex-grow: 1;
|
||||||
|
margin-right: ${theme.spacing.inlineFormMargin};
|
||||||
`,
|
`,
|
||||||
queriesWrapper: css`
|
queriesWrapper: css`
|
||||||
padding-bottom: 16px;
|
padding-bottom: 16px;
|
||||||
|
@ -13,8 +13,7 @@ import {
|
|||||||
InlineFormLabel,
|
InlineFormLabel,
|
||||||
stylesFactory,
|
stylesFactory,
|
||||||
} from '@grafana/ui';
|
} from '@grafana/ui';
|
||||||
import { DataSourceOption } from './DataSourceOption';
|
const { Switch, Input } = LegacyForms;
|
||||||
const { Input, Switch } = LegacyForms;
|
|
||||||
|
|
||||||
// Types
|
// Types
|
||||||
import { PanelModel } from '../state';
|
import { PanelModel } from '../state';
|
||||||
@ -57,46 +56,6 @@ interface State {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export class QueryOptions extends PureComponent<Props, State> {
|
export class QueryOptions extends PureComponent<Props, State> {
|
||||||
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{' '}
|
|
||||||
<code>1m</code> if your data is written every minute. Access auto interval via variable{' '}
|
|
||||||
<code>$__interval</code> for time range string and <code>$__interval_ms</code> for numeric variable that can
|
|
||||||
be used in math expressions.
|
|
||||||
</>
|
|
||||||
),
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
constructor(props: Props) {
|
constructor(props: Props) {
|
||||||
super(props);
|
super(props);
|
||||||
|
|
||||||
@ -127,6 +86,7 @@ export class QueryOptions extends PureComponent<Props, State> {
|
|||||||
const { value } = event.target;
|
const { value } = event.target;
|
||||||
const { panel } = this.props;
|
const { panel } = this.props;
|
||||||
const emptyToNullValue = emptyToNull(value);
|
const emptyToNullValue = emptyToNull(value);
|
||||||
|
|
||||||
if (status === LegacyInputStatus.Valid && panel.timeFrom !== emptyToNullValue) {
|
if (status === LegacyInputStatus.Valid && panel.timeFrom !== emptyToNullValue) {
|
||||||
panel.timeFrom = emptyToNullValue;
|
panel.timeFrom = emptyToNullValue;
|
||||||
panel.refresh();
|
panel.refresh();
|
||||||
@ -137,6 +97,7 @@ export class QueryOptions extends PureComponent<Props, State> {
|
|||||||
const { value } = event.target;
|
const { value } = event.target;
|
||||||
const { panel } = this.props;
|
const { panel } = this.props;
|
||||||
const emptyToNullValue = emptyToNull(value);
|
const emptyToNullValue = emptyToNull(value);
|
||||||
|
|
||||||
if (status === LegacyInputStatus.Valid && panel.timeShift !== emptyToNullValue) {
|
if (status === LegacyInputStatus.Valid && panel.timeShift !== emptyToNullValue) {
|
||||||
panel.timeShift = emptyToNullValue;
|
panel.timeShift = emptyToNullValue;
|
||||||
panel.refresh();
|
panel.refresh();
|
||||||
@ -163,35 +124,132 @@ export class QueryOptions extends PureComponent<Props, State> {
|
|||||||
this.setState({ ...this.state, [panelKey]: event.target.value });
|
this.setState({ ...this.state, [panelKey]: event.target.value });
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
renderCacheTimeoutOption() {
|
||||||
* Show options for any value that is set, or values that the
|
|
||||||
* current datasource says it will use
|
|
||||||
*/
|
|
||||||
renderOptions = () => {
|
|
||||||
const { datasource } = this.props;
|
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 => {
|
if (!datasource.meta.queryOptions?.maxDataPoints) {
|
||||||
const options = this.allOptions[key];
|
return null;
|
||||||
const panelKey = options.panelKey || key;
|
}
|
||||||
|
|
||||||
// @ts-ignore
|
return (
|
||||||
const value = this.state[panelKey];
|
<div className="gf-form-inline">
|
||||||
|
<div className="gf-form">
|
||||||
if (queryOptions[key]) {
|
<InlineFormLabel width={9} tooltip={tooltip}>
|
||||||
return (
|
Cache timeout
|
||||||
<DataSourceOption
|
</InlineFormLabel>
|
||||||
key={key}
|
<Input
|
||||||
{...options}
|
type="text"
|
||||||
onChange={this.onDataSourceOptionChange(panelKey)}
|
className="width-6"
|
||||||
onBlur={this.onDataSourceOptionBlur(panelKey)}
|
placeholder="60"
|
||||||
value={value}
|
name={name}
|
||||||
|
spellCheck={false}
|
||||||
|
onBlur={this.onDataSourceOptionBlur('maxDataPoints')}
|
||||||
|
onChange={this.onDataSourceOptionChange('maxDataPoints')}
|
||||||
|
value={cacheTimeout}
|
||||||
/>
|
/>
|
||||||
);
|
</div>
|
||||||
}
|
</div>
|
||||||
return null; // nothing to render
|
);
|
||||||
});
|
}
|
||||||
};
|
|
||||||
|
renderMaxDataPointsOption() {
|
||||||
|
const { data } = this.props;
|
||||||
|
const { maxDataPoints } = this.state;
|
||||||
|
const realMd = data.request?.maxDataPoints;
|
||||||
|
const isAuto = maxDataPoints === '';
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="gf-form-inline">
|
||||||
|
<div className="gf-form">
|
||||||
|
<InlineFormLabel
|
||||||
|
width={9}
|
||||||
|
tooltip={
|
||||||
|
<>
|
||||||
|
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
|
||||||
|
</InlineFormLabel>
|
||||||
|
<Input
|
||||||
|
type="text"
|
||||||
|
className="width-6"
|
||||||
|
placeholder={`${realMd}`}
|
||||||
|
name={name}
|
||||||
|
spellCheck={false}
|
||||||
|
onBlur={this.onDataSourceOptionBlur('maxDataPoints')}
|
||||||
|
onChange={this.onDataSourceOptionChange('maxDataPoints')}
|
||||||
|
value={maxDataPoints}
|
||||||
|
/>
|
||||||
|
{isAuto && (
|
||||||
|
<>
|
||||||
|
<div className="gf-form-label query-segment-operator">=</div>
|
||||||
|
<div className="gf-form-label">Width of panel</div>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
renderIntervalOption() {
|
||||||
|
const { data } = this.props;
|
||||||
|
const { interval } = this.state;
|
||||||
|
const realInterval = data.request?.interval;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<div className="gf-form-inline">
|
||||||
|
<div className="gf-form">
|
||||||
|
<InlineFormLabel
|
||||||
|
width={9}
|
||||||
|
tooltip={
|
||||||
|
<>
|
||||||
|
A lower limit for the interval. Recommended to be set to write frequency, for example <code>1m</code>{' '}
|
||||||
|
if your data is written every minute. Default value can be set in data source settings for most data
|
||||||
|
sources.
|
||||||
|
</>
|
||||||
|
}
|
||||||
|
>
|
||||||
|
Min interval
|
||||||
|
</InlineFormLabel>
|
||||||
|
<Input
|
||||||
|
type="text"
|
||||||
|
className="width-6"
|
||||||
|
placeholder={`${realInterval}`}
|
||||||
|
name={name}
|
||||||
|
spellCheck={false}
|
||||||
|
onBlur={this.onDataSourceOptionBlur('interval')}
|
||||||
|
onChange={this.onDataSourceOptionChange('interval')}
|
||||||
|
value={interval}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="gf-form-inline">
|
||||||
|
<div className="gf-form">
|
||||||
|
<InlineFormLabel
|
||||||
|
width={9}
|
||||||
|
tooltip={
|
||||||
|
<>
|
||||||
|
The evaluated Interval that is sent to data source and is used in <code>$__interval</code> and{' '}
|
||||||
|
<code>$__interval_ms</code>
|
||||||
|
</>
|
||||||
|
}
|
||||||
|
>
|
||||||
|
Interval
|
||||||
|
</InlineFormLabel>
|
||||||
|
<InlineFormLabel width={6}>{realInterval}</InlineFormLabel>
|
||||||
|
<div className="gf-form-label query-segment-operator">=</div>
|
||||||
|
<div className="gf-form-label">Max data points / time range</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
onOpenOptions = () => {
|
onOpenOptions = () => {
|
||||||
this.setState({ isOpen: true });
|
this.setState({ isOpen: true });
|
||||||
@ -215,8 +273,8 @@ export class QueryOptions extends PureComponent<Props, State> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let intervalDesc = interval;
|
let intervalDesc = interval;
|
||||||
if (intervalDesc === '' && data.request) {
|
if (data.request) {
|
||||||
intervalDesc = `auto = ${data.request.interval}`;
|
intervalDesc = `${data.request.interval}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@ -240,7 +298,9 @@ export class QueryOptions extends PureComponent<Props, State> {
|
|||||||
onOpen={this.onOpenOptions}
|
onOpen={this.onOpenOptions}
|
||||||
onClose={this.onCloseOptions}
|
onClose={this.onCloseOptions}
|
||||||
>
|
>
|
||||||
{this.renderOptions()}
|
{this.renderMaxDataPointsOption()}
|
||||||
|
{this.renderIntervalOption()}
|
||||||
|
{this.renderCacheTimeoutOption()}
|
||||||
|
|
||||||
<div className="gf-form">
|
<div className="gf-form">
|
||||||
<InlineFormLabel width={9}>Relative time</InlineFormLabel>
|
<InlineFormLabel width={9}>Relative time</InlineFormLabel>
|
||||||
|
@ -31,7 +31,6 @@ interface ScenarioContext {
|
|||||||
|
|
||||||
// Options used in setup
|
// Options used in setup
|
||||||
maxDataPoints?: number | null;
|
maxDataPoints?: number | null;
|
||||||
widthPixels: number;
|
|
||||||
dsInterval?: string;
|
dsInterval?: string;
|
||||||
minInterval?: string;
|
minInterval?: string;
|
||||||
scopedVars: ScopedVars;
|
scopedVars: ScopedVars;
|
||||||
@ -53,7 +52,7 @@ function describeQueryRunnerScenario(description: string, scenarioFn: ScenarioFn
|
|||||||
getTransformations: () => undefined,
|
getTransformations: () => undefined,
|
||||||
};
|
};
|
||||||
const ctx: ScenarioContext = {
|
const ctx: ScenarioContext = {
|
||||||
widthPixels: 200,
|
maxDataPoints: 200,
|
||||||
scopedVars: {
|
scopedVars: {
|
||||||
server: { text: 'Server1', value: 'server-1' },
|
server: { text: 'Server1', value: 'server-1' },
|
||||||
},
|
},
|
||||||
@ -93,12 +92,11 @@ function describeQueryRunnerScenario(description: string, scenarioFn: ScenarioFn
|
|||||||
datasource,
|
datasource,
|
||||||
scopedVars: ctx.scopedVars,
|
scopedVars: ctx.scopedVars,
|
||||||
minInterval: ctx.minInterval,
|
minInterval: ctx.minInterval,
|
||||||
widthPixels: ctx.widthPixels,
|
|
||||||
maxDataPoints: ctx.maxDataPoints,
|
maxDataPoints: ctx.maxDataPoints,
|
||||||
timeRange: {
|
timeRange: {
|
||||||
from: grafanaData.dateTime().subtract(1, 'days'),
|
from: grafanaData.dateTime().subtract(1, 'days'),
|
||||||
to: grafanaData.dateTime(),
|
to: grafanaData.dateTime(),
|
||||||
raw: { from: '1h', to: 'now' },
|
raw: { from: '1d', to: 'now' },
|
||||||
},
|
},
|
||||||
panelId: 1,
|
panelId: 1,
|
||||||
queries: [{ refId: 'A', test: 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.setup(() => {
|
||||||
ctx.maxDataPoints = null;
|
ctx.maxDataPoints = 200;
|
||||||
ctx.widthPixels = 200;
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should return data', async () => {
|
it('should return data', async () => {
|
||||||
@ -163,7 +160,7 @@ describe('PanelQueryRunner', () => {
|
|||||||
|
|
||||||
describeQueryRunnerScenario('with no panel min interval but datasource min interval', ctx => {
|
describeQueryRunnerScenario('with no panel min interval but datasource min interval', ctx => {
|
||||||
ctx.setup(() => {
|
ctx.setup(() => {
|
||||||
ctx.widthPixels = 20000;
|
ctx.maxDataPoints = 20000;
|
||||||
ctx.dsInterval = '15s';
|
ctx.dsInterval = '15s';
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -174,7 +171,7 @@ describe('PanelQueryRunner', () => {
|
|||||||
|
|
||||||
describeQueryRunnerScenario('with panel min interval and data source min interval', ctx => {
|
describeQueryRunnerScenario('with panel min interval and data source min interval', ctx => {
|
||||||
ctx.setup(() => {
|
ctx.setup(() => {
|
||||||
ctx.widthPixels = 20000;
|
ctx.maxDataPoints = 20000;
|
||||||
ctx.dsInterval = '15s';
|
ctx.dsInterval = '15s';
|
||||||
ctx.minInterval = '30s';
|
ctx.minInterval = '30s';
|
||||||
});
|
});
|
||||||
@ -192,6 +189,10 @@ describe('PanelQueryRunner', () => {
|
|||||||
it('should pass maxDataPoints if specified', async () => {
|
it('should pass maxDataPoints if specified', async () => {
|
||||||
expect(ctx.queryCalledWith?.maxDataPoints).toBe(10);
|
expect(ctx.queryCalledWith?.maxDataPoints).toBe(10);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should use instead of width to calculate interval', async () => {
|
||||||
|
expect(ctx.queryCalledWith?.interval).toBe('2h');
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describeQueryRunnerScenario(
|
describeQueryRunnerScenario(
|
||||||
|
@ -38,8 +38,7 @@ export interface QueryRunnerOptions<
|
|||||||
timezone?: string;
|
timezone?: string;
|
||||||
timeRange: TimeRange;
|
timeRange: TimeRange;
|
||||||
timeInfo?: string; // String description of time range for display
|
timeInfo?: string; // String description of time range for display
|
||||||
widthPixels: number;
|
maxDataPoints: number;
|
||||||
maxDataPoints: number | undefined | null;
|
|
||||||
minInterval: string | undefined | null;
|
minInterval: string | undefined | null;
|
||||||
scopedVars?: ScopedVars;
|
scopedVars?: ScopedVars;
|
||||||
cacheTimeout?: string;
|
cacheTimeout?: string;
|
||||||
@ -115,7 +114,6 @@ export class PanelQueryRunner {
|
|||||||
timeRange,
|
timeRange,
|
||||||
timeInfo,
|
timeInfo,
|
||||||
cacheTimeout,
|
cacheTimeout,
|
||||||
widthPixels,
|
|
||||||
maxDataPoints,
|
maxDataPoints,
|
||||||
scopedVars,
|
scopedVars,
|
||||||
minInterval,
|
minInterval,
|
||||||
@ -139,7 +137,7 @@ export class PanelQueryRunner {
|
|||||||
interval: '',
|
interval: '',
|
||||||
intervalMs: 0,
|
intervalMs: 0,
|
||||||
targets: cloneDeep(queries),
|
targets: cloneDeep(queries),
|
||||||
maxDataPoints: maxDataPoints || widthPixels,
|
maxDataPoints: maxDataPoints,
|
||||||
scopedVars: scopedVars || {},
|
scopedVars: scopedVars || {},
|
||||||
cacheTimeout,
|
cacheTimeout,
|
||||||
startTime: Date.now(),
|
startTime: Date.now(),
|
||||||
@ -160,7 +158,7 @@ export class PanelQueryRunner {
|
|||||||
});
|
});
|
||||||
|
|
||||||
const lowerIntervalLimit = minInterval ? templateSrv.replace(minInterval, request.scopedVars) : ds.interval;
|
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,
|
// make shallow copy of scoped vars,
|
||||||
// and add built in variables interval and interval_ms
|
// and add built in variables interval and interval_ms
|
||||||
|
@ -188,8 +188,7 @@ class MetricsPanelCtrl extends PanelCtrl {
|
|||||||
timezone: this.dashboard.getTimezone(),
|
timezone: this.dashboard.getTimezone(),
|
||||||
timeInfo: this.timeInfo,
|
timeInfo: this.timeInfo,
|
||||||
timeRange: this.range,
|
timeRange: this.range,
|
||||||
widthPixels: this.width,
|
maxDataPoints: panel.maxDataPoints || this.width,
|
||||||
maxDataPoints: panel.maxDataPoints,
|
|
||||||
minInterval: panel.interval,
|
minInterval: panel.interval,
|
||||||
scopedVars: panel.scopedVars,
|
scopedVars: panel.scopedVars,
|
||||||
cacheTimeout: panel.cacheTimeout,
|
cacheTimeout: panel.cacheTimeout,
|
||||||
|
@ -25,12 +25,12 @@ export const PromSettings = (props: Props) => {
|
|||||||
<FormField
|
<FormField
|
||||||
label="Scrape interval"
|
label="Scrape interval"
|
||||||
labelWidth={13}
|
labelWidth={13}
|
||||||
placeholder="15s"
|
|
||||||
inputEl={
|
inputEl={
|
||||||
<Input
|
<Input
|
||||||
className="width-6"
|
className="width-6"
|
||||||
value={value.jsonData.timeInterval}
|
value={value.jsonData.timeInterval}
|
||||||
spellCheck={false}
|
spellCheck={false}
|
||||||
|
placeholder="15s"
|
||||||
onChange={onChangeHandler('timeInterval', value, onChange)}
|
onChange={onChangeHandler('timeInterval', value, onChange)}
|
||||||
validationEvents={promSettingsValidationEvents}
|
validationEvents={promSettingsValidationEvents}
|
||||||
/>
|
/>
|
||||||
|
@ -90,6 +90,10 @@ $input-border: 1px solid $input-border-color;
|
|||||||
.select-container {
|
.select-container {
|
||||||
margin-right: $space-xs;
|
margin-right: $space-xs;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.gf-form-spacing {
|
||||||
|
margin-right: $space-xs;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.gf-form-button-row {
|
.gf-form-button-row {
|
||||||
|
Loading…
Reference in New Issue
Block a user