WIP Create groupby time series trunction
Co-authored-by: Deniz Kusefoglu <deniz@influxdata.com>pull/10616/head
parent
424ef25d13
commit
fc5e16ce56
|
@ -56,6 +56,10 @@ interface QueryAST {
|
|||
limits: {limit: number}
|
||||
sources: Sources[]
|
||||
condition?: any
|
||||
groupBy?: {
|
||||
tags?: string[]
|
||||
time: {interval: string}
|
||||
}
|
||||
}
|
||||
|
||||
interface Props {
|
||||
|
|
|
@ -50,7 +50,7 @@ class TableGraph extends Component {
|
|||
}
|
||||
|
||||
componentWillReceiveProps(nextProps) {
|
||||
const {data} = timeSeriesToTableGraph(nextProps.data)
|
||||
const {data} = timeSeriesToTableGraph(nextProps.data, nextProps.queryASTs)
|
||||
if (_.isEmpty(data[0])) {
|
||||
return
|
||||
}
|
||||
|
@ -158,7 +158,7 @@ class TableGraph extends Component {
|
|||
}
|
||||
|
||||
handleClickFieldName = fieldName => () => {
|
||||
const {tableOptions} = this.props
|
||||
const {tableOptions, queryASTs} = this.props
|
||||
const {data, sortField, sortDirection} = this.state
|
||||
const verticalTimeAxis = _.get(tableOptions, 'verticalTimeAxis', true)
|
||||
const fieldNames = _.get(tableOptions, 'fieldNames', [TIME_FIELD_DEFAULT])
|
||||
|
@ -175,7 +175,8 @@ class TableGraph extends Component {
|
|||
fieldName,
|
||||
direction,
|
||||
verticalTimeAxis,
|
||||
fieldNames
|
||||
fieldNames,
|
||||
timeFormat
|
||||
)
|
||||
|
||||
this.setState({
|
||||
|
|
|
@ -2,6 +2,7 @@ import _ from 'lodash'
|
|||
import {shiftDate} from 'shared/query/helpers'
|
||||
import {map, reduce, filter, forEach, concat, clone} from 'fast.js'
|
||||
import {calculateColumnWidths} from 'src/dashboards/utils/tableGraph'
|
||||
import {groupByTag} from 'src/kapacitor/actions/queryConfigs'
|
||||
|
||||
/**
|
||||
* Accepts an array of raw influxdb responses and returns a format
|
||||
|
@ -172,8 +173,174 @@ export const timeSeriesToDygraph = (raw = [], isInDataExplorer) => {
|
|||
}
|
||||
}
|
||||
|
||||
export const timeSeriesToTableGraph = raw => {
|
||||
const {sortedLabels, sortedTimeSeries} = timeSeriesTransform(raw)
|
||||
const hasGroupBy = queryASTs => {
|
||||
return queryASTs.some(queryAST => {
|
||||
return _.get(queryAST, ['groupBy', 'tags'], false)
|
||||
})
|
||||
}
|
||||
|
||||
const groupByTimeSeriesTransform = (raw = [], queryASTs = []) => {
|
||||
const groupBys = queryASTs.map(queryAST => {
|
||||
return _.get(queryAST, ['groupBy', 'tags'], false)
|
||||
})
|
||||
|
||||
raw.forEach((r, i) => {
|
||||
if (groupBys[i]) {
|
||||
// treat it like a groupBy
|
||||
} else {
|
||||
// don't treat it like a groupby..
|
||||
}
|
||||
})
|
||||
|
||||
console.log('queryASTs', queryASTs)
|
||||
// foreachqueryAST in queryASTs
|
||||
// determine if hasGroupBy
|
||||
// if hasGroupBy time// tag/ select
|
||||
// if nothasGroupBy append
|
||||
console.log('raw', 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}))]
|
||||
},
|
||||
[]
|
||||
)
|
||||
console.log('serieses', serieses)
|
||||
|
||||
const tags = queryASTs.reduce((acc, queryAST) => {
|
||||
return [...acc, ..._.get(queryAST, ['groupBy', 'tags'], [])]
|
||||
}, [])
|
||||
|
||||
tags.forEach(tag => {
|
||||
const filtered = serieses.filter(s => {
|
||||
const t = _.get(s, '')
|
||||
})
|
||||
})
|
||||
|
||||
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 timeSeriesToTableGraph = (raw, queryASTs) => {
|
||||
const {sortedLabels, sortedTimeSeries} = hasGroupBy(queryASTs)
|
||||
? groupByTimeSeriesTransform(raw, queryASTs)
|
||||
: timeSeriesTransform(raw)
|
||||
|
||||
const labels = ['time', ...map(sortedLabels, ({label}) => label)]
|
||||
|
||||
|
|
Loading…
Reference in New Issue