mirror of
https://github.com/SigNoz/signoz.git
synced 2026-02-03 08:33:26 +00:00
fix: query variable referencing custom variable (#10023)
* fix: custom variable to query mapping * chore: add test
This commit is contained in:
@@ -94,7 +94,7 @@ function DashboardVariableSelection(): JSX.Element | null {
|
||||
cycleNodes,
|
||||
});
|
||||
}
|
||||
}, [setVariablesToGetUpdated, variables, variablesTableData]);
|
||||
}, [variables, variablesTableData]);
|
||||
|
||||
// this handles the case where the dependency order changes i.e. variable list updated via creation or deletion etc. and we need to refetch the variables
|
||||
// also trigger when the global time changes
|
||||
|
||||
@@ -257,6 +257,15 @@ export const onUpdateVariableNode = (
|
||||
): void => {
|
||||
const visited = new Set<string>();
|
||||
|
||||
// If nodeToUpdate is not in topologicalOrder (e.g., CUSTOM variable),
|
||||
// we still need to mark its children as needing updates
|
||||
if (!topologicalOrder.includes(nodeToUpdate)) {
|
||||
// Mark direct children of the node as visited so they get processed
|
||||
(graph[nodeToUpdate] || []).forEach((child) => {
|
||||
visited.add(child);
|
||||
});
|
||||
}
|
||||
|
||||
// Start processing from the node to update
|
||||
topologicalOrder.forEach((node) => {
|
||||
if (node === nodeToUpdate || visited.has(node)) {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { areArraysEqual } from './util';
|
||||
import { areArraysEqual, onUpdateVariableNode, VariableGraph } from './util';
|
||||
|
||||
describe('areArraysEqual', () => {
|
||||
it('should return true for equal arrays with same order', () => {
|
||||
@@ -31,3 +31,121 @@ describe('areArraysEqual', () => {
|
||||
expect(areArraysEqual(array1, array2)).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('onUpdateVariableNode', () => {
|
||||
// Graph structure:
|
||||
// deployment -> namespace -> service -> pod
|
||||
// deployment has no parents, namespace depends on deployment, etc.
|
||||
const graph: VariableGraph = {
|
||||
deployment: ['namespace'],
|
||||
namespace: ['service'],
|
||||
service: ['pod'],
|
||||
pod: [],
|
||||
customVar: ['namespace'], // CUSTOM variable that affects namespace
|
||||
};
|
||||
|
||||
const topologicalOrder = ['deployment', 'namespace', 'service', 'pod'];
|
||||
|
||||
it('should call callback for the node and all its descendants', () => {
|
||||
const visited: string[] = [];
|
||||
const callback = (node: string): void => {
|
||||
visited.push(node);
|
||||
};
|
||||
|
||||
onUpdateVariableNode('deployment', graph, topologicalOrder, callback);
|
||||
|
||||
expect(visited).toEqual(['deployment', 'namespace', 'service', 'pod']);
|
||||
});
|
||||
|
||||
it('should call callback starting from a middle node', () => {
|
||||
const visited: string[] = [];
|
||||
const callback = (node: string): void => {
|
||||
visited.push(node);
|
||||
};
|
||||
|
||||
onUpdateVariableNode('namespace', graph, topologicalOrder, callback);
|
||||
|
||||
expect(visited).toEqual(['namespace', 'service', 'pod']);
|
||||
});
|
||||
|
||||
it('should only call callback for the leaf node when updating leaf', () => {
|
||||
const visited: string[] = [];
|
||||
const callback = (node: string): void => {
|
||||
visited.push(node);
|
||||
};
|
||||
|
||||
onUpdateVariableNode('pod', graph, topologicalOrder, callback);
|
||||
|
||||
expect(visited).toEqual(['pod']);
|
||||
});
|
||||
|
||||
it('should handle CUSTOM variable not in topologicalOrder by updating its children', () => {
|
||||
const visited: string[] = [];
|
||||
const callback = (node: string): void => {
|
||||
visited.push(node);
|
||||
};
|
||||
|
||||
// customVar is not in topologicalOrder but has namespace as a child
|
||||
onUpdateVariableNode('customVar', graph, topologicalOrder, callback);
|
||||
|
||||
// Should process namespace and its descendants (service, pod)
|
||||
expect(visited).toEqual(['namespace', 'service', 'pod']);
|
||||
});
|
||||
|
||||
it('should handle node not in graph gracefully', () => {
|
||||
const visited: string[] = [];
|
||||
const callback = (node: string): void => {
|
||||
visited.push(node);
|
||||
};
|
||||
|
||||
onUpdateVariableNode('unknownNode', graph, topologicalOrder, callback);
|
||||
|
||||
// Should not call callback for any node since unknownNode has no children
|
||||
expect(visited).toEqual([]);
|
||||
});
|
||||
|
||||
it('should handle empty graph', () => {
|
||||
const visited: string[] = [];
|
||||
const callback = (node: string): void => {
|
||||
visited.push(node);
|
||||
};
|
||||
|
||||
onUpdateVariableNode('deployment', {}, topologicalOrder, callback);
|
||||
|
||||
// deployment is in topologicalOrder, so callback is called for it
|
||||
expect(visited).toEqual(['deployment']);
|
||||
});
|
||||
|
||||
it('should handle empty topologicalOrder', () => {
|
||||
const visited: string[] = [];
|
||||
const callback = (node: string): void => {
|
||||
visited.push(node);
|
||||
};
|
||||
|
||||
onUpdateVariableNode('deployment', graph, [], callback);
|
||||
|
||||
expect(visited).toEqual([]);
|
||||
});
|
||||
|
||||
it('should handle CUSTOM variable with multiple children', () => {
|
||||
const graphWithMultipleChildren: VariableGraph = {
|
||||
...graph,
|
||||
customMulti: ['namespace', 'service'], // CUSTOM variable affecting multiple nodes
|
||||
};
|
||||
|
||||
const visited: string[] = [];
|
||||
const callback = (node: string): void => {
|
||||
visited.push(node);
|
||||
};
|
||||
|
||||
onUpdateVariableNode(
|
||||
'customMulti',
|
||||
graphWithMultipleChildren,
|
||||
topologicalOrder,
|
||||
callback,
|
||||
);
|
||||
|
||||
// Should process namespace, service, and pod (descendants)
|
||||
expect(visited).toEqual(['namespace', 'service', 'pod']);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -318,7 +318,9 @@ function GridCardGraph({
|
||||
version={version}
|
||||
threshold={threshold}
|
||||
headerMenuList={menuList}
|
||||
isFetchingResponse={queryResponse.isFetching}
|
||||
isFetchingResponse={
|
||||
queryResponse.isFetching || variablesToGetUpdated.length > 0
|
||||
}
|
||||
setRequestData={setRequestData}
|
||||
onClickHandler={onClickHandler}
|
||||
onDragSelect={onDragSelect}
|
||||
|
||||
Reference in New Issue
Block a user