mirror of https://github.com/grafana/grafana
Influxdb: Remove backend migration feature toggle (#61308)
* Remove influxdbBackendMigration feature toggle * Remove code blocks related to influxdbBackendMigration feature toggle * Fix annotations * Remove commented lines * Fix unit testspull/61623/head
parent
efed0151f8
commit
67c02f660a
@ -1,218 +0,0 @@ |
||||
import { each, map, includes, flatten, keys } from 'lodash'; |
||||
|
||||
import { FieldType, QueryResultMeta, TimeSeries, TableData } from '@grafana/data'; |
||||
import TableModel from 'app/core/TableModel'; |
||||
|
||||
export default class InfluxSeries { |
||||
refId?: string; |
||||
series: any; |
||||
alias: any; |
||||
annotation: any; |
||||
meta?: QueryResultMeta; |
||||
|
||||
constructor(options: { series: any; alias?: any; annotation?: any; meta?: QueryResultMeta; refId?: string }) { |
||||
this.series = options.series; |
||||
this.alias = options.alias; |
||||
this.annotation = options.annotation; |
||||
this.meta = options.meta; |
||||
this.refId = options.refId; |
||||
} |
||||
|
||||
getTimeSeries(): TimeSeries[] { |
||||
const output: TimeSeries[] = []; |
||||
let i, j; |
||||
|
||||
if (this.series.length === 0) { |
||||
return output; |
||||
} |
||||
|
||||
each(this.series, (series) => { |
||||
const columns = series.columns.length; |
||||
const tags = map(series.tags, (value, key) => { |
||||
return key + ': ' + value; |
||||
}); |
||||
|
||||
for (j = 1; j < columns; j++) { |
||||
let seriesName = series.name; |
||||
const columnName = series.columns[j]; |
||||
if (columnName !== 'value') { |
||||
seriesName = seriesName + '.' + columnName; |
||||
} |
||||
|
||||
if (this.alias) { |
||||
seriesName = this._getSeriesName(series, j); |
||||
} else if (series.tags) { |
||||
seriesName = seriesName + ' {' + tags.join(', ') + '}'; |
||||
} |
||||
|
||||
const datapoints = []; |
||||
if (series.values) { |
||||
for (i = 0; i < series.values.length; i++) { |
||||
datapoints[i] = [series.values[i][j], series.values[i][0]]; |
||||
} |
||||
} |
||||
|
||||
output.push({ |
||||
title: seriesName, |
||||
target: seriesName, |
||||
datapoints: datapoints, |
||||
tags: series.tags, |
||||
meta: this.meta, |
||||
refId: this.refId, |
||||
}); |
||||
} |
||||
}); |
||||
|
||||
return output; |
||||
} |
||||
|
||||
_getSeriesName(series: any, index: number) { |
||||
const regex = /\$(\w+)|\[\[([\s\S]+?)\]\]/g; |
||||
const segments = series.name.split('.'); |
||||
|
||||
return this.alias.replace(regex, (match: any, g1: any, g2: any) => { |
||||
const group = g1 || g2; |
||||
const segIndex = parseInt(group, 10); |
||||
|
||||
if (group === 'm' || group === 'measurement') { |
||||
return series.name; |
||||
} |
||||
if (group === 'col') { |
||||
return series.columns[index]; |
||||
} |
||||
if (!isNaN(segIndex)) { |
||||
return segments[segIndex] ?? match; |
||||
} |
||||
if (group.indexOf('tag_') !== 0) { |
||||
return match; |
||||
} |
||||
|
||||
const tag = group.replace('tag_', ''); |
||||
if (!series.tags) { |
||||
return match; |
||||
} |
||||
return series.tags[tag]; |
||||
}); |
||||
} |
||||
|
||||
getAnnotations() { |
||||
const list: any[] = []; |
||||
|
||||
each(this.series, (series) => { |
||||
let titleCol: any = null; |
||||
let timeCol: any = null; |
||||
let timeEndCol: any = null; |
||||
const tagsCol: any = []; |
||||
let textCol: any = null; |
||||
|
||||
each(series.columns, (column, index) => { |
||||
if (column === 'time') { |
||||
timeCol = index; |
||||
return; |
||||
} |
||||
if (column === 'sequence_number') { |
||||
return; |
||||
} |
||||
if (column === this.annotation.titleColumn) { |
||||
titleCol = index; |
||||
return; |
||||
} |
||||
if (includes((this.annotation.tagsColumn || '').replace(' ', '').split(','), column)) { |
||||
tagsCol.push(index); |
||||
return; |
||||
} |
||||
if (column === this.annotation.textColumn) { |
||||
textCol = index; |
||||
return; |
||||
} |
||||
if (column === this.annotation.timeEndColumn) { |
||||
timeEndCol = index; |
||||
return; |
||||
} |
||||
// legacy case
|
||||
if (!titleCol && textCol !== index) { |
||||
titleCol = index; |
||||
} |
||||
}); |
||||
|
||||
each(series.values, (value) => { |
||||
const data = { |
||||
annotation: this.annotation, |
||||
time: +new Date(value[timeCol]), |
||||
title: value[titleCol], |
||||
timeEnd: value[timeEndCol], |
||||
// Remove empty values, then split in different tags for comma separated values
|
||||
tags: flatten( |
||||
tagsCol |
||||
.filter((t: any) => { |
||||
return value[t]; |
||||
}) |
||||
.map((t: any) => { |
||||
return value[t].split(','); |
||||
}) |
||||
), |
||||
text: value[textCol], |
||||
}; |
||||
|
||||
list.push(data); |
||||
}); |
||||
}); |
||||
|
||||
return list; |
||||
} |
||||
|
||||
getTable(): TableData { |
||||
const table = new TableModel(); |
||||
let i, j; |
||||
|
||||
table.refId = this.refId; |
||||
table.meta = this.meta; |
||||
|
||||
if (this.series.length === 0) { |
||||
return table; |
||||
} |
||||
|
||||
// the order is:
|
||||
// - first the first item from the value-array (this is often (always?) the timestamp)
|
||||
// - then all the tag-values
|
||||
// - then the rest of the value-array
|
||||
//
|
||||
// we have to keep this order both in table.columns and table.rows
|
||||
|
||||
each(this.series, (series: any, seriesIndex: number) => { |
||||
if (seriesIndex === 0) { |
||||
const firstCol = series.columns[0]; |
||||
// Check the first column's name, if it is `time`, we
|
||||
// mark it as having the type time
|
||||
const firstTableCol = firstCol === 'time' ? { text: 'Time', type: FieldType.time } : { text: firstCol }; |
||||
table.columns.push(firstTableCol); |
||||
each(keys(series.tags), (key) => { |
||||
table.columns.push({ text: key }); |
||||
}); |
||||
for (j = 1; j < series.columns.length; j++) { |
||||
table.columns.push({ text: series.columns[j] }); |
||||
} |
||||
} |
||||
|
||||
if (series.values) { |
||||
for (i = 0; i < series.values.length; i++) { |
||||
const values = series.values[i]; |
||||
const reordered = [values[0]]; |
||||
if (series.tags) { |
||||
for (const key in series.tags) { |
||||
if (series.tags.hasOwnProperty(key)) { |
||||
reordered.push(series.tags[key]); |
||||
} |
||||
} |
||||
} |
||||
for (j = 1; j < values.length; j++) { |
||||
reordered.push(values[j]); |
||||
} |
||||
table.rows.push(reordered); |
||||
} |
||||
} |
||||
}); |
||||
|
||||
return table; |
||||
} |
||||
} |
@ -1,371 +0,0 @@ |
||||
import produce from 'immer'; |
||||
|
||||
import InfluxSeries from '../influx_series'; |
||||
|
||||
describe('when generating timeseries from influxdb response', () => { |
||||
describe('given multiple fields for series', () => { |
||||
const options = { |
||||
alias: '', |
||||
series: [ |
||||
{ |
||||
name: 'cpu', |
||||
tags: { app: 'test', server: 'server1' }, |
||||
columns: ['time', 'mean', 'max', 'min'], |
||||
values: [ |
||||
[1431946625000, 10, 11, 9], |
||||
[1431946626000, 20, 21, 19], |
||||
], |
||||
}, |
||||
], |
||||
}; |
||||
describe('and no alias', () => { |
||||
it('should generate multiple datapoints for each column', () => { |
||||
const series = new InfluxSeries(options); |
||||
const result = series.getTimeSeries(); |
||||
|
||||
expect(result.length).toBe(3); |
||||
expect(result[0].target).toBe('cpu.mean {app: test, server: server1}'); |
||||
expect(result[0].datapoints[0][0]).toBe(10); |
||||
expect(result[0].datapoints[0][1]).toBe(1431946625000); |
||||
expect(result[0].datapoints[1][0]).toBe(20); |
||||
expect(result[0].datapoints[1][1]).toBe(1431946626000); |
||||
|
||||
expect(result[1].target).toBe('cpu.max {app: test, server: server1}'); |
||||
expect(result[1].datapoints[0][0]).toBe(11); |
||||
expect(result[1].datapoints[0][1]).toBe(1431946625000); |
||||
expect(result[1].datapoints[1][0]).toBe(21); |
||||
expect(result[1].datapoints[1][1]).toBe(1431946626000); |
||||
|
||||
expect(result[2].target).toBe('cpu.min {app: test, server: server1}'); |
||||
expect(result[2].datapoints[0][0]).toBe(9); |
||||
expect(result[2].datapoints[0][1]).toBe(1431946625000); |
||||
expect(result[2].datapoints[1][0]).toBe(19); |
||||
expect(result[2].datapoints[1][1]).toBe(1431946626000); |
||||
}); |
||||
}); |
||||
|
||||
describe('and simple alias', () => { |
||||
it('should use alias', () => { |
||||
options.alias = 'new series'; |
||||
const series = new InfluxSeries(options); |
||||
const result = series.getTimeSeries(); |
||||
|
||||
expect(result[0].target).toBe('new series'); |
||||
expect(result[1].target).toBe('new series'); |
||||
expect(result[2].target).toBe('new series'); |
||||
}); |
||||
}); |
||||
|
||||
describe('and alias patterns', () => { |
||||
it('should replace patterns', () => { |
||||
options.alias = 'alias: $m -> $tag_server ([[measurement]])'; |
||||
const series = new InfluxSeries(options); |
||||
const result = series.getTimeSeries(); |
||||
|
||||
expect(result[0].target).toBe('alias: cpu -> server1 (cpu)'); |
||||
expect(result[1].target).toBe('alias: cpu -> server1 (cpu)'); |
||||
expect(result[2].target).toBe('alias: cpu -> server1 (cpu)'); |
||||
}); |
||||
}); |
||||
}); |
||||
|
||||
describe('given measurement with default fieldname', () => { |
||||
const options = { |
||||
series: [ |
||||
{ |
||||
name: 'cpu', |
||||
tags: { app: 'test', server: 'server1' }, |
||||
columns: ['time', 'value'], |
||||
values: [ |
||||
['2015-05-18T10:57:05Z', 10], |
||||
['2015-05-18T10:57:06Z', 12], |
||||
], |
||||
}, |
||||
{ |
||||
name: 'cpu', |
||||
tags: { app: 'test2', server: 'server2' }, |
||||
columns: ['time', 'value'], |
||||
values: [ |
||||
['2015-05-18T10:57:05Z', 15], |
||||
['2015-05-18T10:57:06Z', 16], |
||||
], |
||||
}, |
||||
], |
||||
}; |
||||
|
||||
describe('and no alias', () => { |
||||
it('should generate label with no field', () => { |
||||
const series = new InfluxSeries(options); |
||||
const result = series.getTimeSeries(); |
||||
|
||||
expect(result[0].target).toBe('cpu {app: test, server: server1}'); |
||||
expect(result[1].target).toBe('cpu {app: test2, server: server2}'); |
||||
}); |
||||
}); |
||||
}); |
||||
|
||||
describe('given two series', () => { |
||||
const options = { |
||||
alias: '', |
||||
series: [ |
||||
{ |
||||
name: 'cpu', |
||||
tags: { app: 'test', server: 'server1' }, |
||||
columns: ['time', 'mean'], |
||||
values: [ |
||||
[1431946625000, 10], |
||||
[1431946626000, 12], |
||||
], |
||||
}, |
||||
{ |
||||
name: 'cpu', |
||||
tags: { app: 'test2', server: 'server2' }, |
||||
columns: ['time', 'mean'], |
||||
values: [ |
||||
[1431946625000, 15], |
||||
[1431946626000, 16], |
||||
], |
||||
}, |
||||
], |
||||
}; |
||||
|
||||
describe('and no alias', () => { |
||||
it('should generate two time series', () => { |
||||
const series = new InfluxSeries(options); |
||||
const result = series.getTimeSeries(); |
||||
|
||||
expect(result.length).toBe(2); |
||||
expect(result[0].target).toBe('cpu.mean {app: test, server: server1}'); |
||||
expect(result[0].datapoints[0][0]).toBe(10); |
||||
expect(result[0].datapoints[0][1]).toBe(1431946625000); |
||||
expect(result[0].datapoints[1][0]).toBe(12); |
||||
expect(result[0].datapoints[1][1]).toBe(1431946626000); |
||||
expect(result[0].tags).toMatchObject({ |
||||
app: 'test', |
||||
server: 'server1', |
||||
}); |
||||
|
||||
expect(result[1].target).toBe('cpu.mean {app: test2, server: server2}'); |
||||
expect(result[1].datapoints[0][0]).toBe(15); |
||||
expect(result[1].datapoints[0][1]).toBe(1431946625000); |
||||
expect(result[1].datapoints[1][0]).toBe(16); |
||||
expect(result[1].datapoints[1][1]).toBe(1431946626000); |
||||
expect(result[1].tags).toMatchObject({ |
||||
app: 'test2', |
||||
server: 'server2', |
||||
}); |
||||
}); |
||||
}); |
||||
|
||||
describe('and simple alias', () => { |
||||
it('should use alias', () => { |
||||
options.alias = 'new series'; |
||||
const series = new InfluxSeries(options); |
||||
const result = series.getTimeSeries(); |
||||
|
||||
expect(result[0].target).toBe('new series'); |
||||
}); |
||||
}); |
||||
|
||||
describe('and alias patterns', () => { |
||||
it('should replace patterns', () => { |
||||
options.alias = 'alias: $m -> $tag_server ([[measurement]])'; |
||||
const series = new InfluxSeries(options); |
||||
const result = series.getTimeSeries(); |
||||
|
||||
expect(result[0].target).toBe('alias: cpu -> server1 (cpu)'); |
||||
expect(result[1].target).toBe('alias: cpu -> server2 (cpu)'); |
||||
}); |
||||
}); |
||||
}); |
||||
|
||||
describe('given measurement with dots', () => { |
||||
const options = { |
||||
alias: '', |
||||
series: [ |
||||
{ |
||||
name: 'app.prod.server1.count', |
||||
tags: {}, |
||||
columns: ['time', 'mean'], |
||||
values: [ |
||||
[1431946625000, 10], |
||||
[1431946626000, 12], |
||||
], |
||||
}, |
||||
], |
||||
}; |
||||
|
||||
it('should replace patterns', () => { |
||||
options.alias = 'alias: $1 -> [[3]]'; |
||||
const series = new InfluxSeries(options); |
||||
const result = series.getTimeSeries(); |
||||
|
||||
expect(result[0].target).toBe('alias: prod -> count'); |
||||
}); |
||||
|
||||
it('should handle too large indexes', () => { |
||||
options.alias = 'alias: $0 $1 $2 $3 $4 $5'; |
||||
const series = new InfluxSeries(options); |
||||
const result = series.getTimeSeries(); |
||||
|
||||
expect(result[0].target).toBe('alias: app prod server1 count $4 $5'); |
||||
}); |
||||
}); |
||||
|
||||
describe('given table response', () => { |
||||
const options = { |
||||
alias: '', |
||||
series: [ |
||||
{ |
||||
name: 'app.prod.server1.count', |
||||
tags: { datacenter: 'Africa', server: 'server2' }, |
||||
columns: ['time', 'value2', 'value'], |
||||
values: [ |
||||
[1431946625000, 23, 10], |
||||
[1431946626000, 25, 12], |
||||
], |
||||
}, |
||||
], |
||||
}; |
||||
|
||||
it('should return table', () => { |
||||
const series = new InfluxSeries(options); |
||||
const table = series.getTable(); |
||||
|
||||
expect(table.type).toBe('table'); |
||||
expect(table.columns.length).toBe(5); |
||||
expect(table.columns[0].text).toEqual('Time'); |
||||
expect(table.rows[0]).toEqual([1431946625000, 'Africa', 'server2', 23, 10]); |
||||
}); |
||||
}); |
||||
|
||||
describe('given table response from SHOW CARDINALITY', () => { |
||||
const options = { |
||||
alias: '', |
||||
series: [ |
||||
{ |
||||
name: 'cpu', |
||||
columns: ['count'], |
||||
values: [[37]], |
||||
}, |
||||
], |
||||
}; |
||||
|
||||
it('should return table', () => { |
||||
const series = new InfluxSeries(options); |
||||
const table = series.getTable(); |
||||
|
||||
expect(table.type).toBe('table'); |
||||
expect(table.columns.length).toBe(1); |
||||
expect(table.columns[0].text).toEqual('count'); |
||||
expect(table.rows[0]).toEqual([37]); |
||||
}); |
||||
}); |
||||
|
||||
describe('given annotation response', () => { |
||||
describe('with empty tagsColumn', () => { |
||||
const options = { |
||||
alias: '', |
||||
annotation: {}, |
||||
series: [ |
||||
{ |
||||
name: 'logins.count', |
||||
tags: { datacenter: 'Africa', server: 'server2' }, |
||||
columns: ['time', 'datacenter', 'hostname', 'source', 'value'], |
||||
values: [[1481549440372, 'America', '10.1.100.10', 'backend', 215.7432653659507]], |
||||
}, |
||||
], |
||||
}; |
||||
|
||||
it('should multiple tags', () => { |
||||
const series = new InfluxSeries(options); |
||||
const annotations = series.getAnnotations(); |
||||
|
||||
expect(annotations[0].tags.length).toBe(0); |
||||
}); |
||||
}); |
||||
|
||||
describe('given annotation response', () => { |
||||
const options = { |
||||
alias: '', |
||||
annotation: { |
||||
tagsColumn: 'datacenter, source', |
||||
}, |
||||
series: [ |
||||
{ |
||||
name: 'logins.count', |
||||
tags: { datacenter: 'Africa', server: 'server2' }, |
||||
columns: ['time', 'datacenter', 'hostname', 'source', 'value'], |
||||
values: [[1481549440372, 'America', '10.1.100.10', 'backend', 215.7432653659507]], |
||||
}, |
||||
], |
||||
}; |
||||
|
||||
it('should multiple tags', () => { |
||||
const series = new InfluxSeries(options); |
||||
const annotations = series.getAnnotations(); |
||||
|
||||
expect(annotations[0].tags.length).toBe(2); |
||||
expect(annotations[0].tags[0]).toBe('America'); |
||||
expect(annotations[0].tags[1]).toBe('backend'); |
||||
}); |
||||
}); |
||||
|
||||
describe('given a time-column in the json-response', () => { |
||||
const options = { |
||||
alias: '', |
||||
series: [ |
||||
{ |
||||
name: 'cpu', |
||||
tags: { cpu: 'cpu1' }, |
||||
columns: ['time', 'usage_idle'], |
||||
values: [[1481549440372, 42]], |
||||
}, |
||||
], |
||||
}; |
||||
|
||||
it('the column-names should be correct if the time-column is not renamed', () => { |
||||
const series = new InfluxSeries(options); |
||||
const table = series.getTable(); |
||||
|
||||
expect(table.columns).toStrictEqual([ |
||||
{ |
||||
text: 'Time', |
||||
type: 'time', |
||||
}, |
||||
{ |
||||
text: 'cpu', |
||||
}, |
||||
{ |
||||
text: 'usage_idle', |
||||
}, |
||||
]); |
||||
|
||||
expect(table.rows).toStrictEqual([[1481549440372, 'cpu1', 42]]); |
||||
}); |
||||
|
||||
it('the column-names should be correct if the time-column is renamed', () => { |
||||
const renamedOptions = produce(options, (draft) => { |
||||
// we rename the time-column to `zeit`
|
||||
draft.series[0].columns[0] = 'zeit'; |
||||
}); |
||||
const series = new InfluxSeries(renamedOptions); |
||||
const table = series.getTable(); |
||||
|
||||
expect(table.columns).toStrictEqual([ |
||||
{ |
||||
text: 'zeit', |
||||
}, |
||||
{ |
||||
text: 'cpu', |
||||
}, |
||||
{ |
||||
text: 'usage_idle', |
||||
}, |
||||
]); |
||||
|
||||
expect(table.rows).toStrictEqual([[1481549440372, 'cpu1', 42]]); |
||||
}); |
||||
}); |
||||
}); |
||||
}); |
Loading…
Reference in new issue