-
Notifications
You must be signed in to change notification settings - Fork 8.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[Security Solution] Alerts visualization free field selection #120610
[Security Solution] Alerts visualization free field selection #120610
Conversation
Hey Kevin! A few comments:
Question:
|
@@ -40,7 +39,7 @@ export const AlertsCountPanel = memo<AlertsCountPanelProps>( | |||
// create a unique, but stable (across re-renders) query id | |||
const uniqueQueryId = useMemo(() => `${DETECTIONS_ALERTS_COUNT_ID}-${uuid.v4()}`, []); | |||
const [selectedStackByOption, setSelectedStackByOption] = | |||
useState<AlertsStackByField>(DEFAULT_STACK_BY_FIELD); | |||
useState<string>(DEFAULT_STACK_BY_FIELD); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
useState<string>(DEFAULT_STACK_BY_FIELD); | |
useState(DEFAULT_STACK_BY_FIELD); |
💅 TS will automatically assume it's a string
@@ -109,7 +109,7 @@ export const AlertsHistogramPanel = memo<AlertsHistogramPanelProps>( | |||
const [isInspectDisabled, setIsInspectDisabled] = useState(false); | |||
const [defaultNumberFormat] = useUiSetting$<string>(DEFAULT_NUMBER_FORMAT); | |||
const [totalAlertsObj, setTotalAlertsObj] = useState<AlertsTotal>(defaultTotalAlertsObj); | |||
const [selectedStackByOption, setSelectedStackByOption] = useState<AlertsStackByField>( | |||
const [selectedStackByOption, setSelectedStackByOption] = useState<string>( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You can drop the <string>
here as well, I think.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
💅
aria-label={i18n.STACK_BY_ARIA_LABEL} | ||
placeholder={i18n.STACK_BY_PLACEHOLDER} | ||
prepend={i18n.STACK_BY_LABEL} | ||
singleSelection={{ asPlainText: true }} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Refactoring { asPlainText: true }
into a constant outside the component or into a ref inside the component will prevent rerenders of the EuiComboBox
.
min-width: 350px; | ||
`; | ||
|
||
export const StackByComboBox: React.FC<StackedBySelectProps> = ({ selected, onSelect }) => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
More a question: I saw that a lot of other modules use React.memo
here instead. Is this something that we should do here as well wrt to performance?
>(undefined); | ||
const { pathname } = useLocation(); | ||
|
||
const { browserFields } = useSourcererDataView(getScopeFromPath(pathname)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does useSourcererDataView()
update during runtime sometimes or can we assume browserFields
is static at this point?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yes I believe it can be changed by a form control present on most pages that allows a user to change the index patter...data views that are being used to generate the data on a page, this hook will be re-evaluated then.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks :)
export const useStackByFields = () => { | ||
const [stackByFieldOptions, setStackByFieldOptions] = useState< | ||
undefined | EuiComboBoxOptionOption[] | ||
>(undefined); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I was thinking about a way to get rid of undefined
here. If this piece of state is initialized later in the function, we can eliminate it, I think. Something similar like this:
function fieldsToOptions(fields) {
return Object.entries(allFields).reduce<EuiComboBoxOptionOption[]>(
(filteredOptions: EuiComboBoxOptionOption[], [key, field]) => {
if (field.aggregatable === true) {
return [...filteredOptions, { label: key, value: key }];
} else {
return filteredOptions;
}
},
[]
);
}
export const useStackByFields = () => {
const { pathname } = useLocation();
const { browserFields } = useSourcererDataView(getScopeFromPath(pathname));
const allFields = useMemo(() => getAllFieldsByName(browserFields), [browserFields]);
const [stackByFieldOptions, setStackByFieldOptions] = useState(() => fieldsToOptions(allFields));
useEffect(() => {
setStackByFieldOptions(fieldsToOptions(allfields));
}, [allFields]);
return useMemo(() => stackByFieldOptions, [stackByFieldOptions]);
};
In case allFields
does not change, we can even remove the useEffect
in there. Wdyt?
(event: React.ChangeEvent<HTMLSelectElement>) => { | ||
onSelect(event.target.value as AlertsStackByField); | ||
export const StackByComboBoxWrapper = styled.div` | ||
min-width: 350px; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🎉
|
||
export const getAlertsCountQuery = ( | ||
stackByField: AlertsStackByField, | ||
stackByField: string, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we have an ECS fields type? Ignore, this can accept any aggregate-able field.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I believe we do, but this field can be any arbitrary field present in the documents, so I think string is as specific as we can be. The types used to derive this prop support that as well.
|
||
export const StackByComboBox: React.FC<StackedBySelectProps> = ({ selected, onSelect }) => { | ||
const onChange = useCallback( | ||
(options) => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
is options === selectedOption
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
no, it's defined by eui here https://github.com/elastic/eui/blob/main/src/components/combo_box/combo_box.tsx#L102
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM 👍
@monina-n updated the styles, please see the second screenshot. re: no value selected, both the table and the graph show the empty state in that case. |
@@ -48,3 +54,28 @@ export const useInspectButton = ({ | |||
}; | |||
}, [setQuery, loading, response, request, refetch, uniqueQueryId, deleteQuery]); | |||
}; | |||
|
|||
function fieldsToOptions(fields: { [fieldName: string]: Partial<BrowserField> }) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would rename this to getAggregatableFields
💛 Build succeeded, but was flaky
Test FailuresMetrics [docs]Async chunks
History
To update your PR or re-run it, just comment with: |
💔 Backport failedThe backport operation could not be completed due to the following error: The backport PRs will be merged automatically after passing CI. To backport manually run: |
…c#120610) * Use EuiComboBox in place of a select for alert page visuals * Remove console.log * Better variable name in reduce function * Remove comment * Remove typo * Fix linting/tests * PR feedback * Add missing mocks * Add router mocks * Rename getAggregatableFields
Summary
This pr changes the controls on the alerts aggregation visualization to be an EuiComboBox where any aggregatable field can be used for showing aggregate statistics instead of just 10 static possible values in an EuiSelect.
Updated styles: 400px fixed width to match max-width from eui, compressed=true
Checklist
Delete any items that are not applicable to this PR.