UNPKG

@grafana/runtime

Version:
1 lines 11.2 kB
{"version":3,"file":"queryResponse.mjs","sources":["../../../src/utils/queryResponse.ts"],"sourcesContent":["import {\n DataQueryResponse,\n KeyValue,\n LoadingState,\n DataQueryError,\n TimeSeries,\n TableData,\n toDataFrame,\n DataFrame,\n MetricFindValue,\n FieldType,\n DataQuery,\n DataFrameJSON,\n dataFrameFromJSON,\n QueryResultMetaNotice,\n} from '@grafana/data';\n\nimport { FetchError, FetchResponse } from '../services';\n\nimport { HealthCheckResultDetails } from './DataSourceWithBackend';\nimport { toDataQueryError } from './toDataQueryError';\n\nexport const cachedResponseNotice: QueryResultMetaNotice = { severity: 'info', text: 'Cached response' };\n\n/**\n * Single response object from a backend data source. Properties are optional but response should contain at least\n * an error or a some data (but can contain both). Main way to send data is with dataframes attribute as series and\n * tables data attributes are legacy formats.\n *\n * @internal\n */\nexport interface DataResponse {\n error?: string;\n refId?: string;\n frames?: DataFrameJSON[];\n status?: number;\n\n // Legacy TSDB format...\n series?: TimeSeries[];\n tables?: TableData[];\n}\n\n/**\n * This is the type of response expected form backend datasource.\n *\n * @internal\n */\nexport interface BackendDataSourceResponse {\n results: KeyValue<DataResponse>;\n}\n\n/**\n * Parse the results from /api/ds/query into a DataQueryResponse\n *\n * @param res - the HTTP response data.\n * @param queries - optional DataQuery array that will order the response based on the order of query refId's.\n *\n * @public\n */\nexport function toDataQueryResponse(\n res:\n | { data: BackendDataSourceResponse | undefined }\n | FetchResponse<BackendDataSourceResponse | undefined>\n | DataQueryError,\n queries?: DataQuery[]\n): DataQueryResponse {\n const rsp: DataQueryResponse = { data: [], state: LoadingState.Done };\n\n const traceId = 'traceId' in res ? res.traceId : undefined;\n\n if (traceId != null) {\n rsp.traceIds = [traceId];\n }\n\n // If the response isn't in a correct shape we just ignore the data and pass empty DataQueryResponse.\n const fetchResponse = res as FetchResponse;\n if (fetchResponse.data?.results) {\n const results = fetchResponse.data.results;\n const refIDs = queries?.length ? queries.map((q) => q.refId) : Object.keys(results);\n const cachedResponse = isCachedResponse(fetchResponse);\n const data: DataResponse[] = [];\n\n for (const refId of refIDs) {\n const dr = results[refId];\n if (!dr) {\n continue;\n }\n dr.refId = refId;\n data.push(dr);\n }\n\n for (const dr of data) {\n if (dr.error) {\n const errorObj: DataQueryError = {\n refId: dr.refId,\n message: dr.error,\n status: dr.status,\n };\n if (traceId != null) {\n errorObj.traceId = traceId;\n }\n if (!rsp.error) {\n rsp.error = { ...errorObj };\n }\n if (rsp.errors) {\n rsp.errors.push({ ...errorObj });\n } else {\n rsp.errors = [{ ...errorObj }];\n }\n rsp.state = LoadingState.Error;\n }\n\n if (dr.frames?.length) {\n for (let js of dr.frames) {\n if (cachedResponse) {\n js = addCacheNotice(js);\n }\n const df = dataFrameFromJSON(js);\n if (!df.refId) {\n df.refId = dr.refId;\n }\n rsp.data.push(df);\n }\n continue; // the other tests are legacy\n }\n\n if (dr.series?.length) {\n for (const s of dr.series) {\n if (!s.refId) {\n s.refId = dr.refId;\n }\n rsp.data.push(toDataFrame(s));\n }\n }\n\n if (dr.tables?.length) {\n for (const s of dr.tables) {\n if (!s.refId) {\n s.refId = dr.refId;\n }\n rsp.data.push(toDataFrame(s));\n }\n }\n }\n }\n\n // When it is not an OK response, make sure the error gets added\n if (fetchResponse.status && fetchResponse.status !== 200) {\n if (rsp.state !== LoadingState.Error) {\n rsp.state = LoadingState.Error;\n }\n if (!rsp.error) {\n rsp.error = toDataQueryError(res);\n }\n }\n\n return rsp;\n}\n\nfunction isCachedResponse(res: FetchResponse<BackendDataSourceResponse | undefined>): boolean {\n const headers = res?.headers;\n if (!headers || !headers.get) {\n return false;\n }\n return headers.get('X-Cache') === 'HIT';\n}\n\nfunction addCacheNotice(frame: DataFrameJSON): DataFrameJSON {\n return {\n ...frame,\n schema: {\n ...frame.schema,\n fields: [...(frame.schema?.fields ?? [])],\n meta: {\n ...frame.schema?.meta,\n notices: [...(frame.schema?.meta?.notices ?? []), cachedResponseNotice],\n isCachedResponse: true,\n },\n },\n };\n}\n\nexport interface TestingStatus {\n message?: string | null;\n status?: string | null;\n details?: HealthCheckResultDetails;\n}\n\n/**\n * Data sources using api/ds/query to test data sources can use this function to\n * handle errors and convert them to TestingStatus object.\n *\n * If possible, this should be avoided in favor of implementing /health endpoint\n * and testing data source with DataSourceWithBackend.testDataSource()\n *\n * Re-thrown errors are handled by testDataSource() in public/app/features/datasources/state/actions.ts\n *\n * @returns {TestingStatus}\n */\nexport function toTestingStatus(err: FetchError): TestingStatus {\n const queryResponse = toDataQueryResponse(err);\n // POST api/ds/query errors returned as { message: string, error: string } objects\n if (queryResponse.error?.data?.message) {\n return {\n status: 'error',\n message: queryResponse.error.data.message,\n details: queryResponse.error?.data?.error ? { message: queryResponse.error.data.error } : undefined,\n };\n }\n // POST api/ds/query errors returned in results object\n else if (queryResponse.error?.refId && queryResponse.error?.message) {\n return {\n status: 'error',\n message: queryResponse.error.message,\n };\n }\n\n throw err;\n}\n\n/**\n * Return the first string or non-time field as the value\n *\n * @beta\n */\nexport function frameToMetricFindValue(frame: DataFrame): MetricFindValue[] {\n if (!frame || !frame.length) {\n return [];\n }\n\n const values: MetricFindValue[] = [];\n let field = frame.fields.find((f) => f.type === FieldType.string);\n if (!field) {\n field = frame.fields.find((f) => f.type !== FieldType.time);\n }\n if (field) {\n for (let i = 0; i < field.values.length; i++) {\n values.push({ text: '' + field.values[i] });\n }\n }\n return values;\n}\n"],"names":[],"mappings":"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"}