diff --git a/CHANGELOG.md b/CHANGELOG.md index 592ad07795..a31e4066de 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,7 @@ 1. [#6103](https://github.com/influxdata/chronograf/pull/6103): Set active database for InfluxQL meta queries. 2. [#6105](https://github.com/influxdata/chronograf/pull/6105): Prevent dangerous InfluxQL statements from auto-execution. 3. [#6111](https://github.com/influxdata/chronograf/pull/6111): Loading Hosts page for large number of hosts. +4. [#6116](https://github.com/influxdata/chronograf/pull/6116): Showing tag values in Flux query builder connected to InfluxDB Enterprise. ### Other diff --git a/ui/src/shared/components/TimeMachine/fluxQueryBuilder/apis/fluxQueries.ts b/ui/src/shared/components/TimeMachine/fluxQueryBuilder/apis/fluxQueries.ts index 96fb4d1b41..5daf58e116 100644 --- a/ui/src/shared/components/TimeMachine/fluxQueryBuilder/apis/fluxQueries.ts +++ b/ui/src/shared/components/TimeMachine/fluxQueryBuilder/apis/fluxQueries.ts @@ -82,18 +82,16 @@ export interface FindValuesOptions { limit?: number } -export function findValues({ - source, - bucket, - tagsSelections, - key, - searchTerm = '', - timeRange = DEFAULT_TIME_RANGE, - limit = FQB_RESULTS_LIMIT, -}: FindValuesOptions): CancelBox> { - const tagFilter = formatTagFilter(tagsSelections) - const timeRangeArguments = rangeArguments(timeRange) - +export function createValuesQuery( + searchTerm: string, + dbVersion: string, + tagsSelections: BuilderTagsType[], + bucket: string, + timeRangeArguments: string, + tagFilter: string, + key: string, + limit: number +) { // requires Flux package to work which we will put in the query const searchFilter = !searchTerm ? '' @@ -103,8 +101,9 @@ export function findValues({ // 1.x InfluxDB produce wrong results when _field tag is filtered, // experiments showed that keeping an extra column is a workaround + const version = dbVersion || '' const v1ExtraKeep = - (source.version || '').startsWith('1.') && + (version.startsWith('1.') || version === 'ENT') && tagsSelections.some(x => x.tagKey === '_field' && x.tagValues?.length) ? ', "_field"' : '' @@ -118,6 +117,30 @@ from(bucket: ${fluxString(bucket)}) |> distinct(column: ${fluxString(key)})${searchFilter} |> sort() |> limit(n: ${limit})` + return query +} + +export function findValues({ + source, + bucket, + tagsSelections, + key, + searchTerm = '', + timeRange = DEFAULT_TIME_RANGE, + limit = FQB_RESULTS_LIMIT, +}: FindValuesOptions): CancelBox> { + const tagFilter = formatTagFilter(tagsSelections) + const timeRangeArguments = rangeArguments(timeRange) + const query = createValuesQuery( + searchTerm, + source.version, + tagsSelections, + bucket, + timeRangeArguments, + tagFilter, + key, + limit + ) return extractBoxedCol(runQuery(source, query), '_value', limit) } diff --git a/ui/test/flux/components/fluxQueries.test.ts b/ui/test/flux/components/fluxQueries.test.ts new file mode 100644 index 0000000000..d7d6083215 --- /dev/null +++ b/ui/test/flux/components/fluxQueries.test.ts @@ -0,0 +1,140 @@ +import {createValuesQuery} from 'src/shared/components/TimeMachine/fluxQueryBuilder/apis/fluxQueries' +import {BuilderTagsType} from 'src/shared/components/TimeMachine/fluxQueryBuilder/types' + +describe('createQuery', () => { + ;[ + { + name: 'query for v1 with no _field', + searchTerm: '', + dbVersion: '1.11.0', + tagsSelections: [ + { + tagKey: '_measurement', + tagValues: ['win_cpu'], + }, + ] as BuilderTagsType[], + bucket: 'telegraf', + timeRangeArguments: 'start: -6h', + tagFilter: '\n |> filter(fn: (r) => (r["_measurement"] == "win_cpu"))', + key: '_measurement', + limit: 200, + query: `import "regexp" + +from(bucket: "telegraf") + |> range(start: -6h) + |> filter(fn: (r) => (r["_measurement"] == "win_cpu")) + |> keep(columns: ["_measurement"]) + |> group() + |> distinct(column: "_measurement") + |> sort() + |> limit(n: 200)`, + }, + { + name: 'query for v1 with _field', + searchTerm: '', + dbVersion: '1.11.0', + tagsSelections: [ + { + tagKey: '_measurement', + tagValues: ['win_cpu'], + }, + { + tagKey: '_field', + tagValues: ['Percent_Idle_Time'], + }, + ] as BuilderTagsType[], + bucket: 'telegraf', + timeRangeArguments: 'start: -1h', + tagFilter: + '\n |> filter(fn: (r) => (r["_measurement"] == "win_cpu") and (r["_field"] == "Percent_Idle_Time"))', + key: 'host', + limit: 200, + query: `import "regexp" + +from(bucket: "telegraf") + |> range(start: -1h) + |> filter(fn: (r) => (r["_measurement"] == "win_cpu") and (r["_field"] == "Percent_Idle_Time")) + |> keep(columns: ["host", "_field"]) + |> group() + |> distinct(column: "host") + |> sort() + |> limit(n: 200)`, + }, + { + name: 'query for ENT with _field', + searchTerm: '', + dbVersion: 'ENT', + tagsSelections: [ + { + tagKey: '_measurement', + tagValues: ['win_cpu'], + }, + { + tagKey: '_field', + tagValues: ['Percent_Idle_Time'], + }, + ] as BuilderTagsType[], + bucket: 'telegraf', + timeRangeArguments: 'start: -1h', + tagFilter: + '\n |> filter(fn: (r) => (r["_measurement"] == "win_cpu") and (r["_field"] == "Percent_Idle_Time"))', + key: 'host', + limit: 200, + query: `import "regexp" + +from(bucket: "telegraf") + |> range(start: -1h) + |> filter(fn: (r) => (r["_measurement"] == "win_cpu") and (r["_field"] == "Percent_Idle_Time")) + |> keep(columns: ["host", "_field"]) + |> group() + |> distinct(column: "host") + |> sort() + |> limit(n: 200)`, + }, + { + name: 'query for v2 w/o _field', + searchTerm: '', + dbVersion: '2.7.0', + tagsSelections: [ + { + tagKey: '_measurement', + tagValues: ['win_cpu'], + }, + { + tagKey: '_field', + tagValues: ['Percent_Idle_Time'], + }, + ] as BuilderTagsType[], + bucket: 'telegraf', + timeRangeArguments: 'start: -1h', + tagFilter: + '\n |> filter(fn: (r) => (r["_measurement"] == "win_cpu") and (r["_field"] == "Percent_Idle_Time"))', + key: 'host', + limit: 100, + query: `import "regexp" + +from(bucket: "telegraf") + |> range(start: -1h) + |> filter(fn: (r) => (r["_measurement"] == "win_cpu") and (r["_field"] == "Percent_Idle_Time")) + |> keep(columns: ["host"]) + |> group() + |> distinct(column: "host") + |> sort() + |> limit(n: 100)`, + }, + ].forEach(x => { + it('creates a query ' + x.name, () => { + const query = createValuesQuery( + x.searchTerm, + x.dbVersion, + x.tagsSelections, + x.bucket, + x.timeRangeArguments, + x.tagFilter, + x.key, + x.limit + ) + expect(query).toEqual(x.query) + }) + }) +})