Skip to content

Commit

Permalink
Surface errors appearing within Flux tables
Browse files Browse the repository at this point in the history
  • Loading branch information
chnn committed Mar 22, 2019
1 parent f281ee9 commit 8b98cd0
Show file tree
Hide file tree
Showing 6 changed files with 97 additions and 2 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
1. [12706](https://github.com/influxdata/influxdb/pull/12706): Add ability to add variable to script from the side menu.
1. [12791](https://github.com/influxdata/influxdb/pull/12791): Use time range for metaqueries in Data Explorer and Cell Editor Overlay
1. [12827](https://github.com/influxdata/influxdb/pull/12827): Fix screen tearing bug in Raw Data View
1. [12826](https://github.com/influxdata/influxdb/pull/12826): Enable copying error messages to the clipboard from dashboard cells

### Bug Fixes

Expand Down
7 changes: 6 additions & 1 deletion ui/src/shared/components/EmptyGraphError.scss
Original file line number Diff line number Diff line change
Expand Up @@ -23,4 +23,9 @@
top: $ix-marg-b;
right: $ix-marg-b;
opacity: 0.9;
}
display: none;

.empty-graph-error:hover & {
display: inherit;
}
}
3 changes: 3 additions & 0 deletions ui/src/shared/components/TimeSeries.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import {
// Utils
import {parseResponse} from 'src/shared/parsing/flux/response'
import {getActiveOrg} from 'src/organizations/selectors'
import {checkQueryResult} from 'src/shared/utils/checkQueryResult'

// Types
import {RemoteDataState, FluxTable} from 'src/types'
Expand Down Expand Up @@ -137,6 +138,8 @@ class TimeSeries extends Component<Props, State> {
const tables = flatten(results.map(r => parseResponse(r.csv)))
const files = results.map(r => r.csv)

files.forEach(checkQueryResult)

this.setState({
tables,
files,
Expand Down
28 changes: 28 additions & 0 deletions ui/src/shared/utils/checkQueryResult.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import {checkQueryResult} from 'src/shared/utils/checkQueryResult'

describe('checkQueryResult', () => {
test('throws an error when the response has an error table', () => {
const RESPONSE = `#group,true,true
#datatype,string,string
#default,,
,error,reference
,"function references unknown column ""_value""",`

expect(() => {
checkQueryResult(RESPONSE)
}).toThrow('function references unknown column')
})

test('does not throw an error when the response is valid', () => {
const RESPONSE = `#group,false,false,true,true,false,false,true,true,true
#datatype,string,long,dateTime:RFC3339,dateTime:RFC3339,dateTime:RFC3339,long,string,string,string
#default,_result,,,,,,,,
,result,table,_start,_stop,_time,_value,_measurement,host,_field
,,0,2019-03-21T18:54:14.113478Z,2019-03-21T19:54:14.113478Z,2019-03-21T18:54:21Z,4780101632,mem,oox4k.local,active
,,0,2019-03-21T18:54:14.113478Z,2019-03-21T19:54:14.113478Z,2019-03-21T18:54:31Z,5095436288,mem,oox4k.local,active`

expect(() => {
checkQueryResult(RESPONSE)
}).not.toThrow()
})
})
56 changes: 56 additions & 0 deletions ui/src/shared/utils/checkQueryResult.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
/*
Given Flux query response as a CSV, check if the CSV contains an error table
as the first result. If it does, throw the error message contained within
that table.
For example, given the following response:
#datatype,string,long
,error,reference
,Failed to parse query,897
we want to throw an error with the message "Failed to parse query".
See https://github.com/influxdata/flux/blob/master/docs/SPEC.md#errors.
*/
export const checkQueryResult = (file: string): void => {
// Don't check the whole file, since it could be huge and the error table
// will be within the first few lines (if it exists)
const fileHead = file.slice(0, findNthIndex(file, '\n', 6))

const lines = fileHead.split('\n').filter(line => !line.startsWith('#'))

if (!lines.length || !lines[0].includes('error') || !lines[1]) {
return
}

const header = lines[0].split(',').map(s => s.trim())
const row = lines[1].split(',').map(s => s.trim())
const index = header.indexOf('error')

if (index === -1 || !row[index]) {
return
}

// Trim off extra quotes at start and end of message
const errorMessage = row[index].replace(/^"/, '').replace(/"$/, '')

throw new Error(errorMessage)
}

const findNthIndex = (s: string, c: string, n: number) => {
let count = 0
let i = 0

while (i < s.length) {
if (s[i] == c) {
count += 1
}

if (count === n) {
return i
}

i += 1
}
}
4 changes: 3 additions & 1 deletion ui/src/timeMachine/actions/queries.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import {getActiveOrg} from 'src/organizations/selectors'
import {getVariableAssignments} from 'src/variables/selectors'
import {getTimeRangeVars} from 'src/variables/utils/getTimeRangeVars'
import {filterUnusedVars} from 'src/shared/utils/filterUnusedVars'
import {checkQueryResult} from 'src/shared/utils/checkQueryResult'
import {
getVariablesForOrg,
getVariable,
Expand Down Expand Up @@ -113,9 +114,10 @@ export const executeQueries = () => async (dispatch, getState: GetState) => {
const results = await Promise.all(pendingResults.map(r => r.promise))

const duration = Date.now() - startTime

const files = results.map(r => r.csv)

files.forEach(checkQueryResult)

dispatch(setQueryResults(RemoteDataState.Done, files, duration))
} catch (e) {
if (e instanceof CancellationError) {
Expand Down

0 comments on commit 8b98cd0

Please sign in to comment.