mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
InfluxDB: Fix sending retention policy with InfluxQL queries (#63820)
* Send retention policy if that is specified * Define the type * Update default retention policy name * Update unit tests * fix unit tests * fix unit tests again * Load retention policies at first * Fix tests * Fix Editor tests * Remove unused code * A simpler approach * Even simpler * Even simpler
This commit is contained in:
parent
273e05a9a2
commit
0aee7338ad
@ -4959,8 +4959,8 @@ exports[`better eslint`] = {
|
|||||||
[0, 0, 0, "Unexpected any. Specify a different type.", "2"],
|
[0, 0, 0, "Unexpected any. Specify a different type.", "2"],
|
||||||
[0, 0, 0, "Unexpected any. Specify a different type.", "3"],
|
[0, 0, 0, "Unexpected any. Specify a different type.", "3"],
|
||||||
[0, 0, 0, "Unexpected any. Specify a different type.", "4"],
|
[0, 0, 0, "Unexpected any. Specify a different type.", "4"],
|
||||||
[0, 0, 0, "Unexpected any. Specify a different type.", "5"],
|
[0, 0, 0, "Do not use any type assertions.", "5"],
|
||||||
[0, 0, 0, "Do not use any type assertions.", "6"],
|
[0, 0, 0, "Unexpected any. Specify a different type.", "6"],
|
||||||
[0, 0, 0, "Unexpected any. Specify a different type.", "7"],
|
[0, 0, 0, "Unexpected any. Specify a different type.", "7"],
|
||||||
[0, 0, 0, "Unexpected any. Specify a different type.", "8"],
|
[0, 0, 0, "Unexpected any. Specify a different type.", "8"],
|
||||||
[0, 0, 0, "Unexpected any. Specify a different type.", "9"],
|
[0, 0, 0, "Unexpected any. Specify a different type.", "9"],
|
||||||
@ -4970,13 +4970,13 @@ exports[`better eslint`] = {
|
|||||||
[0, 0, 0, "Unexpected any. Specify a different type.", "13"],
|
[0, 0, 0, "Unexpected any. Specify a different type.", "13"],
|
||||||
[0, 0, 0, "Unexpected any. Specify a different type.", "14"],
|
[0, 0, 0, "Unexpected any. Specify a different type.", "14"],
|
||||||
[0, 0, 0, "Unexpected any. Specify a different type.", "15"],
|
[0, 0, 0, "Unexpected any. Specify a different type.", "15"],
|
||||||
[0, 0, 0, "Unexpected any. Specify a different type.", "16"],
|
[0, 0, 0, "Do not use any type assertions.", "16"],
|
||||||
[0, 0, 0, "Do not use any type assertions.", "17"],
|
[0, 0, 0, "Unexpected any. Specify a different type.", "17"],
|
||||||
[0, 0, 0, "Unexpected any. Specify a different type.", "18"],
|
[0, 0, 0, "Unexpected any. Specify a different type.", "18"],
|
||||||
[0, 0, 0, "Unexpected any. Specify a different type.", "19"],
|
[0, 0, 0, "Unexpected any. Specify a different type.", "19"],
|
||||||
[0, 0, 0, "Unexpected any. Specify a different type.", "20"],
|
[0, 0, 0, "Unexpected any. Specify a different type.", "20"],
|
||||||
[0, 0, 0, "Unexpected any. Specify a different type.", "21"],
|
[0, 0, 0, "Do not use any type assertions.", "21"],
|
||||||
[0, 0, 0, "Do not use any type assertions.", "22"],
|
[0, 0, 0, "Unexpected any. Specify a different type.", "22"],
|
||||||
[0, 0, 0, "Unexpected any. Specify a different type.", "23"],
|
[0, 0, 0, "Unexpected any. Specify a different type.", "23"],
|
||||||
[0, 0, 0, "Unexpected any. Specify a different type.", "24"],
|
[0, 0, 0, "Unexpected any. Specify a different type.", "24"],
|
||||||
[0, 0, 0, "Unexpected any. Specify a different type.", "25"],
|
[0, 0, 0, "Unexpected any. Specify a different type.", "25"],
|
||||||
@ -4986,8 +4986,7 @@ exports[`better eslint`] = {
|
|||||||
[0, 0, 0, "Unexpected any. Specify a different type.", "29"],
|
[0, 0, 0, "Unexpected any. Specify a different type.", "29"],
|
||||||
[0, 0, 0, "Unexpected any. Specify a different type.", "30"],
|
[0, 0, 0, "Unexpected any. Specify a different type.", "30"],
|
||||||
[0, 0, 0, "Unexpected any. Specify a different type.", "31"],
|
[0, 0, 0, "Unexpected any. Specify a different type.", "31"],
|
||||||
[0, 0, 0, "Unexpected any. Specify a different type.", "32"],
|
[0, 0, 0, "Unexpected any. Specify a different type.", "32"]
|
||||||
[0, 0, 0, "Unexpected any. Specify a different type.", "33"]
|
|
||||||
],
|
],
|
||||||
"public/app/plugins/datasource/influxdb/influx_query_model.ts:5381": [
|
"public/app/plugins/datasource/influxdb/influx_query_model.ts:5381": [
|
||||||
[0, 0, 0, "Unexpected any. Specify a different type.", "0"],
|
[0, 0, 0, "Unexpected any. Specify a different type.", "0"],
|
||||||
@ -5009,8 +5008,7 @@ exports[`better eslint`] = {
|
|||||||
[0, 0, 0, "Unexpected any. Specify a different type.", "16"],
|
[0, 0, 0, "Unexpected any. Specify a different type.", "16"],
|
||||||
[0, 0, 0, "Unexpected any. Specify a different type.", "17"],
|
[0, 0, 0, "Unexpected any. Specify a different type.", "17"],
|
||||||
[0, 0, 0, "Unexpected any. Specify a different type.", "18"],
|
[0, 0, 0, "Unexpected any. Specify a different type.", "18"],
|
||||||
[0, 0, 0, "Unexpected any. Specify a different type.", "19"],
|
[0, 0, 0, "Unexpected any. Specify a different type.", "19"]
|
||||||
[0, 0, 0, "Unexpected any. Specify a different type.", "20"]
|
|
||||||
],
|
],
|
||||||
"public/app/plugins/datasource/influxdb/influx_series.ts:5381": [
|
"public/app/plugins/datasource/influxdb/influx_series.ts:5381": [
|
||||||
[0, 0, 0, "Unexpected any. Specify a different type.", "0"],
|
[0, 0, 0, "Unexpected any. Specify a different type.", "0"],
|
||||||
|
@ -11,6 +11,7 @@ import { Editor } from './Editor';
|
|||||||
jest.mock('../../influxQLMetadataQuery', () => {
|
jest.mock('../../influxQLMetadataQuery', () => {
|
||||||
return {
|
return {
|
||||||
__esModule: true,
|
__esModule: true,
|
||||||
|
getAllPolicies: jest.fn().mockReturnValueOnce(Promise.resolve(['default', 'autogen'])),
|
||||||
getFieldKeysForMeasurement: jest
|
getFieldKeysForMeasurement: jest
|
||||||
.fn()
|
.fn()
|
||||||
.mockReturnValueOnce(Promise.resolve(['free', 'total']))
|
.mockReturnValueOnce(Promise.resolve(['free', 'total']))
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { render } from '@testing-library/react';
|
import { act, render } from '@testing-library/react';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
|
||||||
import InfluxDatasource from '../../datasource';
|
import InfluxDatasource from '../../datasource';
|
||||||
@ -35,24 +35,27 @@ jest.mock('./Seg', () => {
|
|||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
function assertEditor(query: InfluxQuery, textContent: string) {
|
async function assertEditor(query: InfluxQuery, textContent: string) {
|
||||||
const onChange = jest.fn();
|
const onChange = jest.fn();
|
||||||
const onRunQuery = jest.fn();
|
const onRunQuery = jest.fn();
|
||||||
const datasource: InfluxDatasource = {
|
const datasource: InfluxDatasource = {
|
||||||
metricFindQuery: () => Promise.resolve([]),
|
metricFindQuery: () => Promise.resolve([]),
|
||||||
} as unknown as InfluxDatasource;
|
} as unknown as InfluxDatasource;
|
||||||
const { container } = render(
|
await act(async () => {
|
||||||
|
const { container } = await render(
|
||||||
<Editor query={query} datasource={datasource} onChange={onChange} onRunQuery={onRunQuery} />
|
<Editor query={query} datasource={datasource} onChange={onChange} onRunQuery={onRunQuery} />
|
||||||
);
|
);
|
||||||
expect(container.textContent).toBe(textContent);
|
expect(container.textContent).toBe(textContent);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
describe('InfluxDB InfluxQL Visual Editor', () => {
|
describe('InfluxDB InfluxQL Visual Editor', () => {
|
||||||
it('should handle minimal query', () => {
|
it('should handle minimal query', async () => {
|
||||||
const query: InfluxQuery = {
|
const query: InfluxQuery = {
|
||||||
refId: 'A',
|
refId: 'A',
|
||||||
|
policy: 'default',
|
||||||
};
|
};
|
||||||
assertEditor(
|
await assertEditor(
|
||||||
query,
|
query,
|
||||||
'FROM[default][select measurement]WHERE[+]' +
|
'FROM[default][select measurement]WHERE[+]' +
|
||||||
'SELECT[field]([value])[mean]()[+]' +
|
'SELECT[field]([value])[mean]()[+]' +
|
||||||
@ -62,13 +65,14 @@ describe('InfluxDB InfluxQL Visual Editor', () => {
|
|||||||
'FORMAT AS[time_series]ALIAS[Naming pattern]'
|
'FORMAT AS[time_series]ALIAS[Naming pattern]'
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
it('should have the alias-field hidden when format-as-table', () => {
|
it('should have the alias-field hidden when format-as-table', async () => {
|
||||||
const query: InfluxQuery = {
|
const query: InfluxQuery = {
|
||||||
refId: 'A',
|
refId: 'A',
|
||||||
alias: 'test-alias',
|
alias: 'test-alias',
|
||||||
resultFormat: 'table',
|
resultFormat: 'table',
|
||||||
|
policy: 'default',
|
||||||
};
|
};
|
||||||
assertEditor(
|
await assertEditor(
|
||||||
query,
|
query,
|
||||||
'FROM[default][select measurement]WHERE[+]' +
|
'FROM[default][select measurement]WHERE[+]' +
|
||||||
'SELECT[field]([value])[mean]()[+]' +
|
'SELECT[field]([value])[mean]()[+]' +
|
||||||
@ -78,7 +82,7 @@ describe('InfluxDB InfluxQL Visual Editor', () => {
|
|||||||
'FORMAT AS[table]'
|
'FORMAT AS[table]'
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
it('should handle complex query', () => {
|
it('should handle complex query', async () => {
|
||||||
const query: InfluxQuery = {
|
const query: InfluxQuery = {
|
||||||
refId: 'A',
|
refId: 'A',
|
||||||
policy: 'default',
|
policy: 'default',
|
||||||
@ -147,7 +151,7 @@ describe('InfluxDB InfluxQL Visual Editor', () => {
|
|||||||
tz: 'UTC',
|
tz: 'UTC',
|
||||||
alias: 'all i as',
|
alias: 'all i as',
|
||||||
};
|
};
|
||||||
assertEditor(
|
await assertEditor(
|
||||||
query,
|
query,
|
||||||
'FROM[default][cpu]WHERE[cpu][=][cpu1][AND][cpu][<][cpu3][+]' +
|
'FROM[default][cpu]WHERE[cpu][=][cpu1][AND][cpu][<][cpu3][+]' +
|
||||||
'SELECT[field]([usage_idle])[mean]()[+]' +
|
'SELECT[field]([usage_idle])[mean]()[+]' +
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import { css } from '@emotion/css';
|
import { css } from '@emotion/css';
|
||||||
import React, { useMemo } from 'react';
|
import React, { useMemo } from 'react';
|
||||||
|
import { useAsync } from 'react-use';
|
||||||
|
|
||||||
import { GrafanaTheme2 } from '@grafana/data';
|
import { GrafanaTheme2 } from '@grafana/data';
|
||||||
import { getTemplateSrv } from '@grafana/runtime';
|
import { getTemplateSrv } from '@grafana/runtime';
|
||||||
@ -76,6 +77,9 @@ export const Editor = (props: Props): JSX.Element => {
|
|||||||
const { datasource } = props;
|
const { datasource } = props;
|
||||||
const { measurement, policy } = query;
|
const { measurement, policy } = query;
|
||||||
|
|
||||||
|
const policyData = useAsync(() => getAllPolicies(datasource), [datasource]);
|
||||||
|
const retentionPolicies = !!policyData.error ? [] : policyData.value ?? [];
|
||||||
|
|
||||||
const allTagKeys = useMemo(async () => {
|
const allTagKeys = useMemo(async () => {
|
||||||
const tagKeys = (await getTagKeysForMeasurementAndTags(measurement, policy, [], datasource)).map(
|
const tagKeys = (await getTagKeysForMeasurementAndTags(measurement, policy, [], datasource)).map(
|
||||||
(tag) => `${tag}::tag`
|
(tag) => `${tag}::tag`
|
||||||
@ -143,7 +147,7 @@ export const Editor = (props: Props): JSX.Element => {
|
|||||||
<div>
|
<div>
|
||||||
<SegmentSection label="FROM" fill={true}>
|
<SegmentSection label="FROM" fill={true}>
|
||||||
<FromSection
|
<FromSection
|
||||||
policy={policy}
|
policy={policy ?? retentionPolicies[0]}
|
||||||
measurement={measurement}
|
measurement={measurement}
|
||||||
getPolicyOptions={() => getAllPolicies(datasource)}
|
getPolicyOptions={() => getAllPolicies(datasource)}
|
||||||
getMeasurementOptions={(filter) =>
|
getMeasurementOptions={(filter) =>
|
||||||
|
@ -3,8 +3,6 @@ import React from 'react';
|
|||||||
import { Seg } from './Seg';
|
import { Seg } from './Seg';
|
||||||
import { toSelectableValue } from './toSelectableValue';
|
import { toSelectableValue } from './toSelectableValue';
|
||||||
|
|
||||||
const DEFAULT_POLICY = 'default';
|
|
||||||
|
|
||||||
// we use the value "default" as a magic-value, it means
|
// we use the value "default" as a magic-value, it means
|
||||||
// we use the default retention-policy.
|
// we use the default retention-policy.
|
||||||
// unfortunately, IF the user has a retention-policy named "default",
|
// unfortunately, IF the user has a retention-policy named "default",
|
||||||
@ -33,12 +31,7 @@ export const FromSection = ({
|
|||||||
}: Props): JSX.Element => {
|
}: Props): JSX.Element => {
|
||||||
const handlePolicyLoadOptions = async () => {
|
const handlePolicyLoadOptions = async () => {
|
||||||
const allPolicies = await getPolicyOptions();
|
const allPolicies = await getPolicyOptions();
|
||||||
// if `default` does not exist in the list of policies, we add it
|
return allPolicies.map(toSelectableValue);
|
||||||
const allPoliciesWithDefault = allPolicies.some((p) => p === 'default')
|
|
||||||
? allPolicies
|
|
||||||
: [DEFAULT_POLICY, ...allPolicies];
|
|
||||||
|
|
||||||
return allPoliciesWithDefault.map(toSelectableValue);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleMeasurementLoadOptions = async (filter: string) => {
|
const handleMeasurementLoadOptions = async (filter: string) => {
|
||||||
@ -50,7 +43,7 @@ export const FromSection = ({
|
|||||||
<>
|
<>
|
||||||
<Seg
|
<Seg
|
||||||
allowCustomValue
|
allowCustomValue
|
||||||
value={policy ?? 'using default policy'}
|
value={policy ?? ''}
|
||||||
loadOptions={handlePolicyLoadOptions}
|
loadOptions={handlePolicyLoadOptions}
|
||||||
onChange={(v) => {
|
onChange={(v) => {
|
||||||
onChange(v.value, measurement);
|
onChange(v.value, measurement);
|
||||||
|
@ -123,7 +123,7 @@ export default class InfluxDatasource extends DataSourceWithBackend<InfluxQuery,
|
|||||||
withCredentials: any;
|
withCredentials: any;
|
||||||
access: 'direct' | 'proxy';
|
access: 'direct' | 'proxy';
|
||||||
interval: any;
|
interval: any;
|
||||||
responseParser: any;
|
responseParser: ResponseParser;
|
||||||
httpMode: string;
|
httpMode: string;
|
||||||
isFlux: boolean;
|
isFlux: boolean;
|
||||||
isProxyAccess: boolean;
|
isProxyAccess: boolean;
|
||||||
@ -606,6 +606,10 @@ export default class InfluxDatasource extends DataSourceWithBackend<InfluxQuery,
|
|||||||
params.db = this.database;
|
params.db = this.database;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (options?.policy) {
|
||||||
|
params.rp = options.policy;
|
||||||
|
}
|
||||||
|
|
||||||
const { q } = data;
|
const { q } = data;
|
||||||
|
|
||||||
if (method === 'POST' && has(data, 'q')) {
|
if (method === 'POST' && has(data, 'q')) {
|
||||||
|
@ -11,7 +11,8 @@ const runExploreQuery = (
|
|||||||
): Promise<Array<{ text: string }>> => {
|
): Promise<Array<{ text: string }>> => {
|
||||||
const builder = new InfluxQueryBuilder(target, datasource.database);
|
const builder = new InfluxQueryBuilder(target, datasource.database);
|
||||||
const q = builder.buildExploreQuery(type, withKey, withMeasurementFilter);
|
const q = builder.buildExploreQuery(type, withKey, withMeasurementFilter);
|
||||||
return datasource.metricFindQuery(q);
|
const options = { policy: target.policy };
|
||||||
|
return datasource.metricFindQuery(q, options);
|
||||||
};
|
};
|
||||||
|
|
||||||
export async function getAllPolicies(datasource: InfluxDatasource): Promise<string[]> {
|
export async function getAllPolicies(datasource: InfluxDatasource): Promise<string[]> {
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { map, find, filter, indexOf } from 'lodash';
|
import { filter, find, indexOf, map } from 'lodash';
|
||||||
|
|
||||||
import { escapeRegex, ScopedVars } from '@grafana/data';
|
import { escapeRegex, ScopedVars } from '@grafana/data';
|
||||||
import { TemplateSrv } from '@grafana/runtime';
|
import { TemplateSrv } from '@grafana/runtime';
|
||||||
@ -20,7 +20,6 @@ export default class InfluxQueryModel {
|
|||||||
this.templateSrv = templateSrv;
|
this.templateSrv = templateSrv;
|
||||||
this.scopedVars = scopedVars;
|
this.scopedVars = scopedVars;
|
||||||
|
|
||||||
target.policy = target.policy || 'default';
|
|
||||||
target.resultFormat = target.resultFormat || 'time_series';
|
target.resultFormat = target.resultFormat || 'time_series';
|
||||||
target.orderByTime = target.orderByTime || 'ASC';
|
target.orderByTime = target.orderByTime || 'ASC';
|
||||||
target.tags = target.tags || [];
|
target.tags = target.tags || [];
|
||||||
@ -183,7 +182,7 @@ export default class InfluxQueryModel {
|
|||||||
return str + escapedKey + ' ' + operator + ' ' + value;
|
return str + escapedKey + ' ' + operator + ' ' + value;
|
||||||
}
|
}
|
||||||
|
|
||||||
getMeasurementAndPolicy(interpolate: any) {
|
getMeasurementAndPolicy(interpolate?: boolean) {
|
||||||
let policy = this.target.policy;
|
let policy = this.target.policy;
|
||||||
let measurement = this.target.measurement || 'measurement';
|
let measurement = this.target.measurement || 'measurement';
|
||||||
|
|
||||||
@ -193,13 +192,7 @@ export default class InfluxQueryModel {
|
|||||||
measurement = this.templateSrv.replace(measurement, this.scopedVars, 'regex');
|
measurement = this.templateSrv.replace(measurement, this.scopedVars, 'regex');
|
||||||
}
|
}
|
||||||
|
|
||||||
if (policy !== 'default') {
|
return `"${policy}".${measurement}`;
|
||||||
policy = '"' + this.target.policy + '".';
|
|
||||||
} else {
|
|
||||||
policy = '';
|
|
||||||
}
|
|
||||||
|
|
||||||
return policy + measurement;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
interpolateQueryStr(value: any[], variable: { multi: any; includeAll: any }, defaultFormatFn: any) {
|
interpolateQueryStr(value: any[], variable: { multi: any; includeAll: any }, defaultFormatFn: any) {
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import { cloneDeep } from 'lodash';
|
import { cloneDeep } from 'lodash';
|
||||||
|
|
||||||
import { buildRawQuery, normalizeQuery, changeSelectPart, changeGroupByPart } from './queryUtils';
|
import { buildRawQuery, changeGroupByPart, changeSelectPart, normalizeQuery } from './queryUtils';
|
||||||
import { InfluxQuery } from './types';
|
import { InfluxQuery } from './types';
|
||||||
|
|
||||||
describe('InfluxDB query utils', () => {
|
describe('InfluxDB query utils', () => {
|
||||||
@ -37,12 +37,15 @@ describe('InfluxDB query utils', () => {
|
|||||||
],
|
],
|
||||||
],
|
],
|
||||||
})
|
})
|
||||||
).toBe('SELECT mean("value") FROM "measurement" WHERE $timeFilter GROUP BY time($__interval) fill(null)');
|
).toBe(
|
||||||
|
'SELECT mean("value") FROM "default"."measurement" WHERE $timeFilter GROUP BY time($__interval)' + ' fill(null)'
|
||||||
|
);
|
||||||
});
|
});
|
||||||
it('should handle small query', () => {
|
it('should handle small query', () => {
|
||||||
expect(
|
expect(
|
||||||
buildRawQuery({
|
buildRawQuery({
|
||||||
refId: 'A',
|
refId: 'A',
|
||||||
|
policy: 'autogen',
|
||||||
select: [
|
select: [
|
||||||
[
|
[
|
||||||
{
|
{
|
||||||
@ -53,12 +56,13 @@ describe('InfluxDB query utils', () => {
|
|||||||
],
|
],
|
||||||
groupBy: [],
|
groupBy: [],
|
||||||
})
|
})
|
||||||
).toBe('SELECT "value" FROM "measurement" WHERE $timeFilter');
|
).toBe('SELECT "value" FROM "autogen"."measurement" WHERE $timeFilter');
|
||||||
});
|
});
|
||||||
it('should handle string limit/slimit', () => {
|
it('should handle string limit/slimit', () => {
|
||||||
expect(
|
expect(
|
||||||
buildRawQuery({
|
buildRawQuery({
|
||||||
refId: 'A',
|
refId: 'A',
|
||||||
|
policy: 'autogen',
|
||||||
select: [
|
select: [
|
||||||
[
|
[
|
||||||
{
|
{
|
||||||
@ -71,12 +75,13 @@ describe('InfluxDB query utils', () => {
|
|||||||
limit: '12',
|
limit: '12',
|
||||||
slimit: '23',
|
slimit: '23',
|
||||||
})
|
})
|
||||||
).toBe('SELECT "value" FROM "measurement" WHERE $timeFilter LIMIT 12 SLIMIT 23');
|
).toBe('SELECT "value" FROM "autogen"."measurement" WHERE $timeFilter LIMIT 12 SLIMIT 23');
|
||||||
});
|
});
|
||||||
it('should handle number limit/slimit', () => {
|
it('should handle number limit/slimit', () => {
|
||||||
expect(
|
expect(
|
||||||
buildRawQuery({
|
buildRawQuery({
|
||||||
refId: 'A',
|
refId: 'A',
|
||||||
|
policy: 'autogen',
|
||||||
select: [
|
select: [
|
||||||
[
|
[
|
||||||
{
|
{
|
||||||
@ -89,12 +94,13 @@ describe('InfluxDB query utils', () => {
|
|||||||
limit: 12,
|
limit: 12,
|
||||||
slimit: 23,
|
slimit: 23,
|
||||||
})
|
})
|
||||||
).toBe('SELECT "value" FROM "measurement" WHERE $timeFilter LIMIT 12 SLIMIT 23');
|
).toBe('SELECT "value" FROM "autogen"."measurement" WHERE $timeFilter LIMIT 12 SLIMIT 23');
|
||||||
});
|
});
|
||||||
it('should handle all the tag-operators', () => {
|
it('should handle all the tag-operators', () => {
|
||||||
expect(
|
expect(
|
||||||
buildRawQuery({
|
buildRawQuery({
|
||||||
refId: 'A',
|
refId: 'A',
|
||||||
|
policy: 'autogen',
|
||||||
select: [
|
select: [
|
||||||
[
|
[
|
||||||
{
|
{
|
||||||
@ -147,7 +153,10 @@ describe('InfluxDB query utils', () => {
|
|||||||
groupBy: [],
|
groupBy: [],
|
||||||
})
|
})
|
||||||
).toBe(
|
).toBe(
|
||||||
`SELECT "value" FROM "measurement" WHERE ("cpu" = 'cpu0' AND "cpu" != 'cpu0' AND "cpu" <> 'cpu0' AND "cpu" < cpu0 AND "cpu" > cpu0 AND "cpu" =~ /cpu0/ AND "cpu" !~ /cpu0/) AND $timeFilter`
|
`SELECT "value" ` +
|
||||||
|
`FROM "autogen"."measurement" ` +
|
||||||
|
`WHERE ("cpu" = 'cpu0' AND "cpu" != 'cpu0' AND "cpu" <> 'cpu0' AND "cpu" < cpu0 AND ` +
|
||||||
|
`"cpu" > cpu0 AND "cpu" =~ /cpu0/ AND "cpu" !~ /cpu0/) AND $timeFilter`
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
it('should handle a complex query', () => {
|
it('should handle a complex query', () => {
|
||||||
@ -229,7 +238,12 @@ describe('InfluxDB query utils', () => {
|
|||||||
tz: 'UTC',
|
tz: 'UTC',
|
||||||
})
|
})
|
||||||
).toBe(
|
).toBe(
|
||||||
`SELECT holt_winters_with_fit(mean("usage_idle"), 30, 5), median("usage_guest") FROM "cpu" WHERE ("cpu" = 'cpu2' OR "cpu" = 'cpu3' AND "cpu" = 'cpu1') AND $timeFilter GROUP BY time($__interval), "cpu", "host" fill(none) ORDER BY time DESC LIMIT 12 SLIMIT 23 tz('UTC')`
|
`SELECT holt_winters_with_fit(mean("usage_idle"), 30, 5), median("usage_guest") ` +
|
||||||
|
`FROM "default"."cpu" ` +
|
||||||
|
`WHERE ("cpu" = 'cpu2' OR "cpu" = 'cpu3' AND "cpu" = 'cpu1') ` +
|
||||||
|
`AND $timeFilter ` +
|
||||||
|
`GROUP BY time($__interval), "cpu", "host" fill(none) ` +
|
||||||
|
`ORDER BY time DESC LIMIT 12 SLIMIT 23 tz('UTC')`
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@ -238,13 +252,14 @@ describe('InfluxDB query utils', () => {
|
|||||||
it('should handle minimal query', () => {
|
it('should handle minimal query', () => {
|
||||||
const query: InfluxQuery = {
|
const query: InfluxQuery = {
|
||||||
refId: 'A',
|
refId: 'A',
|
||||||
|
policy: 'autogen',
|
||||||
};
|
};
|
||||||
|
|
||||||
const queryClone = cloneDeep(query);
|
const queryClone = cloneDeep(query);
|
||||||
|
|
||||||
expect(normalizeQuery(query)).toStrictEqual({
|
expect(normalizeQuery(query)).toStrictEqual({
|
||||||
refId: 'A',
|
refId: 'A',
|
||||||
policy: 'default',
|
policy: 'autogen',
|
||||||
resultFormat: 'time_series',
|
resultFormat: 'time_series',
|
||||||
orderByTime: 'ASC',
|
orderByTime: 'ASC',
|
||||||
tags: [],
|
tags: [],
|
||||||
|
@ -18,8 +18,8 @@ export default class ResponseParser {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const normalizedQuery = query.toLowerCase();
|
const normalizedQuery = query.toLowerCase();
|
||||||
const isValueFirst =
|
const isRetentionPolicyQuery = normalizedQuery.indexOf('show retention policies') >= 0;
|
||||||
normalizedQuery.indexOf('show field keys') >= 0 || normalizedQuery.indexOf('show retention policies') >= 0;
|
const isValueFirst = normalizedQuery.indexOf('show field keys') >= 0 || isRetentionPolicyQuery;
|
||||||
|
|
||||||
const res = new Set<string>();
|
const res = new Set<string>();
|
||||||
each(influxResults.series, (serie) => {
|
each(influxResults.series, (serie) => {
|
||||||
@ -38,14 +38,27 @@ export default class ResponseParser {
|
|||||||
// (while the newer versions—first).
|
// (while the newer versions—first).
|
||||||
|
|
||||||
if (isValueFirst) {
|
if (isValueFirst) {
|
||||||
addUnique(res, value[0]);
|
// We want to know whether the given retention policy is the default one or not.
|
||||||
} else if (value[1] !== undefined) {
|
// If it is default policy then we should add it to the beginning.
|
||||||
addUnique(res, value[1]);
|
// The index 4 gives us if that policy is default or not.
|
||||||
|
// https://docs.influxdata.com/influxdb/v1.8/query_language/explore-schema/#show-retention-policies
|
||||||
|
// Only difference is v0.9. In that version we don't receive shardGroupDuration value.
|
||||||
|
// https://archive.docs.influxdata.com/influxdb/v0.9/query_language/schema_exploration/#show-retention-policies
|
||||||
|
// Since it is always the last value we will check that last value always.
|
||||||
|
if (isRetentionPolicyQuery && value[value.length - 1] === true) {
|
||||||
|
const newSetValues = [value[0].toString(), ...Array.from(res)];
|
||||||
|
res.clear();
|
||||||
|
newSetValues.forEach((sv) => res.add(sv));
|
||||||
} else {
|
} else {
|
||||||
addUnique(res, value[0]);
|
res.add(value[0].toString());
|
||||||
|
}
|
||||||
|
} else if (value[1] !== undefined) {
|
||||||
|
res.add(value[1].toString());
|
||||||
|
} else {
|
||||||
|
res.add(value[0].toString());
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
addUnique(res, value);
|
res.add(value.toString());
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@ -264,10 +277,6 @@ function incrementName(name: string, nameIncremenet: string, params: string[], i
|
|||||||
return nameIncremenet;
|
return nameIncremenet;
|
||||||
}
|
}
|
||||||
|
|
||||||
function addUnique(s: Set<string>, value: string | number) {
|
|
||||||
s.add(value.toString());
|
|
||||||
}
|
|
||||||
|
|
||||||
function rawQuerySelectedFieldsInDataframe(query: string | undefined, dfs: DataFrame[]) {
|
function rawQuerySelectedFieldsInDataframe(query: string | undefined, dfs: DataFrame[]) {
|
||||||
const names: Array<string | undefined> = dfs.map((df: DataFrame) => df.name);
|
const names: Array<string | undefined> = dfs.map((df: DataFrame) => df.name);
|
||||||
|
|
||||||
|
@ -11,13 +11,16 @@ describe('InfluxQuery', () => {
|
|||||||
{
|
{
|
||||||
refId: 'A',
|
refId: 'A',
|
||||||
measurement: 'cpu',
|
measurement: 'cpu',
|
||||||
|
policy: 'autogen',
|
||||||
},
|
},
|
||||||
templateSrv,
|
templateSrv,
|
||||||
{}
|
{}
|
||||||
);
|
);
|
||||||
|
|
||||||
const queryText = query.render();
|
const queryText = query.render();
|
||||||
expect(queryText).toBe('SELECT mean("value") FROM "cpu" WHERE $timeFilter GROUP BY time($__interval) fill(null)');
|
expect(queryText).toBe(
|
||||||
|
'SELECT mean("value") FROM "autogen"."cpu" WHERE $timeFilter GROUP BY time($__interval)' + ' fill(null)'
|
||||||
|
);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -46,6 +49,7 @@ describe('InfluxQuery', () => {
|
|||||||
{
|
{
|
||||||
refId: 'A',
|
refId: 'A',
|
||||||
measurement: 'cpu',
|
measurement: 'cpu',
|
||||||
|
policy: 'autogen',
|
||||||
select: [
|
select: [
|
||||||
[
|
[
|
||||||
{ type: 'field', params: ['value'] },
|
{ type: 'field', params: ['value'] },
|
||||||
@ -61,7 +65,7 @@ describe('InfluxQuery', () => {
|
|||||||
|
|
||||||
const queryText = query.render();
|
const queryText = query.render();
|
||||||
expect(queryText).toBe(
|
expect(queryText).toBe(
|
||||||
'SELECT mean("value") /100 AS "text" FROM "cpu" WHERE $timeFilter GROUP BY time($__interval) fill(null)'
|
'SELECT mean("value") /100 AS "text" FROM "autogen"."cpu" WHERE $timeFilter GROUP BY time($__interval) fill(null)'
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@ -72,6 +76,7 @@ describe('InfluxQuery', () => {
|
|||||||
{
|
{
|
||||||
refId: 'A',
|
refId: 'A',
|
||||||
measurement: 'cpu',
|
measurement: 'cpu',
|
||||||
|
policy: 'autogen',
|
||||||
groupBy: [{ type: 'time', params: ['auto'] }],
|
groupBy: [{ type: 'time', params: ['auto'] }],
|
||||||
tags: [{ key: 'hostname', value: 'server\\1' }],
|
tags: [{ key: 'hostname', value: 'server\\1' }],
|
||||||
},
|
},
|
||||||
@ -82,7 +87,7 @@ describe('InfluxQuery', () => {
|
|||||||
const queryText = query.render();
|
const queryText = query.render();
|
||||||
|
|
||||||
expect(queryText).toBe(
|
expect(queryText).toBe(
|
||||||
'SELECT mean("value") FROM "cpu" WHERE ("hostname" = \'server\\\\1\') AND $timeFilter' +
|
'SELECT mean("value") FROM "autogen"."cpu" WHERE ("hostname" = \'server\\\\1\') AND $timeFilter' +
|
||||||
' GROUP BY time($__interval)'
|
' GROUP BY time($__interval)'
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
@ -92,6 +97,7 @@ describe('InfluxQuery', () => {
|
|||||||
{
|
{
|
||||||
refId: 'A',
|
refId: 'A',
|
||||||
measurement: 'cpu',
|
measurement: 'cpu',
|
||||||
|
policy: 'autogen',
|
||||||
groupBy: [{ type: 'time', params: ['auto'] }],
|
groupBy: [{ type: 'time', params: ['auto'] }],
|
||||||
tags: [{ key: 'app', value: '/e.*/' }],
|
tags: [{ key: 'app', value: '/e.*/' }],
|
||||||
},
|
},
|
||||||
@ -101,7 +107,7 @@ describe('InfluxQuery', () => {
|
|||||||
|
|
||||||
const queryText = query.render();
|
const queryText = query.render();
|
||||||
expect(queryText).toBe(
|
expect(queryText).toBe(
|
||||||
'SELECT mean("value") FROM "cpu" WHERE ("app" =~ /e.*/) AND $timeFilter GROUP BY time($__interval)'
|
'SELECT mean("value") FROM "autogen"."cpu" WHERE ("app" =~ /e.*/) AND $timeFilter GROUP BY time($__interval)'
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@ -112,6 +118,7 @@ describe('InfluxQuery', () => {
|
|||||||
{
|
{
|
||||||
refId: 'A',
|
refId: 'A',
|
||||||
measurement: 'cpu',
|
measurement: 'cpu',
|
||||||
|
policy: 'autogen',
|
||||||
groupBy: [{ type: 'time', params: ['auto'] }],
|
groupBy: [{ type: 'time', params: ['auto'] }],
|
||||||
tags: [
|
tags: [
|
||||||
{ key: 'hostname', value: 'server1' },
|
{ key: 'hostname', value: 'server1' },
|
||||||
@ -124,7 +131,7 @@ describe('InfluxQuery', () => {
|
|||||||
|
|
||||||
const queryText = query.render();
|
const queryText = query.render();
|
||||||
expect(queryText).toBe(
|
expect(queryText).toBe(
|
||||||
'SELECT mean("value") FROM "cpu" WHERE ("hostname" = \'server1\' AND "app" = \'email\') AND ' +
|
'SELECT mean("value") FROM "autogen"."cpu" WHERE ("hostname" = \'server1\' AND "app" = \'email\') AND ' +
|
||||||
'$timeFilter GROUP BY time($__interval)'
|
'$timeFilter GROUP BY time($__interval)'
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
@ -136,6 +143,7 @@ describe('InfluxQuery', () => {
|
|||||||
{
|
{
|
||||||
refId: 'A',
|
refId: 'A',
|
||||||
measurement: 'cpu',
|
measurement: 'cpu',
|
||||||
|
policy: 'autogen',
|
||||||
groupBy: [{ type: 'time', params: ['auto'] }],
|
groupBy: [{ type: 'time', params: ['auto'] }],
|
||||||
tags: [
|
tags: [
|
||||||
{ key: 'hostname', value: 'server1' },
|
{ key: 'hostname', value: 'server1' },
|
||||||
@ -148,7 +156,7 @@ describe('InfluxQuery', () => {
|
|||||||
|
|
||||||
const queryText = query.render();
|
const queryText = query.render();
|
||||||
expect(queryText).toBe(
|
expect(queryText).toBe(
|
||||||
'SELECT mean("value") FROM "cpu" WHERE ("hostname" = \'server1\' OR "hostname" = \'server2\') AND ' +
|
'SELECT mean("value") FROM "autogen"."cpu" WHERE ("hostname" = \'server1\' OR "hostname" = \'server2\') AND ' +
|
||||||
'$timeFilter GROUP BY time($__interval)'
|
'$timeFilter GROUP BY time($__interval)'
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
@ -160,6 +168,7 @@ describe('InfluxQuery', () => {
|
|||||||
{
|
{
|
||||||
refId: 'A',
|
refId: 'A',
|
||||||
measurement: 'cpu',
|
measurement: 'cpu',
|
||||||
|
policy: 'autogen',
|
||||||
groupBy: [{ type: 'time', params: ['auto'] }],
|
groupBy: [{ type: 'time', params: ['auto'] }],
|
||||||
tags: [
|
tags: [
|
||||||
{ key: 'name', value: "Let's encrypt." },
|
{ key: 'name', value: "Let's encrypt." },
|
||||||
@ -172,7 +181,7 @@ describe('InfluxQuery', () => {
|
|||||||
|
|
||||||
const queryText = query.render();
|
const queryText = query.render();
|
||||||
expect(queryText).toBe(
|
expect(queryText).toBe(
|
||||||
'SELECT mean("value") FROM "cpu" WHERE ("name" = \'Let\\\'s encrypt.\' OR "hostname" = \'server2\') AND ' +
|
'SELECT mean("value") FROM "autogen"."cpu" WHERE ("name" = \'Let\\\'s encrypt.\' OR "hostname" = \'server2\') AND ' +
|
||||||
'$timeFilter GROUP BY time($__interval)'
|
'$timeFilter GROUP BY time($__interval)'
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
@ -184,6 +193,7 @@ describe('InfluxQuery', () => {
|
|||||||
{
|
{
|
||||||
refId: 'A',
|
refId: 'A',
|
||||||
measurement: 'cpu',
|
measurement: 'cpu',
|
||||||
|
policy: 'autogen',
|
||||||
groupBy: [],
|
groupBy: [],
|
||||||
tags: [{ key: 'value', value: '5', operator: '>' }],
|
tags: [{ key: 'value', value: '5', operator: '>' }],
|
||||||
},
|
},
|
||||||
@ -192,7 +202,7 @@ describe('InfluxQuery', () => {
|
|||||||
);
|
);
|
||||||
|
|
||||||
const queryText = query.render();
|
const queryText = query.render();
|
||||||
expect(queryText).toBe('SELECT mean("value") FROM "cpu" WHERE ("value" > 5) AND $timeFilter');
|
expect(queryText).toBe('SELECT mean("value") FROM "autogen"."cpu" WHERE ("value" > 5) AND $timeFilter');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -202,6 +212,7 @@ describe('InfluxQuery', () => {
|
|||||||
{
|
{
|
||||||
refId: 'A',
|
refId: 'A',
|
||||||
measurement: 'cpu',
|
measurement: 'cpu',
|
||||||
|
policy: 'autogen',
|
||||||
tags: [],
|
tags: [],
|
||||||
groupBy: [
|
groupBy: [
|
||||||
{ type: 'time', interval: 'auto' },
|
{ type: 'time', interval: 'auto' },
|
||||||
@ -213,7 +224,9 @@ describe('InfluxQuery', () => {
|
|||||||
);
|
);
|
||||||
|
|
||||||
const queryText = query.render();
|
const queryText = query.render();
|
||||||
expect(queryText).toBe('SELECT mean("value") FROM "cpu" WHERE $timeFilter GROUP BY time($__interval), "host"');
|
expect(queryText).toBe(
|
||||||
|
'SELECT mean("value") FROM "autogen"."cpu" WHERE $timeFilter GROUP BY time($__interval), "host"'
|
||||||
|
);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -223,6 +236,7 @@ describe('InfluxQuery', () => {
|
|||||||
{
|
{
|
||||||
refId: 'A',
|
refId: 'A',
|
||||||
measurement: 'cpu',
|
measurement: 'cpu',
|
||||||
|
policy: 'autogen',
|
||||||
select: [[{ type: 'field', params: ['value'] }]],
|
select: [[{ type: 'field', params: ['value'] }]],
|
||||||
groupBy: [],
|
groupBy: [],
|
||||||
},
|
},
|
||||||
@ -230,7 +244,7 @@ describe('InfluxQuery', () => {
|
|||||||
{}
|
{}
|
||||||
);
|
);
|
||||||
const queryText = query.render();
|
const queryText = query.render();
|
||||||
expect(queryText).toBe('SELECT "value" FROM "cpu" WHERE $timeFilter');
|
expect(queryText).toBe('SELECT "value" FROM "autogen"."cpu" WHERE $timeFilter');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -240,6 +254,7 @@ describe('InfluxQuery', () => {
|
|||||||
{
|
{
|
||||||
refId: 'A',
|
refId: 'A',
|
||||||
measurement: 'cpu',
|
measurement: 'cpu',
|
||||||
|
policy: 'autogen',
|
||||||
select: [[{ type: 'field', params: ['value'] }]],
|
select: [[{ type: 'field', params: ['value'] }]],
|
||||||
groupBy: [{ type: 'time' }, { type: 'fill', params: ['0'] }],
|
groupBy: [{ type: 'time' }, { type: 'fill', params: ['0'] }],
|
||||||
},
|
},
|
||||||
@ -247,7 +262,9 @@ describe('InfluxQuery', () => {
|
|||||||
{}
|
{}
|
||||||
);
|
);
|
||||||
const queryText = query.render();
|
const queryText = query.render();
|
||||||
expect(queryText).toBe('SELECT "value" FROM "cpu" WHERE $timeFilter GROUP BY time($__interval) fill(0)');
|
expect(queryText).toBe(
|
||||||
|
'SELECT "value" FROM "autogen"."cpu" WHERE $timeFilter GROUP BY time($__interval) fill(0)'
|
||||||
|
);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -257,6 +274,7 @@ describe('InfluxQuery', () => {
|
|||||||
{
|
{
|
||||||
refId: 'A',
|
refId: 'A',
|
||||||
measurement: 'cpu',
|
measurement: 'cpu',
|
||||||
|
policy: 'autogen',
|
||||||
groupBy: [{ type: 'time' }, { type: 'fill' }],
|
groupBy: [{ type: 'time' }, { type: 'fill' }],
|
||||||
},
|
},
|
||||||
templateSrv,
|
templateSrv,
|
||||||
|
Loading…
Reference in New Issue
Block a user