Merge pull request #4615 from influxdata/flux/show-errors

Show errors instead of 'No Results' when error occurs
remember-threesizer
Iris Scholten 2018-10-19 10:17:32 -07:00 committed by GitHub
commit 5eba55af1e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 55 additions and 10 deletions

View File

@ -51,6 +51,7 @@ export const getAST = async (request: ASTRequest) => {
export interface GetRawTimeSeriesResult {
didTruncate: boolean
csv: string
ok: boolean
uuid?: string
}
@ -74,15 +75,17 @@ export const getRawTimeSeries = async (
)
try {
const {body, byteLength, uuid: responseUUID} = await manager.fetchFluxData(
url,
renderedScript,
uuid
)
const {
body,
byteLength,
ok,
uuid: responseUUID,
} = await manager.fetchFluxData(url, renderedScript, uuid)
return {
csv: body,
didTruncate: byteLength >= MAX_RESPONSE_BYTES,
ok,
uuid: responseUUID,
}
} catch (error) {
@ -112,7 +115,7 @@ export const getTimeSeries = async (
fluxASTLink: string,
maxSideLength: number
): Promise<GetTimeSeriesResult> => {
const {csv, didTruncate, uuid: responseUUID} = await getRawTimeSeries(
const {csv, didTruncate, ok, uuid: responseUUID} = await getRawTimeSeries(
source,
script,
uuid,
@ -121,6 +124,12 @@ export const getTimeSeries = async (
maxSideLength
)
if (!ok) {
// error will be string of {error: value}
const error = _.get(JSON.parse(csv), 'error', '')
throw new Error(error)
}
const tables = parseResponse(csv)
try {
@ -136,7 +145,6 @@ export const getTimeSeries = async (
console.error('Could not parse response body', error)
return {
// REVIEW: Why is this being returned as a `FluxTable[]`?
csv,
tables: parseResponseError(csv),
didTruncate: false,

View File

@ -15,6 +15,7 @@ import RawFluxDataTable from 'src/shared/components/TimeMachine/RawFluxDataTable
import TableGraphTransform from 'src/shared/components/TableGraphTransform'
import TableGraphFormat from 'src/shared/components/TableGraphFormat'
import AutoRefresh from 'src/shared/components/AutoRefresh'
import InvalidData from 'src/shared/components/InvalidData'
// Constants
import {emptyGraphCopy} from 'src/shared/copy/cell'
@ -166,6 +167,7 @@ class RefreshingGraph extends Component<Props> {
rawFluxData,
loading,
uuid,
errorMessage,
}) => {
const hasValues =
timeSeriesFlux.length ||
@ -180,6 +182,9 @@ class RefreshingGraph extends Component<Props> {
})
if (!hasValues) {
if (errorMessage) {
return <InvalidData message={errorMessage} />
}
if (cellNoteVisibility === NoteVisibility.ShowWhenNoData) {
return <MarkdownCell text={cellNote} />
}

View File

@ -41,6 +41,7 @@ interface RenderProps {
rawFluxData: string
loading: RemoteDataState
uuid: string
errorMessage: string
}
interface Props {
@ -66,6 +67,7 @@ interface State {
timeSeriesInfluxQL: TimeSeriesServerResponse[]
timeSeriesFlux: FluxTable[]
latestUUID: string
errorMessage: string
}
const TEMP_RES = 300 // FIXME
@ -118,6 +120,7 @@ class TimeSeries extends PureComponent<Props, State> {
timeSeriesFlux: [],
rawFluxData: '',
latestUUID: null,
errorMessage: '',
}
}
@ -147,6 +150,7 @@ class TimeSeries extends PureComponent<Props, State> {
loading,
isFirstFetch,
latestUUID,
errorMessage,
} = this.state
if (isFirstFetch && loading === RemoteDataState.Loading) {
@ -162,6 +166,7 @@ class TimeSeries extends PureComponent<Props, State> {
rawFluxData,
loading,
uuid: latestUUID,
errorMessage,
})}
</>
)
@ -222,6 +227,8 @@ class TimeSeries extends PureComponent<Props, State> {
isFirstFetch: false,
})
let errorMessage = ''
try {
if (this.isFluxQuery) {
const results = await this.executeFluxQuery(latestUUID)
@ -235,8 +242,9 @@ class TimeSeries extends PureComponent<Props, State> {
}
loading = RemoteDataState.Done
} catch {
} catch (err) {
loading = RemoteDataState.Error
errorMessage = err.toString()
}
this.setState({
@ -245,6 +253,7 @@ class TimeSeries extends PureComponent<Props, State> {
rawFluxData,
loading,
latestUUID: responseUUID,
errorMessage,
})
if (grabDataForDownload) {

View File

@ -64,6 +64,11 @@ export const parseTables = (responseChunk: string): FluxTable[] => {
const nonAnnotationData = Papa.parse(nonAnnotationLines).data
const annotationData = Papa.parse(annotationLines).data
const headerRow: string[] = nonAnnotationData[0]
if (headerRow[1] === 'error' && headerRow[2] === 'reference') {
throw new Error(_.get(nonAnnotationData, '1.1'))
}
const tableColIndex = headerRow.findIndex(h => h === 'table')
const timeColIndex = headerRow.findIndex(h => h === '_time')

View File

@ -22,6 +22,7 @@ import {LastValues} from 'src/worker/jobs/fluxTablesToSingleStat'
interface DecodeFluxRespWithLimitResult {
body: string
byteLength: number
ok: boolean
uuid?: string
}

View File

@ -5,6 +5,7 @@ import {MAX_RESPONSE_BYTES} from 'src/flux/constants'
interface DecodeFluxRespWithLimitResult {
body: string
byteLength: number
ok: boolean
uuid?: string
}
@ -42,7 +43,7 @@ export default async (msg: Message): Promise<DecodeFluxRespWithLimitResult> => {
reader.cancel()
return {body: bodyString, byteLength: bytesRead, uuid}
return {body: bodyString, byteLength: bytesRead, ok: response.ok, uuid}
} else {
bodyString += currentText
}
@ -52,5 +53,5 @@ export default async (msg: Message): Promise<DecodeFluxRespWithLimitResult> => {
reader.cancel()
return {body: bodyString, byteLength: bytesRead, uuid}
return {body: bodyString, byteLength: bytesRead, ok: response.ok, uuid}
}

View File

@ -184,3 +184,11 @@ export const TRUNCATED_RESPONSE = `
#datatype,string,long,dateTime:RFC3339,dateTime:RFC3339,dateTime:RFC3339,long,string,string,string,string,string,string,string
#group,false,false,false,false,false,false,true,true,true,true,true,true,true
#default,_result,,,,,,,,,,,,`
export const ERROR =
'failed to create physical plan: invalid time bounds from procedure from: bounds contain zero time'
export const ERROR_RESPONSE = `#datatype,string,string
#group,true,true
#default,,
,error,reference
,${ERROR}`

View File

@ -5,6 +5,8 @@ import {
MULTI_SCHEMA_RESPONSE,
EXPECTED_COLUMNS,
TRUNCATED_RESPONSE,
ERROR_RESPONSE,
ERROR,
} from 'test/shared/parsing/flux/constants'
describe('Flux results parser', () => {
@ -46,4 +48,10 @@ describe('Flux results parser', () => {
expect(actual).toHaveLength(2)
})
})
describe('error responses', () => {
it('should throw an error if an error csv ', () => {
expect(() => parseResponse(ERROR_RESPONSE)).toThrowError(ERROR)
})
})
})