Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support to render values of multiple queries in the same table #10050

Merged
merged 8 commits into from
Dec 14, 2017
7 changes: 4 additions & 3 deletions public/app/plugins/datasource/prometheus/datasource.ts
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ export class PrometheusDatasource {
}

if (activeTargets[index].format === "table") {
result.push(self.transformMetricDataToTable(response.data.data.result));
result.push(self.transformMetricDataToTable(response.data.data.result, responseList.length, index));
} else {
for (let metricData of response.data.data.result) {
if (response.data.data.resultType === 'matrix') {
Expand Down Expand Up @@ -301,7 +301,7 @@ export class PrometheusDatasource {
return { target: metricLabel, datapoints: dps };
}

transformMetricDataToTable(md) {
transformMetricDataToTable(md, resultCount: number, resultIndex: number) {
var table = new TableModel();
var i, j;
var metricLabels = {};
Expand All @@ -326,7 +326,8 @@ export class PrometheusDatasource {
metricLabels[label] = labelIndex + 1;
table.columns.push({text: label});
});
table.columns.push({text: 'Value'});
let valueText = resultCount > 1 ? `Value #${String.fromCharCode(65 + resultIndex)}` : 'Value';
table.columns.push({text: valueText});

// Populate rows, set value to empty string when label not present.
_.each(md, function(series) {
Expand Down
227 changes: 227 additions & 0 deletions public/app/plugins/panel/table/specs/transformers.jest.ts
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,232 @@ describe('when transforming time series table', () => {
expect(table.columns[2].text).toBe('Min');
});
});
});

describe('table data sets', () => {
describe('Table', () => {
const transform = 'table';
var panel = {
transform,
};
var time = new Date().getTime();

var nonTableData = [
{
type: 'foo',
columns: [
{ text: 'Time' },
{ text: 'Label Key 1' },
{ text: 'Value' },
],
rows: [
[time, 'Label Value 1', 42],
],
}
];

var singleQueryData = [
{
type: 'table',
columns: [
{ text: 'Time' },
{ text: 'Label Key 1' },
{ text: 'Value' },
],
rows: [
[time, 'Label Value 1', 42],
],
}
];

var multipleQueriesDataSameLabels = [
{
type: 'table',
columns: [
{ text: 'Time' },
{ text: 'Label Key 1' },
{ text: 'Label Key 2' },
{ text: 'Value #A' },
],
rows: [
[time, 'Label Value 1', 'Label Value 2', 42],
],
},
{
type: 'table',
columns: [
{ text: 'Time' },
{ text: 'Label Key 1' },
{ text: 'Label Key 2' },
{ text: 'Value #B' },
],
rows: [
[time, 'Label Value 1', 'Label Value 2', 13],
],
},
{
type: 'table',
columns: [
{ text: 'Time' },
{ text: 'Label Key 1' },
{ text: 'Label Key 2' },
{ text: 'Value #C' },
],
rows: [
[time, 'Label Value 1', 'Label Value 2', 4],
],
},
{
type: 'table',
columns: [
{ text: 'Time' },
{ text: 'Label Key 1' },
{ text: 'Label Key 2' },
{ text: 'Value #C' },
],
rows: [
[time, 'Label Value 1', 'Label Value 2', 7],
],
}
];

var multipleQueriesDataDifferentLabels = [
{
type: 'table',
columns: [
{ text: 'Time' },
{ text: 'Label Key 1' },
{ text: 'Value #A' },
],
rows: [
[time, 'Label Value 1', 42],
],
},
{
type: 'table',
columns: [
{ text: 'Time' },
{ text: 'Label Key 2' },
{ text: 'Value #B' },
],
rows: [
[time, 'Label Value 2', 13],
],
},
{
type: 'table',
columns: [
{ text: 'Time' },
{ text: 'Label Key 1' },
{ text: 'Value #C' },
],
rows: [
[time, 'Label Value 3', 7],
],
}
];

describe('getColumns', function() {
it('should return data columns given a single query', function() {
var columns = transformers[transform].getColumns(singleQueryData);
expect(columns[0].text).toBe('Time');
expect(columns[1].text).toBe('Label Key 1');
expect(columns[2].text).toBe('Value');
});

it('should return the union of data columns given a multiple queries', function() {
var columns = transformers[transform].getColumns(multipleQueriesDataSameLabels);
expect(columns[0].text).toBe('Time');
expect(columns[1].text).toBe('Label Key 1');
expect(columns[2].text).toBe('Label Key 2');
expect(columns[3].text).toBe('Value #A');
expect(columns[4].text).toBe('Value #B');
});

it('should return the union of data columns given a multiple queries with different labels', function() {
var columns = transformers[transform].getColumns(multipleQueriesDataDifferentLabels);
expect(columns[0].text).toBe('Time');
expect(columns[1].text).toBe('Label Key 1');
expect(columns[2].text).toBe('Value #A');
expect(columns[3].text).toBe('Label Key 2');
expect(columns[4].text).toBe('Value #B');
expect(columns[5].text).toBe('Value #C');
});
});

describe('transform', function() {
it ('should throw an error with non-table data', () => {
expect(() => transformDataToTable(nonTableData, panel)).toThrow();
});

it ('should return 3 columns for single queries', () => {
table = transformDataToTable(singleQueryData, panel);
expect(table.columns.length).toBe(3);
expect(table.columns[0].text).toBe('Time');
expect(table.columns[1].text).toBe('Label Key 1');
expect(table.columns[2].text).toBe('Value');
});

it ('should return the union of columns for multiple queries', () => {
table = transformDataToTable(multipleQueriesDataSameLabels, panel);
expect(table.columns.length).toBe(6);
expect(table.columns[0].text).toBe('Time');
expect(table.columns[1].text).toBe('Label Key 1');
expect(table.columns[2].text).toBe('Label Key 2');
expect(table.columns[3].text).toBe('Value #A');
expect(table.columns[4].text).toBe('Value #B');
expect(table.columns[5].text).toBe('Value #C');
});

it ('should return 1 row for a single query', () => {
table = transformDataToTable(singleQueryData, panel);
expect(table.rows.length).toBe(1);
expect(table.rows[0][0]).toBe(time);
expect(table.rows[0][1]).toBe('Label Value 1');
expect(table.rows[0][2]).toBe(42);
});

it ('should return 2 rows for a mulitple queries with same label values plus one extra row', () => {
table = transformDataToTable(multipleQueriesDataSameLabels, panel);
expect(table.rows.length).toBe(2);
expect(table.rows[0][0]).toBe(time);
expect(table.rows[0][1]).toBe('Label Value 1');
expect(table.rows[0][2]).toBe('Label Value 2');
expect(table.rows[0][3]).toBe(42);
expect(table.rows[0][4]).toBe(13);
expect(table.rows[0][5]).toBe(4);
expect(table.rows[1][0]).toBe(time);
expect(table.rows[1][1]).toBe('Label Value 1');
expect(table.rows[1][2]).toBe('Label Value 2');
expect(table.rows[1][3]).toBeUndefined();
expect(table.rows[1][4]).toBeUndefined();
expect(table.rows[1][5]).toBe(7);
});

it ('should return 2 rows for mulitple queries with different label values', () => {
table = transformDataToTable(multipleQueriesDataDifferentLabels, panel);
expect(table.rows.length).toBe(2);
expect(table.columns.length).toBe(6);

expect(table.rows[0][0]).toBe(time);
expect(table.rows[0][1]).toBe('Label Value 1');
expect(table.rows[0][2]).toBe(42);
expect(table.rows[0][3]).toBe('Label Value 2');
expect(table.rows[0][4]).toBe(13);
expect(table.rows[0][5]).toBeUndefined();

expect(table.rows[1][0]).toBe(time);
expect(table.rows[1][1]).toBe('Label Value 3');
expect(table.rows[1][2]).toBeUndefined();
expect(table.rows[1][3]).toBeUndefined();
expect(table.rows[1][4]).toBeUndefined();
expect(table.rows[1][5]).toBe(7);
});
});
});
});

describe('doc data sets', () => {
describe('JSON Data', () => {
var panel = {
transform: 'json',
Expand Down Expand Up @@ -148,7 +373,9 @@ describe('when transforming time series table', () => {
});
});
});
});

describe('annotation data', () => {
describe('Annnotations', () => {
var panel = {transform: 'annotations'};
var rawData = {
Expand Down
Loading