[release-11.6.4] Graphite: Fix recursion (#107567)

Graphite: Fix recursion (#106983)

* Fix for repeated row variables

* Add unit tests

* Do not recursively replace queries that self-reference

---------


(cherry picked from commit 7135832fff)

Co-authored-by: Andreas Christou <andreas.christou@grafana.com>
Co-authored-by: Ivan Ortega <ivanortegaalba@gmail.com>
This commit is contained in:
grafana-delivery-bot[bot]
2025-07-03 12:44:56 +01:00
committed by GitHub
parent 5a0687953a
commit 49176aec63
2 changed files with 50 additions and 2 deletions
@@ -510,6 +510,48 @@ describe('graphiteDatasource', () => {
expect(results[0]).toBe('target=' + encodeURIComponent('avg(web01.cpu)'));
});
it('should not recursively replace queries that reference themselves', () => {
const originalTargetMap = {
A: 'sumSeries(carbon.test.test-host.cpuUsage, #A)',
};
const results = ctx.ds.buildGraphiteParams(
{
targets: [{ target: 'sumSeries(carbon.test.test-host.cpuUsage, #A)' }],
},
originalTargetMap
);
expect(results[0]).toBe(
'target=' +
encodeURIComponent('sumSeries(carbon.test.test-host.cpuUsage, sumSeries(carbon.test.test-host.cpuUsage, #A))')
);
});
it('should not recursively replace queries that reference themselves, but will replace nested references', () => {
const originalTargetMap = {
A: 'sumSeries(carbon.test.test-host.cpuUsage, #A, #B)',
B: 'add(carbon.test.test-host.cpuUsage, 1.5)',
};
const results = ctx.ds.buildGraphiteParams(
{
targets: [
{
target: 'sumSeries(carbon.test.test-host.cpuUsage, #A, #B)',
},
{
target: 'add(carbon.test.test-host.cpuUsage, 1.5)',
},
],
},
originalTargetMap
);
expect(results[0]).toBe(
'target=' +
encodeURIComponent(
'sumSeries(carbon.test.test-host.cpuUsage, sumSeries(carbon.test.test-host.cpuUsage, #A, #B), add(carbon.test.test-host.cpuUsage, 1.5))'
)
);
});
it('should fix wrong minute interval parameters', () => {
const originalTargetMap = {
A: "summarize(prod.25m.count, '25m', 'sum')",
@@ -1008,8 +1008,7 @@ export class GraphiteDatasource
const graphiteOptions = ['from', 'until', 'rawData', 'format', 'maxDataPoints', 'cacheTimeout'];
const cleanOptions = [],
targets: Record<string, string> = {};
let target, targetValue, i;
const regex = /\#([A-Z])/g;
let target: GraphiteQuery, targetValue, i;
const intervalFormatFixRegex = /'(\d+)m'/gi;
let hasTargets = false;
@@ -1034,7 +1033,14 @@ export class GraphiteDatasource
targets[target.refId] = targetValue;
}
const regex = /\#([A-Z])/g;
function nestedSeriesRegexReplacer(match: string, g1: string | number) {
// Handle the case where a query references itself to prevent infinite recursion
if (target.refId === g1) {
return targets[g1] || match;
}
// Recursively replace all nested series references
return originalTargetMap[g1].replace(regex, nestedSeriesRegexReplacer) || match;
}