mirror of
https://github.com/SigNoz/signoz.git
synced 2026-05-07 02:50:31 +01:00
Compare commits
4 Commits
dashboard-
...
limiting-a
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a5095bb96c | ||
|
|
4b6e934510 | ||
|
|
421d355e29 | ||
|
|
eb75e636e8 |
@@ -6,6 +6,7 @@ import { IDashboardVariable } from 'types/api/dashboard/getAll';
|
||||
import {
|
||||
buildDependencies,
|
||||
buildDependencyGraph,
|
||||
buildParentDependencyGraph,
|
||||
onUpdateVariableNode,
|
||||
VariableGraph,
|
||||
} from './util';
|
||||
@@ -29,6 +30,7 @@ function DashboardVariableSelection(): JSX.Element | null {
|
||||
const [dependencyData, setDependencyData] = useState<{
|
||||
order: string[];
|
||||
graph: VariableGraph;
|
||||
parentDependencyGraph: VariableGraph;
|
||||
} | null>(null);
|
||||
|
||||
useEffect(() => {
|
||||
@@ -59,9 +61,11 @@ function DashboardVariableSelection(): JSX.Element | null {
|
||||
if (variablesTableData.length > 0 && !initializationRef.current) {
|
||||
const depGrp = buildDependencies(variablesTableData);
|
||||
const { order, graph } = buildDependencyGraph(depGrp);
|
||||
const parentDependencyGraph = buildParentDependencyGraph(graph);
|
||||
setDependencyData({
|
||||
order,
|
||||
graph,
|
||||
parentDependencyGraph,
|
||||
});
|
||||
initializationRef.current = true;
|
||||
}
|
||||
@@ -120,7 +124,7 @@ function DashboardVariableSelection(): JSX.Element | null {
|
||||
dependencyData.order,
|
||||
(node) => updatedVariables.push(node),
|
||||
);
|
||||
setVariablesToGetUpdated(updatedVariables.filter((v) => v !== name)); // question?
|
||||
setVariablesToGetUpdated(updatedVariables.filter((v) => v !== name));
|
||||
} else if (isMountedCall) {
|
||||
setVariablesToGetUpdated((prev) => prev.filter((v) => v !== name));
|
||||
}
|
||||
@@ -151,6 +155,7 @@ function DashboardVariableSelection(): JSX.Element | null {
|
||||
onValueUpdate={onValueUpdate}
|
||||
variablesToGetUpdated={variablesToGetUpdated}
|
||||
setVariablesToGetUpdated={setVariablesToGetUpdated}
|
||||
dependencyData={dependencyData}
|
||||
/>
|
||||
))}
|
||||
</Row>
|
||||
|
||||
@@ -35,12 +35,15 @@ import { popupContainer } from 'utils/selectPopupContainer';
|
||||
|
||||
import { variablePropsToPayloadVariables } from '../utils';
|
||||
import { SelectItemStyle } from './styles';
|
||||
import { areArraysEqual } from './util';
|
||||
import {
|
||||
areArraysEqual,
|
||||
checkAPIInvocation,
|
||||
onUpdateVariableNode,
|
||||
VariableGraph,
|
||||
} from './util';
|
||||
|
||||
const ALL_SELECT_VALUE = '__ALL__';
|
||||
|
||||
const variableRegexPattern = /\{\{\s*?\.([^\s}]+)\s*?\}\}/g;
|
||||
|
||||
enum ToggleTagValue {
|
||||
Only = 'Only',
|
||||
All = 'All',
|
||||
@@ -58,6 +61,11 @@ interface VariableItemProps {
|
||||
) => void;
|
||||
variablesToGetUpdated: string[];
|
||||
setVariablesToGetUpdated: React.Dispatch<React.SetStateAction<string[]>>;
|
||||
dependencyData: {
|
||||
order: string[];
|
||||
graph: VariableGraph;
|
||||
parentDependencyGraph: VariableGraph;
|
||||
} | null;
|
||||
}
|
||||
|
||||
const getSelectValue = (
|
||||
@@ -80,6 +88,7 @@ function VariableItem({
|
||||
onValueUpdate,
|
||||
variablesToGetUpdated,
|
||||
setVariablesToGetUpdated,
|
||||
dependencyData,
|
||||
}: VariableItemProps): JSX.Element {
|
||||
const [optionsData, setOptionsData] = useState<(string | number | boolean)[]>(
|
||||
[],
|
||||
@@ -112,45 +121,6 @@ function VariableItem({
|
||||
|
||||
const [errorMessage, setErrorMessage] = useState<null | string>(null);
|
||||
|
||||
const getDependentVariables = (queryValue: string): string[] => {
|
||||
const matches = queryValue.match(variableRegexPattern);
|
||||
|
||||
// Extract variable names from the matches array without {{ . }}
|
||||
return matches
|
||||
? matches.map((match) => match.replace(variableRegexPattern, '$1'))
|
||||
: [];
|
||||
};
|
||||
|
||||
const getQueryKey = (variableData: IDashboardVariable): string[] => {
|
||||
let dependentVariablesStr = '';
|
||||
|
||||
const dependentVariables = getDependentVariables(
|
||||
variableData.queryValue || '',
|
||||
);
|
||||
|
||||
const variableName = variableData.name || '';
|
||||
|
||||
dependentVariables?.forEach((element) => {
|
||||
const [, variable] =
|
||||
Object.entries(existingVariables).find(
|
||||
([, value]) => value.name === element,
|
||||
) || [];
|
||||
|
||||
dependentVariablesStr += `${element}${variable?.selectedValue}`;
|
||||
});
|
||||
|
||||
const variableKey = dependentVariablesStr.replace(/\s/g, '');
|
||||
|
||||
// added this time dependency for variables query as API respects the passed time range now
|
||||
return [
|
||||
REACT_QUERY_KEY.DASHBOARD_BY_ID,
|
||||
variableName,
|
||||
variableKey,
|
||||
`${minTime}`,
|
||||
`${maxTime}`,
|
||||
];
|
||||
};
|
||||
|
||||
// eslint-disable-next-line sonarjs/cognitive-complexity
|
||||
const getOptions = (variablesRes: VariableResponseProps | null): void => {
|
||||
if (variablesRes && variableData.type === 'QUERY') {
|
||||
@@ -240,36 +210,75 @@ function VariableItem({
|
||||
}
|
||||
};
|
||||
|
||||
const { isLoading } = useQuery(getQueryKey(variableData), {
|
||||
enabled: variableData && variableData.type === 'QUERY',
|
||||
queryFn: () =>
|
||||
dashboardVariablesQuery({
|
||||
query: variableData.queryValue || '',
|
||||
variables: variablePropsToPayloadVariables(existingVariables),
|
||||
}),
|
||||
refetchOnWindowFocus: false,
|
||||
onSuccess: (response) => {
|
||||
getOptions(response.payload);
|
||||
},
|
||||
onError: (error: {
|
||||
details: {
|
||||
error: string;
|
||||
};
|
||||
}) => {
|
||||
const { details } = error;
|
||||
|
||||
if (details.error) {
|
||||
let message = details.error;
|
||||
if (details.error.includes('Syntax error:')) {
|
||||
message =
|
||||
'Please make sure query is valid and dependent variables are selected';
|
||||
const { isLoading } = useQuery(
|
||||
[
|
||||
REACT_QUERY_KEY.DASHBOARD_BY_ID,
|
||||
variableData.name || '',
|
||||
`${minTime}`,
|
||||
`${maxTime}`,
|
||||
],
|
||||
{
|
||||
enabled:
|
||||
variableData &&
|
||||
variableData.type === 'QUERY' &&
|
||||
checkAPIInvocation(
|
||||
variablesToGetUpdated,
|
||||
variableData,
|
||||
dependencyData?.parentDependencyGraph,
|
||||
),
|
||||
queryFn: () =>
|
||||
dashboardVariablesQuery({
|
||||
query: variableData.queryValue || '',
|
||||
variables: variablePropsToPayloadVariables(existingVariables),
|
||||
}),
|
||||
refetchOnWindowFocus: false,
|
||||
onSuccess: (response) => {
|
||||
getOptions(response.payload);
|
||||
if (
|
||||
dependencyData?.parentDependencyGraph[variableData.name || ''].length === 0
|
||||
) {
|
||||
const updatedVariables: string[] = [];
|
||||
onUpdateVariableNode(
|
||||
variableData.name || '',
|
||||
dependencyData.graph,
|
||||
dependencyData.order,
|
||||
(node) => updatedVariables.push(node),
|
||||
);
|
||||
setVariablesToGetUpdated((prev) => [
|
||||
...prev,
|
||||
...updatedVariables.filter((v) => v !== variableData.name),
|
||||
]);
|
||||
}
|
||||
setErrorMessage(message);
|
||||
}
|
||||
},
|
||||
onError: (error: {
|
||||
details: {
|
||||
error: string;
|
||||
};
|
||||
}) => {
|
||||
const { details } = error;
|
||||
|
||||
if (details.error) {
|
||||
let message = details.error;
|
||||
if (details.error.includes('Syntax error:')) {
|
||||
message =
|
||||
'Please make sure query is valid and dependent variables are selected';
|
||||
}
|
||||
setErrorMessage(message);
|
||||
}
|
||||
},
|
||||
},
|
||||
});
|
||||
);
|
||||
|
||||
const handleChange = (value: string | string[]): void => {
|
||||
// if value is equal to selected value then return
|
||||
if (
|
||||
value === variableData.selectedValue ||
|
||||
(Array.isArray(value) &&
|
||||
Array.isArray(variableData.selectedValue) &&
|
||||
areArraysEqual(value, variableData.selectedValue))
|
||||
) {
|
||||
return;
|
||||
}
|
||||
if (variableData.name) {
|
||||
if (
|
||||
value === ALL_SELECT_VALUE ||
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { isEmpty } from 'lodash-es';
|
||||
import { Dashboard, IDashboardVariable } from 'types/api/dashboard/getAll';
|
||||
|
||||
export function areArraysEqual(
|
||||
@@ -136,3 +137,51 @@ export const onUpdateVariableNode = (
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
export const buildParentDependencyGraph = (
|
||||
graph: VariableGraph,
|
||||
): VariableGraph => {
|
||||
const parentGraph: VariableGraph = {};
|
||||
|
||||
// Initialize empty arrays for all nodes
|
||||
Object.keys(graph).forEach((node) => {
|
||||
parentGraph[node] = [];
|
||||
});
|
||||
|
||||
// For each node and its children in the original graph
|
||||
Object.entries(graph).forEach(([node, children]) => {
|
||||
// For each child, add the current node as its parent
|
||||
children.forEach((child) => {
|
||||
parentGraph[child].push(node);
|
||||
});
|
||||
});
|
||||
|
||||
return parentGraph;
|
||||
};
|
||||
|
||||
export const checkAPIInvocation = (
|
||||
variablesToGetUpdated: string[],
|
||||
variableData: IDashboardVariable,
|
||||
parentDependencyGraph?: VariableGraph,
|
||||
): boolean => {
|
||||
if (isEmpty(variableData.name)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (isEmpty(parentDependencyGraph)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// if no dependency then true
|
||||
const haveDependency =
|
||||
parentDependencyGraph?.[variableData.name || '']?.length > 0;
|
||||
if (!haveDependency) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// if variable is in the list and has dependency then check if its the top element in the queue then true else false
|
||||
return (
|
||||
variablesToGetUpdated.length > 0 &&
|
||||
variablesToGetUpdated[0] === variableData.name
|
||||
);
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user