From ea375db8b23a04a2317a78801cd1fab7208fcd2b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=A1bor=20Farkas?= Date: Tue, 20 Jul 2021 10:52:36 +0200 Subject: [PATCH] influxdb: influxql: for timeseries-queries, return dataframes (#36850) --- .../plugins/datasource/influxdb/datasource.ts | 74 ++++++++++++++++++- 1 file changed, 73 insertions(+), 1 deletion(-) diff --git a/public/app/plugins/datasource/influxdb/datasource.ts b/public/app/plugins/datasource/influxdb/datasource.ts index e1c27768937..ac0c1720894 100644 --- a/public/app/plugins/datasource/influxdb/datasource.ts +++ b/public/app/plugins/datasource/influxdb/datasource.ts @@ -13,6 +13,12 @@ import { AnnotationQueryRequest, AnnotationEvent, DataQueryError, + DataFrame, + TimeSeries, + TIME_SERIES_TIME_FIELD_NAME, + TIME_SERIES_VALUE_FIELD_NAME, + FieldType, + ArrayVector, } from '@grafana/data'; import { v4 as uuidv4 } from 'uuid'; import InfluxSeries from './influx_series'; @@ -26,6 +32,72 @@ import { Observable, throwError, of } from 'rxjs'; import { FluxQueryEditor } from './components/FluxQueryEditor'; import { catchError, map } from 'rxjs/operators'; +// we detect the field type based on the value-array +function getFieldType(values: unknown[]): FieldType { + if (values.length === 0) { + // if we get called with an empty value-array, + // we will assume the values are numbers + return FieldType.number; + } + + const valueType = typeof values[0]; + + switch (valueType) { + case 'string': + return FieldType.string; + case 'boolean': + return FieldType.boolean; + case 'number': + return FieldType.number; + default: + // this should never happen, influxql values + // can only be numbers, strings and booleans. + throw new Error(`InfluxQL: invalid value type ${valueType}`); + } +} + +// this conversion function is specialized to work with the timeseries +// data returned by InfluxDatasource.getTimeSeries() +function timeSeriesToDataFrame(timeSeries: TimeSeries): DataFrame { + const times: number[] = []; + const values: unknown[] = []; + + // the data we process here is not correctly typed. + // the typescript types say every data-point is number|null, + // but in fact it can be string or boolean too. + + const points = timeSeries.datapoints; + for (const point of points) { + values.push(point[0]); + times.push(point[1] as number); + } + + const timeField = { + name: TIME_SERIES_TIME_FIELD_NAME, + type: FieldType.time, + config: {}, + values: new ArrayVector(times), + }; + + const valueField = { + name: TIME_SERIES_VALUE_FIELD_NAME, + type: getFieldType(values), + config: {}, + values: new ArrayVector(values), + labels: timeSeries.tags, + }; + + const fields = [timeField, valueField]; + + return { + name: timeSeries.target, + refId: timeSeries.refId, + meta: timeSeries.meta, + fields, + length: values.length, + }; +} + export default class InfluxDatasource extends DataSourceWithBackend { type: string; urls: string[]; @@ -200,7 +272,7 @@ export default class InfluxDatasource extends DataSourceWithBackend