[SecuritySolution] Fix topN histograms for custom fields (#123489)

* custom fields topN histograms fixed

* add runtime_mappings to response inspect mock

Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com>
This commit is contained in:
Sergi Massaneda 2022-01-28 15:32:52 +01:00 committed by GitHub
parent 5aa26ed37d
commit e0a7a1bb9e
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
11 changed files with 64 additions and 1 deletions

View file

@ -5,6 +5,7 @@
* 2.0.
*/
import { MappingRuntimeFields } from '@elastic/elasticsearch/lib/api/typesWithBodyKey';
import type { IEsSearchResponse } from '../../../../../../../src/plugins/data/common';
import { AuthenticationHit } from '../hosts';
import { Inspect, Maybe, TimerangeInput } from '../../common';
@ -64,6 +65,7 @@ export interface MatrixHistogramRequestOptions extends RequestBasicOptions {
inspect?: Maybe<Inspect>;
isPtrIncluded?: boolean;
includeMissingData?: boolean;
runtimeMappings?: MappingRuntimeFields;
}
export interface MatrixHistogramStrategyResponse extends IEsSearchResponse {

View file

@ -12,6 +12,7 @@ import { MatrixHistogram } from '.';
import { useMatrixHistogramCombined } from '../../containers/matrix_histogram';
import { MatrixHistogramType } from '../../../../common/search_strategy/security_solution';
import { TestProviders } from '../../mock';
import { mockRuntimeMappings } from '../../containers/source/mock';
jest.mock('../../lib/kibana');
@ -58,6 +59,7 @@ describe('Matrix Histogram Component', () => {
subtitle: 'mockSubtitle',
totalCount: -1,
title: 'mockTitle',
runtimeMappings: mockRuntimeMappings,
};
beforeAll(() => {
@ -75,6 +77,19 @@ describe('Matrix Histogram Component', () => {
});
describe('on initial load', () => {
test('it requests Matrix Histogram', () => {
expect(useMatrixHistogramCombined).toHaveBeenCalledWith({
endDate: mockMatrixOverTimeHistogramProps.endDate,
errorMessage: mockMatrixOverTimeHistogramProps.errorMessage,
histogramType: mockMatrixOverTimeHistogramProps.histogramType,
indexNames: mockMatrixOverTimeHistogramProps.indexNames,
startDate: mockMatrixOverTimeHistogramProps.startDate,
stackByField: mockMatrixOverTimeHistogramProps.defaultStackByOption.value,
runtimeMappings: mockMatrixOverTimeHistogramProps.runtimeMappings,
isPtrIncluded: mockMatrixOverTimeHistogramProps.isPtrIncluded,
skip: mockMatrixOverTimeHistogramProps.skip,
});
});
test('it renders MatrixLoader', () => {
expect(wrapper.find('MatrixLoader').exists()).toBe(true);
});

View file

@ -75,6 +75,7 @@ export const MatrixHistogramComponent: React.FC<MatrixHistogramComponentProps> =
hideHistogramIfEmpty = false,
id,
indexNames,
runtimeMappings,
isPtrIncluded,
legendPosition,
mapping,
@ -145,6 +146,7 @@ export const MatrixHistogramComponent: React.FC<MatrixHistogramComponentProps> =
onError,
startDate,
stackByField: selectedStackByOption.value,
runtimeMappings,
isPtrIncluded,
docValueFields,
skip,

View file

@ -8,6 +8,7 @@
import type React from 'react';
import { EuiTitleSize } from '@elastic/eui';
import { ScaleType, Position, TickFormatter } from '@elastic/charts';
import { MappingRuntimeFields } from '@elastic/elasticsearch/lib/api/typesWithBodyKey';
import { ActionCreator } from 'redux';
import { ESQuery } from '../../../../common/typed_json';
import { InputsModelId } from '../../store/inputs/constants';
@ -81,6 +82,7 @@ export interface MatrixHistogramQueryProps {
skip?: boolean;
isPtrIncluded?: boolean;
includeMissingData?: boolean;
runtimeMappings?: MappingRuntimeFields;
}
export interface MatrixHistogramProps extends MatrixHistogramBasicProps {

View file

@ -89,7 +89,9 @@ const TopNComponent: React.FC<Props> = ({
(value: string) => setView(value as TimelineEventsType),
[setView]
);
const { selectedPatterns } = useSourcererDataView(getSourcererScopeName({ timelineId, view }));
const { selectedPatterns, runtimeMappings } = useSourcererDataView(
getSourcererScopeName({ timelineId, view })
);
useEffect(() => {
setView(defaultView);
@ -134,6 +136,7 @@ const TopNComponent: React.FC<Props> = ({
headerChildren={headerChildren}
indexPattern={indexPattern}
indexNames={selectedPatterns}
runtimeMappings={runtimeMappings}
onlyField={field}
paddingSize={paddingSize}
query={query}
@ -156,6 +159,7 @@ const TopNComponent: React.FC<Props> = ({
showLegend={showLegend}
setAbsoluteRangeDatePickerTarget={setAbsoluteRangeDatePickerTarget}
timelineId={timelineId}
runtimeMappings={runtimeMappings}
/>
)}
</TopNContent>

View file

@ -56,6 +56,7 @@ export const useMatrixHistogram = ({
isPtrIncluded,
onError,
stackByField,
runtimeMappings,
startDate,
threshold,
skip = false,
@ -97,6 +98,7 @@ export const useMatrixHistogram = ({
histogramType: initialHistogramType ?? histogramType,
timerange: initialTimerange,
stackByField,
runtimeMappings,
threshold,
...(isPtrIncluded != null ? { isPtrIncluded } : {}),
...(!isEmpty(docValueFields) ? { docValueFields } : {}),

View file

@ -7,6 +7,7 @@
import { Position } from '@elastic/charts';
import numeral from '@elastic/numeral';
import { MappingRuntimeFields } from '@elastic/elasticsearch/lib/api/typesWithBodyKey';
import React, { useEffect, useMemo, useCallback } from 'react';
import uuid from 'uuid';
@ -44,6 +45,7 @@ interface Props extends Pick<GlobalTimeArgs, 'from' | 'to' | 'deleteQuery' | 'se
headerChildren?: React.ReactNode;
indexPattern: DataViewBase;
indexNames: string[];
runtimeMappings?: MappingRuntimeFields;
onlyField?: string;
paddingSize?: 's' | 'm' | 'l' | 'none';
query: Query;
@ -67,6 +69,7 @@ const EventsByDatasetComponent: React.FC<Props> = ({
headerChildren,
indexPattern,
indexNames,
runtimeMappings,
onlyField,
paddingSize,
query,
@ -176,6 +179,7 @@ const EventsByDatasetComponent: React.FC<Props> = ({
headerChildren={headerContent}
id={uniqueQueryId}
indexNames={indexNames}
runtimeMappings={runtimeMappings}
onError={toggleTopN}
paddingSize={paddingSize}
setAbsoluteRangeDatePickerTarget={setAbsoluteRangeDatePickerTarget}

View file

@ -8,6 +8,7 @@
import React, { useCallback } from 'react';
import { useDispatch } from 'react-redux';
import { Filter, Query } from '@kbn/es-query';
import { MappingRuntimeFields } from '@elastic/elasticsearch/lib/api/typesWithBodyKey';
import { AlertsHistogramPanel } from '../../../detections/components/alerts_kpis/alerts_histogram_panel';
import { useSignalIndex } from '../../../detections/containers/detection_engine/alerts/use_signal_index';
@ -33,6 +34,7 @@ interface Props {
setAbsoluteRangeDatePickerTarget?: InputsModelId;
showLegend?: boolean;
timelineId?: string;
runtimeMappings?: MappingRuntimeFields;
}
const SignalsByCategoryComponent: React.FC<Props> = ({
@ -45,6 +47,7 @@ const SignalsByCategoryComponent: React.FC<Props> = ({
showLegend,
setAbsoluteRangeDatePickerTarget = 'global',
timelineId,
runtimeMappings,
}) => {
const dispatch = useDispatch();
const { signalIndexName } = useSignalIndex();
@ -81,6 +84,7 @@ const SignalsByCategoryComponent: React.FC<Props> = ({
showStackBy={onlyField == null}
showTotalAlertsCount={true}
signalIndexName={signalIndexName}
runtimeMappings={runtimeMappings}
timelineId={timelineId}
title={i18n.ALERT_COUNT}
titleSize={onlyField == null ? 'm' : 's'}

View file

@ -999,6 +999,14 @@ export const formattedEventsSearchStrategyResponse: MatrixHistogramStrategyRespo
],
},
},
runtime_mappings: {
'@a.runtime.field': {
script: {
source: 'emit("Radically mocked dude: " + doc[\'host.name\'].value)',
},
type: 'keyword',
},
},
size: 0,
},
},

View file

@ -11,6 +11,15 @@ import {
MatrixHistogramType,
} from '../../../../../../../common/search_strategy';
const runtimeMappings: MatrixHistogramRequestOptions['runtimeMappings'] = {
'@a.runtime.field': {
script: {
source: 'emit("Radically mocked dude: " + doc[\'host.name\'].value)',
},
type: 'keyword',
},
};
export const mockOptions: MatrixHistogramRequestOptions = {
defaultIndex: [
'apm-*-transaction*',
@ -27,6 +36,7 @@ export const mockOptions: MatrixHistogramRequestOptions = {
histogramType: MatrixHistogramType.events,
timerange: { interval: '12h', from: '2020-09-08T16:11:26.215Z', to: '2020-09-09T16:11:26.215Z' },
stackByField: 'event.action',
runtimeMappings,
};
export const expectedDsl = {
@ -80,6 +90,7 @@ export const expectedDsl = {
],
},
},
runtime_mappings: runtimeMappings,
size: 0,
},
};
@ -137,6 +148,7 @@ export const expectedThresholdDsl = {
],
},
},
runtime_mappings: runtimeMappings,
size: 0,
},
};
@ -192,6 +204,7 @@ export const expectedThresholdMissingFieldDsl = {
],
},
},
runtime_mappings: runtimeMappings,
size: 0,
},
};
@ -242,6 +255,7 @@ export const expectedThresholdWithCardinalityDsl = {
],
},
},
runtime_mappings: runtimeMappings,
size: 0,
},
ignore_unavailable: true,
@ -311,6 +325,7 @@ export const expectedThresholdWithGroupFieldsAndCardinalityDsl = {
],
},
},
runtime_mappings: runtimeMappings,
size: 0,
},
};
@ -363,6 +378,7 @@ export const expectedThresholdGroupWithCardinalityDsl = {
],
},
},
runtime_mappings: runtimeMappings,
size: 0,
},
ignore_unavailable: true,
@ -438,6 +454,7 @@ export const expectedIpIncludingMissingDataDsl = {
],
},
},
runtime_mappings: runtimeMappings,
size: 0,
},
};
@ -496,6 +513,7 @@ export const expectedIpNotIncludingMissingDataDsl = {
],
},
},
runtime_mappings: runtimeMappings,
size: 0,
},
};

View file

@ -23,6 +23,7 @@ export const buildEventsHistogramQuery = ({
stackByField = 'event.action',
threshold,
includeMissingData = true,
runtimeMappings,
}: MatrixHistogramRequestOptions) => {
const [queryFilterFirstClause, ...queryFilterClauses] = createQueryFilterClauses(filterQuery);
const stackByIpField =
@ -162,6 +163,7 @@ export const buildEventsHistogramQuery = ({
filter,
},
},
runtime_mappings: runtimeMappings,
size: 0,
},
};