Graphite: Ensure frames have refId set (#99911)
Ensure frames have refIDs - Sanitise the refID - Alias the query target with the refID - Set the appropriate refID on the created frames - Update tests
This commit is contained in:
@@ -55,6 +55,10 @@ describe('graphiteDatasource', () => {
|
|||||||
|
|
||||||
describe('convertResponseToDataFrames', () => {
|
describe('convertResponseToDataFrames', () => {
|
||||||
it('should transform regular result', () => {
|
it('should transform regular result', () => {
|
||||||
|
const refIDMap = {
|
||||||
|
refIDA: 'A',
|
||||||
|
refIDB: 'B',
|
||||||
|
};
|
||||||
const result = ctx.ds.convertResponseToDataFrames(
|
const result = ctx.ds.convertResponseToDataFrames(
|
||||||
createFetchResponse({
|
createFetchResponse({
|
||||||
meta: {
|
meta: {
|
||||||
@@ -65,7 +69,7 @@ describe('graphiteDatasource', () => {
|
|||||||
},
|
},
|
||||||
series: [
|
series: [
|
||||||
{
|
{
|
||||||
target: 'seriesA',
|
target: 'seriesA refIDA',
|
||||||
datapoints: [
|
datapoints: [
|
||||||
[100, 200],
|
[100, 200],
|
||||||
[101, 201],
|
[101, 201],
|
||||||
@@ -85,7 +89,7 @@ describe('graphiteDatasource', () => {
|
|||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
target: 'seriesB',
|
target: 'seriesB refIDB',
|
||||||
meta: [
|
meta: [
|
||||||
{
|
{
|
||||||
'aggnum-norm': 1,
|
'aggnum-norm': 1,
|
||||||
@@ -105,7 +109,8 @@ describe('graphiteDatasource', () => {
|
|||||||
],
|
],
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
})
|
}),
|
||||||
|
refIDMap
|
||||||
);
|
);
|
||||||
|
|
||||||
expect(result.data.length).toBe(2);
|
expect(result.data.length).toBe(2);
|
||||||
@@ -113,24 +118,28 @@ describe('graphiteDatasource', () => {
|
|||||||
expect(getFrameDisplayName(result.data[1])).toBe('seriesB');
|
expect(getFrameDisplayName(result.data[1])).toBe('seriesB');
|
||||||
expect(result.data[0].length).toBe(2);
|
expect(result.data[0].length).toBe(2);
|
||||||
expect(result.data[0].meta.notices.length).toBe(1);
|
expect(result.data[0].meta.notices.length).toBe(1);
|
||||||
|
expect(result.data[0].refId).toBe('A');
|
||||||
expect(result.data[0].meta.notices[0].text).toBe('Data is rolled up, aggregated over 2h using Average function');
|
expect(result.data[0].meta.notices[0].text).toBe('Data is rolled up, aggregated over 2h using Average function');
|
||||||
expect(result.data[1].meta.notices).toBeUndefined();
|
expect(result.data[1].meta.notices).toBeUndefined();
|
||||||
|
expect(result.data[1].refId).toBe('B');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('When querying graphite with one target using query editor target spec', () => {
|
describe('When querying graphite with one target using query editor target spec', () => {
|
||||||
const query = {
|
|
||||||
panelId: 3,
|
|
||||||
dashboardId: 5,
|
|
||||||
range: { from: dateTime('2022-04-01T00:00:00'), to: dateTime('2022-07-01T00:00:00') },
|
|
||||||
targets: [{ target: 'prod1.count' }, { target: 'prod2.count' }],
|
|
||||||
maxDataPoints: 500,
|
|
||||||
};
|
|
||||||
|
|
||||||
let response: unknown;
|
let response: unknown;
|
||||||
let requestOptions: BackendSrvRequest;
|
let requestOptions: BackendSrvRequest;
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
|
const query = {
|
||||||
|
panelId: 3,
|
||||||
|
dashboardId: 5,
|
||||||
|
range: { from: dateTime('2022-04-01T00:00:00'), to: dateTime('2022-07-01T00:00:00') },
|
||||||
|
targets: [
|
||||||
|
{ target: 'prod1.count', refId: 'A' },
|
||||||
|
{ target: 'prod2.count', refId: 'B' },
|
||||||
|
],
|
||||||
|
maxDataPoints: 500,
|
||||||
|
};
|
||||||
fetchMock.mockImplementation((options) => {
|
fetchMock.mockImplementation((options) => {
|
||||||
requestOptions = options;
|
requestOptions = options;
|
||||||
return of(
|
return of(
|
||||||
@@ -164,8 +173,8 @@ describe('graphiteDatasource', () => {
|
|||||||
|
|
||||||
it('should query correctly', () => {
|
it('should query correctly', () => {
|
||||||
const params = requestOptions.data.split('&');
|
const params = requestOptions.data.split('&');
|
||||||
expect(params).toContain('target=prod1.count');
|
expect(params).toContain(`target=${encodeURIComponent(`aliasSub(prod1.count, "(^.*$)", "\\1 A")`)}`);
|
||||||
expect(params).toContain('target=prod2.count');
|
expect(params).toContain(`target=${encodeURIComponent(`aliasSub(prod2.count, "(^.*$)", "\\1 B")`)}`);
|
||||||
expect(params).toContain('from=1648789200');
|
expect(params).toContain('from=1648789200');
|
||||||
expect(params).toContain('until=1656655200');
|
expect(params).toContain('until=1656655200');
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -209,6 +209,17 @@ export class GraphiteDatasource
|
|||||||
return merge(...streams);
|
return merge(...streams);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Use this object to map the original refID of the query to our sanitised one
|
||||||
|
const refIds: { [key: string]: string } = {};
|
||||||
|
for (const target of options.targets) {
|
||||||
|
// Sanitise the refID otherwise the Graphite query will fail
|
||||||
|
const formattedRefId = target.refId.replaceAll(' ', '_');
|
||||||
|
refIds[formattedRefId] = target.refId;
|
||||||
|
// Use aliasSub to include the refID in the response series name. This allows us to set the refID on the frame.
|
||||||
|
const updatedTarget = `aliasSub(${target.target}, "(^.*$)", "\\1 ${formattedRefId}")`;
|
||||||
|
target.target = updatedTarget;
|
||||||
|
}
|
||||||
|
|
||||||
// handle the queries here
|
// handle the queries here
|
||||||
const graphOptions = {
|
const graphOptions = {
|
||||||
from: this.translateTime(options.range.from, false, options.timezone),
|
from: this.translateTime(options.range.from, false, options.timezone),
|
||||||
@@ -243,7 +254,7 @@ export class GraphiteDatasource
|
|||||||
httpOptions.requestId = this.name + '.panelId.' + options.panelId;
|
httpOptions.requestId = this.name + '.panelId.' + options.panelId;
|
||||||
}
|
}
|
||||||
|
|
||||||
return this.doGraphiteRequest(httpOptions).pipe(map(this.convertResponseToDataFrames));
|
return this.doGraphiteRequest(httpOptions).pipe(map((result) => this.convertResponseToDataFrames(result, refIds)));
|
||||||
}
|
}
|
||||||
|
|
||||||
addTracingHeaders(
|
addTracingHeaders(
|
||||||
@@ -267,7 +278,7 @@ export class GraphiteDatasource
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
convertResponseToDataFrames = (result: FetchResponse): DataQueryResponse => {
|
convertResponseToDataFrames = (result: FetchResponse, refIdMap: { [key: string]: string }): DataQueryResponse => {
|
||||||
const data: DataFrame[] = [];
|
const data: DataFrame[] = [];
|
||||||
if (!result || !result.data) {
|
if (!result || !result.data) {
|
||||||
return { data };
|
return { data };
|
||||||
@@ -282,6 +293,9 @@ export class GraphiteDatasource
|
|||||||
|
|
||||||
for (let i = 0; i < series.length; i++) {
|
for (let i = 0; i < series.length; i++) {
|
||||||
const s = series[i];
|
const s = series[i];
|
||||||
|
// Retrieve the original refID of the query
|
||||||
|
const [target, refId] = s.target.split(' ');
|
||||||
|
s.target = target;
|
||||||
|
|
||||||
// Disables Grafana own series naming
|
// Disables Grafana own series naming
|
||||||
s.title = s.target;
|
s.title = s.target;
|
||||||
@@ -291,6 +305,8 @@ export class GraphiteDatasource
|
|||||||
}
|
}
|
||||||
|
|
||||||
const frame = toDataFrame(s);
|
const frame = toDataFrame(s);
|
||||||
|
// Set the refID value on the frame
|
||||||
|
frame.refId = refIdMap[refId];
|
||||||
|
|
||||||
// Metrictank metadata
|
// Metrictank metadata
|
||||||
if (s.meta) {
|
if (s.meta) {
|
||||||
|
|||||||
Reference in New Issue
Block a user