Skip to content

Commit

Permalink
session view search will now only search through verbose stuff if ver…
Browse files Browse the repository at this point in the history
…bose mode is on.
  • Loading branch information
mitodrummer committed Apr 11, 2022
1 parent bcdb0b2 commit ba27e1c
Show file tree
Hide file tree
Showing 14 changed files with 177 additions and 68 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -1264,6 +1264,7 @@ export const childProcessMock: Process = {
getAlerts: () => [],
updateAlertsStatus: (_) => undefined,
hasExec: () => false,
isVerbose: () => true,
getOutput: () => '',
getDetails: () =>
({
Expand Down Expand Up @@ -1345,6 +1346,7 @@ export const processMock: Process = {
getAlerts: () => [],
updateAlertsStatus: (_) => undefined,
hasExec: () => false,
isVerbose: () => true,
getOutput: () => '',
getDetails: () =>
({
Expand Down Expand Up @@ -1540,6 +1542,7 @@ export const mockProcessMap = mockEvents.reduce(
getDetails: () => event,
isUserEntered: () => false,
getMaxAlertLevel: () => null,
isVerbose: () => true,
};
return processMap;
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,7 @@ export interface Process {
isUserEntered(): boolean;
getMaxAlertLevel(): number | null;
getChildren(verboseMode: boolean): Process[];
isVerbose(): boolean;
}

export type ProcessMap = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ describe('process tree hook helpers tests', () => {
});

it('searchProcessTree works', () => {
const searchResults = searchProcessTree(mockProcessMap, SEARCH_QUERY);
const searchResults = searchProcessTree(mockProcessMap, SEARCH_QUERY, true);

// search returns the process with search query in its event args
expect(searchResults[0].id).toBe(SEARCH_RESULT_PROCESS_ID);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -137,13 +137,25 @@ export const buildProcessTree = (
// this funtion also returns a list of process results which is used by session_view_search_bar to drive
// result navigation UX
// FYI: this function mutates properties of models contained in processMap
export const searchProcessTree = (processMap: ProcessMap, searchQuery: string | undefined) => {
export const searchProcessTree = (
processMap: ProcessMap,
searchQuery: string | undefined,
verboseMode: boolean
) => {
const results = [];

for (const processId of Object.keys(processMap)) {
const process = processMap[processId];

if (searchQuery) {
const details = process.getDetails();
const entryLeader = details?.process?.entry_leader;

// if this is the entry leader process OR verbose mode is OFF and is a verbose process, don't match.
if (entryLeader?.entity_id === process.id || (!verboseMode && process.isVerbose())) {
continue;
}

const event = process.getDetails();
const { working_directory: workingDirectory, args } = event.process || {};

Expand Down
38 changes: 27 additions & 11 deletions x-pack/plugins/session_view/public/components/process_tree/hooks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ interface UseProcessTreeDeps {
alerts: ProcessEvent[];
searchQuery?: string;
updatedAlertsStatus: AlertStatusEventEntityIdMap;
verboseMode: boolean;
}

export class ProcessImpl implements Process {
Expand Down Expand Up @@ -83,18 +84,12 @@ export class ProcessImpl implements Process {
return false;
}

const { group_leader: groupLeader, session_leader: sessionLeader } =
child.getDetails().process ?? {};

// search matches or processes with alerts will never be filtered out
if (child.autoExpand || child.searchMatched || child.hasAlerts()) {
// processes with alerts will never be filtered out
if (child.autoExpand || child.hasAlerts()) {
return true;
}

// Hide processes that have their session leader as their process group leader.
// This accounts for a lot of noise from bash and other shells forking, running auto completion processes and
// other shell startup activities (e.g bashrc .profile etc)
if (!groupLeader || !sessionLeader || groupLeader.pid === sessionLeader.pid) {
if (child.isVerbose()) {
return false;
}

Expand All @@ -105,6 +100,26 @@ export class ProcessImpl implements Process {
return children;
}

isVerbose() {
const {
group_leader: groupLeader,
session_leader: sessionLeader,
entry_leader: entryLeader,
} = this.getDetails().process ?? {};

// Processes that have their session leader as their process group leader are considered "verbose"
// This accounts for a lot of noise from bash and other shells forking, running auto completion processes and
// other shell startup activities (e.g bashrc .profile etc)
if (
this.id !== entryLeader?.entity_id &&
(!groupLeader || !sessionLeader || groupLeader.pid === sessionLeader.pid)
) {
return true;
}

return false;
}

hasOutput() {
return !!this.findEventByAction(this.events, EventAction.output);
}
Expand Down Expand Up @@ -231,6 +246,7 @@ export const useProcessTree = ({
alerts,
searchQuery,
updatedAlertsStatus,
verboseMode,
}: UseProcessTreeDeps) => {
// initialize map, as well as a placeholder for session leader process
// we add a fake session leader event, sourced from wide event data.
Expand Down Expand Up @@ -304,9 +320,9 @@ export const useProcessTree = ({
}, [processMap, alerts, alertsProcessed]);

useEffect(() => {
setSearchResults(searchProcessTree(processMap, searchQuery));
setSearchResults(searchProcessTree(processMap, searchQuery, verboseMode));
autoExpandProcessTree(processMap);
}, [searchQuery, processMap]);
}, [searchQuery, processMap, verboseMode]);

// set new orphans array on the session leader
const sessionLeader = processMap[sessionEntityId];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ describe('ProcessTree component', () => {
});

it('When Verbose mode is OFF, it should not show all childrens', () => {
renderResult = mockedContext.render(<ProcessTree {...props} verboseModeOn={false} />);
renderResult = mockedContext.render(<ProcessTree {...props} verboseMode={false} />);
expect(renderResult.queryByText('cat')).toBeFalsy();

const selectionArea = renderResult.queryAllByTestId('sessionView:processTreeNode');
Expand All @@ -115,7 +115,7 @@ describe('ProcessTree component', () => {
});

it('When Verbose mode is ON, it should show all childrens', () => {
renderResult = mockedContext.render(<ProcessTree {...props} verboseModeOn={true} />);
renderResult = mockedContext.render(<ProcessTree {...props} verboseMode={true} />);
expect(renderResult.queryByText('cat')).toBeTruthy();

const selectionArea = renderResult.queryAllByTestId('sessionView:processTreeNode');
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,8 +62,8 @@ export interface ProcessTreeDeps {
// a map for alerts with updated status and process.entity_id
updatedAlertsStatus: AlertStatusEventEntityIdMap;
onShowAlertDetails: (alertUuid: string) => void;
timeStampOn?: boolean;
verboseModeOn?: boolean;
showTimestamp?: boolean;
verboseMode?: boolean;
}

export const ProcessTree = ({
Expand All @@ -83,8 +83,8 @@ export const ProcessTree = ({
setSearchResults,
updatedAlertsStatus,
onShowAlertDetails,
timeStampOn,
verboseModeOn,
showTimestamp = true,
verboseMode = false,
}: ProcessTreeDeps) => {
const [isInvestigatedEventVisible, setIsInvestigatedEventVisible] = useState<boolean>(true);
const [isInvestigatedEventAbove, setIsInvestigatedEventAbove] = useState<boolean>(false);
Expand All @@ -96,6 +96,7 @@ export const ProcessTree = ({
alerts,
searchQuery,
updatedAlertsStatus,
verboseMode,
});

const eventsRemaining = useMemo(() => {
Expand Down Expand Up @@ -232,8 +233,8 @@ export const ProcessTree = ({
scrollerRef={scrollerRef}
onChangeJumpToEventVisibility={onChangeJumpToEventVisibility}
onShowAlertDetails={onShowAlertDetails}
timeStampOn={timeStampOn}
verboseModeOn={verboseModeOn}
showTimestamp={showTimestamp}
verboseMode={verboseMode}
searchResults={searchResults}
loadPreviousButton={
hasPreviousPage ? (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,11 @@ import { useButtonStyles } from './use_button_styles';
export const ChildrenProcessesButton = ({
onToggle,
isExpanded,
disabled,
}: {
onToggle: () => void;
isExpanded: boolean;
disabled: boolean;
}) => {
const { button, buttonArrow, expandedIcon } = useButtonStyles({ isExpanded });

Expand All @@ -24,6 +26,7 @@ export const ChildrenProcessesButton = ({
css={button}
onClick={onToggle}
data-test-subj="sessionView:processTreeNodeChildProcessesButton"
disabled={disabled}
>
<FormattedMessage id="xpack.sessionView.childProcesses" defaultMessage="Child processes" />
<EuiIcon css={buttonArrow} size="s" type={expandedIcon} />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ describe('ProcessTreeNode component', () => {
} as unknown as RefObject<HTMLDivElement>,
onChangeJumpToEventVisibility: jest.fn(),
onShowAlertDetails: jest.fn(),
showTimestamp: true,
verboseMode: false,
};

beforeEach(() => {
Expand Down Expand Up @@ -196,7 +198,7 @@ describe('ProcessTreeNode component', () => {
it('When Timestamp is ON, it shows Timestamp', async () => {
// set a mock where Timestamp is turned ON
renderResult = mockedContext.render(
<ProcessTreeNode {...props} timeStampOn={true} process={processMock} />
<ProcessTreeNode {...props} showTimestamp={true} process={processMock} />
);

expect(renderResult.getByTestId('sessionView:processTreeNodeTimestamp')).toBeTruthy();
Expand All @@ -205,7 +207,7 @@ describe('ProcessTreeNode component', () => {
it('When Timestamp is OFF, it doesnt show Timestamp', async () => {
// set a mock where Timestamp is turned OFF
renderResult = mockedContext.render(
<ProcessTreeNode {...props} timeStampOn={false} process={processMock} />
<ProcessTreeNode {...props} showTimestamp={false} process={processMock} />
);

expect(renderResult.queryByTestId('sessionView:processTreeNodeTimestamp')).toBeFalsy();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,8 @@ export interface ProcessDeps {
jumpToEntityId?: string;
investigatedAlertId?: string;
selectedProcessId?: string;
timeStampOn?: boolean;
verboseModeOn?: boolean;
showTimestamp: boolean;
verboseMode: boolean;
searchResults?: Process[];
scrollerRef: RefObject<HTMLDivElement>;
onChangeJumpToEventVisibility: (isVisible: boolean, isAbove: boolean) => void;
Expand All @@ -63,8 +63,8 @@ export function ProcessTreeNode({
jumpToEntityId,
investigatedAlertId,
selectedProcessId,
timeStampOn = true,
verboseModeOn = true,
showTimestamp,
verboseMode,
searchResults,
scrollerRef,
onChangeJumpToEventVisibility,
Expand All @@ -74,14 +74,10 @@ export function ProcessTreeNode({
}: ProcessDeps) {
const textRef = useRef<HTMLSpanElement>(null);

const [childrenExpanded, setChildrenExpanded] = useState(isSessionLeader || process.autoExpand);
const [childrenExpanded, setChildrenExpanded] = useState(isSessionLeader);
const [alertsExpanded, setAlertsExpanded] = useState(false);
const { searchMatched } = process;

useEffect(() => {
setChildrenExpanded(isSessionLeader || process.autoExpand);
}, [isSessionLeader, process.autoExpand]);

const alerts = process.getAlerts();
const hasAlerts = useMemo(() => !!alerts.length, [alerts]);
const hasInvestigatedAlert = useMemo(
Expand Down Expand Up @@ -194,8 +190,8 @@ export function ProcessTreeNode({
// hidden processes.
}

return process.getChildren(verboseModeOn);
}, [process, verboseModeOn, searchResults]);
return process.getChildren(verboseMode);
}, [process, verboseMode, searchResults]);

if (!processDetails?.process) {
return null;
Expand All @@ -213,7 +209,7 @@ export function ProcessTreeNode({
start,
} = processDetails.process;

const shouldRenderChildren = childrenExpanded && children?.length > 0;
const shouldRenderChildren = (process.autoExpand || childrenExpanded) && children?.length > 0;
const childrenTreeDepth = depth + 1;

const showUserEscalation = !isSessionLeader && !!user?.id && user.id !== parent?.user?.id;
Expand Down Expand Up @@ -263,7 +259,7 @@ export function ProcessTreeNode({
</small>
)}
</span>
{timeStampOn && (
{showTimestamp && (
<span data-test-subj="sessionView:processTreeNodeTimestamp" css={styles.timeStamp}>
{timeStampsNormal}
</span>
Expand All @@ -284,7 +280,11 @@ export function ProcessTreeNode({
</EuiButton>
)}
{!isSessionLeader && children.length > 0 && (
<ChildrenProcessesButton isExpanded={childrenExpanded} onToggle={onChildrenToggle} />
<ChildrenProcessesButton
disabled={process.autoExpand}
isExpanded={process.autoExpand || childrenExpanded}
onToggle={onChildrenToggle}
/>
)}
{alerts.length > 0 && (
<AlertButton
Expand Down Expand Up @@ -319,8 +319,8 @@ export function ProcessTreeNode({
jumpToEntityId={jumpToEntityId}
investigatedAlertId={investigatedAlertId}
selectedProcessId={selectedProcessId}
timeStampOn={timeStampOn}
verboseModeOn={verboseModeOn}
showTimestamp={showTimestamp}
verboseMode={verboseMode}
searchResults={searchResults}
scrollerRef={scrollerRef}
onChangeJumpToEventVisibility={onChangeJumpToEventVisibility}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/
import React, { useState, useCallback, useEffect } from 'react';
import React, { useState, useCallback, useEffect, useMemo } from 'react';
import {
EuiEmptyPrompt,
EuiButton,
Expand Down Expand Up @@ -72,6 +72,11 @@ export const SessionView = ({

const styles = useStyles({ height, isFullScreen });

// to give an indication to the user that there may be more search results if they turn on verbose mode.
const showVerboseSearchTooltip = useMemo(() => {
return !!(!displayOptions?.verboseMode && searchQuery && searchResults?.length === 0);
}, [displayOptions?.verboseMode, searchResults, searchQuery]);

const onProcessSelected = useCallback((process: Process | null) => {
setSelectedProcess(process);
}, []);
Expand Down Expand Up @@ -194,6 +199,7 @@ export const SessionView = ({
<SessionViewDisplayOptions
displayOptions={displayOptions!}
onChange={handleOptionChange}
showVerboseSearchTooltip={showVerboseSearchTooltip}
/>
</EuiFlexItem>

Expand Down Expand Up @@ -273,8 +279,8 @@ export const SessionView = ({
setSearchResults={setSearchResults}
updatedAlertsStatus={updatedAlertsStatus}
onShowAlertDetails={onShowAlertDetails}
timeStampOn={displayOptions?.timestamp}
verboseModeOn={displayOptions?.verboseMode}
showTimestamp={displayOptions?.timestamp}
verboseMode={displayOptions?.verboseMode}
/>
</div>
)}
Expand Down
Loading

0 comments on commit ba27e1c

Please sign in to comment.