Use timeSeriesTransform for dygraphs.

table/group-by
ebb-tide 2018-04-24 13:18:01 -07:00
parent 70b7d73040
commit bb277189b1
4 changed files with 21 additions and 162 deletions

View File

@ -3,7 +3,7 @@ import PropTypes from 'prop-types'
import Dygraph from 'shared/components/Dygraph'
import SingleStat from 'src/shared/components/SingleStat'
import timeSeriesToDygraph from 'utils/timeSeriesTransformers'
import {timeSeriesToDygraph} from 'utils/timeSeriesTransformers'
import {colorsStringSchema} from 'shared/schemas'
import {ErrorHandling} from 'src/shared/decorators/errors'

View File

@ -125,8 +125,9 @@ const insertGroupByValues = (
groupBys,
seriesLabels,
labelsToValueIndex,
dashArray
sortedLabels
) => {
const dashArray = Array(sortedLabels.length).fill('-')
const timeSeries = []
let existingRowIndex
forEach(serieses, (s, sind) => {
@ -137,7 +138,7 @@ const insertGroupByValues = (
forEach(vs.slice(1), (v, i) => {
const label = seriesLabels[sind][i].label
timeSeries[existingRowIndex].values[
labelsToValueIndex[label + s.seriesIndex]
labelsToValueIndex[label + s.responseIndex + s.seriesIndex]
] = v
})
})
@ -154,13 +155,13 @@ const constructTimeSeries = (
groupBys,
seriesLabels
) => {
const dashArray = Array(sortedLabels.length).fill('-')
const nullArray = Array(sortedLabels.length).fill(null)
const labelsToValueIndex = reduce(
sortedLabels,
(acc, {label, seriesIndex}, i) => {
(acc, {label, responseIndex, seriesIndex}, i) => {
// adding series index prevents overwriting of two distinct labels that have the same field and measurements
acc[label + seriesIndex] = i
acc[label + responseIndex + seriesIndex] = i
return acc
},
{}
@ -173,7 +174,7 @@ const constructTimeSeries = (
groupBys,
seriesLabels,
labelsToValueIndex,
dashArray
sortedLabels
)
let existingRowIndex
@ -184,6 +185,7 @@ const constructTimeSeries = (
const value = cells.value[i]
const label = cells.label[i]
const seriesIndex = cells.seriesIndex[i]
const responseIndex = cells.responseIndex[i]
if (groupBys[cells.responseIndex[i]]) {
// we've already inserted GroupByValues
@ -200,7 +202,7 @@ const constructTimeSeries = (
if (existingRowIndex === undefined) {
timeSeries.push({
time,
values: clone(dashArray),
values: clone(nullArray),
})
existingRowIndex = timeSeries.length - 1
@ -208,14 +210,17 @@ const constructTimeSeries = (
}
timeSeries[existingRowIndex].values[
labelsToValueIndex[label + seriesIndex]
labelsToValueIndex[label + responseIndex + seriesIndex]
] = value
}
return _.sortBy(timeSeries, 'time')
}
export const groupByTimeSeriesTransform = (raw, groupBys = []) => {
export const groupByTimeSeriesTransform = (raw, groupBys) => {
if (!groupBys) {
groupBys = Array(raw.length).fill(false)
}
const results = constructResults(raw, groupBys)
const serieses = constructSerieses(results)

View File

@ -1,153 +1,9 @@
import _ from 'lodash'
import {shiftDate} from 'shared/query/helpers'
import {map, reduce, forEach, concat, clone} from 'fast.js'
import {map, reduce} from 'fast.js'
import {groupByTimeSeriesTransform} from 'src/utils/groupBy.js'
/**
* Accepts an array of raw influxdb responses and returns a format
* that Dygraph understands.
**/
const DEFAULT_SIZE = 0
const cells = {
label: new Array(DEFAULT_SIZE),
value: new Array(DEFAULT_SIZE),
time: new Array(DEFAULT_SIZE),
seriesIndex: new Array(DEFAULT_SIZE),
responseIndex: new Array(DEFAULT_SIZE),
}
const timeSeriesTransform = (raw = []) => {
// collect results from each influx response
const results = reduce(
raw,
(acc, rawResponse, responseIndex) => {
const responses = _.get(rawResponse, 'response.results', [])
const indexedResponses = map(responses, response => ({
...response,
responseIndex,
}))
return [...acc, ...indexedResponses]
},
[]
)
// collect each series
const serieses = reduce(
results,
(acc, {series = [], responseIndex}, index) => {
return [...acc, ...map(series, item => ({...item, responseIndex, index}))]
},
[]
)
const size = reduce(
serieses,
(acc, {columns, values}) => {
if (columns.length && (values && values.length)) {
return acc + (columns.length - 1) * values.length
}
return acc
},
0
)
// convert series into cells with rows and columns
let cellIndex = 0
let labels = []
forEach(
serieses,
({
name: measurement,
columns,
values,
index: seriesIndex,
responseIndex,
tags = {},
}) => {
const rows = map(values || [], vals => ({
vals,
}))
// tagSet is each tag key and value for a series
const tagSet = map(Object.keys(tags), tag => `[${tag}=${tags[tag]}]`)
.sort()
.join('')
const unsortedLabels = map(columns.slice(1), field => ({
label: `${measurement}.${field}${tagSet}`,
responseIndex,
seriesIndex,
}))
labels = concat(labels, unsortedLabels)
forEach(rows, ({vals}) => {
const [time, ...rowValues] = vals
forEach(rowValues, (value, i) => {
cells.label[cellIndex] = unsortedLabels[i].label
cells.value[cellIndex] = value
cells.time[cellIndex] = time
cells.seriesIndex[cellIndex] = seriesIndex
cells.responseIndex[cellIndex] = responseIndex
cellIndex++ // eslint-disable-line no-plusplus
})
})
}
)
const sortedLabels = _.sortBy(labels, 'label')
const tsMemo = {}
const nullArray = Array(sortedLabels.length).fill(null)
const labelsToValueIndex = reduce(
sortedLabels,
(acc, {label, seriesIndex}, i) => {
// adding series index prevents overwriting of two distinct labels that have the same field and measurements
acc[label + seriesIndex] = i
return acc
},
{}
)
const timeSeries = []
for (let i = 0; i < size; i++) {
let time = cells.time[i]
const value = cells.value[i]
const label = cells.label[i]
const seriesIndex = cells.seriesIndex[i]
if (label.includes('_shifted__')) {
const [, quantity, duration] = label.split('__')
time = +shiftDate(time, quantity, duration).format('x')
}
let existingRowIndex = tsMemo[time]
if (existingRowIndex === undefined) {
timeSeries.push({
time,
values: clone(nullArray),
})
existingRowIndex = timeSeries.length - 1
tsMemo[time] = existingRowIndex
}
timeSeries[existingRowIndex].values[
labelsToValueIndex[label + seriesIndex]
] = value
}
const sortedTimeSeries = _.sortBy(timeSeries, 'time')
return {
sortedLabels,
sortedTimeSeries,
}
}
export const timeSeriesToDygraph = (raw = [], isInDataExplorer) => {
const {sortedLabels, sortedTimeSeries} = timeSeriesTransform(raw)
const {sortedLabels, sortedTimeSeries} = groupByTimeSeriesTransform(raw)
const dygraphSeries = reduce(
sortedLabels,
@ -193,5 +49,3 @@ export const timeSeriesToTableGraph = (raw, queryASTs) => {
sortedLabels,
}
}
export default timeSeriesToDygraph

View File

@ -1,4 +1,5 @@
import timeSeriesToDygraph, {
import {
timeSeriesToDygraph,
timeSeriesToTableGraph,
} from 'src/utils/timeSeriesTransformers'
@ -185,7 +186,6 @@ describe('timeSeriesToDygraph', () => {
},
},
]
const actual = timeSeriesToDygraph(influxResponse)
const expected = {
@ -382,9 +382,9 @@ describe('timeSeriesToTableGraph', () => {
const actual = timeSeriesToTableGraph(influxResponse, qASTs)
const expected = [
['time', 'ma.f1', 'mb.f1', 'mc.f1', 'mc.f2'],
[1000, 1, 1, '-', '-'],
[1000, 1, 1, null, null],
[2000, 2, 2, 3, 3],
[4000, '-', '-', 4, 4],
[4000, null, null, 4, 4],
]
expect(actual.data).toEqual(expected)