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}
|
limits: {limit: number}
|
||||||
sources: Sources[]
|
sources: Sources[]
|
||||||
condition?: any
|
condition?: any
|
||||||
|
groupBy?: {
|
||||||
|
tags?: string[]
|
||||||
|
time: {interval: string}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
|
|
|
@ -50,7 +50,7 @@ class TableGraph extends Component {
|
||||||
}
|
}
|
||||||
|
|
||||||
componentWillReceiveProps(nextProps) {
|
componentWillReceiveProps(nextProps) {
|
||||||
const {data} = timeSeriesToTableGraph(nextProps.data)
|
const {data} = timeSeriesToTableGraph(nextProps.data, nextProps.queryASTs)
|
||||||
if (_.isEmpty(data[0])) {
|
if (_.isEmpty(data[0])) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -158,7 +158,7 @@ class TableGraph extends Component {
|
||||||
}
|
}
|
||||||
|
|
||||||
handleClickFieldName = fieldName => () => {
|
handleClickFieldName = fieldName => () => {
|
||||||
const {tableOptions} = this.props
|
const {tableOptions, queryASTs} = this.props
|
||||||
const {data, sortField, sortDirection} = this.state
|
const {data, sortField, sortDirection} = this.state
|
||||||
const verticalTimeAxis = _.get(tableOptions, 'verticalTimeAxis', true)
|
const verticalTimeAxis = _.get(tableOptions, 'verticalTimeAxis', true)
|
||||||
const fieldNames = _.get(tableOptions, 'fieldNames', [TIME_FIELD_DEFAULT])
|
const fieldNames = _.get(tableOptions, 'fieldNames', [TIME_FIELD_DEFAULT])
|
||||||
|
@ -175,7 +175,8 @@ class TableGraph extends Component {
|
||||||
fieldName,
|
fieldName,
|
||||||
direction,
|
direction,
|
||||||
verticalTimeAxis,
|
verticalTimeAxis,
|
||||||
fieldNames
|
fieldNames,
|
||||||
|
timeFormat
|
||||||
)
|
)
|
||||||
|
|
||||||
this.setState({
|
this.setState({
|
||||||
|
|
|
@ -2,6 +2,7 @@ import _ from 'lodash'
|
||||||
import {shiftDate} from 'shared/query/helpers'
|
import {shiftDate} from 'shared/query/helpers'
|
||||||
import {map, reduce, filter, forEach, concat, clone} from 'fast.js'
|
import {map, reduce, filter, forEach, concat, clone} from 'fast.js'
|
||||||
import {calculateColumnWidths} from 'src/dashboards/utils/tableGraph'
|
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
|
* 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 hasGroupBy = queryASTs => {
|
||||||
const {sortedLabels, sortedTimeSeries} = timeSeriesTransform(raw)
|
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)]
|
const labels = ['time', ...map(sortedLabels, ({label}) => label)]
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue