@grafana/runtime
Version:
Grafana Runtime Library
1 lines • 12.3 kB
Source Map (JSON)
{"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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"}