Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,11 @@
"Advanced Search": "Advanced Search",
"Advanced search parameters": "Advanced search parameters",
"Cancel": "Cancel",
"Cancel the current search": "Cancel the current search",
"Canceled": "Canceled",
"Close": "Close",
"Correlation graph already matches search": "Correlation graph already matches search",
"Correlation graph is focused on the current view.": "Correlation graph is focused on the current view.",
"Correlation result was empty.": "Correlation result was empty.",
"Current view does not provide a starting point for correlation": "Current view does not provide a starting point for correlation",
"Custom": "Custom",
"Custom duration": "Custom duration",
Expand All @@ -29,6 +31,7 @@
"Netflow Plugin Disabled": "Netflow Plugin Disabled",
"No correlated data found": "No correlated data found",
"No Correlated Signals Found": "No Correlated Signals Found",
"No results.": "No results.",
"No starting point for correlation": "No starting point for correlation",
"Open the Troubleshooting Panel": "Open the Troubleshooting Panel",
"Other duration": "Other duration",
Expand All @@ -40,6 +43,7 @@
"Search Error": "Search Error",
"Search Failed": "Search Failed",
"Search Type": "Search Type",
"Search was interrupted": "Search was interrupted",
"Searching": "Searching",
"seconds": "seconds",
"Select starting data": "Select starting data",
Expand Down
8 changes: 4 additions & 4 deletions web/src/components/AdvancedSearchForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -30,13 +30,13 @@ import { HelpPopover } from './HelpPopover';
interface AdvancedSearchFormProps {
search: Search;
onSearch: (search: Search) => void;
onCancel: () => void;
onClose: () => void;
}

export const AdvancedSearchForm: React.FC<AdvancedSearchFormProps> = ({
search,
onSearch,
onCancel,
onClose,
}) => {
const { t } = useTranslation('plugin__troubleshooting-panel-console-plugin');
const domains = useDomains();
Expand Down Expand Up @@ -283,8 +283,8 @@ export const AdvancedSearchForm: React.FC<AdvancedSearchFormProps> = ({
</Button>
</Tooltip>
</div>
<Button variant="secondary" size="sm" onClick={onCancel}>
{t('Cancel')}
<Button variant="secondary" size="sm" onClick={onClose}>
{t('Close')}
</Button>
</ActionGroup>
</Form>
Expand Down
97 changes: 70 additions & 27 deletions web/src/components/Korrel8rPanel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,9 @@ export default function Korrel8rPanel() {
// Showing advanced query
const [showAdvanced, setShowAdvanced] = React.useState(false);

const cancelRef = React.useRef<(() => void) | null>(null);
const [isLoading, setIsLoading] = React.useState(false);

// Compute constraint from search period.
const constraint = React.useMemo((): korrel8r.Constraint | undefined => {
if (!search.period) return undefined;
Expand Down Expand Up @@ -94,14 +97,24 @@ export default function Korrel8rPanel() {

// Fetch a new result from the korrel8r service when the search changes.
React.useEffect(() => {
// Cancel previous
if (cancelRef.current) {
cancelRef.current();
cancelRef.current = null;
setIsLoading(false);
}

// Used the stored result on first open, if there is one.
if (useStoredResult.current) {
useStoredResult.current = false; // Fetch a new result next time.
return;
}
const queryStr = search?.queryStr;
if (!queryStr) return;

let cancelled = false;
const queryStr = search?.queryStr;
if (!queryStr) {
dispatchResult({ title: t('Empty Query'), message: t('No starting point for correlation') });
return;
Comment thread
coderabbitai[bot] marked this conversation as resolved.
}
const start: api.Start = {
queries: [queryStr],
constraint: constraint?.toAPI(),
Expand All @@ -111,25 +124,43 @@ export default function Korrel8rPanel() {
search.searchType === SearchType.Goal
? getGoalsGraph({ start, goals: [search.goal] })
: getNeighborsGraph({ start, depth: search.depth });

setIsLoading(true);
const cancel = () => fetch.cancel();
cancelRef.current = cancel;
const anotherFetchIsRunning = () => cancelRef.current !== cancel;
fetch
.then((response: api.Graph) => {
if (cancelled) return;
if (anotherFetchIsRunning()) return;
dispatchResult(
Array.isArray(response?.nodes) && response.nodes.length > 0
? { graph: new korrel8r.Graph(response) }
: { title: t('Empty Result'), message: t('No correlated data found') },
);
})
.catch((e: api.ApiError) => {
if (cancelled) return;
dispatchResult({
title: e?.body?.error ? t('Search Error') : t('Search Failed'),
message: e?.body?.error || e.message || 'Unknown Error',
isError: true,
});
.catch((e) => {
if (anotherFetchIsRunning()) return;
if (e instanceof api.CancelError) {
dispatchResult({
title: t('Canceled'),
message: t('Search was interrupted'),
isError: true,
});
} else {
dispatchResult({
title: e?.body?.error ? t('Search Error') : t('Search Failed'),
message: e?.body?.error || e.message || 'Unknown Error',
isError: true,
});
}
})
.finally(() => {
if (anotherFetchIsRunning()) return;
cancelRef.current = null;
setIsLoading(false);
});
return () => {
cancelled = true;
if (!anotherFetchIsRunning()) cancelRef.current = null;
fetch.cancel();
};
}, [search, constraint, dispatchResult, t]);
Expand Down Expand Up @@ -198,18 +229,29 @@ export default function Korrel8rPanel() {
</ExpandableSectionToggle>
</Tooltip>

{/* Refresh button */}
<Tooltip content={t('Refresh the graph by re-running the current search.')}>
{/* Refresh / Cancel button */}
{isLoading ? (
<Button
variant="link"
variant="secondary"
size="sm"
isAriaDisabled={!search?.queryStr}
onClick={() => dispatchSearch(search)}
aria-label={t('Refresh')}
onClick={() => cancelRef.current?.()}
aria-label={t('Cancel')}
>
<SyncIcon />
{t('Cancel')}
</Button>
</Tooltip>
) : (
<Tooltip content={t('Refresh the graph by re-running the current search.')}>
<Button
variant="link"
size="sm"
isAriaDisabled={!search?.queryStr}
onClick={() => dispatchSearch(search)}
aria-label={t('Refresh')}
>
<SyncIcon />
</Button>
</Tooltip>
)}
</Flex>
</Flex>

Expand All @@ -223,31 +265,32 @@ export default function Korrel8rPanel() {
<AdvancedSearchForm
search={search}
onSearch={dispatchSearch}
onCancel={() => setShowAdvanced(false)}
onClose={() => setShowAdvanced(false)}
/>
</ExpandableSection>

<Divider />

<StackItem className="tp-plugin__panel-topology-container" isFilled={true}>
<Topology result={result} t={t} constraint={constraint} />
<Topology isLoading={isLoading} result={result} t={t} constraint={constraint} />
</StackItem>
</Stack>
</>
);
}

interface TopologyProps {
isLoading?: boolean;
result?: Result;
constraint?: korrel8r.Constraint;
t: TFunction;
}

const Topology: React.FC<TopologyProps> = ({ result, t, constraint }) => {
const Topology: React.FC<TopologyProps> = ({ isLoading, result, t, constraint }) => {
const [loggingAvailable, loggingAvailableLoading] = usePluginAvailable('logging-view-plugin');
const [netobserveAvailable, netobserveAvailableLoading] = usePluginAvailable('netobserv-plugin');

if (!result || loggingAvailableLoading || netobserveAvailableLoading) {
if (isLoading || loggingAvailableLoading || netobserveAvailableLoading) {
// korrel8r query is loading or the plugin checks are loading
return <Searching />;
}
Expand All @@ -266,10 +309,10 @@ const Topology: React.FC<TopologyProps> = ({ result, t, constraint }) => {

return (
<TopologyInfoState
titleText={result.title || t('No Correlated Signals Found')}
titleText={result?.title || t('No Correlated Signals Found')}
// Only display fisrt 400 characters of error to prevent repeating errors
text={result.message ? result.message.slice(0, 400) : t('Correlation result was empty.')}
isError={result.isError}
text={result?.message ? result?.message.slice(0, 400) : t('No results.')}
isError={result?.isError}
/>
);
};
Expand Down
10 changes: 6 additions & 4 deletions web/src/redux-actions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,14 @@ export type Search = {
period?: Period;
};

// Result displayed in troubleshooting panel, graph or error.
// Result displayed in troubleshooting panel, graph or message.
export type Result = {
graph?: Graph;
message?: string;
title?: string;
graph?: Graph; // Successful result
// True means the call failed and can/should be re-tried.
// False means the call should not be re-tried, it is impossible or succeeded with empty results.
isError?: boolean;
title?: string; // Title when there is no graph.
message?: string; // Message when there is no graph.
};

// Default search parameters do a neighbourhood search of depth 3.
Expand Down