fixed field data sourcing (#177472)

## Summary

This fixes:
SDH issue **882**
https://github.com/elastic/kibana/issues/173627

### Before the fix
Note how the field actually displays an alias instead of the value. This
is due some fallback behavior I think.

![highlighted_before](c66ef18f-d0f9-4964-b69f-94bba6d31c60)

### After the fix

![highlighted_after](ee730392-7617-4654-87bc-a8addb7342e2)


The missing bit was the actual value to display as it was not passed
down correctly from the parent conext

### How to test this?

1. create custom index and populate it with data

```
PUT test

POST test/_doc
{
  "user.id": "888",
  "@timestamp": "2024-02-21T15:20:10.084Z"
}
```

2. create threshold rule looking like this:


![image](07089ba8-e0b9-40f1-8372-15cb8a94e043)

3. actual value that triggered the alert should be rendered in the
highlighted fields panel in the flyout
This commit is contained in:
Luke G 2024-02-22 18:35:46 +01:00 committed by GitHub
parent 3ef768aa45
commit 3ab8e45949
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 93 additions and 18 deletions

View file

@ -7,7 +7,10 @@
import { renderHook } from '@testing-library/react-hooks'; import { renderHook } from '@testing-library/react-hooks';
import { mockDataFormattedForFieldBrowser } from '../mocks/mock_data_formatted_for_field_browser'; import {
mockDataFormattedForFieldBrowser,
mockDataFormattedForFieldBrowserWithOverridenField,
} from '../mocks/mock_data_formatted_for_field_browser';
import { useHighlightedFields } from './use_highlighted_fields'; import { useHighlightedFields } from './use_highlighted_fields';
import { SENTINEL_ONE_AGENT_ID_FIELD } from '../../../../common/utils/sentinelone_alert_check'; import { SENTINEL_ONE_AGENT_ID_FIELD } from '../../../../common/utils/sentinelone_alert_check';
@ -23,6 +26,25 @@ describe('useHighlightedFields', () => {
}); });
}); });
it('should return overriden field value when it is present', () => {
const hookResult = renderHook(() =>
useHighlightedFields({
dataFormattedForFieldBrowser: mockDataFormattedForFieldBrowserWithOverridenField,
})
);
// NOTE: overrideField is constructed based on specific field from the result set
expect(hookResult.result.current).toMatchObject({
'kibana.alert.threshold_result.terms.field': {
overrideField: {
field: 'kibana.alert.threshold_result.terms.value',
values: ['overriden value'], // missing value in the override
},
values: ['original value'],
},
});
});
it('should omit endpoint agent id field if data is not s1 alert', () => { it('should omit endpoint agent id field if data is not s1 alert', () => {
const hookResult = renderHook(() => const hookResult = renderHook(() =>
useHighlightedFields({ useHighlightedFields({

View file

@ -34,7 +34,7 @@ export interface UseHighlightedFieldsResult {
/** /**
* If the field has a custom override * If the field has a custom override
*/ */
overrideField?: string; overrideField?: { field: string; values: string[] };
/** /**
* Values for the field * Values for the field
*/ */
@ -114,7 +114,13 @@ export const useHighlightedFields = ({
return { return {
...acc, ...acc,
[field.id]: { [field.id]: {
...(field.overrideField && { overrideField: field.overrideField }), ...(field.overrideField && {
overrideField: {
field: field.overrideField,
values:
find({ field: field.overrideField }, dataFormattedForFieldBrowser)?.values ?? [],
},
}),
values: fieldValues, values: fieldValues,
}, },
}; };

View file

@ -7,10 +7,15 @@
import type { TimelineEventsDetailsItem } from '@kbn/timelines-plugin/common'; import type { TimelineEventsDetailsItem } from '@kbn/timelines-plugin/common';
/** export const ruleTypeField: TimelineEventsDetailsItem = {
* Mock an array of fields for an alert category: 'kibana',
*/ field: 'kibana.alert.rule.type',
export const mockDataFormattedForFieldBrowser: TimelineEventsDetailsItem[] = [ values: ['query'],
originalValue: ['query'],
isObjectArray: false,
};
export const baseFields: TimelineEventsDetailsItem[] = [
{ {
category: 'base', category: 'base',
field: '@timestamp', field: '@timestamp',
@ -60,13 +65,6 @@ export const mockDataFormattedForFieldBrowser: TimelineEventsDetailsItem[] = [
originalValue: ['rule-parameters-index'], originalValue: ['rule-parameters-index'],
isObjectArray: false, isObjectArray: false,
}, },
{
category: 'kibana',
field: 'kibana.alert.rule.type',
values: ['query'],
originalValue: ['query'],
isObjectArray: false,
},
{ {
category: 'kibana', category: 'kibana',
field: 'kibana.alert.rule.uuid', field: 'kibana.alert.rule.uuid',
@ -89,3 +87,28 @@ export const mockDataFormattedForFieldBrowser: TimelineEventsDetailsItem[] = [
isObjectArray: false, isObjectArray: false,
}, },
]; ];
/**
* Mock an array of fields for an alert
*/
export const mockDataFormattedForFieldBrowser: TimelineEventsDetailsItem[] = [
ruleTypeField,
...baseFields,
];
export const mockDataFormattedForFieldBrowserWithOverridenField = [
{ ...ruleTypeField, values: ['threshold'], originalValue: ['threshold'] },
{
category: 'base',
field: 'kibana.alert.threshold_result.terms.field',
values: ['original value'],
isObjectArray: false,
},
{
category: 'base',
field: 'kibana.alert.threshold_result.terms.value',
values: ['overriden value'],
isObjectArray: false,
},
...baseFields,
];

View file

@ -33,10 +33,10 @@ describe('convertHighlightedFieldsToTableRow', () => {
]); ]);
}); });
it('should convert take override name over default name', () => { it('should convert take override name over default name and use original values if not present in the override', () => {
const highlightedFields = { const highlightedFields = {
'host.name': { 'host.name': {
overrideField: 'host.name-override', overrideField: { field: 'host.name-override', values: [] },
values: ['host-1'], values: ['host-1'],
}, },
}; };
@ -53,6 +53,27 @@ describe('convertHighlightedFieldsToTableRow', () => {
}, },
]); ]);
}); });
it('should convert take override name over default name and use provided values', () => {
const highlightedFields = {
'host.name': {
overrideField: { field: 'host.name-override', values: ['value override!'] },
values: ['host-1'],
},
};
expect(convertHighlightedFieldsToTableRow(highlightedFields, scopeId, isPreview)).toEqual([
{
field: 'host.name-override',
description: {
field: 'host.name-override',
originalField: 'host.name',
values: ['value override!'],
scopeId: 'scopeId',
isPreview,
},
},
]);
});
}); });
describe('convertHighlightedFieldsToPrevalenceFilters', () => { describe('convertHighlightedFieldsToPrevalenceFilters', () => {

View file

@ -21,9 +21,12 @@ export const convertHighlightedFieldsToTableRow = (
): HighlightedFieldsTableRow[] => { ): HighlightedFieldsTableRow[] => {
const fieldNames = Object.keys(highlightedFields); const fieldNames = Object.keys(highlightedFields);
return fieldNames.map((fieldName) => { return fieldNames.map((fieldName) => {
const values = highlightedFields[fieldName].values; const overrideFieldName = highlightedFields[fieldName].overrideField?.field;
const overrideFieldName = highlightedFields[fieldName].overrideField; const overrideFieldValues = highlightedFields[fieldName].overrideField?.values;
const field = overrideFieldName ? overrideFieldName : fieldName; const field = overrideFieldName ? overrideFieldName : fieldName;
const values = overrideFieldValues?.length
? overrideFieldValues
: highlightedFields[fieldName].values;
return { return {
field, field,