From 35930c059928c06879d3d216857ae4d2860a0658 Mon Sep 17 00:00:00 2001 From: Julia Rechkunova Date: Mon, 15 Apr 2024 14:04:58 +0200 Subject: [PATCH 001/148] [Discover][ES|QL] Update inspect details for the main ES|QL fetch (#180204) - Closes https://github.com/elastic/kibana/issues/175419 ## Summary This PR enables customization for title/description we show in Inspector flyout for ES|QL requests. Screenshot 2024-04-09 at 15 25 11 Screenshot 2024-04-09 at 15 25 20 ### Checklist - [x] [Unit or functional tests](https://www.elastic.co/guide/en/kibana/master/development-tests.html) were updated or added to match the most common scenarios --- .../query/text_based_query_state_to_ast.ts | 15 ++++++- ...query_state_to_ast_with_validation.test.ts | 31 +++++++++++++++ ...ased_query_state_to_ast_with_validation.ts | 10 +++++ .../aggregate_query_to_ast.test.ts | 26 ++++++++++++- .../expressions/aggregate_query_to_ast.ts | 17 ++++++-- .../data/common/search/expressions/esql.ts | 39 +++++++++++++++---- .../main/utils/fetch_text_based.ts | 7 ++++ .../apps/discover/group4/_esql_view.ts | 18 +++++++++ .../text_based/text_based_languages.test.ts | 6 +++ .../datasources/text_based/to_expression.ts | 8 ++++ 10 files changed, 162 insertions(+), 15 deletions(-) diff --git a/src/plugins/data/common/query/text_based_query_state_to_ast.ts b/src/plugins/data/common/query/text_based_query_state_to_ast.ts index e24cbbd0a7dab..fe60157800501 100644 --- a/src/plugins/data/common/query/text_based_query_state_to_ast.ts +++ b/src/plugins/data/common/query/text_based_query_state_to_ast.ts @@ -20,13 +20,19 @@ import { interface Args extends QueryState { timeFieldName?: string; inputQuery?: Query; + titleForInspector?: string; + descriptionForInspector?: string; } /** * Converts QueryState to expression AST * @param filters array of kibana filters * @param query kibana query or aggregate query + * @param inputQuery * @param time kibana time range + * @param dataView + * @param titleForInspector + * @param descriptionForInspector */ export function textBasedQueryStateToExpressionAst({ filters, @@ -34,6 +40,8 @@ export function textBasedQueryStateToExpressionAst({ inputQuery, time, timeFieldName, + titleForInspector, + descriptionForInspector, }: Args) { const kibana = buildExpressionFunction('kibana', {}); let q; @@ -51,7 +59,12 @@ export function textBasedQueryStateToExpressionAst({ const mode = getAggregateQueryMode(query); for (const esMode of ['sql', 'esql']) { if (mode === esMode && esMode in query) { - const essql = aggregateQueryToAst(query, timeFieldName); + const essql = aggregateQueryToAst({ + query, + timeField: timeFieldName, + titleForInspector, + descriptionForInspector, + }); if (essql) { ast.chain.push(essql); diff --git a/src/plugins/data/common/query/text_based_query_state_to_ast_with_validation.test.ts b/src/plugins/data/common/query/text_based_query_state_to_ast_with_validation.test.ts index e9ded5d83b8c0..9e99bcc150053 100644 --- a/src/plugins/data/common/query/text_based_query_state_to_ast_with_validation.test.ts +++ b/src/plugins/data/common/query/text_based_query_state_to_ast_with_validation.test.ts @@ -72,4 +72,35 @@ describe('textBasedQueryStateToAstWithValidation', () => { }) ); }); + + it('returns an object with the correct structure for ES|QL', async () => { + const dataView = createStubDataView({ + spec: { + id: 'foo', + title: 'foo', + timeFieldName: '@timestamp', + }, + }); + const actual = await textBasedQueryStateToAstWithValidation({ + filters: [], + query: { esql: 'from logs*' }, + time: { + from: 'now', + to: 'now+7d', + }, + dataView, + titleForInspector: 'Custom title', + descriptionForInspector: 'Custom desc', + }); + expect(actual).toHaveProperty( + 'chain.2.arguments', + expect.objectContaining({ + query: ['from logs*'], + timeField: ['@timestamp'], + locale: ['en'], + titleForInspector: ['Custom title'], + descriptionForInspector: ['Custom desc'], + }) + ); + }); }); diff --git a/src/plugins/data/common/query/text_based_query_state_to_ast_with_validation.ts b/src/plugins/data/common/query/text_based_query_state_to_ast_with_validation.ts index 4d38aad530f45..27e6484a2d430 100644 --- a/src/plugins/data/common/query/text_based_query_state_to_ast_with_validation.ts +++ b/src/plugins/data/common/query/text_based_query_state_to_ast_with_validation.ts @@ -14,13 +14,19 @@ interface Args extends QueryState { dataView?: DataView; inputQuery?: Query; timeFieldName?: string; + titleForInspector?: string; + descriptionForInspector?: string; } /** * Converts QueryState to expression AST * @param filters array of kibana filters * @param query kibana query or aggregate query + * @param inputQuery * @param time kibana time range + * @param dataView + * @param titleForInspector + * @param descriptionForInspector */ export async function textBasedQueryStateToAstWithValidation({ filters, @@ -28,6 +34,8 @@ export async function textBasedQueryStateToAstWithValidation({ inputQuery, time, dataView, + titleForInspector, + descriptionForInspector, }: Args) { let ast; if (query && isOfAggregateQueryType(query)) { @@ -37,6 +45,8 @@ export async function textBasedQueryStateToAstWithValidation({ inputQuery, time, timeFieldName: dataView?.timeFieldName, + titleForInspector, + descriptionForInspector, }); } return ast; diff --git a/src/plugins/data/common/search/expressions/aggregate_query_to_ast.test.ts b/src/plugins/data/common/search/expressions/aggregate_query_to_ast.test.ts index 0ded432eb0508..23a20fbde3f4b 100644 --- a/src/plugins/data/common/search/expressions/aggregate_query_to_ast.test.ts +++ b/src/plugins/data/common/search/expressions/aggregate_query_to_ast.test.ts @@ -10,15 +10,37 @@ import { aggregateQueryToAst } from './aggregate_query_to_ast'; describe('aggregateQueryToAst', () => { it('should return a function', () => { - expect(aggregateQueryToAst({ esql: 'from foo' })).toHaveProperty('type', 'function'); + expect(aggregateQueryToAst({ query: { esql: 'from foo' } })).toHaveProperty('type', 'function'); }); it('should forward arguments', () => { - expect(aggregateQueryToAst({ esql: 'from foo' }, 'baz')).toHaveProperty( + expect( + aggregateQueryToAst({ + query: { esql: 'from foo' }, + timeField: 'baz', + }) + ).toHaveProperty( + 'arguments', + expect.objectContaining({ + query: ['from foo'], + timeField: ['baz'], + }) + ); + + expect( + aggregateQueryToAst({ + query: { esql: 'from foo' }, + timeField: 'baz', + titleForInspector: 'Custom title', + descriptionForInspector: 'Custom desc', + }) + ).toHaveProperty( 'arguments', expect.objectContaining({ query: ['from foo'], timeField: ['baz'], + titleForInspector: ['Custom title'], + descriptionForInspector: ['Custom desc'], }) ); }); diff --git a/src/plugins/data/common/search/expressions/aggregate_query_to_ast.ts b/src/plugins/data/common/search/expressions/aggregate_query_to_ast.ts index 6b69af873585b..e755f6a9f6dbe 100644 --- a/src/plugins/data/common/search/expressions/aggregate_query_to_ast.ts +++ b/src/plugins/data/common/search/expressions/aggregate_query_to_ast.ts @@ -11,10 +11,17 @@ import { AggregateQuery } from '../../query'; import { EssqlExpressionFunctionDefinition } from './essql'; import { EsqlExpressionFunctionDefinition } from './esql'; -export const aggregateQueryToAst = ( - query: AggregateQuery, - timeField?: string -): undefined | ExpressionAstFunction => { +export const aggregateQueryToAst = ({ + query, + timeField, + titleForInspector, + descriptionForInspector, +}: { + query: AggregateQuery; + timeField?: string; + titleForInspector?: string; + descriptionForInspector?: string; +}): undefined | ExpressionAstFunction => { if ('sql' in query) { return buildExpressionFunction('essql', { query: query.sql, @@ -26,6 +33,8 @@ export const aggregateQueryToAst = ( query: query.esql, timeField, locale: i18n.getLocale(), + titleForInspector, + descriptionForInspector, }).toAst(); } }; diff --git a/src/plugins/data/common/search/expressions/esql.ts b/src/plugins/data/common/search/expressions/esql.ts index d9893c8c203f6..a40902b6658ce 100644 --- a/src/plugins/data/common/search/expressions/esql.ts +++ b/src/plugins/data/common/search/expressions/esql.ts @@ -40,6 +40,12 @@ interface Arguments { // timezone?: string; timeField?: string; locale?: string; + + /** + * Requests' meta for showing in Inspector + */ + titleForInspector?: string; + descriptionForInspector?: string; } export type EsqlExpressionFunctionDefinition = ExpressionFunctionDefinition< @@ -107,10 +113,24 @@ export const getEsqlFn = ({ getStartDependencies }: EsqlFnArguments) => { defaultMessage: 'The locale to use.', }), }, + titleForInspector: { + aliases: ['titleForInspector'], + types: ['string'], + help: i18n.translate('data.search.esql.titleForInspector.help', { + defaultMessage: 'The title to show in Inspector.', + }), + }, + descriptionForInspector: { + aliases: ['descriptionForInspector'], + types: ['string'], + help: i18n.translate('data.search.esql.descriptionForInspector.help', { + defaultMessage: 'The description to show in Inspector.', + }), + }, }, fn( input, - { query, /* timezone, */ timeField, locale }, + { query, /* timezone, */ timeField, locale, titleForInspector, descriptionForInspector }, { abortSignal, inspectorAdapters, getKibanaRequest } ) { return defer(() => @@ -158,14 +178,17 @@ export const getEsqlFn = ({ getStartDependencies }: EsqlFnArguments) => { } const request = inspectorAdapters.requests.start( - i18n.translate('data.search.dataRequest.title', { - defaultMessage: 'Data', - }), - { - description: i18n.translate('data.search.es_search.dataRequest.description', { - defaultMessage: - 'This request queries Elasticsearch to fetch the data for the visualization.', + titleForInspector ?? + i18n.translate('data.search.dataRequest.title', { + defaultMessage: 'Data', }), + { + description: + descriptionForInspector ?? + i18n.translate('data.search.es_search.dataRequest.description', { + defaultMessage: + 'This request queries Elasticsearch to fetch the data for the visualization.', + }), }, startTime ); diff --git a/src/plugins/discover/public/application/main/utils/fetch_text_based.ts b/src/plugins/discover/public/application/main/utils/fetch_text_based.ts index 4099a16a9625a..7045eb3c28cbc 100644 --- a/src/plugins/discover/public/application/main/utils/fetch_text_based.ts +++ b/src/plugins/discover/public/application/main/utils/fetch_text_based.ts @@ -7,6 +7,7 @@ */ import { pluck } from 'rxjs'; import { lastValueFrom } from 'rxjs'; +import { i18n } from '@kbn/i18n'; import { Query, AggregateQuery, Filter } from '@kbn/es-query'; import type { Adapters } from '@kbn/inspector-plugin/common'; import type { DataPublicPluginStart } from '@kbn/data-plugin/public'; @@ -41,6 +42,12 @@ export function fetchTextBased( time: timeRange, dataView, inputQuery, + titleForInspector: i18n.translate('discover.inspectorTextBasedRequestTitle', { + defaultMessage: 'Table', + }), + descriptionForInspector: i18n.translate('discover.inspectorTextBasedRequestDescription', { + defaultMessage: 'This request queries Elasticsearch to fetch results for the table.', + }), }) .then((ast) => { if (ast) { diff --git a/test/functional/apps/discover/group4/_esql_view.ts b/test/functional/apps/discover/group4/_esql_view.ts index 9147470d8282a..31f323500b119 100644 --- a/test/functional/apps/discover/group4/_esql_view.ts +++ b/test/functional/apps/discover/group4/_esql_view.ts @@ -18,6 +18,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { const testSubjects = getService('testSubjects'); const monacoEditor = getService('monacoEditor'); const security = getService('security'); + const inspector = getService('inspector'); const retry = getService('retry'); const browser = getService('browser'); const find = getService('find'); @@ -256,6 +257,23 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { }); }); + describe('inspector', () => { + beforeEach(async () => { + await PageObjects.common.navigateToApp('discover'); + await PageObjects.timePicker.setDefaultAbsoluteRange(); + }); + + it('shows Discover and Lens requests in Inspector', async () => { + await PageObjects.discover.selectTextBaseLang(); + await PageObjects.header.waitUntilLoadingHasFinished(); + await PageObjects.discover.waitUntilSearchingHasFinished(); + await inspector.open(); + const requestNames = await inspector.getRequestNames(); + expect(requestNames).to.contain('Table'); + expect(requestNames).to.contain('Visualization'); + }); + }); + describe('query history', () => { beforeEach(async () => { await PageObjects.common.navigateToApp('discover'); diff --git a/x-pack/plugins/lens/public/datasources/text_based/text_based_languages.test.ts b/x-pack/plugins/lens/public/datasources/text_based/text_based_languages.test.ts index bc160ab4bcd57..d15723e074667 100644 --- a/x-pack/plugins/lens/public/datasources/text_based/text_based_languages.test.ts +++ b/x-pack/plugins/lens/public/datasources/text_based/text_based_languages.test.ts @@ -724,12 +724,18 @@ describe('Textbased Data Source', () => { }, Object { "arguments": Object { + "descriptionForInspector": Array [ + "This request queries Elasticsearch to fetch the data for the visualization.", + ], "locale": Array [ "en", ], "query": Array [ "FROM foo", ], + "titleForInspector": Array [ + "Visualization", + ], }, "function": "esql", "type": "function", diff --git a/x-pack/plugins/lens/public/datasources/text_based/to_expression.ts b/x-pack/plugins/lens/public/datasources/text_based/to_expression.ts index 9d7be5d2fb431..148a16232c980 100644 --- a/x-pack/plugins/lens/public/datasources/text_based/to_expression.ts +++ b/x-pack/plugins/lens/public/datasources/text_based/to_expression.ts @@ -5,6 +5,7 @@ * 2.0. */ +import { i18n } from '@kbn/i18n'; import { Ast } from '@kbn/interpreter'; import { textBasedQueryStateToExpressionAst } from '@kbn/data-plugin/common'; import type { OriginalColumn } from '../../../common/types'; @@ -44,6 +45,13 @@ function getExpressionForLayer( const textBasedQueryToAst = textBasedQueryStateToExpressionAst({ query: layer.query, timeFieldName, + titleForInspector: i18n.translate('xpack.lens.inspectorTextBasedRequestDataTitle', { + defaultMessage: 'Visualization', + }), + descriptionForInspector: i18n.translate('xpack.lens.inspectorTextBasedRequestDescription', { + defaultMessage: + 'This request queries Elasticsearch to fetch the data for the visualization.', + }), }); textBasedQueryToAst.chain.push({ From 786200791b9b2354b59f5e2ae098c637a2583cba Mon Sep 17 00:00:00 2001 From: Vitalii Dmyterko <92328789+vitaliidm@users.noreply.github.com> Date: Mon, 15 Apr 2024 13:24:08 +0100 Subject: [PATCH 002/148] [Security Solution][Detection Engine] fixes IM timestamp override errors (#180567) ## Summary - addresses https://github.com/elastic/kibana/issues/174573 ES can return negative sort id for date field, when sort order set to desc this could happen when event has empty sort field Example:
DESC query ```JSON POST /indicator-match/_search?allow_no_indices=true&ignore_unavailable=true { "query": { "bool": { "filter": [ { "bool": { "must": [], "filter": [ { "query_string": { "query": "*" } } ], "should": [], "must_not": [] } }, { "bool": { "minimum_should_match": 1, "should": [ { "range": { "event.ingested": { "lte": "2024-04-10T16:31:58.289Z", "gte": "2024-02-28T16:11:58.289Z", "format": "strict_date_optional_time" } } }, { "bool": { "filter": [ { "range": { "@timestamp": { "lte": "2024-04-10T16:31:58.289Z", "gte": "2024-02-28T16:11:58.289Z", "format": "strict_date_optional_time" } } }, { "bool": { "must_not": { "exists": { "field": "event.ingested" } } } } ] } } ] } } ] } }, "fields": [ { "field": "*", "include_unmapped": true }, { "field": "event.ingested", "format": "strict_date_optional_time" }, { "field": "@timestamp", "format": "strict_date_optional_time" } ], "runtime_mappings": { "kibana.combined_timestamp": { "type": "date", "script": { "source": """ if (doc.containsKey(params.timestampOverride) && doc[params.timestampOverride].size()!=0) { emit(doc[params.timestampOverride].value.millis); } else { emit(doc['@timestamp'].value.millis); } """, "params": { "timestampOverride": "event.ingested" } } } }, "sort": [ { "event.ingested": { "order": "desc", "unmapped_type": "date" } }, { "@timestamp": { "order": "asc", "unmapped_type": "date" } } ], "size": 100 } ``` RESPONSE: ```JSON { "took": 1, "timed_out": false, "_shards": { "total": 1, "successful": 1, "skipped": 0, "failed": 0 }, "hits": { "total": { "value": 1, "relation": "eq" }, "max_score": null, "hits": [ { "_index": "indicator-match", "_id": "OnS8x44BMOVU2ZdAUiTo", "_score": null, "_source": { "@timestamp": "2024-04-09T18:45:02.000Z", "agent.name": "test" }, "fields": { "kibana.combined_timestamp": [ "2024-04-09T18:45:02.000Z" ], "@timestamp": [ "2024-04-09T18:45:02.000Z" ], "agent.name": [ "test" ] }, "sort": [ -9223372036854776000, 1712688302000 ] } ] } } ```
Subsequent query with sort values of ```JSON "searhAfter": [ -9223372036854776000, 1712688302000 ] ``` would lead to the failure ```JSON { "error": { "root_cause": [ { "type": "parse_exception", "reason": "failed to parse date field [-9223372036854776000] with format [strict_date_optional_time||epoch_millis]: [failed to parse date field [-9223372036854776000] with format [strict_date_optional_time||epoch_millis]]" } ], "type": "search_phase_execution_exception", "reason": "all shards failed", "phase": "query", "grouped": true, "failed_shards": [ { "shard": 0, "index": "indicator-match", "node": "518tWuE1QK6Lm0NII7NhEg", "reason": { "type": "parse_exception", "reason": "failed to parse date field [-9223372036854776000] with format [strict_date_optional_time||epoch_millis]: [failed to parse date field [-9223372036854776000] with format [strict_date_optional_time||epoch_millis]]", "caused_by": { "type": "illegal_argument_exception", "reason": "failed to parse date field [-9223372036854776000] with format [strict_date_optional_time||epoch_millis]", "caused_by": { "type": "date_time_parse_exception", "reason": "Failed to parse with all enclosed parsers" } } } } ] }, "status": 400 } ``` This does not happen when sort is set to ASC, since ES returns positive value in sort ids Example of response when sort order set to ASC
ASC query ```JSON POST /indicator-match/_search?allow_no_indices=true&ignore_unavailable=true { "query": { "bool": { "filter": [ { "bool": { "must": [], "filter": [ { "query_string": { "query": "*" } } ], "should": [], "must_not": [] } }, { "bool": { "minimum_should_match": 1, "should": [ { "range": { "event.ingested": { "lte": "2024-04-10T16:31:58.289Z", "gte": "2024-02-28T16:11:58.289Z", "format": "strict_date_optional_time" } } }, { "bool": { "filter": [ { "range": { "@timestamp": { "lte": "2024-04-10T16:31:58.289Z", "gte": "2024-02-28T16:11:58.289Z", "format": "strict_date_optional_time" } } }, { "bool": { "must_not": { "exists": { "field": "event.ingested" } } } } ] } } ] } } ] } }, "fields": [ { "field": "*", "include_unmapped": true }, { "field": "event.ingested", "format": "strict_date_optional_time" }, { "field": "@timestamp", "format": "strict_date_optional_time" } ], "runtime_mappings": { "kibana.combined_timestamp": { "type": "date", "script": { "source": """ if (doc.containsKey(params.timestampOverride) && doc[params.timestampOverride].size()!=0) { emit(doc[params.timestampOverride].value.millis); } else { emit(doc['@timestamp'].value.millis); } """, "params": { "timestampOverride": "event.ingested" } } } }, "sort": [ { "event.ingested": { "order": "asc", "unmapped_type": "date" } }, { "@timestamp": { "order": "asc", "unmapped_type": "date" } } ], "size": 100 } ``` RESPONSE: ```JSON { "took": 2, "timed_out": false, "_shards": { "total": 1, "successful": 1, "skipped": 0, "failed": 0 }, "hits": { "total": { "value": 1, "relation": "eq" }, "max_score": null, "hits": [ { "_index": "indicator-match", "_id": "OnS8x44BMOVU2ZdAUiTo", "_score": null, "_source": { "@timestamp": "2024-04-09T18:45:02.000Z", "agent.name": "test" }, "fields": { "kibana.combined_timestamp": [ "2024-04-09T18:45:02.000Z" ], "@timestamp": [ "2024-04-09T18:45:02.000Z" ], "agent.name": [ "test" ] }, "sort": [ 9223372036854776000, 1712688302000 ] } ] } } ```
### Checklist Delete any items that are not applicable to this PR. - [x] [Unit or functional tests](https://www.elastic.co/guide/en/kibana/master/development-tests.html) were updated or added to match the most common scenarios --- .../threat_mapping/create_threat_signals.ts | 20 ++++- .../utils/search_after_bulk_create_factory.ts | 8 +- .../execution_logic/threat_match.ts | 89 ++++++++++++++++++- 3 files changed, 112 insertions(+), 5 deletions(-) diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/indicator_match/threat_mapping/create_threat_signals.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/indicator_match/threat_mapping/create_threat_signals.ts index 894277d5ad17f..1dc4d92b44ab9 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/indicator_match/threat_mapping/create_threat_signals.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/indicator_match/threat_mapping/create_threat_signals.ts @@ -30,7 +30,7 @@ import { getAllowedFieldsForTermQuery } from './get_allowed_fields_for_terms_que import { getEventCount, getEventList } from './get_event_count'; import { getMappingFilters } from './get_mapping_filters'; import { THREAT_PIT_KEEP_ALIVE } from '../../../../../../common/cti/constants'; -import { getMaxSignalsWarning } from '../../utils/utils'; +import { getMaxSignalsWarning, getSafeSortIds } from '../../utils/utils'; import { getFieldsForWildcard } from '../../utils/get_fields_for_wildcard'; export const createThreatSignals = async ({ @@ -213,8 +213,24 @@ export const createThreatSignals = async ({ } ruleExecutionLogger.debug(`Documents items left to check are ${documentCount}`); + const sortIds = getSafeSortIds(list.hits.hits[list.hits.hits.length - 1].sort); + + // ES can return negative sort id for date field, when sort order set to desc + // this could happen when event has empty sort field + // https://github.com/elastic/kibana/issues/174573 (happens to IM rule only since it uses desc order for events search) + // when negative sort id used in subsequent request it fails, so when negative sort value found we don't do next request + const hasNegativeDateSort = sortIds?.some((val) => val < 0); + + if (hasNegativeDateSort) { + ruleExecutionLogger.debug( + `Negative date sort id value encountered: ${sortIds}. Threat search stopped.` + ); + + break; + } + list = await getDocumentList({ - searchAfter: list.hits.hits[list.hits.hits.length - 1].sort, + searchAfter: sortIds, }); } }; diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/search_after_bulk_create_factory.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/search_after_bulk_create_factory.ts index cdbb0530a0452..1706f655d259b 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/search_after_bulk_create_factory.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/search_after_bulk_create_factory.ts @@ -140,7 +140,13 @@ export const searchAfterAndBulkCreateFactory = async ({ ); } - if (lastSortIds != null && lastSortIds.length !== 0) { + // ES can return negative sort id for date field, when sort order set to desc + // this could happen when event has empty sort field + // https://github.com/elastic/kibana/issues/174573 (happens to IM rule only since it uses desc order for events search) + // when negative sort id used in subsequent request it fails, so when negative sort value found we don't do next request + const hasNegativeNumber = lastSortIds?.some((val) => val < 0); + + if (lastSortIds != null && lastSortIds.length !== 0 && !hasNegativeNumber) { sortIds = lastSortIds; hasSortId = true; } else { diff --git a/x-pack/test/security_solution_api_integration/test_suites/detections_response/detection_engine/rule_execution_logic/trial_license_complete_tier/execution_logic/threat_match.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/detection_engine/rule_execution_logic/trial_license_complete_tier/execution_logic/threat_match.ts index 678750342f4ee..5514f7848b461 100644 --- a/x-pack/test/security_solution_api_integration/test_suites/detections_response/detection_engine/rule_execution_logic/trial_license_complete_tier/execution_logic/threat_match.ts +++ b/x-pack/test/security_solution_api_integration/test_suites/detections_response/detection_engine/rule_execution_logic/trial_license_complete_tier/execution_logic/threat_match.ts @@ -5,6 +5,7 @@ * 2.0. */ +import { v4 as uuidv4 } from 'uuid'; import { get, isEqual, omit } from 'lodash'; import expect from '@kbn/expect'; import { @@ -38,7 +39,13 @@ import { import { RuleExecutionStatusEnum } from '@kbn/security-solution-plugin/common/api/detection_engine/rule_monitoring'; import { getMaxSignalsWarning as getMaxAlertsWarning } from '@kbn/security-solution-plugin/server/lib/detection_engine/rule_types/utils/utils'; import { ENABLE_ASSET_CRITICALITY_SETTING } from '@kbn/security-solution-plugin/common/constants'; -import { previewRule, getAlerts, getPreviewAlerts } from '../../../../utils'; +import { + previewRule, + getAlerts, + getPreviewAlerts, + dataGeneratorFactory, + getThreatMatchRuleForAlertTesting, +} from '../../../../utils'; import { deleteAllAlerts, deleteAllRules, @@ -155,10 +162,15 @@ export default ({ getService }: FtrProviderContext) => { const audibeatHostsPath = dataPathBuilder.getPath('auditbeat/hosts'); const threatIntelPath = dataPathBuilder.getPath('filebeat/threat_intel'); + const { indexListOfDocuments } = dataGeneratorFactory({ + es, + index: 'ecs_compliant', + log, + }); + /** * Specific api integration tests for threat matching rule type */ - // FLAKY: https://github.com/elastic/kibana/issues/155304 describe('@ess @serverless Threat match type rules', () => { before(async () => { await esArchiver.load(audibeatHostsPath); @@ -1670,5 +1682,78 @@ export default ({ getService }: FtrProviderContext) => { expect(fullAlert?.['user.asset.criticality']).to.eql('extreme_impact'); }); }); + + // https://github.com/elastic/kibana/issues/174573 + describe('timestamp override and fallback timestamp', () => { + const timestamp = '2020-10-28T05:45:00.000Z'; + + const eventDoc = (id: string) => ({ + id, + '@timestamp': timestamp, + host: { name: 'host-a' }, + }); + + const threatDoc = (id: string) => ({ + id, + '@timestamp': timestamp, + host: { name: 'host-a' }, + 'agent.type': 'threat', + }); + + const threatMatchRule = (id: string): ThreatMatchRuleCreateProps => ({ + ...getThreatMatchRuleForAlertTesting(['ecs_compliant']), + query: `id:${id} and NOT agent.type:threat`, + threat_query: `id:${id} and agent.type:threat`, + name: 'ALert suppression IM test rule', + from: 'now-35m', + interval: '30m', + timestamp_override: 'event.ingested', + timestamp_override_fallback_disabled: false, + }); + + it('should create alerts using a timestamp override and timestamp fallback enabled on threats first code path execution', async () => { + const id = uuidv4(); + + await indexListOfDocuments([eventDoc(id), eventDoc(id), threatDoc(id)]); + + const { previewId, logs } = await previewRule({ + supertest, + rule: threatMatchRule(id), + timeframeEnd: new Date('2020-10-28T06:00:00.000Z'), + invocationCount: 1, + }); + + const previewAlerts = await getPreviewAlerts({ + es, + previewId, + sort: ['host.name', ALERT_ORIGINAL_TIME], + }); + + expect(previewAlerts.length).to.eql(2); + expect(logs[0].errors).to.have.length(0); + }); + + it('should create alert using a timestamp override and timestamp fallback enabled on events first code path execution', async () => { + const id = uuidv4(); + + await indexListOfDocuments([eventDoc(id), threatDoc(id), threatDoc(id)]); + + const { previewId, logs } = await previewRule({ + supertest, + rule: threatMatchRule(id), + timeframeEnd: new Date('2020-10-28T06:00:00.000Z'), + invocationCount: 1, + }); + + const previewAlerts = await getPreviewAlerts({ + es, + previewId, + sort: ['host.name', ALERT_ORIGINAL_TIME], + }); + + expect(previewAlerts.length).to.eql(1); + expect(logs[0].errors).to.have.length(0); + }); + }); }); }; From b84591786a6bc33e209638607401ec4d307b01a0 Mon Sep 17 00:00:00 2001 From: Angela Chuang <6295984+angorayc@users.noreply.github.com> Date: Mon, 15 Apr 2024 13:58:08 +0100 Subject: [PATCH 003/148] [SecuritySolution] Remove chartEmbeddablesEnabled feature flag and unused code (#173675) --- .../common/api/search_strategy/hosts/hosts.ts | 4 - .../api/search_strategy/hosts/kpi_hosts.ts | 24 - .../search_strategy/hosts/kpi_unique_ips.ts | 24 - .../common/api/search_strategy/index.ts | 25 +- .../matrix_histogram/matrix_histogram.ts | 41 - .../model/factory_query_type.ts | 20 - .../api/search_strategy/network/kpi/dns.ts | 21 - .../api/search_strategy/network/kpi/events.ts | 21 - .../api/search_strategy/network/kpi/index.ts | 16 - .../network/kpi/tls_handshakes.ts | 21 - .../network/kpi/unique_flows.ts | 21 - .../network/kpi/unique_private_ips.ts | 23 - .../api/search_strategy/network/network.ts | 2 - .../users/kpi/authentications.ts | 21 - .../search_strategy/users/kpi/total_users.ts | 21 - .../common/api/search_strategy/users/users.ts | 4 - .../common/experimental_features.ts | 1 - .../common/search_strategy/common/index.ts | 28 +- .../security_solution/hosts/index.ts | 1 - .../hosts/kpi/common/index.ts | 13 - .../hosts/kpi/hosts/index.ts | 16 - .../security_solution/hosts/kpi/index.ts | 25 - .../hosts/kpi/unique_ips/index.ts | 18 - .../security_solution/index.ts | 97 - .../matrix_histogram/alerts/index.ts | 16 - .../matrix_histogram/anomalies/index.ts | 20 - .../matrix_histogram/authentications/index.ts | 20 - .../matrix_histogram/common/index.ts | 11 - .../matrix_histogram/dns/index.ts | 26 - .../matrix_histogram/events/index.ts | 41 - .../matrix_histogram/index.ts | 87 - .../matrix_histogram/preview/index.ts | 16 - .../security_solution/network/index.ts | 1 - .../network/kpi/dns/index.ts | 14 - .../security_solution/network/kpi/index.ts | 33 - .../network/kpi/network_events/index.ts | 14 - .../network/kpi/tls_handshakes/index.ts | 14 - .../network/kpi/unique_flows/index.ts | 14 - .../network/kpi/unique_private_ips/index.ts | 24 - .../security_solution/users/index.ts | 5 - .../users/kpi/authentications/index.ts | 17 - .../security_solution/users/kpi/index.ts | 8 - .../users/kpi/total_users/index.ts | 15 - .../events_tab/events_query_tab_body.tsx | 1 - .../events_tab/histogram_configurations.ts | 6 - .../matrix_histogram/chart_content.tsx | 29 - .../matrix_histogram/index.test.tsx | 250 +- .../components/matrix_histogram/index.tsx | 227 +- .../components/matrix_histogram/types.ts | 102 +- .../components/matrix_histogram/utils.test.ts | 142 -- .../components/matrix_histogram/utils.ts | 85 - .../common/components/page/manage_query.tsx | 11 +- .../page/use_refetch_by_session.tsx | 6 +- .../public/common/components/top_n/top_n.tsx | 4 - .../histogram_configs.ts | 3 - .../anomalies_query_tab_body/index.tsx | 1 - .../containers/matrix_histogram/index.test.ts | 264 -- .../containers/matrix_histogram/index.ts | 300 --- .../matrix_histogram/translations.ts | 22 - .../rule_preview/preview_histogram.tsx | 4 +- .../pages/rule_details/index.tsx | 2 - .../alerts_count_panel/chart_content.tsx | 61 - .../alerts_count_panel/index.test.tsx | 137 +- .../alerts_kpis/alerts_count_panel/index.tsx | 136 +- .../alerts_histogram_panel/index.test.tsx | 369 +-- .../alerts_histogram_panel/index.tsx | 343 +-- .../use_alert_histogram_count.test.tsx | 8 +- .../use_alert_histogram_count.ts | 23 +- .../chart_panels/index.test.tsx | 173 +- .../detection_engine/chart_panels/index.tsx | 7 - .../risk_score_over_time/index.test.tsx | 37 +- .../components/risk_score_over_time/index.tsx | 149 +- .../components/authentication/helpers.tsx | 28 - .../components/kpi/__mocks__/index.tsx} | 5 +- .../public/explore/components/kpi/index.tsx | 29 + .../explore/components/stat_items/index.tsx | 1 - .../components/stat_items/metric.test.tsx | 66 - .../explore/components/stat_items/metric.tsx | 78 - .../stat_items/metric_embeddable.tsx | 15 +- .../components/stat_items/stat_items.test.tsx | 250 +- .../components/stat_items/stat_items.tsx | 228 +- .../explore/components/stat_items/types.ts | 33 +- .../stat_items/use_kpi_matrix_status.test.tsx | 90 - .../stat_items/use_kpi_matrix_status.ts | 39 - .../stat_items/use_toggle_status.ts | 19 +- .../components/stat_items/utils.test.tsx | 35 - .../explore/components/stat_items/utils.tsx | 95 - .../components/kpi_hosts/common/index.tsx | 75 - .../components/kpi_hosts/hosts/index.test.tsx | 108 +- .../components/kpi_hosts/hosts/index.tsx | 62 +- .../hosts/components/kpi_hosts/index.tsx | 60 +- .../hosts/components/kpi_hosts/types.ts | 8 - .../kpi_hosts/unique_ips/index.test.tsx | 108 +- .../components/kpi_hosts/unique_ips/index.tsx | 63 +- .../containers/kpi_hosts/hosts/index.test.tsx | 28 - .../containers/kpi_hosts/hosts/index.tsx | 157 -- .../kpi_hosts/hosts/translations.ts | 22 - .../kpi_hosts/unique_ips/index.test.tsx | 28 - .../containers/kpi_hosts/unique_ips/index.tsx | 165 -- .../kpi_hosts/unique_ips/translations.ts | 22 - .../public/explore/hosts/pages/hosts.tsx | 30 +- .../authentications_query_tab_body.tsx | 1 - .../uncommon_process_query_tab_body.tsx | 2 +- .../components/kpi_network/dns/index.test.tsx | 105 +- .../components/kpi_network/dns/index.tsx | 62 +- .../network/components/kpi_network/index.tsx | 94 +- .../network/components/kpi_network/mock.ts | 158 -- .../kpi_network/network_events/index.test.tsx | 108 +- .../kpi_network/network_events/index.tsx | 62 +- .../kpi_network/tls_handshakes/index.test.tsx | 108 +- .../kpi_network/tls_handshakes/index.tsx | 62 +- .../network/components/kpi_network/types.ts | 8 - .../kpi_network/unique_flows/index.test.tsx | 108 +- .../kpi_network/unique_flows/index.tsx | 62 +- .../unique_private_ips/index.test.tsx | 108 +- .../kpi_network/unique_private_ips/index.tsx | 65 +- .../containers/kpi_network/dns/index.test.tsx | 28 - .../containers/kpi_network/dns/index.tsx | 154 -- .../kpi_network/dns/translations.ts | 22 - .../kpi_network/network_events/index.test.tsx | 28 - .../kpi_network/network_events/index.tsx | 158 -- .../network_events/translations.ts | 22 - .../kpi_network/tls_handshakes/index.test.tsx | 28 - .../kpi_network/tls_handshakes/index.tsx | 157 -- .../tls_handshakes/translations.ts | 22 - .../kpi_network/unique_flows/index.test.tsx | 28 - .../kpi_network/unique_flows/index.tsx | 157 -- .../kpi_network/unique_flows/translations.ts | 22 - .../unique_private_ips/index.test.tsx | 28 - .../kpi_network/unique_private_ips/index.tsx | 171 -- .../unique_private_ips/translations.ts | 22 - .../pages/navigation/dns_query_tab_body.tsx | 5 - .../public/explore/network/pages/network.tsx | 31 +- .../kpi_users/authentications/index.test.tsx | 109 +- .../kpi_users/authentications/index.tsx | 63 +- .../users/components/kpi_users/index.tsx | 38 +- .../kpi_users/total_users/index.test.tsx | 110 +- .../kpi_users/total_users/index.tsx | 77 +- .../users/components/kpi_users/types.ts | 8 - .../users/authentications/index.test.tsx | 28 - .../users/authentications/index.tsx | 167 -- .../users/authentications/translations.ts | 22 - .../authentications_query_tab_body.tsx | 1 - .../public/explore/users/pages/users.tsx | 31 +- ...use_alerts_by_status_visualization_data.ts | 12 +- .../components/events_by_dataset/index.tsx | 8 - .../signals_by_category.tsx | 16 +- .../public/overview/pages/overview.tsx | 2 +- .../format_general_histogram_data.test.ts | 57 - .../common/format_general_histogram_data.ts | 22 - .../factory/hosts/index.test.ts | 8 +- .../security_solution/factory/hosts/index.ts | 14 +- .../factory/hosts/kpi/hosts/index.ts | 42 - .../kpi/hosts/query.hosts_kpi_hosts.dsl.ts | 73 - .../factory/hosts/kpi/unique_ips/index.ts | 55 - .../query.hosts_kpi_unique_ips.dsl.ts | 92 - .../security_solution/factory/index.ts | 2 - .../matrix_histogram/__mocks__/index.ts | 2180 ----------------- .../alerts/__mocks__/index.ts | 116 - .../matrix_histogram/alerts/index.test.ts | 23 - .../factory/matrix_histogram/alerts/index.ts | 15 - .../alerts/query.alerts_histogram.dsl.test.ts | 15 - .../alerts/query.alerts_histogram.dsl.ts | 101 - .../anomalies/__mocks__/index.ts | 95 - .../matrix_histogram/anomalies/index.test.ts | 23 - .../matrix_histogram/anomalies/index.ts | 15 - .../query.anomalies_histogram.dsl.test.ts | 15 - .../query.anomalies_histogram.dsl.ts | 82 - .../authentications/__mocks__/index.ts | 86 - .../authentications/index.test.ts | 23 - .../matrix_histogram/authentications/index.ts | 15 - ...uery.authentications_histogram.dsl.test.ts | 15 - .../query.authentications_histogram.dsl.ts | 94 - .../matrix_histogram/dns/__mocks__/index.ts | 87 - .../factory/matrix_histogram/dns/helpers.ts | 34 - .../matrix_histogram/dns/index.test.ts | 29 - .../factory/matrix_histogram/dns/index.ts | 17 - .../dns/query.dns_histogram.dsl.test.ts | 15 - .../dns/query.dns_histogram.dsl.ts | 113 - .../events/__mocks__/index.ts | 463 ---- .../matrix_histogram/events/helpers.test.ts | 175 -- .../matrix_histogram/events/helpers.ts | 114 - .../matrix_histogram/events/index.test.ts | 23 - .../factory/matrix_histogram/events/index.ts | 15 - .../events/query.events_histogram.dsl.test.ts | 90 - .../events/query.events_histogram.dsl.ts | 173 -- .../matrix_histogram/events/translations.ts | 15 - .../factory/matrix_histogram/helpers.test.ts | 22 - .../factory/matrix_histogram/helpers.ts | 35 - .../factory/matrix_histogram/index.test.ts | 249 -- .../factory/matrix_histogram/index.ts | 80 - .../factory/matrix_histogram/mock_data.ts | 46 - .../preview/__mocks__/index.ts | 89 - .../factory/matrix_histogram/preview/index.ts | 15 - .../query.preview_histogram.dsl.test.ts | 15 - .../preview/query.preview_histogram.dsl.ts | 84 - .../factory/network/index.test.ts | 20 +- .../factory/network/index.ts | 17 +- .../factory/network/kpi/common/index.ts | 39 - .../factory/network/kpi/dns/index.ts | 34 - .../kpi/dns/query.network_kpi_dns.dsl.ts | 74 - .../network/kpi/network_events/index.ts | 34 - .../query.network_kpi_network_events.dsl.ts | 47 - .../network/kpi/tls_handshakes/index.ts | 34 - .../query.network_kpi_tls_handshakes.dsl.ts | 73 - .../factory/network/kpi/unique_flows/index.ts | 35 - .../query.network_kpi_unique_flows.dsl.ts | 55 - .../network/kpi/unique_private_ips/index.ts | 62 - ...uery.network_kpi_unique_private_ips.dsl.ts | 104 - .../security_solution/factory/users/index.ts | 5 +- .../users/kpi/authentications/index.ts | 58 - .../query.users_kpi_authentications.dsl.ts | 111 - .../factory/users/kpi/total_users/index.ts | 47 - .../query.build_total_users_kpi.dsl.ts | 65 - .../translations/translations/fr-FR.json | 19 - .../translations/translations/ja-JP.json | 19 - .../translations/translations/zh-CN.json | 19 - .../apis/security_solution/index.js | 3 - .../apis/security_solution/kpi_hosts.ts | 201 -- .../apis/security_solution/kpi_network.ts | 323 --- .../apis/security_solution/kpi_users.ts | 99 - .../security_solution/matrix_dns_histogram.ts | 68 - .../test/security_solution_cypress/config.ts | 1 - .../cypress/screens/sourcerer.ts | 2 +- 224 files changed, 864 insertions(+), 14721 deletions(-) delete mode 100644 x-pack/plugins/security_solution/common/api/search_strategy/hosts/kpi_hosts.ts delete mode 100644 x-pack/plugins/security_solution/common/api/search_strategy/hosts/kpi_unique_ips.ts delete mode 100644 x-pack/plugins/security_solution/common/api/search_strategy/network/kpi/dns.ts delete mode 100644 x-pack/plugins/security_solution/common/api/search_strategy/network/kpi/events.ts delete mode 100644 x-pack/plugins/security_solution/common/api/search_strategy/network/kpi/index.ts delete mode 100644 x-pack/plugins/security_solution/common/api/search_strategy/network/kpi/tls_handshakes.ts delete mode 100644 x-pack/plugins/security_solution/common/api/search_strategy/network/kpi/unique_flows.ts delete mode 100644 x-pack/plugins/security_solution/common/api/search_strategy/network/kpi/unique_private_ips.ts delete mode 100644 x-pack/plugins/security_solution/common/api/search_strategy/users/kpi/authentications.ts delete mode 100644 x-pack/plugins/security_solution/common/api/search_strategy/users/kpi/total_users.ts delete mode 100644 x-pack/plugins/security_solution/common/search_strategy/security_solution/hosts/kpi/common/index.ts delete mode 100644 x-pack/plugins/security_solution/common/search_strategy/security_solution/hosts/kpi/hosts/index.ts delete mode 100644 x-pack/plugins/security_solution/common/search_strategy/security_solution/hosts/kpi/index.ts delete mode 100644 x-pack/plugins/security_solution/common/search_strategy/security_solution/hosts/kpi/unique_ips/index.ts delete mode 100644 x-pack/plugins/security_solution/common/search_strategy/security_solution/matrix_histogram/alerts/index.ts delete mode 100644 x-pack/plugins/security_solution/common/search_strategy/security_solution/matrix_histogram/anomalies/index.ts delete mode 100644 x-pack/plugins/security_solution/common/search_strategy/security_solution/matrix_histogram/authentications/index.ts delete mode 100644 x-pack/plugins/security_solution/common/search_strategy/security_solution/matrix_histogram/common/index.ts delete mode 100644 x-pack/plugins/security_solution/common/search_strategy/security_solution/matrix_histogram/dns/index.ts delete mode 100644 x-pack/plugins/security_solution/common/search_strategy/security_solution/matrix_histogram/events/index.ts delete mode 100644 x-pack/plugins/security_solution/common/search_strategy/security_solution/matrix_histogram/index.ts delete mode 100644 x-pack/plugins/security_solution/common/search_strategy/security_solution/matrix_histogram/preview/index.ts delete mode 100644 x-pack/plugins/security_solution/common/search_strategy/security_solution/network/kpi/dns/index.ts delete mode 100644 x-pack/plugins/security_solution/common/search_strategy/security_solution/network/kpi/index.ts delete mode 100644 x-pack/plugins/security_solution/common/search_strategy/security_solution/network/kpi/network_events/index.ts delete mode 100644 x-pack/plugins/security_solution/common/search_strategy/security_solution/network/kpi/tls_handshakes/index.ts delete mode 100644 x-pack/plugins/security_solution/common/search_strategy/security_solution/network/kpi/unique_flows/index.ts delete mode 100644 x-pack/plugins/security_solution/common/search_strategy/security_solution/network/kpi/unique_private_ips/index.ts delete mode 100644 x-pack/plugins/security_solution/common/search_strategy/security_solution/users/kpi/authentications/index.ts delete mode 100644 x-pack/plugins/security_solution/common/search_strategy/security_solution/users/kpi/index.ts delete mode 100644 x-pack/plugins/security_solution/common/search_strategy/security_solution/users/kpi/total_users/index.ts delete mode 100644 x-pack/plugins/security_solution/public/common/components/matrix_histogram/chart_content.tsx delete mode 100644 x-pack/plugins/security_solution/public/common/components/matrix_histogram/utils.test.ts delete mode 100644 x-pack/plugins/security_solution/public/common/containers/matrix_histogram/index.test.ts delete mode 100644 x-pack/plugins/security_solution/public/common/containers/matrix_histogram/index.ts delete mode 100644 x-pack/plugins/security_solution/public/common/containers/matrix_histogram/translations.ts delete mode 100644 x-pack/plugins/security_solution/public/detections/components/alerts_kpis/alerts_count_panel/chart_content.tsx rename x-pack/plugins/security_solution/{server/search_strategy/security_solution/factory/hosts/kpi/index.ts => public/explore/components/kpi/__mocks__/index.tsx} (72%) create mode 100644 x-pack/plugins/security_solution/public/explore/components/kpi/index.tsx delete mode 100644 x-pack/plugins/security_solution/public/explore/components/stat_items/metric.test.tsx delete mode 100644 x-pack/plugins/security_solution/public/explore/components/stat_items/metric.tsx delete mode 100644 x-pack/plugins/security_solution/public/explore/components/stat_items/use_kpi_matrix_status.test.tsx delete mode 100644 x-pack/plugins/security_solution/public/explore/components/stat_items/use_kpi_matrix_status.ts delete mode 100644 x-pack/plugins/security_solution/public/explore/components/stat_items/utils.test.tsx delete mode 100644 x-pack/plugins/security_solution/public/explore/hosts/components/kpi_hosts/common/index.tsx delete mode 100644 x-pack/plugins/security_solution/public/explore/hosts/containers/kpi_hosts/hosts/index.test.tsx delete mode 100644 x-pack/plugins/security_solution/public/explore/hosts/containers/kpi_hosts/hosts/index.tsx delete mode 100644 x-pack/plugins/security_solution/public/explore/hosts/containers/kpi_hosts/hosts/translations.ts delete mode 100644 x-pack/plugins/security_solution/public/explore/hosts/containers/kpi_hosts/unique_ips/index.test.tsx delete mode 100644 x-pack/plugins/security_solution/public/explore/hosts/containers/kpi_hosts/unique_ips/index.tsx delete mode 100644 x-pack/plugins/security_solution/public/explore/hosts/containers/kpi_hosts/unique_ips/translations.ts delete mode 100644 x-pack/plugins/security_solution/public/explore/network/components/kpi_network/mock.ts delete mode 100644 x-pack/plugins/security_solution/public/explore/network/containers/kpi_network/dns/index.test.tsx delete mode 100644 x-pack/plugins/security_solution/public/explore/network/containers/kpi_network/dns/index.tsx delete mode 100644 x-pack/plugins/security_solution/public/explore/network/containers/kpi_network/dns/translations.ts delete mode 100644 x-pack/plugins/security_solution/public/explore/network/containers/kpi_network/network_events/index.test.tsx delete mode 100644 x-pack/plugins/security_solution/public/explore/network/containers/kpi_network/network_events/index.tsx delete mode 100644 x-pack/plugins/security_solution/public/explore/network/containers/kpi_network/network_events/translations.ts delete mode 100644 x-pack/plugins/security_solution/public/explore/network/containers/kpi_network/tls_handshakes/index.test.tsx delete mode 100644 x-pack/plugins/security_solution/public/explore/network/containers/kpi_network/tls_handshakes/index.tsx delete mode 100644 x-pack/plugins/security_solution/public/explore/network/containers/kpi_network/tls_handshakes/translations.ts delete mode 100644 x-pack/plugins/security_solution/public/explore/network/containers/kpi_network/unique_flows/index.test.tsx delete mode 100644 x-pack/plugins/security_solution/public/explore/network/containers/kpi_network/unique_flows/index.tsx delete mode 100644 x-pack/plugins/security_solution/public/explore/network/containers/kpi_network/unique_flows/translations.ts delete mode 100644 x-pack/plugins/security_solution/public/explore/network/containers/kpi_network/unique_private_ips/index.test.tsx delete mode 100644 x-pack/plugins/security_solution/public/explore/network/containers/kpi_network/unique_private_ips/index.tsx delete mode 100644 x-pack/plugins/security_solution/public/explore/network/containers/kpi_network/unique_private_ips/translations.ts delete mode 100644 x-pack/plugins/security_solution/public/explore/users/containers/users/authentications/index.test.tsx delete mode 100644 x-pack/plugins/security_solution/public/explore/users/containers/users/authentications/index.tsx delete mode 100644 x-pack/plugins/security_solution/public/explore/users/containers/users/authentications/translations.ts delete mode 100644 x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/common/format_general_histogram_data.test.ts delete mode 100644 x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/common/format_general_histogram_data.ts delete mode 100644 x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/hosts/kpi/hosts/index.ts delete mode 100644 x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/hosts/kpi/hosts/query.hosts_kpi_hosts.dsl.ts delete mode 100644 x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/hosts/kpi/unique_ips/index.ts delete mode 100644 x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/hosts/kpi/unique_ips/query.hosts_kpi_unique_ips.dsl.ts delete mode 100644 x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/matrix_histogram/__mocks__/index.ts delete mode 100644 x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/matrix_histogram/alerts/__mocks__/index.ts delete mode 100644 x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/matrix_histogram/alerts/index.test.ts delete mode 100644 x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/matrix_histogram/alerts/index.ts delete mode 100644 x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/matrix_histogram/alerts/query.alerts_histogram.dsl.test.ts delete mode 100644 x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/matrix_histogram/alerts/query.alerts_histogram.dsl.ts delete mode 100644 x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/matrix_histogram/anomalies/__mocks__/index.ts delete mode 100644 x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/matrix_histogram/anomalies/index.test.ts delete mode 100644 x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/matrix_histogram/anomalies/index.ts delete mode 100644 x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/matrix_histogram/anomalies/query.anomalies_histogram.dsl.test.ts delete mode 100644 x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/matrix_histogram/anomalies/query.anomalies_histogram.dsl.ts delete mode 100644 x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/matrix_histogram/authentications/__mocks__/index.ts delete mode 100644 x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/matrix_histogram/authentications/index.test.ts delete mode 100644 x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/matrix_histogram/authentications/index.ts delete mode 100644 x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/matrix_histogram/authentications/query.authentications_histogram.dsl.test.ts delete mode 100644 x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/matrix_histogram/authentications/query.authentications_histogram.dsl.ts delete mode 100644 x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/matrix_histogram/dns/__mocks__/index.ts delete mode 100644 x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/matrix_histogram/dns/helpers.ts delete mode 100644 x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/matrix_histogram/dns/index.test.ts delete mode 100644 x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/matrix_histogram/dns/index.ts delete mode 100644 x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/matrix_histogram/dns/query.dns_histogram.dsl.test.ts delete mode 100644 x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/matrix_histogram/dns/query.dns_histogram.dsl.ts delete mode 100644 x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/matrix_histogram/events/__mocks__/index.ts delete mode 100644 x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/matrix_histogram/events/helpers.test.ts delete mode 100644 x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/matrix_histogram/events/helpers.ts delete mode 100644 x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/matrix_histogram/events/index.test.ts delete mode 100644 x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/matrix_histogram/events/index.ts delete mode 100644 x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/matrix_histogram/events/query.events_histogram.dsl.test.ts delete mode 100644 x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/matrix_histogram/events/query.events_histogram.dsl.ts delete mode 100644 x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/matrix_histogram/events/translations.ts delete mode 100644 x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/matrix_histogram/helpers.test.ts delete mode 100644 x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/matrix_histogram/helpers.ts delete mode 100644 x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/matrix_histogram/index.test.ts delete mode 100644 x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/matrix_histogram/index.ts delete mode 100644 x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/matrix_histogram/mock_data.ts delete mode 100644 x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/matrix_histogram/preview/__mocks__/index.ts delete mode 100644 x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/matrix_histogram/preview/index.ts delete mode 100644 x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/matrix_histogram/preview/query.preview_histogram.dsl.test.ts delete mode 100644 x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/matrix_histogram/preview/query.preview_histogram.dsl.ts delete mode 100644 x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/kpi/common/index.ts delete mode 100644 x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/kpi/dns/index.ts delete mode 100644 x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/kpi/dns/query.network_kpi_dns.dsl.ts delete mode 100644 x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/kpi/network_events/index.ts delete mode 100644 x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/kpi/network_events/query.network_kpi_network_events.dsl.ts delete mode 100644 x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/kpi/tls_handshakes/index.ts delete mode 100644 x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/kpi/tls_handshakes/query.network_kpi_tls_handshakes.dsl.ts delete mode 100644 x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/kpi/unique_flows/index.ts delete mode 100644 x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/kpi/unique_flows/query.network_kpi_unique_flows.dsl.ts delete mode 100644 x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/kpi/unique_private_ips/index.ts delete mode 100644 x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/kpi/unique_private_ips/query.network_kpi_unique_private_ips.dsl.ts delete mode 100644 x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/users/kpi/authentications/index.ts delete mode 100644 x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/users/kpi/authentications/query.users_kpi_authentications.dsl.ts delete mode 100644 x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/users/kpi/total_users/index.ts delete mode 100644 x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/users/kpi/total_users/query.build_total_users_kpi.dsl.ts delete mode 100644 x-pack/test/api_integration/apis/security_solution/kpi_hosts.ts delete mode 100644 x-pack/test/api_integration/apis/security_solution/kpi_network.ts delete mode 100644 x-pack/test/api_integration/apis/security_solution/kpi_users.ts delete mode 100644 x-pack/test/api_integration/apis/security_solution/matrix_dns_histogram.ts diff --git a/x-pack/plugins/security_solution/common/api/search_strategy/hosts/hosts.ts b/x-pack/plugins/security_solution/common/api/search_strategy/hosts/hosts.ts index a5931bd42972e..7be1b0d4d6c0d 100644 --- a/x-pack/plugins/security_solution/common/api/search_strategy/hosts/hosts.ts +++ b/x-pack/plugins/security_solution/common/api/search_strategy/hosts/hosts.ts @@ -12,7 +12,3 @@ export * from './details'; export * from './overview'; export * from './uncommon_processes'; - -export * from './kpi_hosts'; - -export * from './kpi_unique_ips'; diff --git a/x-pack/plugins/security_solution/common/api/search_strategy/hosts/kpi_hosts.ts b/x-pack/plugins/security_solution/common/api/search_strategy/hosts/kpi_hosts.ts deleted file mode 100644 index e49741efe0d24..0000000000000 --- a/x-pack/plugins/security_solution/common/api/search_strategy/hosts/kpi_hosts.ts +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { z } from 'zod'; -import { HostsKpiQueries } from '../model/factory_query_type'; -import { pagination } from '../model/pagination'; -import { requestBasicOptionsSchema } from '../model/request_basic_options'; -import { timerange } from '../model/timerange'; -import { sort } from './model/sort'; - -export const kpiHostsSchema = requestBasicOptionsSchema.extend({ - sort, - pagination, - timerange, - factoryQueryType: z.literal(HostsKpiQueries.kpiHosts), -}); - -export type KpiHostsRequestOptionsInput = z.input; - -export type KpiHostsRequestOptions = z.infer; diff --git a/x-pack/plugins/security_solution/common/api/search_strategy/hosts/kpi_unique_ips.ts b/x-pack/plugins/security_solution/common/api/search_strategy/hosts/kpi_unique_ips.ts deleted file mode 100644 index 998b6a076bd9a..0000000000000 --- a/x-pack/plugins/security_solution/common/api/search_strategy/hosts/kpi_unique_ips.ts +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { z } from 'zod'; -import { HostsKpiQueries } from '../model/factory_query_type'; -import { pagination } from '../model/pagination'; -import { requestBasicOptionsSchema } from '../model/request_basic_options'; -import { timerange } from '../model/timerange'; -import { sort } from './model/sort'; - -export const kpiUniqueIpsSchema = requestBasicOptionsSchema.extend({ - sort, - pagination, - timerange, - factoryQueryType: z.literal(HostsKpiQueries.kpiUniqueIps), -}); - -export type KpiUniqueIpsRequestOptionsInput = z.input; - -export type KpiUniqueIpsRequestOptions = z.infer; diff --git a/x-pack/plugins/security_solution/common/api/search_strategy/index.ts b/x-pack/plugins/security_solution/common/api/search_strategy/index.ts index 7282cb9e09ff3..2cc95948b8a17 100644 --- a/x-pack/plugins/security_solution/common/api/search_strategy/index.ts +++ b/x-pack/plugins/security_solution/common/api/search_strategy/index.ts @@ -18,20 +18,11 @@ import { hostDetailsSchema, hostOverviewSchema, hostUncommonProcessesSchema, - kpiHostsSchema, - kpiUniqueIpsSchema, } from './hosts/hosts'; -import { matrixHistogramSchema } from './matrix_histogram/matrix_histogram'; import { networkDetailsSchema } from './network/details'; import { networkDnsSchema } from './network/dns'; import { networkHttpSchema } from './network/http'; -import { - networkKpiDns, - networkKpiEvents, - networkKpiTlsHandshakes, - networkKpiUniqueFlows, - networkKpiUniquePrivateIps, -} from './network/kpi'; + import { networkOverviewSchema } from './network/overview'; import { networkTlsSchema } from './network/tls'; import { networkTopCountriesSchema } from './network/top_countries'; @@ -50,10 +41,8 @@ import { } from './risk_score/risk_score'; import { - authenticationsKpiSchema, managedUserDetailsSchema, observedUserDetailsSchema, - totalUsersKpiSchema, userAuthenticationsSchema, usersSchema, } from './users/users'; @@ -64,8 +53,6 @@ export * from './hosts/hosts'; export * from './users/users'; -export * from './matrix_histogram/matrix_histogram'; - export * from './network/network'; export * from './related_entities/related_entities'; @@ -84,15 +71,11 @@ export const searchStrategyRequestSchema = z.discriminatedUnion('factoryQueryTyp firstLastSeenRequestOptionsSchema, allHostsSchema, hostDetailsSchema, - kpiHostsSchema, - kpiUniqueIpsSchema, hostOverviewSchema, hostUncommonProcessesSchema, usersSchema, observedUserDetailsSchema, managedUserDetailsSchema, - totalUsersKpiSchema, - authenticationsKpiSchema, userAuthenticationsSchema, hostsRiskScoreRequestOptionsSchema, usersRiskScoreRequestOptionsSchema, @@ -108,12 +91,6 @@ export const searchStrategyRequestSchema = z.discriminatedUnion('factoryQueryTyp networkTopNFlowSchema, networkTopNFlowCountSchema, networkUsersSchema, - networkKpiDns, - networkKpiEvents, - networkKpiTlsHandshakes, - networkKpiUniqueFlows, - networkKpiUniquePrivateIps, - matrixHistogramSchema, threatIntelSourceRequestOptionsSchema, eventEnrichmentRequestOptionsSchema, ]); diff --git a/x-pack/plugins/security_solution/common/api/search_strategy/matrix_histogram/matrix_histogram.ts b/x-pack/plugins/security_solution/common/api/search_strategy/matrix_histogram/matrix_histogram.ts index 7ad60f8d8b6fc..35152b5d17697 100644 --- a/x-pack/plugins/security_solution/common/api/search_strategy/matrix_histogram/matrix_histogram.ts +++ b/x-pack/plugins/security_solution/common/api/search_strategy/matrix_histogram/matrix_histogram.ts @@ -5,13 +5,6 @@ * 2.0. */ -import { z } from 'zod'; -import { MatrixHistogramQuery } from '../model/factory_query_type'; -import { inspect } from '../model/inspect'; -import { requestBasicOptionsSchema } from '../model/request_basic_options'; -import { runtimeMappings } from '../model/runtime_mappings'; -import { timerange } from '../model/timerange'; - export enum MatrixHistogramType { authentications = 'authentications', anomalies = 'anomalies', @@ -20,37 +13,3 @@ export enum MatrixHistogramType { dns = 'dns', preview = 'preview', } - -export const matrixHistogramSchema = requestBasicOptionsSchema.extend({ - histogramType: z.enum([ - MatrixHistogramType.alerts, - MatrixHistogramType.anomalies, - MatrixHistogramType.authentications, - MatrixHistogramType.dns, - MatrixHistogramType.events, - MatrixHistogramType.preview, - ]), - stackByField: z.string().optional(), - threshold: z - .object({ - field: z.array(z.string()), - value: z.string(), - cardinality: z - .object({ - field: z.array(z.string()), - value: z.string(), - }) - .optional(), - }) - .optional(), - inspect, - isPtrIncluded: z.boolean().default(false), - includeMissingData: z.boolean().default(true), - runtimeMappings, - timerange, - factoryQueryType: z.literal(MatrixHistogramQuery), -}); - -export type MatrixHistogramRequestOptionsInput = z.input; - -export type MatrixHistogramRequestOptions = z.infer; diff --git a/x-pack/plugins/security_solution/common/api/search_strategy/model/factory_query_type.ts b/x-pack/plugins/security_solution/common/api/search_strategy/model/factory_query_type.ts index 38de7349f1311..83a924f89253b 100644 --- a/x-pack/plugins/security_solution/common/api/search_strategy/model/factory_query_type.ts +++ b/x-pack/plugins/security_solution/common/api/search_strategy/model/factory_query_type.ts @@ -12,26 +12,11 @@ export enum HostsQueries { uncommonProcesses = 'uncommonProcesses', } -export enum NetworkKpiQueries { - dns = 'networkKpiDns', - networkEvents = 'networkKpiNetworkEvents', - tlsHandshakes = 'networkKpiTlsHandshakes', - uniqueFlows = 'networkKpiUniqueFlows', - uniquePrivateIps = 'networkKpiUniquePrivateIps', -} - -export enum HostsKpiQueries { - kpiHosts = 'hostsKpiHosts', - kpiUniqueIps = 'hostsKpiUniqueIps', -} - export enum UsersQueries { observedDetails = 'observedUserDetails', managedDetails = 'managedUserDetails', - kpiTotalUsers = 'usersKpiTotalUsers', users = 'allUsers', authentications = 'authentications', - kpiAuthentications = 'usersKpiAuthentications', } export enum NetworkQueries { @@ -57,8 +42,6 @@ export enum CtiQueries { dataSource = 'dataSource', } -export const MatrixHistogramQuery = 'matrixHistogram'; - export const FirstLastSeenQuery = 'firstlastseen'; export enum RelatedEntitiesQueries { @@ -68,12 +51,9 @@ export enum RelatedEntitiesQueries { export type FactoryQueryTypes = | HostsQueries - | HostsKpiQueries | UsersQueries | NetworkQueries - | NetworkKpiQueries | RiskQueries | CtiQueries - | typeof MatrixHistogramQuery | typeof FirstLastSeenQuery | RelatedEntitiesQueries; diff --git a/x-pack/plugins/security_solution/common/api/search_strategy/network/kpi/dns.ts b/x-pack/plugins/security_solution/common/api/search_strategy/network/kpi/dns.ts deleted file mode 100644 index fd614dd76e224..0000000000000 --- a/x-pack/plugins/security_solution/common/api/search_strategy/network/kpi/dns.ts +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { z } from 'zod'; -import { NetworkKpiQueries } from '../../model/factory_query_type'; - -import { requestBasicOptionsSchema } from '../../model/request_basic_options'; -import { timerange } from '../../model/timerange'; - -export const networkKpiDns = requestBasicOptionsSchema.extend({ - timerange, - factoryQueryType: z.literal(NetworkKpiQueries.dns), -}); - -export type NetworkKpiDnsRequestOptionsInput = z.input; - -export type NetworkKpiDnsRequestOptions = z.infer; diff --git a/x-pack/plugins/security_solution/common/api/search_strategy/network/kpi/events.ts b/x-pack/plugins/security_solution/common/api/search_strategy/network/kpi/events.ts deleted file mode 100644 index 7aef866065f29..0000000000000 --- a/x-pack/plugins/security_solution/common/api/search_strategy/network/kpi/events.ts +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { z } from 'zod'; -import { NetworkKpiQueries } from '../../model/factory_query_type'; - -import { requestBasicOptionsSchema } from '../../model/request_basic_options'; -import { timerange } from '../../model/timerange'; - -export const networkKpiEvents = requestBasicOptionsSchema.extend({ - timerange, - factoryQueryType: z.literal(NetworkKpiQueries.networkEvents), -}); - -export type NetworkKpiEventsRequestOptionsInput = z.input; - -export type NetworkKpiEventsRequestOptions = z.infer; diff --git a/x-pack/plugins/security_solution/common/api/search_strategy/network/kpi/index.ts b/x-pack/plugins/security_solution/common/api/search_strategy/network/kpi/index.ts deleted file mode 100644 index 2fce614035fd6..0000000000000 --- a/x-pack/plugins/security_solution/common/api/search_strategy/network/kpi/index.ts +++ /dev/null @@ -1,16 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -export * from './dns'; - -export * from './events'; - -export * from './tls_handshakes'; - -export * from './unique_flows'; - -export * from './unique_private_ips'; diff --git a/x-pack/plugins/security_solution/common/api/search_strategy/network/kpi/tls_handshakes.ts b/x-pack/plugins/security_solution/common/api/search_strategy/network/kpi/tls_handshakes.ts deleted file mode 100644 index 6847824032390..0000000000000 --- a/x-pack/plugins/security_solution/common/api/search_strategy/network/kpi/tls_handshakes.ts +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { z } from 'zod'; -import { NetworkKpiQueries } from '../../model/factory_query_type'; - -import { requestBasicOptionsSchema } from '../../model/request_basic_options'; -import { timerange } from '../../model/timerange'; - -export const networkKpiTlsHandshakes = requestBasicOptionsSchema.extend({ - timerange, - factoryQueryType: z.literal(NetworkKpiQueries.tlsHandshakes), -}); - -export type NetworkKpiTlsHandshakesRequestOptionsInput = z.input; - -export type NetworkKpiTlsHandshakesRequestOptions = z.infer; diff --git a/x-pack/plugins/security_solution/common/api/search_strategy/network/kpi/unique_flows.ts b/x-pack/plugins/security_solution/common/api/search_strategy/network/kpi/unique_flows.ts deleted file mode 100644 index 2ecc2f9d699de..0000000000000 --- a/x-pack/plugins/security_solution/common/api/search_strategy/network/kpi/unique_flows.ts +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { z } from 'zod'; -import { NetworkKpiQueries } from '../../model/factory_query_type'; - -import { requestBasicOptionsSchema } from '../../model/request_basic_options'; -import { timerange } from '../../model/timerange'; - -export const networkKpiUniqueFlows = requestBasicOptionsSchema.extend({ - timerange, - factoryQueryType: z.literal(NetworkKpiQueries.uniqueFlows), -}); - -export type NetworkKpiUniqueFlowsRequestOptionsInput = z.input; - -export type NetworkKpiUniqueFlowsRequestOptions = z.infer; diff --git a/x-pack/plugins/security_solution/common/api/search_strategy/network/kpi/unique_private_ips.ts b/x-pack/plugins/security_solution/common/api/search_strategy/network/kpi/unique_private_ips.ts deleted file mode 100644 index f870cd921c308..0000000000000 --- a/x-pack/plugins/security_solution/common/api/search_strategy/network/kpi/unique_private_ips.ts +++ /dev/null @@ -1,23 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { z } from 'zod'; -import { NetworkKpiQueries } from '../../model/factory_query_type'; - -import { requestBasicOptionsSchema } from '../../model/request_basic_options'; -import { timerange } from '../../model/timerange'; - -export const networkKpiUniquePrivateIps = requestBasicOptionsSchema.extend({ - timerange, - factoryQueryType: z.literal(NetworkKpiQueries.uniquePrivateIps), -}); - -export type NetworkKpiUniquePrivateIpsRequestOptionsInput = z.input< - typeof networkKpiUniquePrivateIps ->; - -export type NetworkKpiUniquePrivateIpsRequestOptions = z.infer; diff --git a/x-pack/plugins/security_solution/common/api/search_strategy/network/network.ts b/x-pack/plugins/security_solution/common/api/search_strategy/network/network.ts index 82cb6f78e8875..b9b90ba90b16b 100644 --- a/x-pack/plugins/security_solution/common/api/search_strategy/network/network.ts +++ b/x-pack/plugins/security_solution/common/api/search_strategy/network/network.ts @@ -11,8 +11,6 @@ export * from './dns'; export * from './http'; -export * from './kpi'; - export * from './overview'; export * from './tls'; diff --git a/x-pack/plugins/security_solution/common/api/search_strategy/users/kpi/authentications.ts b/x-pack/plugins/security_solution/common/api/search_strategy/users/kpi/authentications.ts deleted file mode 100644 index 42919d8c5111f..0000000000000 --- a/x-pack/plugins/security_solution/common/api/search_strategy/users/kpi/authentications.ts +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { z } from 'zod'; -import { UsersQueries } from '../../model/factory_query_type'; - -import { requestBasicOptionsSchema } from '../../model/request_basic_options'; -import { timerange } from '../../model/timerange'; - -export const authenticationsKpiSchema = requestBasicOptionsSchema.extend({ - timerange, - factoryQueryType: z.literal(UsersQueries.kpiAuthentications), -}); - -export type AuthenticationsKpiRequestOptionsInput = z.input; - -export type AuthenticationsKpiRequestOptions = z.infer; diff --git a/x-pack/plugins/security_solution/common/api/search_strategy/users/kpi/total_users.ts b/x-pack/plugins/security_solution/common/api/search_strategy/users/kpi/total_users.ts deleted file mode 100644 index 3822845cc58ac..0000000000000 --- a/x-pack/plugins/security_solution/common/api/search_strategy/users/kpi/total_users.ts +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { z } from 'zod'; -import { UsersQueries } from '../../model/factory_query_type'; - -import { requestBasicOptionsSchema } from '../../model/request_basic_options'; -import { timerange } from '../../model/timerange'; - -export const totalUsersKpiSchema = requestBasicOptionsSchema.extend({ - timerange, - factoryQueryType: z.literal(UsersQueries.kpiTotalUsers), -}); - -export type TotalUsersKpiRequestOptionsInput = z.input; - -export type TotalUsersKpiRequestOptions = z.infer; diff --git a/x-pack/plugins/security_solution/common/api/search_strategy/users/users.ts b/x-pack/plugins/security_solution/common/api/search_strategy/users/users.ts index 198af6ad7703f..5997117a542ae 100644 --- a/x-pack/plugins/security_solution/common/api/search_strategy/users/users.ts +++ b/x-pack/plugins/security_solution/common/api/search_strategy/users/users.ts @@ -9,10 +9,6 @@ export * from './observed_details'; export * from './managed_details'; -export * from './kpi/total_users'; - -export * from './kpi/authentications'; - export * from './all'; export * from './authentications'; diff --git a/x-pack/plugins/security_solution/common/experimental_features.ts b/x-pack/plugins/security_solution/common/experimental_features.ts index cd98a9ef812e4..48e22944853a9 100644 --- a/x-pack/plugins/security_solution/common/experimental_features.ts +++ b/x-pack/plugins/security_solution/common/experimental_features.ts @@ -19,7 +19,6 @@ export const allowedExperimentalValues = Object.freeze({ excludePoliciesInFilterEnabled: false, kubernetesEnabled: true, - chartEmbeddablesEnabled: true, donutChartEmbeddablesEnabled: false, // Depends on https://github.com/elastic/kibana/issues/136409 item 2 - 6 /** diff --git a/x-pack/plugins/security_solution/common/search_strategy/common/index.ts b/x-pack/plugins/security_solution/common/search_strategy/common/index.ts index d73b39ceb282d..f50cdc82f5857 100644 --- a/x-pack/plugins/security_solution/common/search_strategy/common/index.ts +++ b/x-pack/plugins/security_solution/common/search_strategy/common/index.ts @@ -19,23 +19,6 @@ export type Maybe = T | null; export type SearchHit = IEsSearchResponse['rawResponse']['hits']['hits'][0]; -export interface KpiHistogramData { - x?: Maybe; - y?: Maybe; -} - -export interface KpiHistogram { - key_as_string: string; - key: number; - doc_count: number; - count: T; -} - -export interface KpiGeneralHistogramCount { - value?: number; - doc_count?: number; -} - export interface PageInfoPaginated { activePage: number; fakeTotalCount: number; @@ -76,3 +59,14 @@ export interface GenericBuckets { } export type StringOrNumber = string | number; + +export type Fields = Record>>; + +export interface EventHit extends SearchHit { + sort: string[]; + _source: EventSource; + fields: Fields; + aggregations: { + [agg: string]: unknown; + }; +} diff --git a/x-pack/plugins/security_solution/common/search_strategy/security_solution/hosts/index.ts b/x-pack/plugins/security_solution/common/search_strategy/security_solution/hosts/index.ts index 3643f036ad563..46b6c5306f4b6 100644 --- a/x-pack/plugins/security_solution/common/search_strategy/security_solution/hosts/index.ts +++ b/x-pack/plugins/security_solution/common/search_strategy/security_solution/hosts/index.ts @@ -10,7 +10,6 @@ import { HostsFields } from '../../../api/search_strategy/hosts/model/sort'; export * from './all'; export * from './common'; export * from './details'; -export * from './kpi'; export * from './overview'; export * from './uncommon_processes'; diff --git a/x-pack/plugins/security_solution/common/search_strategy/security_solution/hosts/kpi/common/index.ts b/x-pack/plugins/security_solution/common/search_strategy/security_solution/hosts/kpi/common/index.ts deleted file mode 100644 index 7a13e661e914e..0000000000000 --- a/x-pack/plugins/security_solution/common/search_strategy/security_solution/hosts/kpi/common/index.ts +++ /dev/null @@ -1,13 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import type { Maybe } from '../../../../common'; - -export interface HostsKpiHistogramData { - x?: Maybe; - y?: Maybe; -} diff --git a/x-pack/plugins/security_solution/common/search_strategy/security_solution/hosts/kpi/hosts/index.ts b/x-pack/plugins/security_solution/common/search_strategy/security_solution/hosts/kpi/hosts/index.ts deleted file mode 100644 index 313275ce3c944..0000000000000 --- a/x-pack/plugins/security_solution/common/search_strategy/security_solution/hosts/kpi/hosts/index.ts +++ /dev/null @@ -1,16 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import type { IEsSearchResponse } from '@kbn/data-plugin/common'; -import type { Inspect, Maybe } from '../../../../common'; -import type { HostsKpiHistogramData } from '../common'; - -export interface HostsKpiHostsStrategyResponse extends IEsSearchResponse { - hosts: Maybe; - hostsHistogram: Maybe; - inspect?: Maybe; -} diff --git a/x-pack/plugins/security_solution/common/search_strategy/security_solution/hosts/kpi/index.ts b/x-pack/plugins/security_solution/common/search_strategy/security_solution/hosts/kpi/index.ts deleted file mode 100644 index fec98228d3ff6..0000000000000 --- a/x-pack/plugins/security_solution/common/search_strategy/security_solution/hosts/kpi/index.ts +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -export * from '../../users/kpi/authentications'; -export * from './common'; -export * from './hosts'; -export * from './unique_ips'; - -import type { UsersKpiAuthenticationsStrategyResponse } from '../../users/kpi/authentications'; -import type { HostsKpiHostsStrategyResponse } from './hosts'; -import type { HostsKpiUniqueIpsStrategyResponse } from './unique_ips'; - -export enum HostsKpiQueries { - kpiHosts = 'hostsKpiHosts', - kpiUniqueIps = 'hostsKpiUniqueIps', -} - -export type HostsKpiStrategyResponse = - | Omit - | Omit - | Omit; diff --git a/x-pack/plugins/security_solution/common/search_strategy/security_solution/hosts/kpi/unique_ips/index.ts b/x-pack/plugins/security_solution/common/search_strategy/security_solution/hosts/kpi/unique_ips/index.ts deleted file mode 100644 index 22cbad1ffd44a..0000000000000 --- a/x-pack/plugins/security_solution/common/search_strategy/security_solution/hosts/kpi/unique_ips/index.ts +++ /dev/null @@ -1,18 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import type { IEsSearchResponse } from '@kbn/data-plugin/common'; -import type { Inspect, Maybe } from '../../../../common'; -import type { HostsKpiHistogramData } from '../common'; - -export interface HostsKpiUniqueIpsStrategyResponse extends IEsSearchResponse { - uniqueSourceIps: Maybe; - uniqueSourceIpsHistogram: Maybe; - uniqueDestinationIps: Maybe; - uniqueDestinationIpsHistogram: Maybe; - inspect?: Maybe; -} diff --git a/x-pack/plugins/security_solution/common/search_strategy/security_solution/index.ts b/x-pack/plugins/security_solution/common/search_strategy/security_solution/index.ts index ee8006ca08b91..c4ec7d767616f 100644 --- a/x-pack/plugins/security_solution/common/search_strategy/security_solution/index.ts +++ b/x-pack/plugins/security_solution/common/search_strategy/security_solution/index.ts @@ -11,9 +11,6 @@ import type { HostsQueries, HostsStrategyResponse, HostsUncommonProcessesStrategyResponse, - HostsKpiQueries, - HostsKpiHostsStrategyResponse, - HostsKpiUniqueIpsStrategyResponse, } from './hosts'; import type { NetworkQueries, @@ -25,15 +22,8 @@ import type { NetworkTopCountriesStrategyResponse, NetworkTopNFlowStrategyResponse, NetworkUsersStrategyResponse, - NetworkKpiQueries, - NetworkKpiDnsStrategyResponse, - NetworkKpiNetworkEventsStrategyResponse, - NetworkKpiTlsHandshakesStrategyResponse, - NetworkKpiUniqueFlowsStrategyResponse, - NetworkKpiUniquePrivateIpsStrategyResponse, NetworkTopNFlowCountStrategyResponse, } from './network'; -import type { MatrixHistogramQuery, MatrixHistogramStrategyResponse } from './matrix_histogram'; import type { CtiEventEnrichmentStrategyResponse, CtiQueries, @@ -48,9 +38,6 @@ import type { } from './risk_score'; import type { UsersQueries } from './users'; import type { ObservedUserDetailsStrategyResponse } from './users/observed_details'; -import type { TotalUsersKpiStrategyResponse } from './users/kpi/total_users'; - -import type { UsersKpiAuthenticationsStrategyResponse } from './users/kpi/authentications'; import type { UsersStrategyResponse } from './users/all'; import type { UserAuthenticationsStrategyResponse } from './users/authentications'; @@ -61,8 +48,6 @@ import type { UsersRelatedHostsStrategyResponse } from './related_entities/relat import type { HostsRelatedUsersStrategyResponse } from './related_entities/related_users'; import type { - AuthenticationsKpiRequestOptions, - AuthenticationsKpiRequestOptionsInput, EventEnrichmentRequestOptions, EventEnrichmentRequestOptionsInput, FirstLastSeenRequestOptions, @@ -75,30 +60,14 @@ import type { HostsRequestOptionsInput, HostUncommonProcessesRequestOptions, HostUncommonProcessesRequestOptionsInput, - KpiHostsRequestOptions, - KpiHostsRequestOptionsInput, - KpiUniqueIpsRequestOptions, - KpiUniqueIpsRequestOptionsInput, ManagedUserDetailsRequestOptions, ManagedUserDetailsRequestOptionsInput, - MatrixHistogramRequestOptions, - MatrixHistogramRequestOptionsInput, NetworkDetailsRequestOptions, NetworkDetailsRequestOptionsInput, NetworkDnsRequestOptions, NetworkDnsRequestOptionsInput, NetworkHttpRequestOptions, NetworkHttpRequestOptionsInput, - NetworkKpiDnsRequestOptions, - NetworkKpiDnsRequestOptionsInput, - NetworkKpiEventsRequestOptions, - NetworkKpiEventsRequestOptionsInput, - NetworkKpiTlsHandshakesRequestOptions, - NetworkKpiTlsHandshakesRequestOptionsInput, - NetworkKpiUniqueFlowsRequestOptions, - NetworkKpiUniqueFlowsRequestOptionsInput, - NetworkKpiUniquePrivateIpsRequestOptions, - NetworkKpiUniquePrivateIpsRequestOptionsInput, NetworkOverviewRequestOptions, NetworkOverviewRequestOptionsInput, NetworkTlsRequestOptions, @@ -123,8 +92,6 @@ import type { RiskScoreRequestOptionsInput, ThreatIntelSourceRequestOptions, ThreatIntelSourceRequestOptionsInput, - TotalUsersKpiRequestOptions, - TotalUsersKpiRequestOptionsInput, UserAuthenticationsRequestOptions, UserAuthenticationsRequestOptionsInput, UsersRequestOptions, @@ -134,7 +101,6 @@ import type { export * from './cti'; export * from './hosts'; export * from './risk_score'; -export * from './matrix_histogram'; export * from './network'; export * from './users'; export * from './first_last_seen'; @@ -142,13 +108,10 @@ export * from './related_entities'; export type FactoryQueryTypes = | HostsQueries - | HostsKpiQueries | UsersQueries | NetworkQueries - | NetworkKpiQueries | RiskQueries | CtiQueries - | typeof MatrixHistogramQuery | typeof FirstLastSeenQuery | RelatedEntitiesQueries; @@ -162,22 +125,14 @@ export type StrategyResponseType = T extends HostsQ ? FirstLastSeenStrategyResponse : T extends HostsQueries.uncommonProcesses ? HostsUncommonProcessesStrategyResponse - : T extends HostsKpiQueries.kpiHosts - ? HostsKpiHostsStrategyResponse - : T extends HostsKpiQueries.kpiUniqueIps - ? HostsKpiUniqueIpsStrategyResponse : T extends UsersQueries.observedDetails ? ObservedUserDetailsStrategyResponse : T extends UsersQueries.managedDetails ? ManagedUserDetailsStrategyResponse - : T extends UsersQueries.kpiTotalUsers - ? TotalUsersKpiStrategyResponse : T extends UsersQueries.authentications ? UserAuthenticationsStrategyResponse : T extends UsersQueries.users ? UsersStrategyResponse - : T extends UsersQueries.kpiAuthentications - ? UsersKpiAuthenticationsStrategyResponse : T extends NetworkQueries.details ? NetworkDetailsStrategyResponse : T extends NetworkQueries.dns @@ -196,18 +151,6 @@ export type StrategyResponseType = T extends HostsQ ? NetworkTopNFlowCountStrategyResponse : T extends NetworkQueries.users ? NetworkUsersStrategyResponse - : T extends NetworkKpiQueries.dns - ? NetworkKpiDnsStrategyResponse - : T extends NetworkKpiQueries.networkEvents - ? NetworkKpiNetworkEventsStrategyResponse - : T extends NetworkKpiQueries.tlsHandshakes - ? NetworkKpiTlsHandshakesStrategyResponse - : T extends NetworkKpiQueries.uniqueFlows - ? NetworkKpiUniqueFlowsStrategyResponse - : T extends NetworkKpiQueries.uniquePrivateIps - ? NetworkKpiUniquePrivateIpsStrategyResponse - : T extends typeof MatrixHistogramQuery - ? MatrixHistogramStrategyResponse : T extends CtiQueries.eventEnrichment ? CtiEventEnrichmentStrategyResponse : T extends CtiQueries.dataSource @@ -234,22 +177,14 @@ export type StrategyRequestInputType = T extends Ho ? FirstLastSeenRequestOptionsInput : T extends HostsQueries.uncommonProcesses ? HostUncommonProcessesRequestOptionsInput - : T extends HostsKpiQueries.kpiHosts - ? KpiHostsRequestOptionsInput - : T extends HostsKpiQueries.kpiUniqueIps - ? KpiUniqueIpsRequestOptionsInput : T extends UsersQueries.authentications ? UserAuthenticationsRequestOptionsInput : T extends UsersQueries.observedDetails ? ObservedUserDetailsRequestOptionsInput : T extends UsersQueries.managedDetails ? ManagedUserDetailsRequestOptionsInput - : T extends UsersQueries.kpiTotalUsers - ? TotalUsersKpiRequestOptionsInput : T extends UsersQueries.users ? UsersRequestOptionsInput - : T extends UsersQueries.kpiAuthentications - ? AuthenticationsKpiRequestOptionsInput : T extends NetworkQueries.details ? NetworkDetailsRequestOptionsInput : T extends NetworkQueries.dns @@ -268,18 +203,6 @@ export type StrategyRequestInputType = T extends Ho ? NetworkTopNFlowCountRequestOptionsInput : T extends NetworkQueries.users ? NetworkUsersRequestOptionsInput - : T extends NetworkKpiQueries.dns - ? NetworkKpiDnsRequestOptionsInput - : T extends NetworkKpiQueries.networkEvents - ? NetworkKpiEventsRequestOptionsInput - : T extends NetworkKpiQueries.tlsHandshakes - ? NetworkKpiTlsHandshakesRequestOptionsInput - : T extends NetworkKpiQueries.uniqueFlows - ? NetworkKpiUniqueFlowsRequestOptionsInput - : T extends NetworkKpiQueries.uniquePrivateIps - ? NetworkKpiUniquePrivateIpsRequestOptionsInput - : T extends typeof MatrixHistogramQuery - ? MatrixHistogramRequestOptionsInput : T extends CtiQueries.eventEnrichment ? EventEnrichmentRequestOptionsInput : T extends CtiQueries.dataSource @@ -306,22 +229,14 @@ export type StrategyRequestType = T extends HostsQu ? FirstLastSeenRequestOptions : T extends HostsQueries.uncommonProcesses ? HostUncommonProcessesRequestOptions - : T extends HostsKpiQueries.kpiHosts - ? KpiHostsRequestOptions - : T extends HostsKpiQueries.kpiUniqueIps - ? KpiUniqueIpsRequestOptions : T extends UsersQueries.authentications ? UserAuthenticationsRequestOptions : T extends UsersQueries.observedDetails ? ObservedUserDetailsRequestOptions : T extends UsersQueries.managedDetails ? ManagedUserDetailsRequestOptions - : T extends UsersQueries.kpiTotalUsers - ? TotalUsersKpiRequestOptions : T extends UsersQueries.users ? UsersRequestOptions - : T extends UsersQueries.kpiAuthentications - ? AuthenticationsKpiRequestOptions : T extends NetworkQueries.details ? NetworkDetailsRequestOptions : T extends NetworkQueries.dns @@ -340,18 +255,6 @@ export type StrategyRequestType = T extends HostsQu ? NetworkTopNFlowCountRequestOptions : T extends NetworkQueries.users ? NetworkUsersRequestOptions - : T extends NetworkKpiQueries.dns - ? NetworkKpiDnsRequestOptions - : T extends NetworkKpiQueries.networkEvents - ? NetworkKpiEventsRequestOptions - : T extends NetworkKpiQueries.tlsHandshakes - ? NetworkKpiTlsHandshakesRequestOptions - : T extends NetworkKpiQueries.uniqueFlows - ? NetworkKpiUniqueFlowsRequestOptions - : T extends NetworkKpiQueries.uniquePrivateIps - ? NetworkKpiUniquePrivateIpsRequestOptions - : T extends typeof MatrixHistogramQuery - ? MatrixHistogramRequestOptions : T extends CtiQueries.eventEnrichment ? EventEnrichmentRequestOptions : T extends CtiQueries.dataSource diff --git a/x-pack/plugins/security_solution/common/search_strategy/security_solution/matrix_histogram/alerts/index.ts b/x-pack/plugins/security_solution/common/search_strategy/security_solution/matrix_histogram/alerts/index.ts deleted file mode 100644 index 7780a5273b596..0000000000000 --- a/x-pack/plugins/security_solution/common/search_strategy/security_solution/matrix_histogram/alerts/index.ts +++ /dev/null @@ -1,16 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import type { HistogramBucket } from '../common'; - -export interface AlertsGroupData { - key: string; - doc_count: number; - alerts: { - buckets: HistogramBucket[]; - }; -} diff --git a/x-pack/plugins/security_solution/common/search_strategy/security_solution/matrix_histogram/anomalies/index.ts b/x-pack/plugins/security_solution/common/search_strategy/security_solution/matrix_histogram/anomalies/index.ts deleted file mode 100644 index d2eb1282ac880..0000000000000 --- a/x-pack/plugins/security_solution/common/search_strategy/security_solution/matrix_histogram/anomalies/index.ts +++ /dev/null @@ -1,20 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -interface AnomaliesOverTimeHistogramData { - key_as_string: string; - key: number; - doc_count: number; -} - -export interface AnomaliesActionGroupData { - key: number; - anomalies: { - bucket: AnomaliesOverTimeHistogramData[]; - }; - doc_count: number; -} diff --git a/x-pack/plugins/security_solution/common/search_strategy/security_solution/matrix_histogram/authentications/index.ts b/x-pack/plugins/security_solution/common/search_strategy/security_solution/matrix_histogram/authentications/index.ts deleted file mode 100644 index 5c57f52b74276..0000000000000 --- a/x-pack/plugins/security_solution/common/search_strategy/security_solution/matrix_histogram/authentications/index.ts +++ /dev/null @@ -1,20 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -export interface AuthenticationsOverTimeHistogramData { - key_as_string: string; - key: number; - doc_count: number; -} - -export interface AuthenticationsActionGroupData { - key: number; - events: { - bucket: AuthenticationsOverTimeHistogramData[]; - }; - doc_count: number; -} diff --git a/x-pack/plugins/security_solution/common/search_strategy/security_solution/matrix_histogram/common/index.ts b/x-pack/plugins/security_solution/common/search_strategy/security_solution/matrix_histogram/common/index.ts deleted file mode 100644 index 4ee1044f5e4a3..0000000000000 --- a/x-pack/plugins/security_solution/common/search_strategy/security_solution/matrix_histogram/common/index.ts +++ /dev/null @@ -1,11 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -export interface HistogramBucket { - key: number; - doc_count: number; -} diff --git a/x-pack/plugins/security_solution/common/search_strategy/security_solution/matrix_histogram/dns/index.ts b/x-pack/plugins/security_solution/common/search_strategy/security_solution/matrix_histogram/dns/index.ts deleted file mode 100644 index 0bff9e11487f9..0000000000000 --- a/x-pack/plugins/security_solution/common/search_strategy/security_solution/matrix_histogram/dns/index.ts +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -export interface DnsHistogramSubBucket { - key: string; - doc_count: number; - orderAgg: { - value: number; - }; -} -interface DnsHistogramBucket { - doc_count_error_upper_bound: number; - sum_other_doc_count: number; - buckets: DnsHistogramSubBucket[]; -} - -export interface DnsHistogramGroupData { - key: number; - doc_count: number; - key_as_string: string; - histogram: DnsHistogramBucket; -} diff --git a/x-pack/plugins/security_solution/common/search_strategy/security_solution/matrix_histogram/events/index.ts b/x-pack/plugins/security_solution/common/search_strategy/security_solution/matrix_histogram/events/index.ts deleted file mode 100644 index ec2ad46a9b75e..0000000000000 --- a/x-pack/plugins/security_solution/common/search_strategy/security_solution/matrix_histogram/events/index.ts +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import type { SearchHit } from '../../../common'; - -interface EventsMatrixHistogramData { - key_as_string: string; - key: number; - doc_count: number; -} - -export interface EventSource { - // eslint-disable-next-line @typescript-eslint/no-explicit-any - [field: string]: any; -} - -export interface EventsActionGroupData { - key: number | string; - events: { - bucket: EventsMatrixHistogramData[]; - }; - doc_count: number; -} - -export interface Fields { - [x: string]: T | Array>; -} - -export interface EventHit extends SearchHit { - sort: string[]; - _source: EventSource; - fields: Fields; - aggregations: { - // eslint-disable-next-line @typescript-eslint/no-explicit-any - [agg: string]: any; - }; -} diff --git a/x-pack/plugins/security_solution/common/search_strategy/security_solution/matrix_histogram/index.ts b/x-pack/plugins/security_solution/common/search_strategy/security_solution/matrix_histogram/index.ts deleted file mode 100644 index 7677b4b5b8824..0000000000000 --- a/x-pack/plugins/security_solution/common/search_strategy/security_solution/matrix_histogram/index.ts +++ /dev/null @@ -1,87 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import type { IEsSearchResponse } from '@kbn/data-plugin/common'; -import type { MatrixHistogramRequestOptions } from '../../../api/search_strategy/matrix_histogram/matrix_histogram'; -import type { Inspect, Maybe } from '../../common'; -import type { AlertsGroupData } from './alerts'; -import type { AnomaliesActionGroupData } from './anomalies'; -import type { DnsHistogramGroupData } from './dns'; -import type { AuthenticationsActionGroupData } from './authentications'; -import type { EventsActionGroupData } from './events'; -import type { PreviewHistogramGroupData } from './preview'; - -export * from './alerts'; -export * from './anomalies'; -export * from './authentications'; -export * from './common'; -export * from './dns'; -export * from './events'; -export * from './preview'; - -export { MatrixHistogramQuery } from '../../../api/search_strategy'; - -export enum MatrixHistogramType { - authentications = 'authentications', - anomalies = 'anomalies', - events = 'events', - alerts = 'alerts', - dns = 'dns', - preview = 'preview', -} - -export const MatrixHistogramTypeToAggName = { - [MatrixHistogramType.alerts]: 'aggregations.alertsGroup.buckets', - [MatrixHistogramType.anomalies]: 'aggregations.anomalyActionGroup.buckets', - [MatrixHistogramType.authentications]: 'aggregations.eventActionGroup.buckets', - [MatrixHistogramType.dns]: 'aggregations.dns_name_query_count.buckets', - [MatrixHistogramType.events]: 'aggregations.eventActionGroup.buckets', - [MatrixHistogramType.preview]: 'aggregations.preview.buckets', -}; - -export interface MatrixHistogramStrategyResponse extends IEsSearchResponse { - inspect?: Maybe; - matrixHistogramData: MatrixHistogramData[]; - totalCount: number; -} - -export interface MatrixHistogramData { - x?: Maybe; - y?: Maybe; - g?: Maybe; -} - -export interface MatrixHistogramBucket { - key: number; - doc_count: number; -} - -export interface MatrixHistogramSchema { - buildDsl: (options: MatrixHistogramRequestOptions) => {}; - aggName: string; - parseKey: string; - parser?: (data: MatrixHistogramParseData, keyBucket: string) => MatrixHistogramData[]; -} - -export type MatrixHistogramParseData = T extends MatrixHistogramType.alerts - ? AlertsGroupData[] - : T extends MatrixHistogramType.anomalies - ? AnomaliesActionGroupData[] - : T extends MatrixHistogramType.dns - ? DnsHistogramGroupData[] - : T extends MatrixHistogramType.authentications - ? AuthenticationsActionGroupData[] - : T extends MatrixHistogramType.events - ? EventsActionGroupData[] - : T extends MatrixHistogramType.preview - ? PreviewHistogramGroupData[] - : never; - -export type MatrixHistogramDataConfig = Record< - MatrixHistogramType, - MatrixHistogramSchema ->; diff --git a/x-pack/plugins/security_solution/common/search_strategy/security_solution/matrix_histogram/preview/index.ts b/x-pack/plugins/security_solution/common/search_strategy/security_solution/matrix_histogram/preview/index.ts deleted file mode 100644 index 1c58eca3b4d9b..0000000000000 --- a/x-pack/plugins/security_solution/common/search_strategy/security_solution/matrix_histogram/preview/index.ts +++ /dev/null @@ -1,16 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import type { HistogramBucket } from '../common'; - -export interface PreviewHistogramGroupData { - key: string; - doc_count: number; - preview: { - buckets: HistogramBucket[]; - }; -} diff --git a/x-pack/plugins/security_solution/common/search_strategy/security_solution/network/index.ts b/x-pack/plugins/security_solution/common/search_strategy/security_solution/network/index.ts index 469bd0eaf38bd..919360fc1ae4f 100644 --- a/x-pack/plugins/security_solution/common/search_strategy/security_solution/network/index.ts +++ b/x-pack/plugins/security_solution/common/search_strategy/security_solution/network/index.ts @@ -9,7 +9,6 @@ export * from './common'; export * from './details'; export * from './dns'; export * from './http'; -export * from './kpi'; export * from './overview'; export * from './tls'; export * from './top_countries'; diff --git a/x-pack/plugins/security_solution/common/search_strategy/security_solution/network/kpi/dns/index.ts b/x-pack/plugins/security_solution/common/search_strategy/security_solution/network/kpi/dns/index.ts deleted file mode 100644 index 3f006530aab19..0000000000000 --- a/x-pack/plugins/security_solution/common/search_strategy/security_solution/network/kpi/dns/index.ts +++ /dev/null @@ -1,14 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import type { IEsSearchResponse } from '@kbn/data-plugin/common'; -import type { Inspect, Maybe } from '../../../../common'; - -export interface NetworkKpiDnsStrategyResponse extends IEsSearchResponse { - dnsQueries: number; - inspect?: Maybe; -} diff --git a/x-pack/plugins/security_solution/common/search_strategy/security_solution/network/kpi/index.ts b/x-pack/plugins/security_solution/common/search_strategy/security_solution/network/kpi/index.ts deleted file mode 100644 index 7c482608cea04..0000000000000 --- a/x-pack/plugins/security_solution/common/search_strategy/security_solution/network/kpi/index.ts +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -export * from './dns'; -export * from './network_events'; -export * from './tls_handshakes'; -export * from './unique_flows'; -export * from './unique_private_ips'; - -import type { NetworkKpiDnsStrategyResponse } from './dns'; -import type { NetworkKpiNetworkEventsStrategyResponse } from './network_events'; -import type { NetworkKpiTlsHandshakesStrategyResponse } from './tls_handshakes'; -import type { NetworkKpiUniqueFlowsStrategyResponse } from './unique_flows'; -import type { NetworkKpiUniquePrivateIpsStrategyResponse } from './unique_private_ips'; - -export enum NetworkKpiQueries { - dns = 'networkKpiDns', - networkEvents = 'networkKpiNetworkEvents', - tlsHandshakes = 'networkKpiTlsHandshakes', - uniqueFlows = 'networkKpiUniqueFlows', - uniquePrivateIps = 'networkKpiUniquePrivateIps', -} - -export type NetworkKpiStrategyResponse = - | Omit - | Omit - | Omit - | Omit - | Omit; diff --git a/x-pack/plugins/security_solution/common/search_strategy/security_solution/network/kpi/network_events/index.ts b/x-pack/plugins/security_solution/common/search_strategy/security_solution/network/kpi/network_events/index.ts deleted file mode 100644 index 781fd8ddfd90a..0000000000000 --- a/x-pack/plugins/security_solution/common/search_strategy/security_solution/network/kpi/network_events/index.ts +++ /dev/null @@ -1,14 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import type { IEsSearchResponse } from '@kbn/data-plugin/common'; -import type { Inspect, Maybe } from '../../../../common'; - -export interface NetworkKpiNetworkEventsStrategyResponse extends IEsSearchResponse { - networkEvents: number; - inspect?: Maybe; -} diff --git a/x-pack/plugins/security_solution/common/search_strategy/security_solution/network/kpi/tls_handshakes/index.ts b/x-pack/plugins/security_solution/common/search_strategy/security_solution/network/kpi/tls_handshakes/index.ts deleted file mode 100644 index c2219c6ec8233..0000000000000 --- a/x-pack/plugins/security_solution/common/search_strategy/security_solution/network/kpi/tls_handshakes/index.ts +++ /dev/null @@ -1,14 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import type { IEsSearchResponse } from '@kbn/data-plugin/common'; -import type { Inspect, Maybe } from '../../../../common'; - -export interface NetworkKpiTlsHandshakesStrategyResponse extends IEsSearchResponse { - tlsHandshakes: number; - inspect?: Maybe; -} diff --git a/x-pack/plugins/security_solution/common/search_strategy/security_solution/network/kpi/unique_flows/index.ts b/x-pack/plugins/security_solution/common/search_strategy/security_solution/network/kpi/unique_flows/index.ts deleted file mode 100644 index eba5f19ddc246..0000000000000 --- a/x-pack/plugins/security_solution/common/search_strategy/security_solution/network/kpi/unique_flows/index.ts +++ /dev/null @@ -1,14 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import type { IEsSearchResponse } from '@kbn/data-plugin/common'; -import type { Inspect, Maybe } from '../../../../common'; - -export interface NetworkKpiUniqueFlowsStrategyResponse extends IEsSearchResponse { - uniqueFlowId: number; - inspect?: Maybe; -} diff --git a/x-pack/plugins/security_solution/common/search_strategy/security_solution/network/kpi/unique_private_ips/index.ts b/x-pack/plugins/security_solution/common/search_strategy/security_solution/network/kpi/unique_private_ips/index.ts deleted file mode 100644 index d002452702332..0000000000000 --- a/x-pack/plugins/security_solution/common/search_strategy/security_solution/network/kpi/unique_private_ips/index.ts +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import type { IEsSearchResponse } from '@kbn/data-plugin/common'; -import type { Inspect, Maybe } from '../../../../common'; - -export interface NetworkKpiHistogramData { - x?: Maybe; - y?: Maybe; -} - -export interface NetworkKpiUniquePrivateIpsStrategyResponse extends IEsSearchResponse { - uniqueSourcePrivateIps: number; - uniqueSourcePrivateIpsHistogram: NetworkKpiHistogramData[] | null; - uniqueDestinationPrivateIps: number; - uniqueDestinationPrivateIpsHistogram: NetworkKpiHistogramData[] | null; - inspect?: Maybe; -} - -export type UniquePrivateAttributeQuery = 'source' | 'destination'; diff --git a/x-pack/plugins/security_solution/common/search_strategy/security_solution/users/index.ts b/x-pack/plugins/security_solution/common/search_strategy/security_solution/users/index.ts index 9989f2eb6d331..27ef092c15019 100644 --- a/x-pack/plugins/security_solution/common/search_strategy/security_solution/users/index.ts +++ b/x-pack/plugins/security_solution/common/search_strategy/security_solution/users/index.ts @@ -5,14 +5,9 @@ * 2.0. */ -import type { TotalUsersKpiStrategyResponse } from './kpi/total_users'; - export * from './all'; export * from './common'; -export * from './kpi'; export * from './observed_details'; export * from './authentications'; export { UsersQueries } from '../../../api/search_strategy'; - -export type UsersKpiStrategyResponse = Omit; diff --git a/x-pack/plugins/security_solution/common/search_strategy/security_solution/users/kpi/authentications/index.ts b/x-pack/plugins/security_solution/common/search_strategy/security_solution/users/kpi/authentications/index.ts deleted file mode 100644 index cd6fd18b86c87..0000000000000 --- a/x-pack/plugins/security_solution/common/search_strategy/security_solution/users/kpi/authentications/index.ts +++ /dev/null @@ -1,17 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import type { IEsSearchResponse } from '@kbn/data-plugin/common'; -import type { Inspect, KpiHistogramData, Maybe } from '../../../../common'; - -export interface UsersKpiAuthenticationsStrategyResponse extends IEsSearchResponse { - authenticationsSuccess: Maybe; - authenticationsSuccessHistogram: Maybe; - authenticationsFailure: Maybe; - authenticationsFailureHistogram: Maybe; - inspect?: Maybe; -} diff --git a/x-pack/plugins/security_solution/common/search_strategy/security_solution/users/kpi/index.ts b/x-pack/plugins/security_solution/common/search_strategy/security_solution/users/kpi/index.ts deleted file mode 100644 index c89414639b417..0000000000000 --- a/x-pack/plugins/security_solution/common/search_strategy/security_solution/users/kpi/index.ts +++ /dev/null @@ -1,8 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -export * from './total_users'; diff --git a/x-pack/plugins/security_solution/common/search_strategy/security_solution/users/kpi/total_users/index.ts b/x-pack/plugins/security_solution/common/search_strategy/security_solution/users/kpi/total_users/index.ts deleted file mode 100644 index 690678c1d78d9..0000000000000 --- a/x-pack/plugins/security_solution/common/search_strategy/security_solution/users/kpi/total_users/index.ts +++ /dev/null @@ -1,15 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import type { IEsSearchResponse } from '@kbn/data-plugin/common'; -import type { Inspect, KpiHistogramData, Maybe } from '../../../../common'; - -export interface TotalUsersKpiStrategyResponse extends IEsSearchResponse { - users: Maybe; - usersHistogram: Maybe; - inspect?: Maybe; -} diff --git a/x-pack/plugins/security_solution/public/common/components/events_tab/events_query_tab_body.tsx b/x-pack/plugins/security_solution/public/common/components/events_tab/events_query_tab_body.tsx index cd2810a5689fb..b6e8985c1d15d 100644 --- a/x-pack/plugins/security_solution/public/common/components/events_tab/events_query_tab_body.tsx +++ b/x-pack/plugins/security_solution/public/common/components/events_tab/events_query_tab_body.tsx @@ -175,7 +175,6 @@ const EventsQueryTabBodyComponent: React.FC = startDate={startDate} endDate={endDate} filterQuery={filterQuery} - indexNames={indexNames} setQuery={setQuery} {...(showExternalAlerts ? alertsHistogramConfig : eventsHistogramConfig)} subtitle={getHistogramSubtitle} diff --git a/x-pack/plugins/security_solution/public/common/components/events_tab/histogram_configurations.ts b/x-pack/plugins/security_solution/public/common/components/events_tab/histogram_configurations.ts index f341f090710a0..12458d5c52a5f 100644 --- a/x-pack/plugins/security_solution/public/common/components/events_tab/histogram_configurations.ts +++ b/x-pack/plugins/security_solution/public/common/components/events_tab/histogram_configurations.ts @@ -6,7 +6,6 @@ */ import numeral from '@elastic/numeral'; -import { MatrixHistogramType } from '../../../../common/search_strategy/security_solution'; import { getExternalAlertLensAttributes } from '../visualization_actions/lens_attributes/common/external_alert'; import { getEventsHistogramLensAttributes } from '../visualization_actions/lens_attributes/common/events'; import type { MatrixHistogramConfigs, MatrixHistogramOption } from '../matrix_histogram/types'; @@ -38,8 +37,6 @@ export const eventsStackByOptions: MatrixHistogramOption[] = [ export const eventsHistogramConfig: MatrixHistogramConfigs = { defaultStackByOption: eventsStackByOptions.find((o) => o.text === DEFAULT_EVENTS_STACK_BY) ?? eventsStackByOptions[0], - errorMessage: i18n.ERROR_FETCHING_EVENTS_DATA, - histogramType: MatrixHistogramType.events, stackByOptions: eventsStackByOptions, subtitle: undefined, title: i18n.EVENTS_GRAPH_TITLE, @@ -62,10 +59,7 @@ const DEFAULT_STACK_BY = 'event.module'; export const alertsHistogramConfig: MatrixHistogramConfigs = { defaultStackByOption: alertsStackByOptions.find((o) => o.text === DEFAULT_STACK_BY) ?? alertsStackByOptions[0], - errorMessage: i18n.ERROR_FETCHING_ALERTS_DATA, - histogramType: MatrixHistogramType.alerts, stackByOptions: alertsStackByOptions, - subtitle: undefined, title: i18n.ALERTS_GRAPH_TITLE, getLensAttributes: getExternalAlertLensAttributes, }; diff --git a/x-pack/plugins/security_solution/public/common/components/matrix_histogram/chart_content.tsx b/x-pack/plugins/security_solution/public/common/components/matrix_histogram/chart_content.tsx deleted file mode 100644 index 65d3774af1eef..0000000000000 --- a/x-pack/plugins/security_solution/public/common/components/matrix_histogram/chart_content.tsx +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import React from 'react'; -import type { BarChartComponentProps } from '../charts/barchart'; -import { BarChart } from '../charts/barchart'; -import { MatrixLoader } from './matrix_loader'; - -const MatrixHistogramChartContentComponent = ({ - isInitialLoading, - barChart, - configs, - stackByField, - scopeId, -}: BarChartComponentProps & { isInitialLoading: boolean }) => { - return isInitialLoading ? ( - - ) : ( - - ); -}; - -export const MatrixHistogramChartContent = React.memo(MatrixHistogramChartContentComponent); - -MatrixHistogramChartContentComponent.displayName = 'MatrixHistogramChartContentComponent'; diff --git a/x-pack/plugins/security_solution/public/common/components/matrix_histogram/index.test.tsx b/x-pack/plugins/security_solution/public/common/components/matrix_histogram/index.test.tsx index ac254714adbb7..c9c2b5cb25c62 100644 --- a/x-pack/plugins/security_solution/public/common/components/matrix_histogram/index.test.tsx +++ b/x-pack/plugins/security_solution/public/common/components/matrix_histogram/index.test.tsx @@ -10,29 +10,13 @@ import { mount } from 'enzyme'; import React from 'react'; 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'; import { getDnsTopDomainsLensAttributes } from '../visualization_actions/lens_attributes/network/dns_top_domains'; import { useQueryToggle } from '../../containers/query_toggle'; -import { useIsExperimentalFeatureEnabled } from '../../hooks/use_experimental_features'; -import type { ExperimentalFeatures } from '../../../../common/experimental_features'; -import { allowedExperimentalValues } from '../../../../common/experimental_features'; -import { VisualizationActions } from '../visualization_actions/actions'; jest.mock('../../containers/query_toggle'); -jest.mock('./matrix_loader', () => ({ - MatrixLoader: () =>
, -})); - -jest.mock('../charts/barchart', () => ({ - BarChart: () =>
, -})); - -jest.mock('../../containers/matrix_histogram'); - jest.mock('../visualization_actions/actions'); jest.mock('../visualization_actions/visualization_embeddable'); @@ -40,20 +24,16 @@ jest.mock('../../hooks/use_experimental_features', () => ({ useIsExperimentalFeatureEnabled: jest.fn(), })); -jest.mock('./utils', () => ({ - getBarchartConfigs: jest.fn(), - getCustomChartData: jest.fn().mockReturnValue(true), -})); - const mockUseVisualizationResponse = jest.fn(() => ({ responses: [{ aggregations: [{ buckets: [{ key: '1234' }] }], hits: { total: 999 } }], + requests: [], + loading: false, })); jest.mock('../visualization_actions/use_visualization_response', () => ({ useVisualizationResponse: () => mockUseVisualizationResponse(), })); const mockLocation = jest.fn().mockReturnValue({ pathname: '/test' }); -const mockUseIsExperimentalFeatureEnabled = useIsExperimentalFeatureEnabled as jest.Mock; jest.mock('react-router-dom', () => { const original = jest.requireActual('react-router-dom'); @@ -74,15 +54,11 @@ describe('Matrix Histogram Component', () => { value: 'dns.question.registered_domain', }, endDate: '2019-07-18T20:00:00.000Z', - errorMessage: 'error', - histogramType: MatrixHistogramType.alerts, id: 'mockId', indexNames: [], isInspected: false, isPtrIncluded: true, setQuery: jest.fn(), - skip: false, - sourceId: 'default', stackByOptions: [ { text: 'dns.question.registered_domain', value: 'dns.question.registered_domain' }, ], @@ -92,51 +68,51 @@ describe('Matrix Histogram Component', () => { title: 'mockTitle', runtimeMappings: mockRuntimeMappings, }; - const mockUseMatrix = useMatrixHistogramCombined as jest.Mock; const mockUseQueryToggle = useQueryToggle as jest.Mock; const mockSetToggle = jest.fn(); - const getMockUseIsExperimentalFeatureEnabled = - (mockMapping?: Partial) => - (flag: keyof typeof allowedExperimentalValues) => - mockMapping ? mockMapping?.[flag] : allowedExperimentalValues?.[flag]; beforeEach(() => { jest.clearAllMocks(); - mockUseIsExperimentalFeatureEnabled.mockImplementation( - getMockUseIsExperimentalFeatureEnabled({ chartEmbeddablesEnabled: false }) - ); + mockUseQueryToggle.mockReturnValue({ toggleStatus: true, setToggleStatus: mockSetToggle }); - mockUseMatrix.mockReturnValue([ - false, - { - data: null, - inspect: false, - totalCount: null, - }, - ]); }); - describe('on initial load', () => { + describe('rendering', () => { beforeEach(() => { wrapper = mount(, { wrappingComponent: TestProviders, }); }); - test('it requests Matrix Histogram', () => { - expect(mockUseMatrix).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 should not render VisualizationActions', () => { + expect(wrapper.find(`[data-test-subj="visualizationActions"]`).exists()).toEqual(false); + }); + + test('it should render Lens Visualization', () => { + expect(wrapper.find(`[data-test-subj="visualization-embeddable"]`).exists()).toEqual(true); + }); + + test('it should render visualization count as subtitle', () => { + wrapper.setProps({ endDate: 100 }); + wrapper.update(); + + expect(wrapper.find(`[data-test-subj="header-section-subtitle"]`).text()).toEqual( + 'Showing: 999 events' + ); }); - test('it renders MatrixLoader', () => { - expect(wrapper.find('MatrixLoader').exists()).toBe(true); + + test('it should render 0 as subtitle when buckets are empty', () => { + mockUseVisualizationResponse.mockReturnValue({ + requests: [], + responses: [{ aggregations: [{ buckets: [] }], hits: { total: 999 } }], + loading: false, + }); + wrapper.setProps({ endDate: 100 }); + wrapper.update(); + + expect(wrapper.find(`[data-test-subj="header-section-subtitle"]`).text()).toEqual( + 'Showing: 0 events' + ); }); }); @@ -145,7 +121,7 @@ describe('Matrix Histogram Component', () => { wrapper = mount(, { wrappingComponent: TestProviders, }); - expect(wrapper.find('[data-test-subj="spacer"]').exists()).toBe(true); + expect(wrapper.find('[data-test-subj="spacer"]').exists()).toEqual(true); }); test('it does NOT render a spacer when showSpacer is false', () => { @@ -155,39 +131,7 @@ describe('Matrix Histogram Component', () => { wrappingComponent: TestProviders, } ); - expect(wrapper.find('[data-test-subj="spacer"]').exists()).toBe(false); - }); - }); - - describe('not initial load', () => { - beforeEach(() => { - wrapper = mount(, { - wrappingComponent: TestProviders, - }); - mockUseMatrix.mockReturnValue([ - false, - { - data: [ - { x: 1, y: 2, g: 'g1' }, - { x: 2, y: 4, g: 'g1' }, - { x: 3, y: 6, g: 'g1' }, - { x: 1, y: 1, g: 'g2' }, - { x: 2, y: 3, g: 'g2' }, - { x: 3, y: 5, g: 'g2' }, - ], - inspect: false, - totalCount: 1, - }, - ]); - wrapper.setProps({ endDate: 100 }); - wrapper.update(); - }); - test('it renders no MatrixLoader', () => { - expect(wrapper.find(`MatrixLoader`).exists()).toBe(false); - }); - - test('it shows BarChart if data available', () => { - expect(wrapper.find(`.barchart`).exists()).toBe(true); + expect(wrapper.find('[data-test-subj="spacer"]').exists()).toEqual(false); }); }); @@ -196,12 +140,12 @@ describe('Matrix Histogram Component', () => { wrapper = mount(, { wrappingComponent: TestProviders, }); - expect(wrapper.find('EuiSelect').exists()).toBe(false); + expect(wrapper.find('EuiSelect').exists()).toEqual(false); }); }); describe('Inspect button', () => { - test("it doesn't render Inspect button by default", () => { + test('it does not render Inspect button', () => { const testProps = { ...mockMatrixOverTimeHistogramProps, getLensAttributes: getDnsTopDomainsLensAttributes, @@ -209,46 +153,7 @@ describe('Matrix Histogram Component', () => { wrapper = mount(, { wrappingComponent: TestProviders, }); - expect(wrapper.find('[data-test-subj="inspect-icon-button"]').exists()).toBe(false); - }); - }); - - describe('VisualizationActions', () => { - const testProps = { - ...mockMatrixOverTimeHistogramProps, - getLensAttributes: jest.fn().mockReturnValue(getDnsTopDomainsLensAttributes()), - }; - beforeEach(() => { - wrapper = mount(, { - wrappingComponent: TestProviders, - }); - }); - test('it renders VisualizationActions if getLensAttributes is provided', () => { - expect(wrapper.find('[data-test-subj="visualizationActions"]').exists()).toBe(true); - expect(wrapper.find('[data-test-subj="visualizationActions"]').prop('className')).toEqual( - 'histogram-viz-actions' - ); - }); - - test('it VisualizationActions with correct properties', () => { - expect((VisualizationActions as unknown as jest.Mock).mock.calls[0][0]).toEqual( - expect.objectContaining({ - className: 'histogram-viz-actions', - extraOptions: { - dnsIsPtrIncluded: testProps.isPtrIncluded, - }, - getLensAttributes: testProps.getLensAttributes, - lensAttributes: undefined, - isInspectButtonDisabled: true, - queryId: testProps.id, - stackByField: testProps.defaultStackByOption.value, - timerange: { - from: testProps.startDate, - to: testProps.endDate, - }, - title: testProps.title, - }) - ); + expect(wrapper.find('[data-test-subj="inspect-icon-button"]').exists()).toEqual(false); }); }); @@ -262,25 +167,16 @@ describe('Matrix Histogram Component', () => { wrapper = mount(, { wrappingComponent: TestProviders, }); - expect(mockUseMatrix.mock.calls[0][0].skip).toEqual(false); + expect(wrapper.find('[data-test-subj="visualization-embeddable"]').exists()).toEqual(true); wrapper.find('[data-test-subj="query-toggle-header"]').first().simulate('click'); expect(mockSetToggle).toBeCalledWith(false); - expect(mockUseMatrix.mock.calls[1][0].skip).toEqual(true); - }); - - test('toggleStatus=true, do not skip', () => { - wrapper = mount(, { - wrappingComponent: TestProviders, - }); - - expect(mockUseMatrix.mock.calls[0][0].skip).toEqual(false); }); test('toggleStatus=true, render components', () => { wrapper = mount(, { wrappingComponent: TestProviders, }); - expect(wrapper.find('MatrixLoader').exists()).toBe(true); + expect(wrapper.find('[data-test-subj="visualization-embeddable"]').exists()).toEqual(true); }); test('toggleStatus=false, do not render components', () => { @@ -297,71 +193,7 @@ describe('Matrix Histogram Component', () => { wrappingComponent: TestProviders, }); - expect(mockUseMatrix.mock.calls[0][0].skip).toEqual(true); - }); - }); - - describe('when the chartEmbeddablesEnabled experimental feature flag is enabled', () => { - beforeEach(() => { - const mockMapping: Partial = { - chartEmbeddablesEnabled: true, - }; - - mockUseIsExperimentalFeatureEnabled.mockImplementation( - getMockUseIsExperimentalFeatureEnabled(mockMapping) - ); - - wrapper = mount(, { - wrappingComponent: TestProviders, - }); - }); - test('it should not render VisualizationActions', () => { - expect(wrapper.find(`[data-test-subj="visualizationActions"]`).exists()).toEqual(false); - }); - - test('it should not fetch Matrix Histogram data', () => { - expect(mockUseMatrix.mock.calls[0][0].skip).toEqual(true); - }); - - test('it should render Lens Embeddable', () => { - expect(wrapper.find(`[data-test-subj="visualization-embeddable"]`).exists()).toEqual(true); - }); - - test('it should render visualization count as subtitle', () => { - mockUseMatrix.mockReturnValue([ - false, - { - data: [], - inspect: false, - totalCount: 0, - }, - ]); - wrapper.setProps({ endDate: 100 }); - wrapper.update(); - - expect(wrapper.find(`[data-test-subj="header-section-subtitle"]`).text()).toEqual( - 'Showing: 999 events' - ); - }); - - test('it should render 0 as subtitle when buckets are empty', () => { - mockUseVisualizationResponse.mockReturnValue({ - responses: [{ aggregations: [{ buckets: [] }], hits: { total: 999 } }], - }); - mockUseMatrix.mockReturnValue([ - false, - { - data: [], - inspect: false, - totalCount: 0, - }, - ]); - wrapper.setProps({ endDate: 100 }); - wrapper.update(); - - expect(wrapper.find(`[data-test-subj="header-section-subtitle"]`).text()).toEqual( - 'Showing: 0 events' - ); + expect(wrapper.find('[data-test-subj="visualization-embeddable"]').exists()).toEqual(false); }); }); }); diff --git a/x-pack/plugins/security_solution/public/common/components/matrix_histogram/index.tsx b/x-pack/plugins/security_solution/public/common/components/matrix_histogram/index.tsx index 28615317c5d84..0009108596847 100644 --- a/x-pack/plugins/security_solution/public/common/components/matrix_histogram/index.tsx +++ b/x-pack/plugins/security_solution/public/common/components/matrix_histogram/index.tsx @@ -6,68 +6,37 @@ */ import React, { useState, useEffect, useCallback, useMemo } from 'react'; -import type { Position } from '@elastic/charts'; import styled from 'styled-components'; -import { EuiFlexGroup, EuiFlexItem, EuiProgress, EuiSelect, EuiSpacer } from '@elastic/eui'; -import { useDispatch } from 'react-redux'; +import { EuiFlexGroup, EuiFlexItem, EuiSelect, EuiSpacer } from '@elastic/eui'; import type { AggregationsTermsAggregateBase } from '@elastic/elasticsearch/lib/api/types'; import { isString } from 'lodash/fp'; import * as i18n from './translations'; import { HeaderSection } from '../header_section'; import { Panel } from '../panel'; -import { getBarchartConfigs, getCustomChartData } from './utils'; -import { useMatrixHistogramCombined } from '../../containers/matrix_histogram'; + import type { - MatrixHistogramProps, MatrixHistogramOption, MatrixHistogramQueryProps, - MatrixHistogramMappingTypes, - GetTitle, - GetSubTitle, + MatrixHistogramConfigs, } from './types'; -import type { MatrixHistogramType } from '../../../../common/search_strategy/security_solution'; import type { GlobalTimeArgs } from '../../containers/use_global_time'; -import { setAbsoluteRangeDatePicker } from '../../store/inputs/actions'; -import { InputsModelId } from '../../store/inputs/constants'; import { HoverVisibilityContainer } from '../hover_visibility_container'; -import { VisualizationActions } from '../visualization_actions/actions'; -import type { - GetLensAttributes, - LensAttributes, - VisualizationResponse, -} from '../visualization_actions/types'; +import type { VisualizationResponse } from '../visualization_actions/types'; import { useQueryToggle } from '../../containers/query_toggle'; -import { useIsExperimentalFeatureEnabled } from '../../hooks/use_experimental_features'; import { VISUALIZATION_ACTIONS_BUTTON_CLASS } from '../visualization_actions/utils'; import { VisualizationEmbeddable } from '../visualization_actions/visualization_embeddable'; -import { MatrixHistogramChartContent } from './chart_content'; import { useVisualizationResponse } from '../visualization_actions/use_visualization_response'; import type { SourcererScopeName } from '../../store/sourcerer/model'; -export type MatrixHistogramComponentProps = MatrixHistogramProps & - Omit & { - defaultStackByOption: MatrixHistogramOption; - errorMessage: string; - getLensAttributes?: GetLensAttributes; +export type MatrixHistogramComponentProps = MatrixHistogramQueryProps & + MatrixHistogramConfigs & { headerChildren?: React.ReactNode; hideHistogramIfEmpty?: boolean; - histogramType: MatrixHistogramType; id: string; - legendPosition?: Position; - lensAttributes?: LensAttributes; - mapping?: MatrixHistogramMappingTypes; - onError?: () => void; showSpacer?: boolean; setQuery: GlobalTimeArgs['setQuery']; - showInspectButton?: boolean; - setAbsoluteRangeDatePickerTarget?: InputsModelId; - showLegend?: boolean; - stackByOptions: MatrixHistogramOption[]; - subtitle?: string | GetSubTitle; - scopeId?: string; sourcererScopeId?: SourcererScopeName; - title: string | GetTitle; hideQueryToggle?: boolean; applyGlobalQueriesAndFilters?: boolean; }; @@ -95,71 +64,28 @@ export const MatrixHistogramComponent: React.FC = chartHeight, defaultStackByOption, endDate, - errorMessage, filterQuery, getLensAttributes, headerChildren, - histogramType, hideHistogramIfEmpty = false, id, - indexNames, - runtimeMappings, isPtrIncluded, - legendPosition, lensAttributes, - mapping, - onError, paddingSize = 'm', panelHeight = DEFAULT_PANEL_HEIGHT, - setAbsoluteRangeDatePickerTarget = InputsModelId.global, setQuery, - showInspectButton = false, - showLegend, showSpacer = true, stackByOptions, startDate, subtitle, - scopeId, sourcererScopeId, title, titleSize, - yTickFormatter, - skip, hideQueryToggle = false, applyGlobalQueriesAndFilters = true, }) => { const visualizationId = `${id}-embeddable`; - const dispatch = useDispatch(); - const handleBrushEnd = useCallback( - ({ x }) => { - if (!x) { - return; - } - const [min, max] = x; - dispatch( - setAbsoluteRangeDatePicker({ - id: setAbsoluteRangeDatePickerTarget, - from: new Date(min).toISOString(), - to: new Date(max).toISOString(), - }) - ); - }, - [dispatch, setAbsoluteRangeDatePickerTarget] - ); - const barchartConfigs = useMemo( - () => - getBarchartConfigs({ - chartHeight, - from: startDate, - legendPosition, - to: endDate, - onBrushEnd: handleBrushEnd, - yTickFormatter, - showLegend, - }), - [chartHeight, startDate, legendPosition, endDate, handleBrushEnd, yTickFormatter, showLegend] - ); const [isInitialLoading, setIsInitialLoading] = useState(true); const [selectedStackByOption, setSelectedStackByOption] = useState(defaultStackByOption); @@ -178,93 +104,48 @@ export const MatrixHistogramComponent: React.FC = ); const { toggleStatus, setToggleStatus } = useQueryToggle(id); - const [querySkip, setQuerySkip] = useState(skip || !toggleStatus); - useEffect(() => { - setQuerySkip(skip || !toggleStatus); - }, [skip, toggleStatus]); + const toggleQuery = useCallback( (status: boolean) => { setToggleStatus(status); - // toggle on = skipQuery false - setQuerySkip(!status); }, - [setQuerySkip, setToggleStatus] + [setToggleStatus] ); - const isChartEmbeddablesEnabled = useIsExperimentalFeatureEnabled('chartEmbeddablesEnabled'); - - const matrixHistogramRequest = { - endDate, - errorMessage, - filterQuery, - histogramType, - indexNames, - onError, - startDate, - stackByField: selectedStackByOption.value, - runtimeMappings, - isPtrIncluded, - skip: querySkip || isChartEmbeddablesEnabled, - }; - const [loading, { data, inspect, totalCount, refetch }] = - useMatrixHistogramCombined(matrixHistogramRequest); - const titleWithStackByField = useMemo( () => (title != null && typeof title === 'function' ? title(selectedStackByOption) : title), [title, selectedStackByOption] ); - const { responses } = useVisualizationResponse({ visualizationId }); + const { responses: visualizationResponses } = useVisualizationResponse({ visualizationId }); + const visualizationTotalCount: number | null = useMemo(() => { + if (!visualizationResponses || !visualizationResponseHasData(visualizationResponses)) { + return 0; + } + return visualizationResponses[0].hits.total; + }, [visualizationResponses]); + const subtitleWithCounts = useMemo(() => { if (isInitialLoading) { return null; } if (typeof subtitle === 'function') { - if (isChartEmbeddablesEnabled) { - if (!responses || !visualizationResponseHasData(responses)) { - return subtitle(0); - } - const visualizationCount = responses[0].hits.total; - return visualizationCount >= 0 ? subtitle(visualizationCount) : null; - } else { - return totalCount >= 0 ? subtitle(totalCount) : null; - } + return visualizationTotalCount >= 0 ? subtitle(visualizationTotalCount) : null; } return subtitle; - }, [isChartEmbeddablesEnabled, isInitialLoading, responses, subtitle, totalCount]); + }, [isInitialLoading, subtitle, visualizationTotalCount]); const hideHistogram = useMemo( - () => (totalCount <= 0 && hideHistogramIfEmpty ? true : false), - [totalCount, hideHistogramIfEmpty] + () => ((visualizationTotalCount ?? 0) <= 0 && hideHistogramIfEmpty ? true : false), + [hideHistogramIfEmpty, visualizationTotalCount] ); - const barChartData = useMemo(() => getCustomChartData(data, mapping), [data, mapping]); useEffect(() => { - if (!loading && !isInitialLoading) { - setQuery({ - id, - inspect, - loading, - refetch, - }); - } - - if (isInitialLoading && !!barChartData && data) { + if (isInitialLoading && !!visualizationResponses) { setIsInitialLoading(false); } - }, [ - barChartData, - data, - id, - inspect, - isChartEmbeddablesEnabled, - isInitialLoading, - loading, - refetch, - setIsInitialLoading, - setQuery, - ]); + }, [id, isInitialLoading, visualizationResponses, setIsInitialLoading, setQuery]); const timerange = useMemo(() => ({ from: startDate, to: endDate }), [startDate, endDate]); const extraVisualizationOptions = useMemo( @@ -297,15 +178,6 @@ export const MatrixHistogramComponent: React.FC = height={toggleStatus ? panelHeight : undefined} paddingSize={paddingSize} > - {loading && !isInitialLoading && ( - - )} - = toggleStatus={toggleStatus} toggleQuery={hideQueryToggle ? undefined : toggleQuery} subtitle={subtitleWithCounts} - inspectMultiple - showInspectButton={showInspectButton && !isChartEmbeddablesEnabled} - isInspectDisabled={filterQuery === undefined} + showInspectButton={false} > - {(getLensAttributes || lensAttributes) && timerange && !isChartEmbeddablesEnabled && ( - - - - )} {stackByOptions.length > 1 && ( = {toggleStatus ? ( - isChartEmbeddablesEnabled ? ( - - ) : ( - - ) + ) : null} diff --git a/x-pack/plugins/security_solution/public/common/components/matrix_histogram/types.ts b/x-pack/plugins/security_solution/public/common/components/matrix_histogram/types.ts index 491a3f3b37ca9..032a768df355e 100644 --- a/x-pack/plugins/security_solution/public/common/components/matrix_histogram/types.ts +++ b/x-pack/plugins/security_solution/public/common/components/matrix_histogram/types.ts @@ -5,23 +5,11 @@ * 2.0. */ -import type React from 'react'; -import type { EuiTitleSize } from '@elastic/eui'; -import type { ScaleType, Position, TickFormatter } from '@elastic/charts'; -import type { ActionCreator } from 'redux'; -import type { RunTimeMappings } from '@kbn/timelines-plugin/common/api/search_strategy'; +import type { EuiPaddingSize, EuiTitleSize } from '@elastic/eui'; +import type { Position } from '@elastic/charts'; import type { ESQuery } from '../../../../common/typed_json'; -import type { InputsModelId } from '../../store/inputs/constants'; -import type { MatrixHistogramType } from '../../../../common/search_strategy/security_solution'; -import type { UpdateDateRange } from '../charts/common'; -import type { GlobalTimeArgs } from '../../containers/use_global_time'; -import type { FieldValueThreshold } from '../../../detection_engine/rule_creation_ui/components/threshold_input'; import type { GetLensAttributes, LensAttributes } from '../visualization_actions/types'; -export type MatrixHistogramMappingTypes = Record< - string, - { key: string; value: null; color?: string | undefined } ->; export interface MatrixHistogramOption { text: string; value: string; @@ -31,103 +19,23 @@ export type GetSubTitle = (count: number) => string; export type GetTitle = (matrixHistogramOption: MatrixHistogramOption) => string; export interface MatrixHistogramConfigs { + chartHeight?: number; defaultStackByOption: MatrixHistogramOption; - errorMessage: string; getLensAttributes?: GetLensAttributes; hideHistogramIfEmpty?: boolean; - histogramType: MatrixHistogramType; legendPosition?: Position; lensAttributes?: LensAttributes; - mapping?: MatrixHistogramMappingTypes; - stackByOptions: MatrixHistogramOption[]; - subtitle?: string | GetSubTitle; - title: string | GetTitle; - titleSize?: EuiTitleSize; -} - -interface MatrixHistogramBasicProps { - chartHeight?: number; - defaultStackByOption: MatrixHistogramOption; - endDate: GlobalTimeArgs['to']; - headerChildren?: React.ReactNode; - hideHistogramIfEmpty?: boolean; - id: string; - legendPosition?: Position; - mapping?: MatrixHistogramMappingTypes; + paddingSize?: EuiPaddingSize; panelHeight?: number; - paddingSize?: 's' | 'm' | 'l' | 'none'; - setQuery: GlobalTimeArgs['setQuery']; - startDate: GlobalTimeArgs['from']; stackByOptions: MatrixHistogramOption[]; subtitle?: string | GetSubTitle; - title?: string | GetTitle; + title: string | GetTitle; titleSize?: EuiTitleSize; } export interface MatrixHistogramQueryProps { endDate: string; - errorMessage: string; - indexNames: string[]; filterQuery?: ESQuery | string | undefined; - onError?: () => void; - setAbsoluteRangeDatePicker?: ActionCreator<{ - id: InputsModelId; - from: string; - to: string; - }>; - setAbsoluteRangeDatePickerTarget?: InputsModelId; - stackByField: string; startDate: string; - histogramType: MatrixHistogramType; - threshold?: FieldValueThreshold; - skip?: boolean; isPtrIncluded?: boolean; - includeMissingData?: boolean; - runtimeMappings?: RunTimeMappings; -} - -export interface MatrixHistogramProps extends MatrixHistogramBasicProps { - legendPosition?: Position; - scaleType?: ScaleType; - showLegend?: boolean; - showSpacer?: boolean; - timelineId?: string; - yTickFormatter?: (value: number) => string; -} - -export interface BarchartConfigs { - series: { - xScaleType: ScaleType; - yScaleType: ScaleType; - stackAccessors: string[]; - }; - axis: { - xTickFormatter: TickFormatter; - yTickFormatter: TickFormatter; - tickSize: number; - }; - settings: { - legendPosition: Position; - onBrushEnd: UpdateDateRange; - showLegend: boolean; - showLegendExtra: boolean; - theme: { - scales: { - barsPadding: number; - }; - chartMargins: { - left: number; - right: number; - top: number; - bottom: number; - }; - chartPaddings: { - left: number; - right: number; - top: number; - bottom: number; - }; - }; - }; - customHeight: number; } diff --git a/x-pack/plugins/security_solution/public/common/components/matrix_histogram/utils.test.ts b/x-pack/plugins/security_solution/public/common/components/matrix_histogram/utils.test.ts deleted file mode 100644 index 860ec4239073e..0000000000000 --- a/x-pack/plugins/security_solution/public/common/components/matrix_histogram/utils.test.ts +++ /dev/null @@ -1,142 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { - getBarchartConfigs, - DEFAULT_CHART_HEIGHT, - DEFAULT_Y_TICK_FORMATTER, - formatToChartDataItem, - getCustomChartData, -} from './utils'; -import type { UpdateDateRange } from '../charts/common'; -import { Position } from '@elastic/charts'; -import type { MatrixHistogramData } from '../../../../common/search_strategy'; -import type { BarchartConfigs } from './types'; - -describe('utils', () => { - describe('getBarchartConfigs', () => { - describe('it should get correct default values', () => { - let configs: BarchartConfigs; - beforeAll(() => { - configs = getBarchartConfigs({ - from: '2020-07-07T08:20:18.966Z', - to: '2020-07-08T08:20:18.966Z', - onBrushEnd: jest.fn() as UpdateDateRange, - }); - }); - - test('it should set default chartHeight', () => { - expect(configs.customHeight).toEqual(DEFAULT_CHART_HEIGHT); - }); - - test('it should show legend by default', () => { - expect(configs.settings.showLegend).toEqual(true); - }); - - test('it should put legend on the right', () => { - expect(configs.settings.legendPosition).toEqual(Position.Right); - }); - - test('it should format Y tick to local string', () => { - expect(configs.axis.yTickFormatter).toEqual(DEFAULT_Y_TICK_FORMATTER); - }); - }); - - describe('it should set custom configs', () => { - let configs: BarchartConfigs; - const mockYTickFormatter = jest.fn(); - const mockChartHeight = 100; - - beforeAll(() => { - configs = getBarchartConfigs({ - chartHeight: mockChartHeight, - from: '2020-07-07T08:20:18.966Z', - to: '2020-07-08T08:20:18.966Z', - onBrushEnd: jest.fn() as UpdateDateRange, - yTickFormatter: mockYTickFormatter, - showLegend: false, - }); - }); - - test('it should set custom chart height', () => { - expect(configs.customHeight).toEqual(mockChartHeight); - }); - - test('it should hide legend', () => { - expect(configs.settings.showLegend).toEqual(false); - }); - - test('it should format y tick with custom formatter', () => { - expect(configs.axis.yTickFormatter).toEqual(mockYTickFormatter); - }); - }); - }); - - describe('formatToChartDataItem', () => { - test('it should format data correctly', () => { - const data: [string, MatrixHistogramData[]] = [ - 'g1', - [ - { x: 1, y: 2, g: 'g1' }, - { x: 2, y: 4, g: 'g1' }, - { x: 3, y: 6, g: 'g1' }, - ], - ]; - const result = formatToChartDataItem(data); - expect(result).toEqual({ - key: 'g1', - value: [ - { x: 1, y: 2, g: 'g1' }, - { x: 2, y: 4, g: 'g1' }, - { x: 3, y: 6, g: 'g1' }, - ], - }); - }); - }); - - describe('getCustomChartData', () => { - test('should handle the case when no data provided', () => { - const data = null; - const result = getCustomChartData(data); - - expect(result).toEqual([]); - }); - - test('should format data correctly', () => { - const data = [ - { x: 1, y: 2, g: 'g1' }, - { x: 2, y: 4, g: 'g1' }, - { x: 3, y: 6, g: 'g1' }, - { x: 1, y: 1, g: 'g2' }, - { x: 2, y: 3, g: 'g2' }, - { x: 3, y: 5, g: 'g2' }, - ]; - const result = getCustomChartData(data); - - expect(result).toEqual([ - { - key: 'g1', - color: '#1EA593', - value: [ - { x: 1, y: 2, g: 'g1' }, - { x: 2, y: 4, g: 'g1' }, - { x: 3, y: 6, g: 'g1' }, - ], - }, - { - key: 'g2', - color: '#2B70F7', - value: [ - { x: 1, y: 1, g: 'g2' }, - { x: 2, y: 3, g: 'g2' }, - { x: 3, y: 5, g: 'g2' }, - ], - }, - ]); - }); - }); -}); diff --git a/x-pack/plugins/security_solution/public/common/components/matrix_histogram/utils.ts b/x-pack/plugins/security_solution/public/common/components/matrix_histogram/utils.ts index 98b90e52a79c8..7c5f01d26ebdb 100644 --- a/x-pack/plugins/security_solution/public/common/components/matrix_histogram/utils.ts +++ b/x-pack/plugins/security_solution/public/common/components/matrix_histogram/utils.ts @@ -5,72 +5,9 @@ * 2.0. */ -import { ScaleType, Position } from '@elastic/charts'; -import { get, groupBy, map, toPairs } from 'lodash/fp'; - -import type { UpdateDateRange, ChartSeriesData } from '../charts/common'; -import type { MatrixHistogramMappingTypes, BarchartConfigs } from './types'; -import type { MatrixHistogramData } from '../../../../common/search_strategy'; -import { histogramDateTimeFormatter } from '../utils'; - -interface GetBarchartConfigsProps { - chartHeight?: number; - from: string; - legendPosition?: Position; - to: string; - onBrushEnd: UpdateDateRange; - yTickFormatter?: (value: number) => string; - showLegend?: boolean; -} - export const DEFAULT_CHART_HEIGHT = 174; export const DEFAULT_Y_TICK_FORMATTER = (value: string | number): string => value.toLocaleString(); -export const getBarchartConfigs = ({ - chartHeight, - from, - legendPosition, - to, - onBrushEnd, - yTickFormatter, - showLegend, -}: GetBarchartConfigsProps): BarchartConfigs => ({ - series: { - xScaleType: ScaleType.Time, - yScaleType: ScaleType.Linear, - stackAccessors: ['g'], - }, - axis: { - xTickFormatter: histogramDateTimeFormatter([from, to]), - yTickFormatter: yTickFormatter != null ? yTickFormatter : DEFAULT_Y_TICK_FORMATTER, - tickSize: 8, - }, - settings: { - legendPosition: legendPosition ?? Position.Right, - onBrushEnd, - showLegend: showLegend ?? true, - showLegendExtra: true, - theme: { - scales: { - barsPadding: 0.08, - }, - chartMargins: { - left: 0, - right: 0, - top: 0, - bottom: 0, - }, - chartPaddings: { - left: 0, - right: 0, - top: 0, - bottom: 0, - }, - }, - }, - customHeight: chartHeight ?? DEFAULT_CHART_HEIGHT, -}); - export const defaultLegendColors = [ '#1EA593', '#2B70F7', @@ -84,25 +21,3 @@ export const defaultLegendColors = [ '#34130C', '#GGGGGG', ]; - -export const formatToChartDataItem = ([key, value]: [ - string, - MatrixHistogramData[] -]): ChartSeriesData => ({ - key, - value, -}); - -export const getCustomChartData = ( - data: MatrixHistogramData[] | null, - mapping?: MatrixHistogramMappingTypes -): ChartSeriesData[] => { - if (!data) return []; - const dataGroupedByEvent = groupBy('g', data); - const dataGroupedEntries = toPairs(dataGroupedByEvent); - const formattedChartData = map(formatToChartDataItem, dataGroupedEntries); - return formattedChartData.map((item: ChartSeriesData, idx: number) => { - const mapItem = get(item.key, mapping); - return { ...item, color: mapItem?.color ?? defaultLegendColors[idx] }; - }); -}; diff --git a/x-pack/plugins/security_solution/public/common/components/page/manage_query.tsx b/x-pack/plugins/security_solution/public/common/components/page/manage_query.tsx index ce8c9d3f68175..5640566d5b92d 100644 --- a/x-pack/plugins/security_solution/public/common/components/page/manage_query.tsx +++ b/x-pack/plugins/security_solution/public/common/components/page/manage_query.tsx @@ -7,10 +7,8 @@ import type { Position } from '@elastic/charts'; import { omit } from 'lodash/fp'; -import type { MutableRefObject } from 'react'; import React, { useEffect } from 'react'; -import type { ISessionService } from '@kbn/data-plugin/public'; import type { inputsModel } from '../../store'; import type { GlobalTimeArgs } from '../../containers/use_global_time'; import type { InputsModelId } from '../../store/inputs/constants'; @@ -23,14 +21,13 @@ export interface OwnProps extends Pick; } export function manageQuery( WrappedComponent: React.ComponentClass | React.ComponentType ): React.FC { const ManageQuery = (props: OwnProps & T) => { - const { deleteQuery, id, inspect = null, loading, refetch, setQuery, session } = props; + const { deleteQuery, id, inspect = null, loading, refetch, setQuery } = props; useQueryInspector({ deleteQuery, @@ -38,7 +35,6 @@ export function manageQuery( loading, queryId: id, refetch, - session, setQuery, }); @@ -57,7 +53,6 @@ interface UseQueryInspectorTypes extends Pick; } export const useQueryInspector = ({ @@ -67,7 +62,6 @@ export const useQueryInspector = ({ inspect, loading, queryId, - session, }: UseQueryInspectorTypes) => { useEffect(() => { setQuery({ @@ -75,9 +69,8 @@ export const useQueryInspector = ({ inspect: inspect ?? null, loading, refetch, - searchSessionId: session?.current.start(), }); - }, [deleteQuery, setQuery, queryId, refetch, inspect, loading, session]); + }, [deleteQuery, setQuery, queryId, refetch, inspect, loading]); useEffect(() => { return () => { diff --git a/x-pack/plugins/security_solution/public/common/components/page/use_refetch_by_session.tsx b/x-pack/plugins/security_solution/public/common/components/page/use_refetch_by_session.tsx index 862014ba3e16e..f4557a002004a 100644 --- a/x-pack/plugins/security_solution/public/common/components/page/use_refetch_by_session.tsx +++ b/x-pack/plugins/security_solution/public/common/components/page/use_refetch_by_session.tsx @@ -19,13 +19,11 @@ import type { Refetch } from '../../store/inputs/model'; interface UseRefetchByRestartingSessionProps { inputId?: InputsModelId; queryId: string; - skip?: boolean; } export const useRefetchByRestartingSession = ({ inputId, queryId, - skip, }: UseRefetchByRestartingSessionProps): { session: MutableRefObject; refetchByRestartingSession: Refetch; @@ -56,10 +54,10 @@ export const useRefetchByRestartingSession = ({ * like most of our components, it refetches when receiving a new search * session ID. **/ - searchSessionId: skip ? undefined : searchSessionId, + searchSessionId, }) ); - }, [dispatch, queryId, selectedInspectIndex, skip]); + }, [dispatch, queryId, selectedInspectIndex]); /** * This is for refetching alert index when the first rule just created diff --git a/x-pack/plugins/security_solution/public/common/components/top_n/top_n.tsx b/x-pack/plugins/security_solution/public/common/components/top_n/top_n.tsx index 0dbd55b9bae34..42ee8b8ed32f6 100644 --- a/x-pack/plugins/security_solution/public/common/components/top_n/top_n.tsx +++ b/x-pack/plugins/security_solution/public/common/components/top_n/top_n.tsx @@ -139,15 +139,11 @@ const TopNComponent: React.FC = ({ /> ) : ( )} diff --git a/x-pack/plugins/security_solution/public/common/containers/anomalies/anomalies_query_tab_body/histogram_configs.ts b/x-pack/plugins/security_solution/public/common/containers/anomalies/anomalies_query_tab_body/histogram_configs.ts index a8f7c55fe5ad0..e154c05e765f0 100644 --- a/x-pack/plugins/security_solution/public/common/containers/anomalies/anomalies_query_tab_body/histogram_configs.ts +++ b/x-pack/plugins/security_solution/public/common/containers/anomalies/anomalies_query_tab_body/histogram_configs.ts @@ -10,7 +10,6 @@ import type { MatrixHistogramOption, MatrixHistogramConfigs, } from '../../../components/matrix_histogram/types'; -import { MatrixHistogramType } from '../../../../../common/search_strategy/security_solution/matrix_histogram'; export const anomaliesStackByOptions: MatrixHistogramOption[] = [ { @@ -24,9 +23,7 @@ const DEFAULT_STACK_BY = i18n.ANOMALIES_STACK_BY_JOB_ID; export const histogramConfigs: MatrixHistogramConfigs = { defaultStackByOption: anomaliesStackByOptions.find((o) => o.text === DEFAULT_STACK_BY) ?? anomaliesStackByOptions[0], - errorMessage: i18n.ERROR_FETCHING_ANOMALIES_DATA, hideHistogramIfEmpty: true, - histogramType: MatrixHistogramType.anomalies, stackByOptions: anomaliesStackByOptions, subtitle: undefined, title: i18n.ANOMALIES_TITLE, diff --git a/x-pack/plugins/security_solution/public/common/containers/anomalies/anomalies_query_tab_body/index.tsx b/x-pack/plugins/security_solution/public/common/containers/anomalies/anomalies_query_tab_body/index.tsx index c3eaf31e2d292..bf662e9fe3cc2 100644 --- a/x-pack/plugins/security_solution/public/common/containers/anomalies/anomalies_query_tab_body/index.tsx +++ b/x-pack/plugins/security_solution/public/common/containers/anomalies/anomalies_query_tab_body/index.tsx @@ -60,7 +60,6 @@ const AnomaliesQueryTabBodyComponent: React.FC = ({ endDate={endDate} filterQuery={mergedFilterQuery} id={ID} - indexNames={indexNames} setQuery={setQuery} startDate={startDate} {...histogramConfigs} diff --git a/x-pack/plugins/security_solution/public/common/containers/matrix_histogram/index.test.ts b/x-pack/plugins/security_solution/public/common/containers/matrix_histogram/index.test.ts deleted file mode 100644 index fab3766d2c5d0..0000000000000 --- a/x-pack/plugins/security_solution/public/common/containers/matrix_histogram/index.test.ts +++ /dev/null @@ -1,264 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { renderHook, act } from '@testing-library/react-hooks'; -import { useKibana } from '../../lib/kibana'; -import { useMatrixHistogram, useMatrixHistogramCombined } from '.'; -import { MatrixHistogramType } from '../../../../common/search_strategy'; -import { TestProviders } from '../../mock/test_providers'; -import { useTrackHttpRequest } from '../../lib/apm/use_track_http_request'; - -jest.mock('../../lib/kibana'); -jest.mock('../../lib/apm/use_track_http_request'); - -const mockEndTracking = jest.fn(); -const mockStartTracking = jest.fn(() => ({ endTracking: mockEndTracking })); -(useTrackHttpRequest as jest.Mock).mockReturnValue({ - startTracking: mockStartTracking, -}); - -const basicResponse = { - isPartial: false, - isRunning: false, - total: 0, - loaded: 0, - rawResponse: { - took: 1, - timed_out: false, - hits: { - max_score: 0, - hits: [], - total: 0, - }, - }, -}; - -describe('useMatrixHistogram', () => { - const props = { - endDate: new Date(Date.now()).toISOString(), - errorMessage: '', - filterQuery: {}, - histogramType: MatrixHistogramType.events, - indexNames: [], - stackByField: 'event.module', - startDate: new Date(Date.now()).toISOString(), - skip: false, - }; - - afterEach(() => { - jest.clearAllMocks(); - }); - - it('should update request when props has changed', async () => { - const localProps = { ...props }; - const { rerender } = renderHook(() => useMatrixHistogram(localProps), { - wrapper: TestProviders, - }); - - localProps.stackByField = 'event.action'; - - rerender(); - - const mockCalls = (useKibana().services.data.search.search as jest.Mock).mock.calls; - - expect(mockCalls.length).toBe(2); - expect(mockCalls[0][0].stackByField).toBe('event.module'); - expect(mockCalls[1][0].stackByField).toBe('event.action'); - }); - - it('returns a memoized value', async () => { - const { result, rerender } = renderHook(() => useMatrixHistogram(props), { - wrapper: TestProviders, - }); - - const result1 = result.current[1]; - act(() => rerender()); - const result2 = result.current[1]; - - expect(result1).toBe(result2); - }); - - it("returns buckets for histogram Type 'events'", async () => { - const localProps = { ...props, histogramType: MatrixHistogramType.events }; - const mockEventsSearchStrategyResponse = { - ...basicResponse, - rawResponse: { - ...basicResponse.rawResponse, - aggregations: { - eventActionGroup: { - doc_count_error_upper_bound: 0, - sum_other_doc_count: 0, - buckets: [ - { - key: 'my dsn test buckets', - doc_count: 1, - }, - ], - }, - }, - }, - }; - - (useKibana().services.data.search.search as jest.Mock).mockReturnValueOnce({ - subscribe: ({ next }: { next: Function }) => next(mockEventsSearchStrategyResponse), - }); - - const { - result: { current }, - } = renderHook(() => useMatrixHistogram(localProps), { - wrapper: TestProviders, - }); - - expect(current[1].buckets).toBe( - mockEventsSearchStrategyResponse.rawResponse.aggregations?.eventActionGroup.buckets - ); - }); - - it("returns buckets for histogram Type 'dns'", async () => { - const mockDnsSearchStrategyResponse = { - ...basicResponse, - rawResponse: { - ...basicResponse.rawResponse, - aggregations: { - dns_name_query_count: { - doc_count_error_upper_bound: 0, - sum_other_doc_count: 0, - buckets: [ - { - key: 'my dsn test buckets', - doc_count: 1, - }, - ], - }, - }, - }, - }; - - const localProps = { ...props, histogramType: MatrixHistogramType.dns }; - (useKibana().services.data.search.search as jest.Mock).mockReturnValueOnce({ - subscribe: ({ next }: { next: Function }) => next(mockDnsSearchStrategyResponse), - }); - - const { - result: { current }, - } = renderHook(() => useMatrixHistogram(localProps), { - wrapper: TestProviders, - }); - - expect(current[1].buckets).toBe( - mockDnsSearchStrategyResponse.rawResponse.aggregations?.dns_name_query_count.buckets - ); - }); - - it('skip = true will cancel any running request', () => { - const abortSpy = jest.spyOn(AbortController.prototype, 'abort'); - const localProps = { ...props }; - const { rerender } = renderHook(() => useMatrixHistogram(localProps), { - wrapper: TestProviders, - }); - localProps.skip = true; - act(() => rerender()); - expect(abortSpy).toHaveBeenCalledTimes(3); - }); - - describe('trackHttpRequest', () => { - it('should start tracking when request starts', () => { - renderHook(useMatrixHistogram, { - initialProps: props, - wrapper: TestProviders, - }); - - expect(mockStartTracking).toHaveBeenCalledWith({ - name: `securitySolutionUI matrixHistogram ${MatrixHistogramType.events}`, - }); - }); - - it('should end tracking success when the request succeeds', () => { - (useKibana().services.data.search.search as jest.Mock).mockReturnValueOnce({ - subscribe: ({ next }: { next: Function }) => next(basicResponse), - }); - - renderHook(useMatrixHistogram, { - initialProps: props, - wrapper: TestProviders, - }); - - expect(mockEndTracking).toHaveBeenCalledWith('success'); - }); - - it('should end tracking error when the request fails', () => { - (useKibana().services.data.search.search as jest.Mock).mockReturnValueOnce({ - subscribe: ({ error }: { error: Function }) => error('some error'), - }); - - renderHook(useMatrixHistogram, { - initialProps: props, - wrapper: TestProviders, - }); - - expect(mockEndTracking).toHaveBeenCalledWith('error'); - }); - }); -}); - -describe('useMatrixHistogramCombined', () => { - const props = { - endDate: new Date(Date.now()).toISOString(), - errorMessage: '', - filterQuery: {}, - histogramType: MatrixHistogramType.events, - indexNames: [], - stackByField: 'event.module', - startDate: new Date(Date.now()).toISOString(), - }; - - afterEach(() => { - (useKibana().services.data.search.search as jest.Mock).mockClear(); - }); - - it('should update request when props has changed', async () => { - const localProps = { ...props }; - const { rerender } = renderHook(() => useMatrixHistogramCombined(localProps), { - wrapper: TestProviders, - }); - - localProps.stackByField = 'event.action'; - - rerender(); - - const mockCalls = (useKibana().services.data.search.search as jest.Mock).mock.calls; - - expect(mockCalls.length).toBe(2); - expect(mockCalls[0][0].stackByField).toBe('event.module'); - expect(mockCalls[1][0].stackByField).toBe('event.action'); - }); - - it('should do two request when stacking by ip field', async () => { - const localProps = { ...props, stackByField: 'source.ip' }; - renderHook(() => useMatrixHistogramCombined(localProps), { - wrapper: TestProviders, - }); - - const mockCalls = (useKibana().services.data.search.search as jest.Mock).mock.calls; - - expect(mockCalls.length).toBe(2); - expect(mockCalls[0][0].stackByField).toBe('source.ip'); - expect(mockCalls[1][0].stackByField).toBe('source.ip'); - }); - - it('returns a memoized value', async () => { - const { result, rerender } = renderHook(() => useMatrixHistogramCombined(props), { - wrapper: TestProviders, - }); - - const result1 = result.current[1]; - act(() => rerender()); - const result2 = result.current[1]; - - expect(result1).toBe(result2); - }); -}); diff --git a/x-pack/plugins/security_solution/public/common/containers/matrix_histogram/index.ts b/x-pack/plugins/security_solution/public/common/containers/matrix_histogram/index.ts deleted file mode 100644 index a9ffa6049d9f9..0000000000000 --- a/x-pack/plugins/security_solution/public/common/containers/matrix_histogram/index.ts +++ /dev/null @@ -1,300 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import deepEqual from 'fast-deep-equal'; -import { getOr, noop } from 'lodash/fp'; -import { useCallback, useEffect, useMemo, useRef, useState } from 'react'; -import { Subscription } from 'rxjs'; - -import { isRunningResponse } from '@kbn/data-plugin/common'; -import type { MatrixHistogramRequestOptionsInput } from '../../../../common/api/search_strategy'; -import type { MatrixHistogramQueryProps } from '../../components/matrix_histogram/types'; -import type { inputsModel } from '../../store'; -import { createFilter } from '../helpers'; -import { useKibana } from '../../lib/kibana'; -import type { - MatrixHistogramStrategyResponse, - MatrixHistogramData, -} from '../../../../common/search_strategy/security_solution'; -import { - MatrixHistogramQuery, - MatrixHistogramTypeToAggName, -} from '../../../../common/search_strategy/security_solution'; -import { getInspectResponse } from '../../../helpers'; -import type { InspectResponse } from '../../../types'; -import * as i18n from './translations'; -import { useAppToasts } from '../../hooks/use_app_toasts'; -import { useTrackHttpRequest } from '../../lib/apm/use_track_http_request'; -import { APP_UI_ID } from '../../../../common/constants'; - -export type Buckets = Array<{ - key: string; - doc_count: number; -}>; - -const bucketEmpty: Buckets = []; - -export interface UseMatrixHistogramArgs { - data: MatrixHistogramData[]; - inspect: InspectResponse; - refetch: inputsModel.Refetch; - totalCount: number; - buckets: Array<{ - key: string; - doc_count: number; - }>; -} - -export const useMatrixHistogram = ({ - endDate, - errorMessage, - filterQuery, - histogramType, - indexNames, - isPtrIncluded, - onError, - stackByField, - runtimeMappings, - startDate, - threshold, - skip = false, - includeMissingData = true, -}: MatrixHistogramQueryProps): [ - boolean, - UseMatrixHistogramArgs, - (to: string, from: string) => void -] => { - const { data } = useKibana().services; - const refetch = useRef(noop); - const abortCtrl = useRef(new AbortController()); - const searchSubscription$ = useRef(new Subscription()); - const [loading, setLoading] = useState(false); - const { startTracking } = useTrackHttpRequest(); - - const [matrixHistogramRequest, setMatrixHistogramRequest] = - useState({ - defaultIndex: indexNames, - factoryQueryType: MatrixHistogramQuery, - filterQuery: createFilter(filterQuery), - histogramType: histogramType ?? histogramType, - timerange: { - interval: '12h', - from: startDate, - to: endDate, - }, - stackByField, - runtimeMappings, - threshold, - ...(isPtrIncluded != null ? { isPtrIncluded } : {}), - ...(includeMissingData != null ? { includeMissingData } : {}), - }); - const { addError } = useAppToasts(); - - const [matrixHistogramResponse, setMatrixHistogramResponse] = useState({ - data: [], - inspect: { - dsl: [], - response: [], - }, - refetch: refetch.current, - totalCount: -1, - buckets: [], - }); - - const search = useCallback( - (request: MatrixHistogramRequestOptionsInput) => { - const asyncSearch = async () => { - abortCtrl.current = new AbortController(); - setLoading(true); - const { endTracking } = startTracking({ - name: `${APP_UI_ID} matrixHistogram ${histogramType}`, - }); - - searchSubscription$.current = data.search - .search(request, { - strategy: 'securitySolutionSearchStrategy', - abortSignal: abortCtrl.current.signal, - }) - .subscribe({ - next: (response) => { - if (!isRunningResponse(response)) { - const histogramBuckets: Buckets = getOr( - bucketEmpty, - MatrixHistogramTypeToAggName[histogramType], - response.rawResponse - ); - setLoading(false); - setMatrixHistogramResponse((prevResponse) => ({ - ...prevResponse, - data: response.matrixHistogramData, - inspect: getInspectResponse(response, prevResponse.inspect), - refetch: refetch.current, - totalCount: histogramBuckets.reduce((acc, bucket) => bucket.doc_count + acc, 0), - buckets: histogramBuckets, - })); - endTracking('success'); - searchSubscription$.current.unsubscribe(); - } - }, - error: (msg) => { - setLoading(false); - addError(msg, { - title: errorMessage ?? i18n.FAIL_MATRIX_HISTOGRAM, - }); - endTracking('error'); - searchSubscription$.current.unsubscribe(); - }, - }); - }; - searchSubscription$.current.unsubscribe(); - abortCtrl.current.abort(); - asyncSearch(); - refetch.current = asyncSearch; - }, - [data.search, histogramType, addError, errorMessage, startTracking] - ); - - useEffect(() => { - setMatrixHistogramRequest((prevRequest) => { - const myRequest = { - ...prevRequest, - defaultIndex: indexNames, - filterQuery: createFilter(filterQuery), - histogramType, - timerange: { - interval: '12h', - from: startDate, - to: endDate, - }, - stackByField, - threshold, - ...(isPtrIncluded != null ? { isPtrIncluded } : {}), - }; - if (!deepEqual(prevRequest, myRequest)) { - return myRequest; - } - return prevRequest; - }); - }, [ - indexNames, - endDate, - filterQuery, - startDate, - stackByField, - histogramType, - threshold, - isPtrIncluded, - ]); - - useEffect(() => { - // We want to search if it is not skipped, stackByField ends with ip and include missing data - if (!skip) { - search(matrixHistogramRequest); - } - return () => { - searchSubscription$.current.unsubscribe(); - abortCtrl.current.abort(); - }; - }, [matrixHistogramRequest, search, skip]); - - useEffect(() => { - if (skip) { - setLoading(false); - searchSubscription$.current.unsubscribe(); - abortCtrl.current.abort(); - } - }, [skip]); - - const runMatrixHistogramSearch = useCallback( - (to: string, from: string) => { - search({ - ...matrixHistogramRequest, - timerange: { - interval: '12h', - from, - to, - }, - }); - }, - [matrixHistogramRequest, search] - ); - - return [loading, matrixHistogramResponse, runMatrixHistogramSearch]; -}; - -/* function needed to split ip histogram data requests due to elasticsearch bug https://github.com/elastic/kibana/issues/89205 - * using includeMissingData parameter to do the "missing data" query separately - **/ -export const useMatrixHistogramCombined = ( - matrixHistogramQueryProps: MatrixHistogramQueryProps -): [boolean, UseMatrixHistogramArgs] => { - const [mainLoading, mainResponse] = useMatrixHistogram({ - ...matrixHistogramQueryProps, - includeMissingData: true, - }); - - const skipMissingData = useMemo( - () => !matrixHistogramQueryProps.stackByField.endsWith('.ip'), - [matrixHistogramQueryProps.stackByField] - ); - const [missingDataLoading, missingDataResponse] = useMatrixHistogram({ - ...matrixHistogramQueryProps, - includeMissingData: false, - skip: - skipMissingData || - matrixHistogramQueryProps.filterQuery === undefined || - matrixHistogramQueryProps.skip, - }); - - const combinedLoading = useMemo( - () => mainLoading || missingDataLoading, - [mainLoading, missingDataLoading] - ); - - const combinedResponse = useMemo(() => { - if (skipMissingData) return mainResponse; - - const { data, inspect, totalCount, refetch, buckets } = mainResponse; - const { - data: extraData, - inspect: extraInspect, - totalCount: extraTotalCount, - refetch: extraRefetch, - } = missingDataResponse; - - const combinedRefetch = () => { - refetch(); - extraRefetch(); - }; - - if (combinedLoading) { - return { - data: [], - inspect: { - dsl: [], - response: [], - }, - refetch: combinedRefetch, - totalCount: -1, - buckets: [], - }; - } - - return { - data: [...data, ...extraData], - inspect: { - dsl: [...inspect.dsl, ...extraInspect.dsl], - response: [...inspect.response, ...extraInspect.response], - }, - totalCount: totalCount + extraTotalCount, - refetch: combinedRefetch, - buckets, - }; - }, [combinedLoading, mainResponse, missingDataResponse, skipMissingData]); - - return [combinedLoading, combinedResponse]; -}; diff --git a/x-pack/plugins/security_solution/public/common/containers/matrix_histogram/translations.ts b/x-pack/plugins/security_solution/public/common/containers/matrix_histogram/translations.ts deleted file mode 100644 index e4ce0c27ae4c3..0000000000000 --- a/x-pack/plugins/security_solution/public/common/containers/matrix_histogram/translations.ts +++ /dev/null @@ -1,22 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { i18n } from '@kbn/i18n'; - -export const ERROR_MATRIX_HISTOGRAM = i18n.translate( - 'xpack.securitySolution.matrixHistogram.errorSearchDescription', - { - defaultMessage: `An error has occurred on matrix histogram search`, - } -); - -export const FAIL_MATRIX_HISTOGRAM = i18n.translate( - 'xpack.securitySolution.matrixHistogram.failSearchDescription', - { - defaultMessage: `Failed to run search on matrix histogram`, - } -); diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_creation_ui/components/rule_preview/preview_histogram.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_creation_ui/components/rule_preview/preview_histogram.tsx index 487fc3a4a4e29..77236be454004 100644 --- a/x-pack/plugins/security_solution/public/detection_engine/rule_creation_ui/components/rule_preview/preview_histogram.tsx +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_creation_ui/components/rule_preview/preview_histogram.tsx @@ -101,11 +101,11 @@ const PreviewHistogramComponent = ({ const previousPreviewId = usePrevious(previewId); const previewQueryId = `${ID}-${previewId}`; const previewEmbeddableId = `${previewQueryId}-embeddable`; - const { responses: visualizationResponse } = useVisualizationResponse({ + const { responses: visualizationResponses } = useVisualizationResponse({ visualizationId: previewEmbeddableId, }); - const totalCount = visualizationResponse?.[0]?.hits?.total ?? 0; + const totalCount = visualizationResponses?.[0]?.hits?.total ?? 0; useEffect(() => { if (previousPreviewId !== previewId && totalCount > 0) { diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_details_ui/pages/rule_details/index.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_details_ui/pages/rule_details/index.tsx index 62bac514beb86..e99e6d6659034 100644 --- a/x-pack/plugins/security_solution/public/detection_engine/rule_details_ui/pages/rule_details/index.tsx +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_details_ui/pages/rule_details/index.tsx @@ -724,11 +724,9 @@ const RuleDetailsPageComponent: React.FC = ({ diff --git a/x-pack/plugins/security_solution/public/detections/components/alerts_kpis/alerts_count_panel/chart_content.tsx b/x-pack/plugins/security_solution/public/detections/components/alerts_kpis/alerts_count_panel/chart_content.tsx deleted file mode 100644 index 5e0077918b717..0000000000000 --- a/x-pack/plugins/security_solution/public/detections/components/alerts_kpis/alerts_count_panel/chart_content.tsx +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ -import React from 'react'; -import type { VisualizationEmbeddableProps } from '../../../../common/components/visualization_actions/types'; -import { VisualizationEmbeddable } from '../../../../common/components/visualization_actions/visualization_embeddable'; -import type { AlertSearchResponse } from '../../../containers/detection_engine/alerts/types'; -import { AlertsCount } from './alerts_count'; -import type { AlertsCountAggregation } from './types'; - -type ChartContentProps = { - isChartEmbeddablesEnabled: boolean; -} & VisualizationEmbeddableProps & { - isLoadingAlerts: boolean; - alertsData: AlertSearchResponse | null; - stackByField0: string; - stackByField1: string | undefined; - }; - -const ChartContentComponent = ({ - alertsData, - extraActions, - extraOptions, - getLensAttributes, - height, - id, - inspectTitle, - isChartEmbeddablesEnabled, - isLoadingAlerts, - scopeId, - stackByField0, - stackByField1, - timerange, -}: ChartContentProps) => { - return isChartEmbeddablesEnabled ? ( - - ) : alertsData != null ? ( - - ) : null; -}; - -export const ChartContent = React.memo(ChartContentComponent); diff --git a/x-pack/plugins/security_solution/public/detections/components/alerts_kpis/alerts_count_panel/index.test.tsx b/x-pack/plugins/security_solution/public/detections/components/alerts_kpis/alerts_count_panel/index.test.tsx index 6b0b0ed9a0e08..9451ce6ca3b27 100644 --- a/x-pack/plugins/security_solution/public/detections/components/alerts_kpis/alerts_count_panel/index.test.tsx +++ b/x-pack/plugins/security_solution/public/detections/components/alerts_kpis/alerts_count_panel/index.test.tsx @@ -6,8 +6,9 @@ */ import React from 'react'; -import { waitFor, act } from '@testing-library/react'; +import { act } from '@testing-library/react'; import { mount } from 'enzyme'; +import type { Action } from '@kbn/ui-actions-plugin/public'; import { AlertsCountPanel } from '.'; import type { Status } from '../../../../../common/api/detection_engine'; @@ -17,7 +18,7 @@ import { TestProviders } from '../../../../common/mock'; import { ChartContextMenu } from '../../../pages/detection_engine/chart_panels/chart_context_menu'; import { TABLE } from '../../../pages/detection_engine/chart_panels/chart_select/translations'; import { useIsExperimentalFeatureEnabled } from '../../../../common/hooks/use_experimental_features'; -import { LensEmbeddable } from '../../../../common/components/visualization_actions/lens_embeddable'; +import { VisualizationEmbeddable } from '../../../../common/components/visualization_actions/visualization_embeddable'; import type { ExperimentalFeatures } from '../../../../../common/experimental_features'; import { allowedExperimentalValues } from '../../../../../common/experimental_features'; @@ -39,24 +40,9 @@ jest.mock('react-router-dom', () => { return { ...actual, useLocation: jest.fn().mockReturnValue({ pathname: '' }) }; }); -const defaultUseQueryAlertsReturn = { - loading: false, - data: {}, - setQuery: () => {}, - response: '', - request: '', - refetch: () => {}, -}; -const mockUseQueryAlerts = jest.fn().mockReturnValue(defaultUseQueryAlertsReturn); -jest.mock('../../../containers/detection_engine/alerts/use_query', () => { - return { - useQueryAlerts: (...props: unknown[]) => mockUseQueryAlerts(...props), - }; -}); - jest.mock('../../../../common/hooks/use_experimental_features'); jest.mock('../../../../common/components/page/use_refetch_by_session'); -jest.mock('../../../../common/components/visualization_actions/lens_embeddable'); +jest.mock('../../../../common/components/visualization_actions/visualization_embeddable'); jest.mock('../../../../common/components/page/use_refetch_by_session'); jest.mock('../common/hooks', () => ({ useInspectButton: jest.fn(), @@ -80,6 +66,7 @@ const defaultProps = { showBuildingBlockAlerts: false, showOnlyThreatIndicatorAlerts: false, status: 'open' as Status, + extraActions: [{ id: 'resetGroupByFields' }] as Action[], }; const mockSetToggle = jest.fn(); const mockUseQueryToggle = useQueryToggle as jest.Mock; @@ -90,7 +77,6 @@ describe('AlertsCountPanel', () => { mockUseQueryToggle.mockReturnValue({ toggleStatus: true, setToggleStatus: mockSetToggle }); mockUseIsExperimentalFeatureEnabled.mockImplementation( getMockUseIsExperimentalFeatureEnabled({ - chartEmbeddablesEnabled: false, alertsPageChartsEnabled: false, }) ); @@ -160,26 +146,6 @@ describe('AlertsCountPanel', () => { }); }); - describe('Query', () => { - it('it render with a illegal KQL', async () => { - jest.mock('@kbn/es-query', () => ({ - buildEsQuery: jest.fn().mockImplementation(() => { - throw new Error('Something went wrong'); - }), - })); - const props = { ...defaultProps, query: { query: 'host.name: "', language: 'kql' } }; - const wrapper = mount( - - - - ); - - await waitFor(() => { - expect(wrapper.find('[data-test-subj="alertsCountPanel"]').exists()).toBeTruthy(); - }); - }); - }); - describe('toggleQuery', () => { it('toggles', async () => { await act(async () => { @@ -199,7 +165,7 @@ describe('AlertsCountPanel', () => { ); - expect(wrapper.find('[data-test-subj="alertsCountTable"]').exists()).toEqual(true); + expect(wrapper.find('[data-test-subj="visualization-embeddable"]').exists()).toEqual(true); }); }); it('alertsPageChartsEnabled is false and toggleStatus=false, hide', async () => { @@ -210,14 +176,13 @@ describe('AlertsCountPanel', () => { ); - expect(wrapper.find('[data-test-subj="alertsCountTable"]').exists()).toEqual(false); + expect(wrapper.find('[data-test-subj="visualization-embeddable"]').exists()).toEqual(false); }); }); it('alertsPageChartsEnabled is true and isExpanded=true, render', async () => { mockUseIsExperimentalFeatureEnabled.mockImplementation( getMockUseIsExperimentalFeatureEnabled({ - chartEmbeddablesEnabled: false, alertsPageChartsEnabled: true, }) ); @@ -227,13 +192,12 @@ describe('AlertsCountPanel', () => { ); - expect(wrapper.find('[data-test-subj="alertsCountTable"]').exists()).toEqual(true); + expect(wrapper.find('[data-test-subj="visualization-embeddable"]').exists()).toEqual(true); }); }); it('alertsPageChartsEnabled is true and isExpanded=false, hide', async () => { mockUseIsExperimentalFeatureEnabled.mockImplementation( getMockUseIsExperimentalFeatureEnabled({ - chartEmbeddablesEnabled: false, alertsPageChartsEnabled: true, }) ); @@ -243,54 +207,61 @@ describe('AlertsCountPanel', () => { ); - expect(wrapper.find('[data-test-subj="alertsCountTable"]').exists()).toEqual(false); + expect(wrapper.find('[data-test-subj="visualization-embeddable"]').exists()).toEqual(false); }); }); }); -}); -describe('when the isChartEmbeddablesEnabled experimental feature flag is enabled', () => { - beforeEach(() => { - jest.clearAllMocks(); - mockUseQueryToggle.mockReturnValue({ toggleStatus: true, setToggleStatus: mockSetToggle }); - mockUseIsExperimentalFeatureEnabled.mockImplementation( - getMockUseIsExperimentalFeatureEnabled({ - chartEmbeddablesEnabled: true, - alertsPageChartsEnabled: false, - }) - ); - }); + describe('Visualization', () => { + it('should render embeddable', async () => { + await act(async () => { + const wrapper = mount( + + + + ); + expect(wrapper.find('[data-test-subj="visualization-embeddable"]').exists()).toBeTruthy(); + }); + }); - it('renders LensEmbeddable', async () => { - await act(async () => { - const wrapper = mount( - - - - ); - expect(wrapper.find('[data-test-subj="embeddable-count-table"]').exists()).toBeTruthy(); + it('should render with provided height', async () => { + await act(async () => { + mount( + + + + ); + expect((VisualizationEmbeddable as unknown as jest.Mock).mock.calls[0][0].height).toEqual( + 218 + ); + }); }); - }); - it('renders LensEmbeddable with provided height', async () => { - await act(async () => { - mount( - - - - ); - expect((LensEmbeddable as unknown as jest.Mock).mock.calls[0][0].height).toEqual(218); + it('should render with extra actions', async () => { + await act(async () => { + mount( + + + + ); + expect( + (VisualizationEmbeddable as unknown as jest.Mock).mock.calls[0][0].extraActions[0].id + ).toEqual('resetGroupByFields'); + }); }); - }); - it('should skip calling getAlertsRiskQuery', async () => { - await act(async () => { - mount( - - - - ); - expect(mockUseQueryAlerts.mock.calls[0][0].skip).toBeTruthy(); + it('should render with extra options', async () => { + await act(async () => { + mount( + + + + ); + expect( + (VisualizationEmbeddable as unknown as jest.Mock).mock.calls[0][0].extraOptions + .breakdownField + ).toEqual(defaultProps.stackByField1); + }); }); }); }); diff --git a/x-pack/plugins/security_solution/public/detections/components/alerts_kpis/alerts_count_panel/index.tsx b/x-pack/plugins/security_solution/public/detections/components/alerts_kpis/alerts_count_panel/index.tsx index ee3a5b12e8fee..4b5efb9ae8dd1 100644 --- a/x-pack/plugins/security_solution/public/detections/components/alerts_kpis/alerts_count_panel/index.tsx +++ b/x-pack/plugins/security_solution/public/detections/components/alerts_kpis/alerts_count_panel/index.tsx @@ -5,33 +5,25 @@ * 2.0. */ -import { EuiProgress } from '@elastic/eui'; import type { EuiComboBox } from '@elastic/eui'; import type { Action } from '@kbn/ui-actions-plugin/public'; -import type { MappingRuntimeFields } from '@elastic/elasticsearch/lib/api/types'; -import React, { memo, useMemo, useEffect, useCallback } from 'react'; +import React, { memo, useMemo, useCallback } from 'react'; import { v4 as uuidv4 } from 'uuid'; -import type { Filter, Query } from '@kbn/es-query'; -import { buildEsQuery } from '@kbn/es-query'; +import type { Filter } from '@kbn/es-query'; import { useGlobalTime } from '../../../../common/containers/use_global_time'; import { HeaderSection } from '../../../../common/components/header_section'; -import { useQueryAlerts } from '../../../containers/detection_engine/alerts/use_query'; -import { ALERTS_QUERY_NAMES } from '../../../containers/detection_engine/alerts/constants'; import { InspectButtonContainer } from '../../../../common/components/inspect'; -import { getAlertsCountQuery } from './helpers'; import * as i18n from './translations'; -import type { AlertsCountAggregation } from './types'; import { KpiPanel } from '../common/components'; -import { useInspectButton } from '../common/hooks'; import { useQueryToggle } from '../../../../common/containers/query_toggle'; import { FieldSelection } from '../../../../common/components/field_selection'; import { useIsExperimentalFeatureEnabled } from '../../../../common/hooks/use_experimental_features'; import { getAlertsTableLensAttributes as getLensAttributes } from '../../../../common/components/visualization_actions/lens_attributes/common/alerts/alerts_table'; import { SourcererScopeName } from '../../../../common/store/sourcerer/model'; -import { ChartContent } from './chart_content'; +import { VisualizationEmbeddable } from '../../../../common/components/visualization_actions/visualization_embeddable'; export const DETECTIONS_ALERTS_COUNT_ID = 'detections-alerts-count'; @@ -42,13 +34,10 @@ interface AlertsCountPanelProps { filters?: Filter[]; inspectTitle: string; panelHeight?: number; - query?: Query; - runtimeMappings?: MappingRuntimeFields; setStackByField0: (stackBy: string) => void; setStackByField0ComboboxInputRef?: (inputRef: HTMLInputElement | null) => void; setStackByField1: (stackBy: string | undefined) => void; setStackByField1ComboboxInputRef?: (inputRef: HTMLInputElement | null) => void; - signalIndexName: string | null; stackByField0: string; stackByField0ComboboxRef?: React.RefObject>; stackByField1: string | undefined; @@ -68,13 +57,10 @@ export const AlertsCountPanel = memo( filters, inspectTitle, panelHeight, - query, - runtimeMappings, setStackByField0, setStackByField0ComboboxInputRef, setStackByField1, setStackByField1ComboboxInputRef, - signalIndexName, stackByField0, stackByField0ComboboxRef, stackByField1, @@ -84,29 +70,11 @@ export const AlertsCountPanel = memo( isExpanded, setIsExpanded, }) => { - const { to, from, deleteQuery, setQuery } = useGlobalTime(); - const isChartEmbeddablesEnabled = useIsExperimentalFeatureEnabled('chartEmbeddablesEnabled'); + const { to, from } = useGlobalTime(); const isAlertsPageChartsEnabled = useIsExperimentalFeatureEnabled('alertsPageChartsEnabled'); // create a unique, but stable (across re-renders) query id const uniqueQueryId = useMemo(() => `${DETECTIONS_ALERTS_COUNT_ID}-${uuidv4()}`, []); - // Disabling the fecth method in useQueryAlerts since it is defaulted to the old one - // const fetchMethod = fetchQueryRuleRegistryAlerts; - - const additionalFilters = useMemo(() => { - try { - return [ - buildEsQuery( - undefined, - query != null ? [query] : [], - filters?.filter((f) => f.meta.disabled === false) ?? [] - ), - ]; - } catch (e) { - return []; - } - }, [query, filters]); - const { toggleStatus, setToggleStatus } = useQueryToggle(DETECTIONS_ALERTS_COUNT_ID); const toggleQuery = useCallback( (newToggleStatus: boolean) => { @@ -119,11 +87,6 @@ export const AlertsCountPanel = memo( [setToggleStatus, setIsExpanded, isAlertsPageChartsEnabled] ); - const querySkip = useMemo( - () => (isAlertsPageChartsEnabled ? !isExpanded : !toggleStatus), - [isAlertsPageChartsEnabled, isExpanded, toggleStatus] - ); - const timerange = useMemo(() => ({ from, to }), [from, to]); const extraVisualizationOptions = useMemo( @@ -133,57 +96,7 @@ export const AlertsCountPanel = memo( }), [filters, stackByField1] ); - const { - loading: isLoadingAlerts, - data: alertsData, - setQuery: setAlertsQuery, - response, - request, - refetch, - } = useQueryAlerts<{}, AlertsCountAggregation>({ - query: getAlertsCountQuery({ - stackByField0, - stackByField1, - from, - to, - additionalFilters, - runtimeMappings, - }), - indexName: signalIndexName, - skip: querySkip || isChartEmbeddablesEnabled, - queryName: ALERTS_QUERY_NAMES.COUNT, - }); - useEffect(() => { - setAlertsQuery( - getAlertsCountQuery({ - additionalFilters, - from, - runtimeMappings, - stackByField0, - stackByField1, - to, - }) - ); - }, [ - additionalFilters, - from, - runtimeMappings, - setAlertsQuery, - stackByField0, - stackByField1, - to, - ]); - - useInspectButton({ - deleteQuery, - loading: isLoadingAlerts, - refetch, - request, - response, - setQuery, - uniqueQueryId, - }); const showCount = useMemo(() => { if (isAlertsPageChartsEnabled) { return isExpanded; @@ -214,9 +127,6 @@ export const AlertsCountPanel = memo( toggleQuery={toggleQuery} > ( stackByField1ComboboxRef={stackByField1ComboboxRef} stackByWidth={stackByWidth} uniqueQueryId={uniqueQueryId} - useLensCompatibleFields={isChartEmbeddablesEnabled} + useLensCompatibleFields={true} /> - {showCount && - (isLoadingAlerts ? ( - - ) : ( - - ))} + {showCount && ( + + )} ); diff --git a/x-pack/plugins/security_solution/public/detections/components/alerts_kpis/alerts_histogram_panel/index.test.tsx b/x-pack/plugins/security_solution/public/detections/components/alerts_kpis/alerts_histogram_panel/index.test.tsx index 0a426edb33cb8..6b92dd328f625 100644 --- a/x-pack/plugins/security_solution/public/detections/components/alerts_kpis/alerts_histogram_panel/index.test.tsx +++ b/x-pack/plugins/security_solution/public/detections/components/alerts_kpis/alerts_histogram_panel/index.test.tsx @@ -11,17 +11,12 @@ import { mount } from 'enzyme'; import type { Filter } from '@kbn/es-query'; import { SecurityPageName } from '../../../../app/types'; -import { CHART_SETTINGS_POPOVER_ARIA_LABEL } from '../../../../common/components/chart_settings_popover/translations'; -import { DEFAULT_WIDTH } from '../../../../common/components/charts/draggable_legend'; -import { MatrixLoader } from '../../../../common/components/matrix_histogram/matrix_loader'; -import { DEFAULT_STACK_BY_FIELD, DEFAULT_STACK_BY_FIELD1 } from '../common/config'; import { useQueryToggle } from '../../../../common/containers/query_toggle'; import { TestProviders } from '../../../../common/mock'; -import * as helpers from './helpers'; import { mockAlertSearchResponse } from './mock_data'; -import { ChartContextMenu } from '../../../pages/detection_engine/chart_panels/chart_context_menu'; -import { AlertsHistogramPanel, LEGEND_WITH_COUNTS_WIDTH } from '.'; -import { LensEmbeddable } from '../../../../common/components/visualization_actions/lens_embeddable'; +import { VisualizationEmbeddable } from '../../../../common/components/visualization_actions/visualization_embeddable'; + +import { AlertsHistogramPanel } from '.'; import type { ExperimentalFeatures } from '../../../../../common'; import { allowedExperimentalValues } from '../../../../../common'; import { useIsExperimentalFeatureEnabled } from '../../../../common/hooks/use_experimental_features'; @@ -81,30 +76,20 @@ jest.mock('../../../../common/lib/kibana', () => { }; }); -jest.mock('../../../../common/components/navigation/use_url_state_query_params'); +jest.mock('../../../../common/components/visualization_actions/visualization_embeddable'); -const defaultUseQueryAlertsReturn = { - loading: true, - setQuery: () => undefined, - data: null, - response: '', - request: '', - refetch: null, -}; -const mockUseQueryAlerts = jest.fn().mockReturnValue(defaultUseQueryAlertsReturn); +jest.mock('../../../../common/hooks/use_experimental_features'); -jest.mock('../../../containers/detection_engine/alerts/use_query', () => { - const original = jest.requireActual('../../../containers/detection_engine/alerts/use_query'); +jest.mock('../../../../common/components/visualization_actions/use_visualization_response', () => { + const original = jest.requireActual( + '../../../../common/components/visualization_actions/use_visualization_response' + ); return { ...original, - useQueryAlerts: (...props: unknown[]) => mockUseQueryAlerts(...props), + useVisualizationResponse: jest.fn().mockReturnValue({ loading: false }), }; }); -jest.mock('../../../../common/hooks/use_experimental_features'); -jest.mock('../../../../common/components/page/use_refetch_by_session'); -jest.mock('../../../../common/components/visualization_actions/lens_embeddable'); -jest.mock('../../../../common/components/page/use_refetch_by_session'); jest.mock('../common/hooks', () => { const actual = jest.requireActual('../common/hooks'); return { @@ -115,7 +100,6 @@ jest.mock('../common/hooks', () => { const mockUseIsExperimentalFeatureEnabled = jest.fn((feature: keyof ExperimentalFeatures) => { if (feature === 'alertsPageChartsEnabled') return false; - if (feature === 'chartEmbeddablesEnabled') return false; return allowedExperimentalValues[feature]; }); @@ -146,6 +130,7 @@ const defaultProps = { }; const mockSetToggle = jest.fn(); const mockUseQueryToggle = useQueryToggle as jest.Mock; +const mockUseVisualizationResponse = useVisualizationResponse as jest.Mock; describe('AlertsHistogramPanel', () => { beforeEach(() => { @@ -157,7 +142,7 @@ describe('AlertsHistogramPanel', () => { ); }); - it('renders correctly', () => { + test('renders correctly', () => { const wrapper = mount( @@ -169,13 +154,9 @@ describe('AlertsHistogramPanel', () => { describe('legend counts', () => { beforeEach(() => { - mockUseQueryAlerts.mockReturnValue({ + mockUseVisualizationResponse.mockReturnValue({ loading: false, - data: mockAlertSearchResponse, - setQuery: () => {}, - response: '', - request: '', - refetch: () => {}, + responses: mockAlertSearchResponse, }); }); @@ -188,16 +169,6 @@ describe('AlertsHistogramPanel', () => { expect(wrapper.find('[data-test-subj="legendItemCount"]').exists()).toBe(false); }); - - test('it renders counts in the legend when `showCountsInLegend` is true', () => { - const wrapper = mount( - - - - ); - - expect(wrapper.find('[data-test-subj="legendItemCount"]').exists()).toBe(true); - }); }); test('it renders the header with the specified `alignHeader` alignment', () => { @@ -212,41 +183,6 @@ describe('AlertsHistogramPanel', () => { ).toContain('flexEnd'); }); - describe('inspect button', () => { - test('it renders the inspect button by default', () => { - const wrapper = mount( - - - - ); - - expect(wrapper.find('[data-test-subj="inspect-icon-button"]').first().exists()).toBe(true); - }); - - test('it does NOT render the inspect button when a `chartOptionsContextMenu` is provided', async () => { - const chartOptionsContextMenu = (queryId: string) => ( - - ); - - const wrapper = mount( - - - - ); - - expect(wrapper.find('[data-test-subj="inspect-icon-button"]').first().exists()).toBe(false); - }); - }); - test('it aligns the panel flex group at flex start to ensure the context menu is displayed at the top of the panel', () => { const wrapper = mount( @@ -263,13 +199,9 @@ describe('AlertsHistogramPanel', () => { const onFieldSelected = jest.fn(); const optionToSelect = 'agent.hostname'; - mockUseQueryAlerts.mockReturnValue({ + mockUseVisualizationResponse.mockReturnValue({ loading: false, - data: mockAlertSearchResponse, - setQuery: () => {}, - response: '', - request: '', - refetch: () => {}, + responses: mockAlertSearchResponse, }); render( @@ -411,67 +343,6 @@ describe('AlertsHistogramPanel', () => { }); }); - test('it renders the chart options context menu when a `chartOptionsContextMenu` is provided', async () => { - const chartOptionsContextMenu = (queryId: string) => ( - - ); - - render( - - - - ); - - expect( - screen.getByRole('button', { name: CHART_SETTINGS_POPOVER_ARIA_LABEL }) - ).toBeInTheDocument(); - }); - - describe('legend width', () => { - beforeEach(() => { - mockUseQueryAlerts.mockReturnValue({ - loading: false, - data: mockAlertSearchResponse, - setQuery: () => {}, - response: '', - request: '', - refetch: () => {}, - }); - }); - - test('it renders the legend with the expected default min-width', () => { - const wrapper = mount( - - - - ); - - expect(wrapper.find('[data-test-subj="draggable-legend"]').first()).toHaveStyleRule( - 'min-width', - `${DEFAULT_WIDTH}px` - ); - }); - - test('it renders the legend with the expected min-width when `showCountsInLegend` is true', () => { - const wrapper = mount( - - - - ); - - expect(wrapper.find('[data-test-subj="draggable-legend"]').first()).toHaveStyleRule( - 'min-width', - `${LEGEND_WITH_COUNTS_WIDTH}px` - ); - }); - }); - describe('Button view alerts', () => { it('renders correctly', () => { const props = { ...defaultProps, showLinkToAlerts: true }; @@ -532,47 +403,8 @@ describe('AlertsHistogramPanel', () => { }); }); - describe('CombinedQueries', () => { - it('combinedQueries props is valid, alerts query include combinedQueries', async () => { - const mockGetAlertsHistogramQuery = jest.spyOn(helpers, 'getAlertsHistogramQuery'); - - const props = { - ...defaultProps, - query: { query: 'host.name: "', language: 'kql' }, - combinedQueries: - '{"bool":{"must":[],"filter":[{"match_all":{}},{"exists":{"field":"process.name"}}],"should":[],"must_not":[]}}', - }; - const wrapper = mount( - - - - ); - - await waitFor(() => { - expect(mockGetAlertsHistogramQuery.mock.calls[0]).toEqual([ - 'kibana.alert.rule.name', - '2020-07-07T08:20:18.966Z', - '2020-07-08T08:20:18.966Z', - [ - { - bool: { - filter: [{ match_all: {} }, { exists: { field: 'process.name' } }], - must: [], - must_not: [], - should: [], - }, - }, - ], - undefined, - ]); - }); - wrapper.unmount(); - }); - }); - describe('Filters', () => { it('filters props is valid, alerts query include filter', async () => { - const mockGetAlertsHistogramQuery = jest.spyOn(helpers, 'getAlertsHistogramQuery'); const statusFilter: Filter = { meta: { alias: null, @@ -593,7 +425,6 @@ describe('AlertsHistogramPanel', () => { const props = { ...defaultProps, - query: { query: '', language: 'kql' }, filters: [statusFilter], }; const wrapper = mount( @@ -603,109 +434,20 @@ describe('AlertsHistogramPanel', () => { ); await waitFor(() => { - expect(mockGetAlertsHistogramQuery.mock.calls[1]).toEqual([ - 'kibana.alert.rule.name', - '2020-07-07T08:20:18.966Z', - '2020-07-08T08:20:18.966Z', - [ - { - bool: { - filter: [{ term: { 'kibana.alert.workflow_status': 'open' } }], - must: [], - must_not: [], - should: [], - }, - }, - ], - undefined, - ]); + expect( + (VisualizationEmbeddable as unknown as jest.Mock).mock.calls[0][0].timerange + ).toEqual({ + from: '2020-07-07T08:20:18.966Z', + to: '2020-07-08T08:20:18.966Z', + }); + expect( + (VisualizationEmbeddable as unknown as jest.Mock).mock.calls[0][0].extraOptions.filters + ).toEqual(props.filters); }); wrapper.unmount(); }); }); - describe('parseCombinedQueries', () => { - it('return empty object when variables is undefined', async () => { - expect(helpers.parseCombinedQueries(undefined)).toEqual({}); - }); - - it('return empty object when variables is empty string', async () => { - expect(helpers.parseCombinedQueries('')).toEqual({}); - }); - - it('return empty object when variables is NOT a valid stringify json object', async () => { - expect(helpers.parseCombinedQueries('hello world')).toEqual({}); - }); - - it('return a valid json object when variables is a valid json stringify', async () => { - expect( - helpers.parseCombinedQueries( - '{"bool":{"must":[],"filter":[{"match_all":{}},{"exists":{"field":"process.name"}}],"should":[],"must_not":[]}}' - ) - ).toMatchInlineSnapshot(` - Object { - "bool": Object { - "filter": Array [ - Object { - "match_all": Object {}, - }, - Object { - "exists": Object { - "field": "process.name", - }, - }, - ], - "must": Array [], - "must_not": Array [], - "should": Array [], - }, - } - `); - }); - }); - - describe('buildCombinedQueries', () => { - it('return empty array when variables is undefined', async () => { - expect(helpers.buildCombinedQueries(undefined)).toEqual([]); - }); - - it('return empty array when variables is empty string', async () => { - expect(helpers.buildCombinedQueries('')).toEqual([]); - }); - - it('return array with empty object when variables is NOT a valid stringify json object', async () => { - expect(helpers.buildCombinedQueries('hello world')).toEqual([{}]); - }); - - it('return a valid json object when variables is a valid json stringify', async () => { - expect( - helpers.buildCombinedQueries( - '{"bool":{"must":[],"filter":[{"match_all":{}},{"exists":{"field":"process.name"}}],"should":[],"must_not":[]}}' - ) - ).toMatchInlineSnapshot(` - Array [ - Object { - "bool": Object { - "filter": Array [ - Object { - "match_all": Object {}, - }, - Object { - "exists": Object { - "field": "process.name", - }, - }, - ], - "must": Array [], - "must_not": Array [], - "should": Array [], - }, - }, - ] - `); - }); - }); - describe('toggleQuery', () => { it('toggles', async () => { await act(async () => { @@ -722,7 +464,6 @@ describe('AlertsHistogramPanel', () => { describe('when alertsPageChartsEnabled = false', () => { beforeEach(() => { jest.clearAllMocks(); - mockUseIsExperimentalFeatureEnabled.mockReturnValueOnce(false); // for chartEmbeddablesEnabled flag mockUseIsExperimentalFeatureEnabled.mockReturnValueOnce(false); // for alertsPageChartsEnabled flag }); @@ -734,7 +475,10 @@ describe('AlertsHistogramPanel', () => { ); - expect(wrapper.find(MatrixLoader).exists()).toEqual(true); + expect(wrapper.find('[data-test-subj="panelFlexGroup"]').exists()).toEqual(true); + expect(wrapper.find('[data-test-subj="embeddable-matrix-histogram"]').exists()).toEqual( + true + ); }); }); it('toggleStatus=false, hide', async () => { @@ -745,7 +489,10 @@ describe('AlertsHistogramPanel', () => { ); - expect(wrapper.find(MatrixLoader).exists()).toEqual(false); + expect(wrapper.find('[data-test-subj="panelFlexGroup"]').exists()).toEqual(false); + expect(wrapper.find('[data-test-subj="embeddable-matrix-histogram"]').exists()).toEqual( + false + ); }); }); }); @@ -753,7 +500,6 @@ describe('AlertsHistogramPanel', () => { describe('when alertsPageChartsEnabled = true', () => { beforeEach(() => { jest.clearAllMocks(); - mockUseIsExperimentalFeatureEnabled.mockReturnValueOnce(false); // for chartEmbeddablesEnabled flag mockUseIsExperimentalFeatureEnabled.mockReturnValueOnce(true); // for alertsPageChartsEnabled flag }); @@ -764,7 +510,10 @@ describe('AlertsHistogramPanel', () => { ); - expect(wrapper.find(MatrixLoader).exists()).toEqual(true); + expect(wrapper.find('[data-test-subj="panelFlexGroup"]').exists()).toEqual(true); + expect(wrapper.find('[data-test-subj="embeddable-matrix-histogram"]').exists()).toEqual( + true + ); }); }); it('isExpanded=false, hide', async () => { @@ -774,7 +523,10 @@ describe('AlertsHistogramPanel', () => { ); - expect(wrapper.find(MatrixLoader).exists()).toEqual(false); + expect(wrapper.find('[data-test-subj="panelFlexGroup"]').exists()).toEqual(false); + expect(wrapper.find('[data-test-subj="embeddable-matrix-histogram"]').exists()).toEqual( + false + ); }); }); it('isExpanded is not passed in and toggleStatus =true, render', async () => { @@ -784,7 +536,10 @@ describe('AlertsHistogramPanel', () => { ); - expect(wrapper.find(MatrixLoader).exists()).toEqual(true); + expect(wrapper.find('[data-test-subj="panelFlexGroup"]').exists()).toEqual(true); + expect(wrapper.find('[data-test-subj="embeddable-matrix-histogram"]').exists()).toEqual( + true + ); }); }); it('isExpanded is not passed in and toggleStatus =false, hide', async () => { @@ -795,17 +550,19 @@ describe('AlertsHistogramPanel', () => { ); - expect(wrapper.find(MatrixLoader).exists()).toEqual(false); + expect(wrapper.find('[data-test-subj="panelFlexGroup"]').exists()).toEqual(false); + expect(wrapper.find('[data-test-subj="embeddable-matrix-histogram"]').exists()).toEqual( + false + ); }); }); }); }); - describe('when isChartEmbeddablesEnabled = true', () => { + describe('VisualizationEmbeddable', () => { beforeEach(() => { jest.clearAllMocks(); mockUseQueryToggle.mockReturnValue({ toggleStatus: true, setToggleStatus: mockSetToggle }); - mockUseIsExperimentalFeatureEnabled.mockReturnValueOnce(true); // for chartEmbeddablesEnabled flag mockUseIsExperimentalFeatureEnabled.mockReturnValueOnce(false); // for alertsPageChartsEnabled flag }); @@ -816,13 +573,14 @@ describe('AlertsHistogramPanel', () => { ); - mockUseQueryAlerts.mockReturnValue({ + mockUseVisualizationResponse.mockReturnValue({ loading: false, - setQuery: () => undefined, - data: null, - response: '', - request: '', - refetch: null, + responses: [ + { + hits: { total: 0 }, + aggregations: { myAgg: { buckets: [{ key: 'A' }, { key: 'B' }, { key: 'C' }] } }, + }, + ], }); wrapper.setProps({ filters: [] }); wrapper.update(); @@ -850,18 +608,9 @@ describe('AlertsHistogramPanel', () => { ); - expect((LensEmbeddable as unknown as jest.Mock).mock.calls[0][0].height).toEqual(155); - }); - }); - - it('should skip calling getAlertsRiskQuery', async () => { - await act(async () => { - mount( - - - + expect((VisualizationEmbeddable as unknown as jest.Mock).mock.calls[0][0].height).toEqual( + 155 ); - expect(mockUseQueryAlerts.mock.calls[0][0].skip).toBeTruthy(); }); }); diff --git a/x-pack/plugins/security_solution/public/detections/components/alerts_kpis/alerts_histogram_panel/index.tsx b/x-pack/plugins/security_solution/public/detections/components/alerts_kpis/alerts_histogram_panel/index.tsx index 11b1cd68f859b..69066b3d3e595 100644 --- a/x-pack/plugins/security_solution/public/detections/components/alerts_kpis/alerts_histogram_panel/index.tsx +++ b/x-pack/plugins/security_solution/public/detections/components/alerts_kpis/alerts_histogram_panel/index.tsx @@ -5,9 +5,7 @@ * 2.0. */ -import type { MappingRuntimeFields } from '@elastic/elasticsearch/lib/api/types'; import type { Action } from '@kbn/ui-actions-plugin/public'; -import type { Position } from '@elastic/charts'; import type { EuiComboBox, EuiTitleSize } from '@elastic/eui'; import { EuiFlexGroup, EuiFlexItem, EuiSpacer, EuiToolTip } from '@elastic/eui'; import React, { memo, useCallback, useMemo, useState, useEffect } from 'react'; @@ -16,41 +14,26 @@ import { isEmpty, noop } from 'lodash/fp'; import { v4 as uuidv4 } from 'uuid'; import { sumBy } from 'lodash'; -import type { Filter, Query } from '@kbn/es-query'; -import { buildEsQuery } from '@kbn/es-query'; -import { getEsQueryConfig } from '@kbn/data-plugin/common'; +import type { Filter } from '@kbn/es-query'; + import { useGlobalTime } from '../../../../common/containers/use_global_time'; import { APP_UI_ID } from '../../../../../common/constants'; import type { UpdateDateRange } from '../../../../common/components/charts/common'; -import type { LegendItem } from '../../../../common/components/charts/draggable_legend_item'; -import { escapeDataProviderId } from '../../../../common/components/drag_and_drop/helpers'; import { HeaderSection } from '../../../../common/components/header_section'; -import { useQueryAlerts } from '../../../containers/detection_engine/alerts/use_query'; -import { ALERTS_QUERY_NAMES } from '../../../containers/detection_engine/alerts/constants'; import { getDetectionEngineUrl, useFormatUrl } from '../../../../common/components/link_to'; -import { defaultLegendColors } from '../../../../common/components/matrix_histogram/utils'; -import { InspectButtonContainer } from '../../../../common/components/inspect'; -import { MatrixLoader } from '../../../../common/components/matrix_histogram/matrix_loader'; import { useKibana } from '../../../../common/lib/kibana'; import { - parseCombinedQueries, - buildCombinedQueries, - formatAlertsData, - getAlertsHistogramQuery, showInitialLoadingSpinner, createGenericSubtitle, createEmbeddedDataSubtitle, } from './helpers'; -import { AlertsHistogram } from './alerts_histogram'; import * as i18n from './translations'; -import type { AlertsAggregation, AlertsTotal } from './types'; import { LinkButton } from '../../../../common/components/links'; import { SecurityPageName } from '../../../../app/types'; import { DEFAULT_STACK_BY_FIELD, PANEL_HEIGHT } from '../common/config'; import type { AlertsStackByField } from '../common/types'; import { KpiPanel, StackByComboBox } from '../common/components'; -import { useInspectButton } from '../common/hooks'; import { useQueryToggle } from '../../../../common/containers/query_toggle'; import { GROUP_BY_TOP_LABEL } from '../common/translations'; import { useIsExperimentalFeatureEnabled } from '../../../../common/hooks/use_experimental_features'; @@ -60,48 +43,30 @@ import { VisualizationEmbeddable } from '../../../../common/components/visualiza import { useAlertHistogramCount } from '../../../hooks/alerts_visualization/use_alert_histogram_count'; import { useVisualizationResponse } from '../../../../common/components/visualization_actions/use_visualization_response'; -const defaultTotalAlertsObj: AlertsTotal = { - value: 0, - relation: 'eq', -}; - export const DETECTIONS_HISTOGRAM_ID = 'detections-histogram'; const ViewAlertsFlexItem = styled(EuiFlexItem)` margin-left: ${({ theme }) => theme.eui.euiSizeL}; `; -const OptionsFlexItem = styled(EuiFlexItem)` - margin-left: ${({ theme }) => theme.eui.euiSizeS}; -`; - -export const LEGEND_WITH_COUNTS_WIDTH = 300; // px - const CHART_HEIGHT = 155; // px interface AlertsHistogramPanelProps { alignHeader?: 'center' | 'baseline' | 'stretch' | 'flexStart' | 'flexEnd'; chartHeight?: number; - chartOptionsContextMenu?: (queryId: string) => React.ReactNode; - combinedQueries?: string; comboboxRef?: React.RefObject>; defaultStackByOption?: string; extraActions?: Action[]; filters?: Filter[]; headerChildren?: React.ReactNode; inspectTitle?: React.ReactNode; - legendPosition?: Position; onFieldSelected?: (field: string) => void; /** Override all defaults, and only display this field */ onlyField?: AlertsStackByField; paddingSize?: 's' | 'm' | 'l' | 'none'; panelHeight?: number; - query?: Query; - runtimeMappings?: MappingRuntimeFields; setComboboxInputRef?: (inputRef: HTMLInputElement | null) => void; - showCountsInLegend?: boolean; showGroupByPlaceholder?: boolean; - showLegend?: boolean; showLinkToAlerts?: boolean; showStackBy?: boolean; showTotalAlertsCount?: boolean; @@ -117,57 +82,42 @@ interface AlertsHistogramPanelProps { setIsExpanded?: (status: boolean) => void; } -const NO_LEGEND_DATA: LegendItem[] = []; - export const AlertsHistogramPanel = memo( ({ alignHeader, chartHeight = CHART_HEIGHT, - chartOptionsContextMenu, - combinedQueries, comboboxRef, defaultStackByOption = DEFAULT_STACK_BY_FIELD, extraActions, filters, headerChildren, inspectTitle, - legendPosition = 'right', onFieldSelected, onlyField, paddingSize = 'm', panelHeight = PANEL_HEIGHT, - query, - runtimeMappings, setComboboxInputRef, - showCountsInLegend = false, showGroupByPlaceholder = false, - showLegend = true, showLinkToAlerts = false, showStackBy = true, showTotalAlertsCount = false, - signalIndexName, stackByLabel, stackByWidth, - timelineId, title = i18n.HISTOGRAM_HEADER, titleSize = 'm', - updateDateRange, hideQueryToggle = false, isExpanded, setIsExpanded, }) => { - const { to, from, deleteQuery, setQuery } = useGlobalTime(); + const { to, from } = useGlobalTime(); // create a unique, but stable (across re-renders) query id const uniqueQueryId = useMemo(() => `${DETECTIONS_HISTOGRAM_ID}-${uuidv4()}`, []); const visualizationId = `alerts-trend-embeddable-${uniqueQueryId}`; const [isInitialLoading, setIsInitialLoading] = useState(true); - const [isInspectDisabled, setIsInspectDisabled] = useState(false); - const [totalAlertsObj, setTotalAlertsObj] = useState(defaultTotalAlertsObj); const [selectedStackByOption, setSelectedStackByOption] = useState( onlyField == null ? defaultStackByOption : onlyField ); - const isChartEmbeddablesEnabled = useIsExperimentalFeatureEnabled('chartEmbeddablesEnabled'); const isAlertsPageChartsEnabled = useIsExperimentalFeatureEnabled('alertsPageChartsEnabled'); const onSelect = useCallback( @@ -197,42 +147,16 @@ export const AlertsHistogramPanel = memo( [setToggleStatus, setIsExpanded, isAlertsPageChartsEnabled] ); - const querySkip = useMemo( - () => - isAlertsPageChartsEnabled && setIsExpanded !== undefined ? !isExpanded : !toggleStatus, - [isAlertsPageChartsEnabled, setIsExpanded, isExpanded, toggleStatus] - ); - const timerange = useMemo(() => ({ from, to }), [from, to]); - const { - loading: isLoadingAlerts, - data: alertsData, - setQuery: setAlertsQuery, - response, - request, - refetch, - } = useQueryAlerts<{}, AlertsAggregation>({ - query: getAlertsHistogramQuery( - selectedStackByOption, - from, - to, - buildCombinedQueries(combinedQueries), - runtimeMappings - ), - indexName: signalIndexName, - skip: querySkip || isChartEmbeddablesEnabled, - queryName: ALERTS_QUERY_NAMES.HISTOGRAM, - }); - const kibana = useKibana(); const { navigateToApp } = kibana.services.application; const { formatUrl, search: urlSearch } = useFormatUrl(SecurityPageName.alerts); - + const { loading: isLoadingAlerts } = useVisualizationResponse({ + visualizationId, + }); const totalAlerts = useAlertHistogramCount({ - totalAlertsObj, visualizationId, - isChartEmbeddablesEnabled, }); const goToDetectionEngine = useCallback( @@ -245,30 +169,6 @@ export const AlertsHistogramPanel = memo( }, [navigateToApp, urlSearch] ); - const formattedAlertsData = useMemo(() => formatAlertsData(alertsData), [alertsData]); - - const legendItems: LegendItem[] = useMemo( - () => - showLegend && alertsData?.aggregations?.alertsByGrouping?.buckets != null - ? alertsData.aggregations.alertsByGrouping.buckets.map((bucket, i) => ({ - color: i < defaultLegendColors.length ? defaultLegendColors[i] : undefined, - count: showCountsInLegend ? bucket.doc_count : undefined, - dataProviderId: escapeDataProviderId( - `draggable-legend-item-${uuidv4()}-${selectedStackByOption}-${bucket.key}` - ), - field: selectedStackByOption, - timelineId, - value: bucket?.key_as_string ?? bucket.key, - })) - : NO_LEGEND_DATA, - [ - alertsData?.aggregations?.alertsByGrouping.buckets, - selectedStackByOption, - showCountsInLegend, - showLegend, - timelineId, - ] - ); useEffect(() => { let canceled = false; @@ -281,60 +181,6 @@ export const AlertsHistogramPanel = memo( }; }, [isInitialLoading, isLoadingAlerts, setIsInitialLoading]); - useInspectButton({ - deleteQuery, - loading: isLoadingAlerts, - refetch, - request, - response, - setQuery, - uniqueQueryId, - }); - - useEffect(() => { - setTotalAlertsObj( - alertsData?.hits.total ?? { - value: 0, - relation: 'eq', - } - ); - }, [alertsData]); - - useEffect(() => { - try { - let converted = null; - if (combinedQueries != null) { - converted = parseCombinedQueries(combinedQueries); - } else { - converted = buildEsQuery( - undefined, - query != null ? [query] : [], - filters?.filter((f) => f.meta.disabled === false) ?? [], - { - ...getEsQueryConfig(kibana.services.uiSettings), - dateFormatTZ: undefined, - } - ); - } - setIsInspectDisabled(false); - setAlertsQuery( - getAlertsHistogramQuery( - selectedStackByOption, - from, - to, - !isEmpty(converted) ? [converted] : [], - runtimeMappings - ) - ); - } catch (e) { - setIsInspectDisabled(true); - setAlertsQuery( - getAlertsHistogramQuery(selectedStackByOption, from, to, [], runtimeMappings) - ); - } - // eslint-disable-next-line react-hooks/exhaustive-deps - }, [selectedStackByOption, from, to, query, filters, combinedQueries, runtimeMappings]); - const linkButton = useMemo(() => { if (showLinkToAlerts) { return ( @@ -385,114 +231,89 @@ export const AlertsHistogramPanel = memo( ); const embeddedDataAvailable = !!aggregationBucketsCount; - const showsEmbeddedData = showHistogram && isChartEmbeddablesEnabled; - const subtitle = showsEmbeddedData + const subtitle = showHistogram ? createEmbeddedDataSubtitle(embeddedDataLoaded, embeddedDataAvailable, totalAlerts) : createGenericSubtitle(isInitialLoading, showTotalAlertsCount, totalAlerts); return ( - - + - - - - {showStackBy && ( - <> - - {showGroupByPlaceholder && ( - <> - - - - - - )} - - )} - {headerChildren != null && headerChildren} - - {chartOptionsContextMenu != null && !isChartEmbeddablesEnabled && ( - - {chartOptionsContextMenu(uniqueQueryId)} - + + + {showStackBy && ( + <> + + {showGroupByPlaceholder && ( + <> + + + + + + )} + )} - {linkButton} - - - {showHistogram ? ( - isChartEmbeddablesEnabled ? ( - - ) : isInitialLoading ? ( - - ) : ( - - ) - ) : null} - - + {headerChildren != null && headerChildren} + + {linkButton} + + + {showHistogram ? ( + + ) : null} + ); } ); diff --git a/x-pack/plugins/security_solution/public/detections/hooks/alerts_visualization/use_alert_histogram_count.test.tsx b/x-pack/plugins/security_solution/public/detections/hooks/alerts_visualization/use_alert_histogram_count.test.tsx index d86b9b37c568f..9781f3ad991e3 100644 --- a/x-pack/plugins/security_solution/public/detections/hooks/alerts_visualization/use_alert_histogram_count.test.tsx +++ b/x-pack/plugins/security_solution/public/detections/hooks/alerts_visualization/use_alert_histogram_count.test.tsx @@ -15,16 +15,10 @@ jest.mock('../../../common/components/visualization_actions/use_visualization_re describe('useAlertHistogramCount', () => { const props = { - totalAlertsObj: { value: 10, relation: '' }, visualizationId: 'mockVisualizationId', - isChartEmbeddablesEnabled: false, }; - it('returns total alerts count', () => { - const { result } = renderHook(() => useAlertHistogramCount(props), { wrapper: TestProviders }); - expect(result.current).toEqual('Showing: 10 alerts'); - }); - it('returns visualization alerts count when isChartEmbeddablesEnabled is true', () => { + it('returns visualization alerts count', () => { const testPops = { ...props, isChartEmbeddablesEnabled: true }; const { result } = renderHook(() => useAlertHistogramCount(testPops), { wrapper: TestProviders, diff --git a/x-pack/plugins/security_solution/public/detections/hooks/alerts_visualization/use_alert_histogram_count.ts b/x-pack/plugins/security_solution/public/detections/hooks/alerts_visualization/use_alert_histogram_count.ts index 39365401a68df..487718b10e193 100644 --- a/x-pack/plugins/security_solution/public/detections/hooks/alerts_visualization/use_alert_histogram_count.ts +++ b/x-pack/plugins/security_solution/public/detections/hooks/alerts_visualization/use_alert_histogram_count.ts @@ -11,40 +11,25 @@ import numeral from '@elastic/numeral'; import { DEFAULT_NUMBER_FORMAT } from '../../../../common/constants'; import { useUiSetting$ } from '../../../common/lib/kibana'; import { SHOWING_ALERTS } from '../../components/alerts_kpis/alerts_histogram_panel/translations'; -import type { AlertsTotal } from '../../components/alerts_kpis/alerts_histogram_panel/types'; import { useVisualizationResponse } from '../../../common/components/visualization_actions/use_visualization_response'; export const useAlertHistogramCount = ({ - totalAlertsObj, visualizationId, - isChartEmbeddablesEnabled, }: { - totalAlertsObj: AlertsTotal; visualizationId: string; - isChartEmbeddablesEnabled: boolean; }): string => { const [defaultNumberFormat] = useUiSetting$(DEFAULT_NUMBER_FORMAT); - const { responses: visualizationResponse } = useVisualizationResponse({ visualizationId }); - - const totalAlerts = useMemo( - () => - SHOWING_ALERTS( - numeral(totalAlertsObj.value).format(defaultNumberFormat), - totalAlertsObj.value, - totalAlertsObj.relation === 'gte' ? '>' : totalAlertsObj.relation === 'lte' ? '<' : '' - ), - [totalAlertsObj.value, totalAlertsObj.relation, defaultNumberFormat] - ); + const { responses: visualizationResponses } = useVisualizationResponse({ visualizationId }); const visualizationAlerts = useMemo(() => { const visualizationAlertsCount = - visualizationResponse != null ? visualizationResponse[0].hits.total : 0; + visualizationResponses != null ? visualizationResponses[0].hits.total : 0; return SHOWING_ALERTS( numeral(visualizationAlertsCount).format(defaultNumberFormat), visualizationAlertsCount, '' ); - }, [defaultNumberFormat, visualizationResponse]); + }, [defaultNumberFormat, visualizationResponses]); - return isChartEmbeddablesEnabled ? visualizationAlerts : totalAlerts; + return visualizationAlerts; }; diff --git a/x-pack/plugins/security_solution/public/detections/pages/detection_engine/chart_panels/index.test.tsx b/x-pack/plugins/security_solution/public/detections/pages/detection_engine/chart_panels/index.test.tsx index feb8b0ead2be4..6319f4d98420d 100644 --- a/x-pack/plugins/security_solution/public/detections/pages/detection_engine/chart_panels/index.test.tsx +++ b/x-pack/plugins/security_solution/public/detections/pages/detection_engine/chart_panels/index.test.tsx @@ -18,6 +18,8 @@ import { TestProviders } from '../../../../common/mock'; import { ChartPanels } from '.'; import { useIsExperimentalFeatureEnabled } from '../../../../common/hooks/use_experimental_features'; import { useQueryToggle } from '../../../../common/containers/query_toggle'; +import { LensEmbeddable } from '../../../../common/components/visualization_actions/lens_embeddable'; +import { createResetGroupByFieldAction } from '../../../components/alerts_kpis/alerts_histogram_panel/helpers'; jest.mock('./alerts_local_storage'); jest.mock('../../../../common/containers/sourcerer'); @@ -227,79 +229,164 @@ describe('ChartPanels', () => { describe(`'Reset group by fields' context menu action`, () => { describe('Group by', () => { - const alertViewSelections = ['trend', 'table', 'treemap']; + test(`it resets the 'Group by' field to the default value, even if the user has triggered validation errors, when 'alertViewSelection' is 'treemap'`, async () => { + (useAlertsLocalStorage as jest.Mock).mockReturnValue({ + ...defaultAlertSettings, + alertViewSelection: 'treemap', + }); + + const defaultValue = 'kibana.alert.rule.name'; + const invalidValue = 'an invalid value'; + + render( + + + + ); + + const initialInput = screen.getAllByTestId('comboBoxSearchInput')[0]; + expect(initialInput).toHaveValue(defaultValue); + + // update the EuiComboBox input to an invalid value: + fireEvent.change(initialInput, { target: { value: invalidValue } }); + + const afterInvalidInput = screen.getAllByTestId('comboBoxSearchInput')[0]; + expect(afterInvalidInput).toHaveValue(invalidValue); // the 'Group by' EuiComboBox is now in the "error state" + expect(afterInvalidInput).toBeInvalid(); + + resetGroupByFields(); // invoke the `Reset group by fields` context menu action + + await waitFor(() => { + const afterReset = screen.getAllByTestId('comboBoxSearchInput')[0]; + expect(afterReset).toHaveValue(defaultValue); // back to the default + }); + }); - alertViewSelections.forEach((alertViewSelection) => { - test(`it resets the 'Group by' field to the default value, even if the user has triggered validation errors, when 'alertViewSelection' is '${alertViewSelection}'`, async () => { + describe.each([['trend'], ['table']])(`when 'alertViewSelection' is '%s'`, (view) => { + test(`it has resets the 'Group by' field as an extra action`, async () => { (useAlertsLocalStorage as jest.Mock).mockReturnValue({ ...defaultAlertSettings, - alertViewSelection, + alertViewSelection: view, }); - const defaultValue = 'kibana.alert.rule.name'; - const invalidValue = 'an invalid value'; + const mockResetGroupByFieldsAction = [ + createResetGroupByFieldAction({ callback: jest.fn(), order: 5 }), + ]; + + const testProps = { + ...defaultProps, + extraActions: mockResetGroupByFieldsAction, + }; render( - + ); - const initialInput = screen.getAllByTestId('comboBoxSearchInput')[0]; - expect(initialInput).toHaveValue(defaultValue); - - // update the EuiComboBox input to an invalid value: - fireEvent.change(initialInput, { target: { value: invalidValue } }); - - const afterInvalidInput = screen.getAllByTestId('comboBoxSearchInput')[0]; - expect(afterInvalidInput).toHaveValue(invalidValue); // the 'Group by' EuiComboBox is now in the "error state" - expect(afterInvalidInput).toBeInvalid(); - - resetGroupByFields(); // invoke the `Reset group by fields` context menu action - await waitFor(() => { - const afterReset = screen.getAllByTestId('comboBoxSearchInput')[0]; - expect(afterReset).toHaveValue(defaultValue); // back to the default + expect( + (LensEmbeddable as unknown as jest.Mock).mock.calls[0][0].extraActions.length + ).toEqual(1); + expect( + (LensEmbeddable as unknown as jest.Mock).mock.calls[0][0].extraActions[0].id + ).toEqual('resetGroupByField'); }); }); }); - }); - - describe('Group by top', () => { - const justTableAndTreemap = ['table', 'treemap']; - justTableAndTreemap.forEach((alertViewSelection) => { - test(`it resets the 'Group by top' field to the default value, even if the user has triggered validation errors, when 'alertViewSelection' is '${alertViewSelection}'`, async () => { + describe.each([ + ['trend', 'kibana.alert.rule.name'], + ['table', 'kibana.alert.rule.name'], + ])(`when 'alertViewSelection' is '%s'`, (view, defaultGroupBy) => { + test(`it has resets the 'Group by' field as an extra action, with default value ${defaultGroupBy}`, async () => { (useAlertsLocalStorage as jest.Mock).mockReturnValue({ ...defaultAlertSettings, - alertViewSelection, + alertViewSelection: view, }); - const defaultValue = 'host.name'; - const invalidValue = 'an-invalid-value'; + const mockResetGroupByFieldsAction = [ + createResetGroupByFieldAction({ callback: jest.fn(), order: 5 }), + ]; + + const testProps = { + ...defaultProps, + extraActions: mockResetGroupByFieldsAction, + }; render( - + ); - const initialInput = screen.getAllByTestId('comboBoxSearchInput')[1]; - expect(initialInput).toHaveValue(defaultValue); + await waitFor(() => { + expect( + (LensEmbeddable as unknown as jest.Mock).mock.calls[0][0].extraActions.length + ).toEqual(1); + expect( + (LensEmbeddable as unknown as jest.Mock).mock.calls[0][0].extraActions[0].id + ).toEqual('resetGroupByField'); + expect((LensEmbeddable as unknown as jest.Mock).mock.calls[0][0].stackByField).toEqual( + defaultGroupBy + ); + }); + }); + }); + }); + + describe('Group by top', () => { + test(`it resets the 'Group by top' field to the default value, even if the user has triggered validation errors, when 'alertViewSelection' is 'treemap'`, async () => { + (useAlertsLocalStorage as jest.Mock).mockReturnValue({ + ...defaultAlertSettings, + alertViewSelection: 'treemap', + }); - // update the EuiComboBox input to an invalid value: - fireEvent.change(initialInput, { target: { value: invalidValue } }); + const defaultValue = 'host.name'; + const invalidValue = 'an-invalid-value'; - const afterInvalidInput = screen.getAllByTestId('comboBoxSearchInput')[1]; - expect(afterInvalidInput).toHaveValue(invalidValue); // the 'Group by top' EuiComboBox is now in the "error state" - expect(afterInvalidInput).toBeInvalid(); + render( + + + + ); - resetGroupByFields(); // invoke the `Reset group by fields` context menu action + const initialInput = screen.getAllByTestId('comboBoxSearchInput')[1]; + expect(initialInput).toHaveValue(defaultValue); - await waitFor(() => { - const afterReset = screen.getAllByTestId('comboBoxSearchInput')[1]; - expect(afterReset).toHaveValue(defaultValue); // back to the default - }); + // update the EuiComboBox input to an invalid value: + fireEvent.change(initialInput, { target: { value: invalidValue } }); + + const afterInvalidInput = screen.getAllByTestId('comboBoxSearchInput')[1]; + expect(afterInvalidInput).toHaveValue(invalidValue); // the 'Group by top' EuiComboBox is now in the "error state" + expect(afterInvalidInput).toBeInvalid(); + + resetGroupByFields(); // invoke the `Reset group by fields` context menu action + + await waitFor(() => { + const afterReset = screen.getAllByTestId('comboBoxSearchInput')[1]; + expect(afterReset).toHaveValue(defaultValue); // back to the default + }); + }); + + test(`it renders the 'Group by top' field to the default value, when 'alertViewSelection' is 'table'`, async () => { + (useAlertsLocalStorage as jest.Mock).mockReturnValue({ + ...defaultAlertSettings, + alertViewSelection: 'table', + }); + + const defaultValue = 'host.name'; + + render( + + + + ); + + await waitFor(() => { + expect( + (LensEmbeddable as unknown as jest.Mock).mock.calls[0][0].extraOptions.breakdownField + ).toEqual(defaultValue); }); }); }); diff --git a/x-pack/plugins/security_solution/public/detections/pages/detection_engine/chart_panels/index.tsx b/x-pack/plugins/security_solution/public/detections/pages/detection_engine/chart_panels/index.tsx index 9ab7fc73c3560..86c402b20288c 100644 --- a/x-pack/plugins/security_solution/public/detections/pages/detection_engine/chart_panels/index.tsx +++ b/x-pack/plugins/security_solution/public/detections/pages/detection_engine/chart_panels/index.tsx @@ -201,7 +201,6 @@ const ChartPanelsComponent: React.FC = ({ = ({ inspectTitle={i18n.TREND} onFieldSelected={updateCommonStackBy0} panelHeight={CHART_PANEL_HEIGHT} - query={query} - runtimeMappings={runtimeMappings} setComboboxInputRef={setStackByField0ComboboxInputRef} - showCountsInLegend={true} showGroupByPlaceholder={false} showTotalAlertsCount={false} signalIndexName={signalIndexName} @@ -239,13 +235,10 @@ const ChartPanelsComponent: React.FC = ({ filters={alertsDefaultFilters} inspectTitle={isAlertsPageChartsEnabled ? i18n.COUNTS : i18n.TABLE} panelHeight={CHART_PANEL_HEIGHT} - query={query} - runtimeMappings={runtimeMappings} setStackByField0={updateCommonStackBy0} setStackByField0ComboboxInputRef={setStackByField0ComboboxInputRef} setStackByField1={updateCommonStackBy1} setStackByField1ComboboxInputRef={setStackByField1ComboboxInputRef} - signalIndexName={signalIndexName} stackByField0={countTableStackBy0} stackByField0ComboboxRef={stackByField0ComboboxRef} stackByField1={countTableStackBy1} diff --git a/x-pack/plugins/security_solution/public/entity_analytics/components/risk_score_over_time/index.test.tsx b/x-pack/plugins/security_solution/public/entity_analytics/components/risk_score_over_time/index.test.tsx index 22458a6d00fd1..d5b35bcef4596 100644 --- a/x-pack/plugins/security_solution/public/entity_analytics/components/risk_score_over_time/index.test.tsx +++ b/x-pack/plugins/security_solution/public/entity_analytics/components/risk_score_over_time/index.test.tsx @@ -7,13 +7,11 @@ import { render } from '@testing-library/react'; import React from 'react'; -import { RiskScoreOverTime, scoreFormatter } from '.'; +import { RiskScoreOverTime } from '.'; import { TestProviders } from '../../../common/mock'; -import { LineSeries } from '@elastic/charts'; import { RiskScoreEntity } from '../../../../common/search_strategy'; import { useIsExperimentalFeatureEnabled } from '../../../common/hooks/use_experimental_features'; -const mockLineSeries = LineSeries as jest.Mock; const mockUseIsExperimentalFeatureEnabled = useIsExperimentalFeatureEnabled as jest.Mock; jest.mock('@elastic/charts', () => { const original = jest.requireActual('@elastic/charts'); @@ -58,17 +56,7 @@ describe('Risk Score Over Time', () => { expect(queryByTestId('RiskScoreOverTime')).toBeInTheDocument(); }); - it('renders loader when loading', () => { - const { queryByTestId } = render( - - - - ); - - expect(queryByTestId('RiskScoreOverTime-loading')).toBeInTheDocument(); - }); - - it('renders VisualizationEmbeddable when isChartEmbeddablesEnabled = true and spaceId exists', () => { + it('renders VisualizationEmbeddable', () => { mockUseIsExperimentalFeatureEnabled.mockReturnValue(true); const { queryByTestId } = render( @@ -79,25 +67,4 @@ describe('Risk Score Over Time', () => { expect(queryByTestId('visualization-embeddable')).toBeInTheDocument(); }); - - describe('scoreFormatter', () => { - it('renders score formatted', () => { - render( - - - - ); - - const tickFormat = mockLineSeries.mock.calls[0][0].tickFormat; - - expect(tickFormat).toBe(scoreFormatter); - }); - - it('renders a formatted score', () => { - expect(scoreFormatter(3.000001)).toEqual('3'); - expect(scoreFormatter(3.4999)).toEqual('3'); - expect(scoreFormatter(3.51111)).toEqual('4'); - expect(scoreFormatter(3.9999)).toEqual('4'); - }); - }); }); diff --git a/x-pack/plugins/security_solution/public/entity_analytics/components/risk_score_over_time/index.tsx b/x-pack/plugins/security_solution/public/entity_analytics/components/risk_score_over_time/index.tsx index 210f578b36ad7..b4555af087d51 100644 --- a/x-pack/plugins/security_solution/public/entity_analytics/components/risk_score_over_time/index.tsx +++ b/x-pack/plugins/security_solution/public/entity_analytics/components/risk_score_over_time/index.tsx @@ -5,38 +5,19 @@ * 2.0. */ -import React, { useMemo, useCallback } from 'react'; -import type { TooltipHeaderFormatter } from '@elastic/charts'; -import { - Chart, - LineSeries, - ScaleType, - Settings, - Axis, - Position, - AnnotationDomainType, - LineAnnotation, - Tooltip, -} from '@elastic/charts'; -import { EuiFlexGroup, EuiFlexItem, EuiLoadingChart, EuiText, EuiPanel } from '@elastic/eui'; -import styled from 'styled-components'; -import { euiThemeVars } from '@kbn/ui-theme'; -import { i18n } from '@kbn/i18n'; -import { chartDefaultSettings, useThemes } from '../../../common/components/charts/common'; -import { useTimeZone } from '../../../common/lib/kibana'; -import { histogramDateTimeFormatter } from '../../../common/components/utils'; +import React, { useMemo } from 'react'; + +import { EuiFlexGroup, EuiFlexItem, EuiPanel } from '@elastic/eui'; + import { HeaderSection } from '../../../common/components/header_section'; -import { InspectButton, InspectButtonContainer } from '../../../common/components/inspect'; -import * as translations from './translations'; -import { PreferenceFormattedDate } from '../../../common/components/formatted_date'; +import { InspectButtonContainer } from '../../../common/components/inspect'; + import type { HostRiskScore, RiskScoreEntity, UserRiskScore, } from '../../../../common/search_strategy'; -import { isUserRiskScore } from '../../../../common/search_strategy'; import { useSpaceId } from '../../../common/hooks/use_space_id'; -import { useIsExperimentalFeatureEnabled } from '../../../common/hooks/use_experimental_features'; import { VisualizationEmbeddable } from '../../../common/components/visualization_actions/visualization_embeddable'; import { getRiskScoreOverTimeAreaAttributes } from '../../lens_attributes/risk_score_over_time_area'; @@ -52,19 +33,7 @@ export interface RiskScoreOverTimeProps { toggleQuery?: (status: boolean) => void; } -const RISKY_THRESHOLD = 70; -const DEFAULT_CHART_HEIGHT = 250; const CHART_HEIGHT = 180; -const StyledEuiText = styled(EuiText)` - font-size: 9px; - font-weight: ${({ theme }) => theme.eui.euiFontWeightSemiBold}; - margin-right: ${({ theme }) => theme.eui.euiSizeXS}; -`; - -const LoadingChart = styled(EuiLoadingChart)` - display: block; - text-align: center; -`; export const scoreFormatter = (d: number) => Math.round(d).toString(); @@ -79,27 +48,7 @@ const RiskScoreOverTimeComponent: React.FC = ({ toggleStatus, toggleQuery, }) => { - const timeZone = useTimeZone(); - - const dataTimeFormatter = useMemo(() => histogramDateTimeFormatter([from, to]), [from, to]); - const headerFormatter = useCallback( - ({ value }) => , - [] - ); - - const { baseTheme, theme } = useThemes(); - const graphData = useMemo( - () => - riskScore - ?.map((data) => ({ - x: data['@timestamp'], - y: (isUserRiskScore(data) ? data.user : data.host).risk.calculated_score_norm, - })) - .reverse() ?? [], - [riskScore] - ); const spaceId = useSpaceId(); - const isChartEmbeddablesEnabled = useIsExperimentalFeatureEnabled('chartEmbeddablesEnabled'); const timerange = useMemo( () => ({ from, @@ -119,17 +68,12 @@ const RiskScoreOverTimeComponent: React.FC = ({ toggleStatus={toggleStatus} /> - {toggleStatus && !isChartEmbeddablesEnabled && ( - - - - )} {toggleStatus && ( - {isChartEmbeddablesEnabled && spaceId ? ( + {spaceId && ( = ({ height={CHART_HEIGHT} extraOptions={{ spaceId }} /> - ) : ( -
- {loading ? ( - - ) : ( - - - - - - - - {translations.RISKY} - - } - /> - - )} -
)}
diff --git a/x-pack/plugins/security_solution/public/explore/components/authentication/helpers.tsx b/x-pack/plugins/security_solution/public/explore/components/authentication/helpers.tsx index 9ca08cc8cd1e4..80b5924860ecb 100644 --- a/x-pack/plugins/security_solution/public/explore/components/authentication/helpers.tsx +++ b/x-pack/plugins/security_solution/public/explore/components/authentication/helpers.tsx @@ -19,11 +19,9 @@ import { UserDetailsLink, } from '../../../common/components/links'; import type { AuthenticationsEdges } from '../../../../common/search_strategy'; -import { MatrixHistogramType } from '../../../../common/search_strategy'; import type { AuthTableColumns } from './types'; import type { MatrixHistogramConfigs, - MatrixHistogramMappingTypes, MatrixHistogramOption, } from '../../../common/components/matrix_histogram/types'; import type { LensAttributes } from '../../../common/components/visualization_actions/types'; @@ -195,36 +193,10 @@ export const authenticationsStackByOptions: MatrixHistogramOption[] = [ ]; const DEFAULT_STACK_BY = 'event.outcome'; -enum AuthenticationsMatrixDataGroup { - authenticationsSuccess = 'success', - authenticationsFailure = 'failure', -} - -export enum ChartColors { - authenticationsSuccess = '#54B399', - authenticationsFailure = '#E7664C', -} - -export const authenticationsMatrixDataMappingFields: MatrixHistogramMappingTypes = { - [AuthenticationsMatrixDataGroup.authenticationsSuccess]: { - key: AuthenticationsMatrixDataGroup.authenticationsSuccess, - value: null, - color: ChartColors.authenticationsSuccess, - }, - [AuthenticationsMatrixDataGroup.authenticationsFailure]: { - key: AuthenticationsMatrixDataGroup.authenticationsFailure, - value: null, - color: ChartColors.authenticationsFailure, - }, -}; - export const histogramConfigs: MatrixHistogramConfigs = { defaultStackByOption: authenticationsStackByOptions.find((o) => o.text === DEFAULT_STACK_BY) ?? authenticationsStackByOptions[0], - errorMessage: i18n.ERROR_FETCHING_AUTHENTICATIONS_DATA, - histogramType: MatrixHistogramType.authentications, - mapping: authenticationsMatrixDataMappingFields, stackByOptions: authenticationsStackByOptions, title: i18n.NAVIGATION_AUTHENTICATIONS_TITLE, lensAttributes: authenticationLensAttributes as LensAttributes, diff --git a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/hosts/kpi/index.ts b/x-pack/plugins/security_solution/public/explore/components/kpi/__mocks__/index.tsx similarity index 72% rename from x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/hosts/kpi/index.ts rename to x-pack/plugins/security_solution/public/explore/components/kpi/__mocks__/index.tsx index 86370222898e3..e0a3ed3f05cae 100644 --- a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/hosts/kpi/index.ts +++ b/x-pack/plugins/security_solution/public/explore/components/kpi/__mocks__/index.tsx @@ -5,5 +5,6 @@ * 2.0. */ -export * from './hosts'; -export * from './unique_ips'; +import React from 'react'; + +export const KpiBaseComponent = jest.fn().mockReturnValue(
); diff --git a/x-pack/plugins/security_solution/public/explore/components/kpi/index.tsx b/x-pack/plugins/security_solution/public/explore/components/kpi/index.tsx new file mode 100644 index 0000000000000..de0794fdafef9 --- /dev/null +++ b/x-pack/plugins/security_solution/public/explore/components/kpi/index.tsx @@ -0,0 +1,29 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React from 'react'; +import { EuiFlexGroup } from '@elastic/eui'; + +import type { StatItems } from '../stat_items'; +import { StatItemsComponent } from '../stat_items'; + +interface KpiBaseComponentProps { + from: string; + id: string; + statItems: Readonly; + to: string; +} + +export const KpiBaseComponent = React.memo(({ statItems, ...props }) => ( + + {statItems.map((statItem) => ( + + ))} + +)); + +KpiBaseComponent.displayName = 'KpiBaseComponent'; diff --git a/x-pack/plugins/security_solution/public/explore/components/stat_items/index.tsx b/x-pack/plugins/security_solution/public/explore/components/stat_items/index.tsx index 4b17b37c96f36..fafd3885914f3 100644 --- a/x-pack/plugins/security_solution/public/explore/components/stat_items/index.tsx +++ b/x-pack/plugins/security_solution/public/explore/components/stat_items/index.tsx @@ -7,4 +7,3 @@ export { StatItemsComponent } from './stat_items'; export type { StatItemsProps, StatItems } from './types'; -export { useKpiMatrixStatus } from './use_kpi_matrix_status'; diff --git a/x-pack/plugins/security_solution/public/explore/components/stat_items/metric.test.tsx b/x-pack/plugins/security_solution/public/explore/components/stat_items/metric.test.tsx deleted file mode 100644 index 30627023c91cf..0000000000000 --- a/x-pack/plugins/security_solution/public/explore/components/stat_items/metric.test.tsx +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import type { MetricProps } from './metric'; -import { Metric } from './metric'; -import type { RenderResult } from '@testing-library/react'; -import { render } from '@testing-library/react'; -import React from 'react'; -import { TestProviders } from '../../../common/mock'; -import type { LensAttributes } from '../../../common/components/visualization_actions/types'; - -jest.mock('../../../common/components/visualization_actions/actions'); - -describe('Metric', () => { - const testProps = { - fields: [ - { - key: 'uniqueSourceIps', - description: 'Source', - value: 1714, - color: '#D36086', - icon: 'cross', - lensAttributes: {} as LensAttributes, - }, - { - key: 'uniqueDestinationIps', - description: 'Dest.', - value: 2359, - color: '#9170B8', - icon: 'cross', - lensAttributes: {} as LensAttributes, - }, - ], - id: 'test', - timerange: { from: '', to: '' }, - isAreaChartDataAvailable: true, - isBarChartDataAvailable: true, - } as MetricProps; - - let res: RenderResult; - - beforeEach(() => { - res = render( - - - - ); - }); - - it('renders icons', () => { - expect(res.getAllByTestId('stat-icon')).toHaveLength(2); - }); - - it('render titles', () => { - expect(res.getAllByTestId('stat-title')[0]).toHaveTextContent('1,714 Source'); - expect(res.getAllByTestId('stat-title')[1]).toHaveTextContent('2,359 Dest.'); - }); - - it('render actions', () => { - expect(res.getAllByTestId('visualizationActions')).toHaveLength(2); - }); -}); diff --git a/x-pack/plugins/security_solution/public/explore/components/stat_items/metric.tsx b/x-pack/plugins/security_solution/public/explore/components/stat_items/metric.tsx deleted file mode 100644 index 1dd14b262108c..0000000000000 --- a/x-pack/plugins/security_solution/public/explore/components/stat_items/metric.tsx +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ -import { EuiFlexGroup, EuiIcon } from '@elastic/eui'; -import React from 'react'; -import type { StatItem } from './types'; -import { HoverVisibilityContainer } from '../../../common/components/hover_visibility_container'; -import { VisualizationActions } from '../../../common/components/visualization_actions/actions'; -import { FlexItem, StatValue } from './utils'; -import { getEmptyTagValue } from '../../../common/components/empty_value'; -import { VISUALIZATION_ACTIONS_BUTTON_CLASS } from '../../../common/components/visualization_actions/utils'; - -export interface MetricProps { - fields: StatItem[]; - id: string; - timerange: { from: string; to: string }; - isAreaChartDataAvailable: boolean; - isBarChartDataAvailable: boolean; - inspectTitle?: string; - inspectIndex?: number; -} - -const MetricComponent = ({ - fields, - id, - timerange, - isAreaChartDataAvailable, - isBarChartDataAvailable, - inspectTitle, - inspectIndex, -}: MetricProps) => { - return ( - - {fields.map((field) => ( - - - {(isAreaChartDataAvailable || isBarChartDataAvailable) && field.icon && ( - - - - )} - - - - -

- {field.value != null ? field.value.toLocaleString() : getEmptyTagValue()}{' '} - {field.description} -

-
- {field.lensAttributes && timerange && ( - - )} -
-
-
-
- ))} -
- ); -}; - -export const Metric = React.memo(MetricComponent); diff --git a/x-pack/plugins/security_solution/public/explore/components/stat_items/metric_embeddable.tsx b/x-pack/plugins/security_solution/public/explore/components/stat_items/metric_embeddable.tsx index ddc242bb13ddc..c6e44b4dda306 100644 --- a/x-pack/plugins/security_solution/public/explore/components/stat_items/metric_embeddable.tsx +++ b/x-pack/plugins/security_solution/public/explore/components/stat_items/metric_embeddable.tsx @@ -7,14 +7,14 @@ import { EuiFlexGroup, EuiIcon } from '@elastic/eui'; import React from 'react'; import { FlexItem, MetricItem, StatValue } from './utils'; -import type { MetricStatItem } from './types'; import { VisualizationEmbeddable } from '../../../common/components/visualization_actions/visualization_embeddable'; +import type { FieldConfigs } from './types'; export interface MetricEmbeddableProps { - fields: MetricStatItem[]; + fields: FieldConfigs[]; id: string; - timerange: { from: string; to: string }; inspectTitle?: string; + timerange: { from: string; to: string }; } const CHART_HEIGHT = 36; @@ -22,14 +22,9 @@ const CHART_HEIGHT = 36; const MetricEmbeddableComponent = ({ fields, id, - timerange, inspectTitle, -}: { - fields: MetricStatItem[]; - id: string; - timerange: { from: string; to: string }; - inspectTitle?: string; -}) => { + timerange, +}: MetricEmbeddableProps) => { return ( {fields.map((field) => ( diff --git a/x-pack/plugins/security_solution/public/explore/components/stat_items/stat_items.test.tsx b/x-pack/plugins/security_solution/public/explore/components/stat_items/stat_items.test.tsx index dbbdab338b623..ad549a5e02e72 100644 --- a/x-pack/plugins/security_solution/public/explore/components/stat_items/stat_items.test.tsx +++ b/x-pack/plugins/security_solution/public/explore/components/stat_items/stat_items.test.tsx @@ -5,245 +5,67 @@ * 2.0. */ -import type { ReactWrapper } from 'enzyme'; -import { mount } from 'enzyme'; import React from 'react'; -import { ThemeProvider } from 'styled-components'; - -import type { StatItemsProps } from '.'; +import { render, fireEvent, waitFor } from '@testing-library/react'; import { StatItemsComponent } from './stat_items'; -import { BarChart } from '../../../common/components/charts/barchart'; -import { AreaChart } from '../../../common/components/charts/areachart'; -import { EuiHorizontalRule } from '@elastic/eui'; -import { mockUpdateDateRange } from '../../network/components/kpi_network/mock'; -import { createMockStore } from '../../../common/mock'; -import { Provider as ReduxStoreProvider } from 'react-redux'; -import { getMockTheme } from '../../../common/lib/kibana/kibana_react.mock'; -import * as module from '../../../common/containers/query_toggle'; import type { LensAttributes } from '../../../common/components/visualization_actions/types'; -import { useIsExperimentalFeatureEnabled } from '../../../common/hooks/use_experimental_features'; - -const from = '2019-06-15T06:00:00.000Z'; -const to = '2019-06-18T06:00:00.000Z'; - -jest.mock('../../../common/components/charts/areachart', () => { - return { AreaChart: () =>
}; -}); - -jest.mock('../../../common/components/charts/barchart', () => { - return { BarChart: () =>
}; -}); - -jest.mock('../../../common/components/visualization_actions/actions'); -jest.mock('../../../common/hooks/use_experimental_features', () => ({ - useIsExperimentalFeatureEnabled: jest.fn(), -})); +import { TestProviders } from '../../../common/mock/test_providers'; +import { useToggleStatus } from './use_toggle_status'; jest.mock('../../../common/components/visualization_actions/visualization_embeddable'); +jest.mock('./use_toggle_status', () => ({ + useToggleStatus: jest.fn().mockReturnValue({ isToggleExpanded: true, onToggle: jest.fn() }), +})); -const mockSetToggle = jest.fn(); -const mockUseIsExperimentalFeatureEnabled = useIsExperimentalFeatureEnabled as jest.Mock; - -jest - .spyOn(module, 'useQueryToggle') - .mockImplementation(() => ({ toggleStatus: true, setToggleStatus: mockSetToggle })); -const mockSetQuerySkip = jest.fn(); -describe('Stat Items Component', () => { - const mockTheme = getMockTheme({ eui: { euiColorMediumShade: '#ece' } }); - const store = createMockStore(); - const testProps = { - description: 'HOSTS', - fields: [{ key: 'hosts', value: null, color: '#6092C0', icon: 'cross' }], - from, - id: 'hostsKpiHostsQuery', - key: 'mock-keys', - loading: false, - setQuerySkip: mockSetQuerySkip, - to, - updateDateRange: mockUpdateDateRange, - }; - beforeEach(() => { - jest.clearAllMocks(); - }); - describe.each([ - [ - mount( - - - - - - ), - ], - [ - mount( - - - - - - ), - ], - ])('disable charts', (wrapper) => { - test('should render titles', () => { - expect(wrapper.find('[data-test-subj="stat-title"]')).toBeTruthy(); - }); - - test('should not render icons', () => { - expect(wrapper.find('[data-test-subj="stat-icon"]').filter('EuiIcon')).toHaveLength(0); - }); - - test('should not render barChart', () => { - expect(wrapper.find(BarChart)).toHaveLength(0); - }); - - test('should not render areaChart', () => { - expect(wrapper.find(AreaChart)).toHaveLength(0); - }); - - test('should not render spliter', () => { - expect(wrapper.find(EuiHorizontalRule)).toHaveLength(0); - }); - }); - - const mockStatItemsData: StatItemsProps = { - ...testProps, - id: 'UniqueIps', - areaChart: [ - { - key: 'uniqueSourceIpsHistogram', - value: [ - { x: new Date('2019-05-03T13:00:00.000Z').toISOString(), y: 565975 }, - { x: new Date('2019-05-04T01:00:00.000Z').toISOString(), y: 1084366 }, - { x: new Date('2019-05-04T13:00:00.000Z').toISOString(), y: 12280 }, - ], - color: '#D36086', - }, - { - key: 'uniqueDestinationIpsHistogram', - value: [ - { x: new Date('2019-05-03T13:00:00.000Z').toISOString(), y: 565975 }, - { x: new Date('2019-05-04T01:00:00.000Z').toISOString(), y: 1084366 }, - { x: new Date('2019-05-04T13:00:00.000Z').toISOString(), y: 12280 }, - ], - color: '#9170B8', - }, - ], - barChart: [ - { key: 'uniqueSourceIps', value: [{ x: 'uniqueSourceIps', y: '1714' }], color: '#D36086' }, - { - key: 'uniqueDestinationIps', - value: [{ x: 'uniqueDestinationIps', y: 2354 }], - color: '#9170B8', - }, - ], - description: 'UNIQUE_PRIVATE_IPS', - enableAreaChart: true, - enableBarChart: true, +describe('StatItemsComponent', () => { + const mockStatItems = { + key: 'hosts', fields: [ { - key: 'uniqueSourceIps', - description: 'Source', - value: 1714, - color: '#D36086', - icon: 'cross', - lensAttributes: {} as LensAttributes, - }, - { - key: 'uniqueDestinationIps', - description: 'Dest.', - value: 2359, - color: '#9170B8', - icon: 'cross', + key: 'hosts', + value: null, + color: '#fff', + icon: 'storage', lensAttributes: {} as LensAttributes, }, ], - barChartLensAttributes: {} as LensAttributes, + enableAreaChart: true, + description: 'Mock Description', areaChartLensAttributes: {} as LensAttributes, }; - let wrapper: ReactWrapper; - describe('rendering kpis with charts', () => { - beforeAll(() => { - wrapper = mount( - - - - ); - }); - - test('should handle multiple titles', () => { - expect(wrapper.find('[data-test-subj="stat-title"]').find('p')).toHaveLength(2); - }); - - test('should render kpi icons', () => { - expect(wrapper.find('[data-test-subj="stat-icon"]').filter('EuiIcon')).toHaveLength(2); - }); + const mockProps = { + statItems: mockStatItems, + from: new Date('2023-01-01').toISOString(), + to: new Date('2023-12-31').toISOString(), + id: 'mockId', + }; - test('should render barChart', () => { - expect(wrapper.find(BarChart)).toHaveLength(1); + it('renders visualizations', () => { + const { getByText, getAllByTestId } = render(, { + wrapper: TestProviders, }); - test('should render areaChart', () => { - expect(wrapper.find(AreaChart)).toHaveLength(1); - }); + expect(getByText('Mock Description')).toBeInTheDocument(); - test('should render separator', () => { - expect(wrapper.find(EuiHorizontalRule)).toHaveLength(1); - }); + expect(getAllByTestId('visualization-embeddable')).toHaveLength(2); }); - describe('Toggle query', () => { - test('toggleQuery updates toggleStatus', () => { - wrapper = mount( - - - - ); - wrapper.find('[data-test-subj="query-toggle-stat"]').first().simulate('click'); - expect(mockSetToggle).toBeCalledWith(false); - expect(mockSetQuerySkip).toBeCalledWith(true); - }); - test('toggleStatus=true, render all', () => { - wrapper = mount( - - - - ); - expect(wrapper.find(`.viz-actions`).exists()).toEqual(true); - expect(wrapper.find('[data-test-subj="stat-title"]').first().exists()).toEqual(true); + it('toggles visualizations', () => { + (useToggleStatus as jest.Mock).mockReturnValue({ + isToggleExpanded: false, + onToggle: jest.fn(), }); - test('toggleStatus=false, render none', () => { - jest - .spyOn(module, 'useQueryToggle') - .mockImplementation(() => ({ toggleStatus: false, setToggleStatus: mockSetToggle })); - wrapper = mount( - - - - ); - expect(wrapper.find('.viz-actions').first().exists()).toEqual(false); - expect(wrapper.find('[data-test-subj="stat-title"]').first().exists()).toEqual(false); + const { getByTestId, getAllByTestId } = render(, { + wrapper: TestProviders, }); - }); - - describe('when isChartEmbeddablesEnabled = true', () => { - beforeAll(() => { - mockUseIsExperimentalFeatureEnabled.mockReturnValue(true); - jest - .spyOn(module, 'useQueryToggle') - .mockImplementation(() => ({ toggleStatus: true, setToggleStatus: mockSetToggle })); - wrapper = mount( - - - - ); - }); + const toggleButton = getByTestId('query-toggle-stat'); + fireEvent.click(toggleButton); - test('renders Lens Embeddables', () => { - expect(wrapper.find('[data-test-subj="visualization-embeddable"]').length).toEqual(4); + waitFor(() => { + expect(getAllByTestId('visualization-embeddable')).toHaveLength(0); }); }); }); diff --git a/x-pack/plugins/security_solution/public/explore/components/stat_items/stat_items.tsx b/x-pack/plugins/security_solution/public/explore/components/stat_items/stat_items.tsx index 1de63dff04903..570ffadca64e7 100644 --- a/x-pack/plugins/security_solution/public/explore/components/stat_items/stat_items.tsx +++ b/x-pack/plugins/security_solution/public/explore/components/stat_items/stat_items.tsx @@ -5,191 +5,89 @@ * 2.0. */ -import { - EuiFlexGroup, - EuiPanel, - EuiHorizontalRule, - EuiFlexItem, - EuiLoadingSpinner, -} from '@elastic/eui'; +import { EuiFlexGroup, EuiPanel, EuiHorizontalRule } from '@elastic/eui'; import React, { useMemo } from 'react'; -import deepEqual from 'fast-deep-equal'; - -import { AreaChart } from '../../../common/components/charts/areachart'; -import { BarChart } from '../../../common/components/charts/barchart'; - -import { histogramDateTimeFormatter } from '../../../common/components/utils'; import { StatItemHeader } from './stat_item_header'; import { useToggleStatus } from './use_toggle_status'; import type { StatItemsProps } from './types'; -import { areachartConfigs, barchartConfigs, FlexItem, ChartHeight } from './utils'; -import { Metric } from './metric'; +import { FlexItem, ChartHeight } from './utils'; import { MetricEmbeddable } from './metric_embeddable'; -import { useIsExperimentalFeatureEnabled } from '../../../common/hooks/use_experimental_features'; import { VisualizationEmbeddable } from '../../../common/components/visualization_actions/visualization_embeddable'; -export const StatItemsComponent = React.memo( - ({ - areaChart, - barChart, +export const StatItemsComponent = React.memo(({ statItems, from, id, to }) => { + const timerange = useMemo( + () => ({ + from, + to, + }), + [from, to] + ); + const { + key, description, enableAreaChart, enableBarChart, fields, - from, - grow, - id, - loading = false, - index, - updateDateRange, - statKey = 'item', - to, barChartLensAttributes, areaChartLensAttributes, - setQuerySkip, - }) => { - const isBarChartDataAvailable = !!( - barChart && - barChart.length && - barChart.every((item) => item.value != null && item.value.length > 0) - ); - const isAreaChartDataAvailable = !!( - areaChart && - areaChart.length && - areaChart.every((item) => item.value != null && item.value.length > 0) - ); + } = statItems; - const timerange = useMemo( - () => ({ - from, - to, - }), - [from, to] - ); + const { isToggleExpanded, onToggle } = useToggleStatus({ id }); - const { isToggleExpanded, onToggle } = useToggleStatus({ id, setQuerySkip }); + return ( + + + - const isChartEmbeddablesEnabled = useIsExperimentalFeatureEnabled('chartEmbeddablesEnabled'); + {isToggleExpanded && ( + <> + - return ( - - - - {loading && ( - - - - - - )} - {isToggleExpanded && !loading && ( - <> - {isChartEmbeddablesEnabled ? ( - - ) : ( - + {(enableAreaChart || enableBarChart) && } + + {enableBarChart && ( + + + )} - {(enableAreaChart || enableBarChart) && } - - {enableBarChart && ( + + {enableAreaChart && from != null && to != null && ( + <> - {isChartEmbeddablesEnabled && barChartLensAttributes ? ( - - ) : ( - - )} + - )} - - {enableAreaChart && from != null && to != null && ( - <> - - {isChartEmbeddablesEnabled && areaChartLensAttributes ? ( - - ) : ( - - )} - - - )} - - - )} - - - ); - }, - (prevProps, nextProps) => - prevProps.description === nextProps.description && - prevProps.enableAreaChart === nextProps.enableAreaChart && - prevProps.enableBarChart === nextProps.enableBarChart && - prevProps.from === nextProps.from && - prevProps.grow === nextProps.grow && - prevProps.loading === nextProps.loading && - prevProps.setQuerySkip === nextProps.setQuerySkip && - prevProps.id === nextProps.id && - prevProps.index === nextProps.index && - prevProps.updateDateRange === nextProps.updateDateRange && - prevProps.statKey === nextProps.statKey && - prevProps.to === nextProps.to && - deepEqual(prevProps.areaChart, nextProps.areaChart) && - deepEqual(prevProps.barChart, nextProps.barChart) && - deepEqual(prevProps.fields, nextProps.fields) -); + + )} + + + )} + + + ); +}); StatItemsComponent.displayName = 'StatItemsComponent'; diff --git a/x-pack/plugins/security_solution/public/explore/components/stat_items/types.ts b/x-pack/plugins/security_solution/public/explore/components/stat_items/types.ts index 07003fd462e82..bece997a63aad 100644 --- a/x-pack/plugins/security_solution/public/explore/components/stat_items/types.ts +++ b/x-pack/plugins/security_solution/public/explore/components/stat_items/types.ts @@ -5,54 +5,31 @@ * 2.0. */ import type { IconType } from '@elastic/eui'; -import type { - ChartSeriesConfigs, - ChartSeriesData, - UpdateDateRange, -} from '../../../common/components/charts/common'; + import type { LensAttributes } from '../../../common/components/visualization_actions/types'; -export interface MetricStatItem { +export interface FieldConfigs { color?: string; description?: string; icon?: IconType; key: string; - name?: string; lensAttributes?: LensAttributes; -} - -export interface StatItem { - color?: string; - description?: string; - icon?: IconType; - key: string; name?: string; - value: number | undefined | null; - lensAttributes?: LensAttributes; } export interface StatItems { - areachartConfigs?: ChartSeriesConfigs; - barchartConfigs?: ChartSeriesConfigs; description?: string; enableAreaChart?: boolean; enableBarChart?: boolean; - fields: StatItem[]; - grow?: 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | true | false | null; - index?: number; + fields: FieldConfigs[]; key: string; - statKey?: string; barChartLensAttributes?: LensAttributes; areaChartLensAttributes?: LensAttributes; } -export interface StatItemsProps extends StatItems { - areaChart?: ChartSeriesData[]; - barChart?: ChartSeriesData[]; +export interface StatItemsProps { from: string; id: string; - updateDateRange: UpdateDateRange; + statItems: StatItems; to: string; - loading: boolean; - setQuerySkip: (skip: boolean) => void; } diff --git a/x-pack/plugins/security_solution/public/explore/components/stat_items/use_kpi_matrix_status.test.tsx b/x-pack/plugins/security_solution/public/explore/components/stat_items/use_kpi_matrix_status.test.tsx deleted file mode 100644 index 0cd675bdd6416..0000000000000 --- a/x-pack/plugins/security_solution/public/explore/components/stat_items/use_kpi_matrix_status.test.tsx +++ /dev/null @@ -1,90 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { mount } from 'enzyme'; -import React from 'react'; -import type { StatItemsProps, StatItems } from '.'; - -import { fieldsMapping as fieldTitleChartMapping } from '../../network/components/kpi_network/unique_private_ips'; -import { - mockData, - mockEnableChartsData, - mockNoChartMappings, - mockUpdateDateRange, -} from '../../network/components/kpi_network/mock'; - -import type { - HostsKpiStrategyResponse, - NetworkKpiStrategyResponse, -} from '../../../../common/search_strategy'; -import { useKpiMatrixStatus } from './use_kpi_matrix_status'; -const mockSetQuerySkip = jest.fn(); -const from = '2019-06-15T06:00:00.000Z'; -const to = '2019-06-18T06:00:00.000Z'; - -describe('useKpiMatrixStatus', () => { - const mockNetworkMappings = fieldTitleChartMapping; - const MockChildComponent = (mappedStatItemProps: StatItemsProps) => ; - const MockHookWrapperComponent = ({ - fieldsMapping, - data, - }: { - fieldsMapping: Readonly; - data: NetworkKpiStrategyResponse | HostsKpiStrategyResponse; - }) => { - const statItemsProps: StatItemsProps[] = useKpiMatrixStatus( - fieldsMapping, - data, - 'statItem', - from, - to, - mockUpdateDateRange, - mockSetQuerySkip, - false - ); - - return ( -
- {statItemsProps.map((mappedStatItemProps) => { - return ; - })} -
- ); - }; - - test('it updates status correctly', () => { - const wrapper = mount( - <> - - - ); - const result = { ...wrapper.find('MockChildComponent').get(0).props }; - const { setQuerySkip, ...restResult } = result; - const { setQuerySkip: a, ...restExpect } = mockEnableChartsData; - expect(restResult).toEqual(restExpect); - }); - - test('it should not append areaChart if enableAreaChart is off', () => { - const wrapper = mount( - <> - - - ); - - expect(wrapper.find('MockChildComponent').get(0).props.areaChart).toBeUndefined(); - }); - - test('it should not append barChart if enableBarChart is off', () => { - const wrapper = mount( - <> - - - ); - - expect(wrapper.find('MockChildComponent').get(0).props.barChart).toBeUndefined(); - }); -}); diff --git a/x-pack/plugins/security_solution/public/explore/components/stat_items/use_kpi_matrix_status.ts b/x-pack/plugins/security_solution/public/explore/components/stat_items/use_kpi_matrix_status.ts deleted file mode 100644 index 9ddeed04b0786..0000000000000 --- a/x-pack/plugins/security_solution/public/explore/components/stat_items/use_kpi_matrix_status.ts +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ -import type { - HostsKpiStrategyResponse, - NetworkKpiStrategyResponse, - UsersKpiStrategyResponse, -} from '../../../../common/search_strategy'; -import type { UpdateDateRange } from '../../../common/components/charts/common'; -import type { StatItems, StatItemsProps } from './types'; -import { addValueToAreaChart, addValueToBarChart, addValueToFields } from './utils'; - -export const useKpiMatrixStatus = ( - mappings: Readonly, - data: HostsKpiStrategyResponse | NetworkKpiStrategyResponse | UsersKpiStrategyResponse, - id: string, - from: string, - to: string, - updateDateRange: UpdateDateRange, - setQuerySkip: (skip: boolean) => void, - loading: boolean -): StatItemsProps[] => - mappings.map((stat) => ({ - ...stat, - areaChart: stat.enableAreaChart ? addValueToAreaChart(stat.fields, data) : undefined, - barChart: stat.enableBarChart ? addValueToBarChart(stat.fields, data) : undefined, - fields: addValueToFields(stat.fields, data), - id, - key: `kpi-summary-${stat.key}`, - statKey: `${stat.key}`, - from, - to, - updateDateRange, - setQuerySkip, - loading, - })); diff --git a/x-pack/plugins/security_solution/public/explore/components/stat_items/use_toggle_status.ts b/x-pack/plugins/security_solution/public/explore/components/stat_items/use_toggle_status.ts index 900a97d99c09e..224229f94939e 100644 --- a/x-pack/plugins/security_solution/public/explore/components/stat_items/use_toggle_status.ts +++ b/x-pack/plugins/security_solution/public/explore/components/stat_items/use_toggle_status.ts @@ -7,24 +7,13 @@ import { useCallback } from 'react'; import { useQueryToggle } from '../../../common/containers/query_toggle'; -export const useToggleStatus = ({ - id, - setQuerySkip, -}: { - id: string; - setQuerySkip: (skip: boolean) => void; -}) => { +export const useToggleStatus = ({ id }: { id: string }) => { const { toggleStatus, setToggleStatus } = useQueryToggle(id); - const toggleQuery = useCallback( - (status: boolean) => { - setToggleStatus(status); - // toggleStatus on = skipQuery false - setQuerySkip(!status); - }, - [setQuerySkip, setToggleStatus] + const onToggle = useCallback( + () => setToggleStatus(!toggleStatus), + [setToggleStatus, toggleStatus] ); - const onToggle = useCallback(() => toggleQuery(!toggleStatus), [toggleQuery, toggleStatus]); return { isToggleExpanded: toggleStatus, diff --git a/x-pack/plugins/security_solution/public/explore/components/stat_items/utils.test.tsx b/x-pack/plugins/security_solution/public/explore/components/stat_items/utils.test.tsx deleted file mode 100644 index afab433b2bf66..0000000000000 --- a/x-pack/plugins/security_solution/public/explore/components/stat_items/utils.test.tsx +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { addValueToFields, addValueToAreaChart, addValueToBarChart } from './utils'; -import { fieldsMapping as fieldTitleChartMapping } from '../../network/components/kpi_network/unique_private_ips'; - -import { mockData, mockEnableChartsData } from '../../network/components/kpi_network/mock'; - -describe('addValueToFields', () => { - const mockNetworkMappings = fieldTitleChartMapping[0]; - test('should update value from data', () => { - const result = addValueToFields(mockNetworkMappings.fields, mockData); - expect(result).toEqual(mockEnableChartsData.fields); - }); -}); - -describe('addValueToAreaChart', () => { - const mockNetworkMappings = fieldTitleChartMapping[0]; - test('should add areaChart from data', () => { - const result = addValueToAreaChart(mockNetworkMappings.fields, mockData); - expect(result).toEqual(mockEnableChartsData.areaChart); - }); -}); - -describe('addValueToBarChart', () => { - const mockNetworkMappings = fieldTitleChartMapping[0]; - test('should add areaChart from data', () => { - const result = addValueToBarChart(mockNetworkMappings.fields, mockData); - expect(result).toEqual(mockEnableChartsData.barChart); - }); -}); diff --git a/x-pack/plugins/security_solution/public/explore/components/stat_items/utils.tsx b/x-pack/plugins/security_solution/public/explore/components/stat_items/utils.tsx index c345c46935000..f0393cf5cc71c 100644 --- a/x-pack/plugins/security_solution/public/explore/components/stat_items/utils.tsx +++ b/x-pack/plugins/security_solution/public/explore/components/stat_items/utils.tsx @@ -5,20 +5,9 @@ * 2.0. */ -import type { BrushEndListener, ElementClickListener, Rotation } from '@elastic/charts'; -import { ScaleType } from '@elastic/charts'; import styled from 'styled-components'; -import { get, getOr } from 'lodash/fp'; import { EuiFlexGroup, EuiFlexItem, EuiTitle } from '@elastic/eui'; -import type { - HostsKpiStrategyResponse, - NetworkKpiStrategyResponse, - UsersKpiStrategyResponse, -} from '../../../../common/search_strategy'; -import type { ChartSeriesData, ChartData } from '../../../common/components/charts/common'; - -import type { StatItem } from './types'; export const ChartHeight = 120; @@ -54,87 +43,3 @@ StatValue.displayName = 'StatValue'; export const StyledTitle = styled.h6` line-height: 200%; `; - -export const numberFormatter = (value: string | number): string => value.toLocaleString(); -export const statItemBarchartRotation: Rotation = 90; -export const statItemChartCustomHeight = 74; - -export const areachartConfigs = (config?: { - xTickFormatter: (value: number) => string; - onBrushEnd?: BrushEndListener; -}) => ({ - series: { - xScaleType: ScaleType.Time, - yScaleType: ScaleType.Linear, - }, - axis: { - xTickFormatter: get('xTickFormatter', config), - yTickFormatter: numberFormatter, - }, - settings: { - onBrushEnd: getOr(() => {}, 'onBrushEnd', config), - }, - customHeight: statItemChartCustomHeight, -}); - -export const barchartConfigs = (config?: { onElementClick?: ElementClickListener }) => ({ - series: { - xScaleType: ScaleType.Ordinal, - yScaleType: ScaleType.Linear, - stackAccessors: ['y0'], - }, - axis: { - xTickFormatter: numberFormatter, - }, - settings: { - onElementClick: getOr(() => {}, 'onElementClick', config), - rotation: statItemBarchartRotation, - }, - customHeight: statItemChartCustomHeight, -}); - -export const addValueToFields = ( - fields: StatItem[], - data: HostsKpiStrategyResponse | NetworkKpiStrategyResponse | UsersKpiStrategyResponse -): StatItem[] => fields.map((field) => ({ ...field, value: get(field.key, data) })); - -export const addValueToAreaChart = ( - fields: StatItem[], - data: HostsKpiStrategyResponse | NetworkKpiStrategyResponse | UsersKpiStrategyResponse -): ChartSeriesData[] => - fields - .filter((field) => get(`${field.key}Histogram`, data) != null) - .map(({ lensAttributes, ...field }) => ({ - ...field, - value: get(`${field.key}Histogram`, data), - key: `${field.key}Histogram`, - })); - -export const addValueToBarChart = ( - fields: StatItem[], - data: HostsKpiStrategyResponse | NetworkKpiStrategyResponse | UsersKpiStrategyResponse -): ChartSeriesData[] => { - if (fields.length === 0) return []; - return fields.reduce((acc: ChartSeriesData[], field: StatItem, idx: number) => { - const { key, color } = field; - const y: number | null = getOr(null, key, data); - const x: string = get(`${idx}.name`, fields) || getOr('', `${idx}.description`, fields); - const value: [ChartData] = [ - { - x, - y, - g: key, - y0: 0, - }, - ]; - - return [ - ...acc, - { - key, - color, - value, - }, - ]; - }, []); -}; diff --git a/x-pack/plugins/security_solution/public/explore/hosts/components/kpi_hosts/common/index.tsx b/x-pack/plugins/security_solution/public/explore/hosts/components/kpi_hosts/common/index.tsx deleted file mode 100644 index 7413563e0c950..0000000000000 --- a/x-pack/plugins/security_solution/public/explore/hosts/components/kpi_hosts/common/index.tsx +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import React from 'react'; -import { EuiFlexGroup } from '@elastic/eui'; -import styled from 'styled-components'; -import deepEqual from 'fast-deep-equal'; - -import { manageQuery } from '../../../../../common/components/page/manage_query'; -import type { - HostsKpiStrategyResponse, - NetworkKpiStrategyResponse, -} from '../../../../../../common/search_strategy'; -import type { StatItemsProps, StatItems } from '../../../../components/stat_items'; -import { StatItemsComponent, useKpiMatrixStatus } from '../../../../components/stat_items'; -import type { UpdateDateRange } from '../../../../../common/components/charts/common'; -import type { UsersKpiStrategyResponse } from '../../../../../../common/search_strategy/security_solution/users'; - -const kpiWidgetHeight = 247; - -export const FlexGroup = styled(EuiFlexGroup)` - min-height: ${kpiWidgetHeight}px; -`; - -FlexGroup.displayName = 'FlexGroup'; - -interface KpiBaseComponentProps { - fieldsMapping: Readonly; - data: HostsKpiStrategyResponse | NetworkKpiStrategyResponse | UsersKpiStrategyResponse; - loading?: boolean; - id: string; - from: string; - to: string; - updateDateRange: UpdateDateRange; - setQuerySkip: (skip: boolean) => void; -} - -export const KpiBaseComponent = React.memo( - ({ fieldsMapping, data, id, loading = false, from, to, updateDateRange, setQuerySkip }) => { - const statItemsProps: StatItemsProps[] = useKpiMatrixStatus( - fieldsMapping, - data, - id, - from, - to, - updateDateRange, - setQuerySkip, - loading - ); - - return ( - - {statItemsProps.map((mappedStatItemProps) => ( - - ))} - - ); - }, - (prevProps, nextProps) => - prevProps.fieldsMapping === nextProps.fieldsMapping && - prevProps.id === nextProps.id && - prevProps.loading === nextProps.loading && - prevProps.from === nextProps.from && - prevProps.to === nextProps.to && - prevProps.updateDateRange === nextProps.updateDateRange && - deepEqual(prevProps.data, nextProps.data) -); - -KpiBaseComponent.displayName = 'KpiBaseComponent'; - -export const KpiBaseComponentManage = manageQuery(KpiBaseComponent); diff --git a/x-pack/plugins/security_solution/public/explore/hosts/components/kpi_hosts/hosts/index.test.tsx b/x-pack/plugins/security_solution/public/explore/hosts/components/kpi_hosts/hosts/index.test.tsx index fb592f3910fb6..6044ee0de6d54 100644 --- a/x-pack/plugins/security_solution/public/explore/hosts/components/kpi_hosts/hosts/index.test.tsx +++ b/x-pack/plugins/security_solution/public/explore/hosts/components/kpi_hosts/hosts/index.test.tsx @@ -5,107 +5,29 @@ * 2.0. */ -import { useHostsKpiHosts } from '../../../containers/kpi_hosts/hosts'; -import { useQueryToggle } from '../../../../../common/containers/query_toggle'; import { render } from '@testing-library/react'; import { TestProviders } from '../../../../../common/mock'; import React from 'react'; -import { HostsKpiHosts } from '.'; -import { useIsExperimentalFeatureEnabled } from '../../../../../common/hooks/use_experimental_features'; -import { useRefetchByRestartingSession } from '../../../../../common/components/page/use_refetch_by_session'; -import { KpiBaseComponentManage } from '../common'; +import { hostsStatItems, HostsKpiHosts } from '.'; +import { KpiBaseComponent } from '../../../../components/kpi'; -jest.mock('../../../../../common/containers/query_toggle'); -jest.mock('../../../containers/kpi_hosts/hosts'); -jest.mock('../common', () => ({ - KpiBaseComponentManage: jest - .fn() - .mockReturnValue(), -})); -jest.mock('../../../../../common/hooks/use_experimental_features', () => ({ - useIsExperimentalFeatureEnabled: jest.fn(), -})); -jest.mock('../../../../../common/components/page/use_refetch_by_session', () => ({ - useRefetchByRestartingSession: jest.fn(), -})); +jest.mock('../../../../components/kpi'); + +describe('Hosts KPI', () => { + const from = new Date('2023-12-30').toISOString(); + const to = new Date('2023-12-31').toISOString(); + const MockKpiBaseComponent = KpiBaseComponent as unknown as jest.Mock; -describe('KPI Hosts', () => { - const mockUseHostsKpiHosts = useHostsKpiHosts as jest.Mock; - const mockUseQueryToggle = useQueryToggle as jest.Mock; - const MockKpiBaseComponentManage = KpiBaseComponentManage as jest.Mock; - const mockRefetchByRestartingSession = jest.fn(); - const mockRefetch = jest.fn(); - const mockSession = { current: { start: jest.fn(() => 'mockNewSearchSessionId') } }; - const defaultProps = { - from: '2019-06-25T04:31:59.345Z', - to: '2019-06-25T06:31:59.345Z', - indexNames: [], - updateDateRange: jest.fn(), - setQuery: jest.fn(), - skip: false, - }; - beforeEach(() => { - mockUseQueryToggle.mockReturnValue({ toggleStatus: true, setToggleStatus: jest.fn() }); - mockUseHostsKpiHosts.mockReturnValue([ - false, - { - id: '123', - inspect: { - dsl: [], - response: [], - }, - refetch: mockRefetch, - }, - ]); - (useIsExperimentalFeatureEnabled as jest.Mock).mockReturnValue(false); - (useRefetchByRestartingSession as jest.Mock).mockReturnValue({ - session: mockSession, - searchSessionId: 'mockSearchSessionId', - refetchByRestartingSession: mockRefetchByRestartingSession, - }); - }); afterEach(() => { jest.clearAllMocks(); }); - it('toggleStatus=true, do not skip', () => { - render( - - - - ); - expect(mockUseHostsKpiHosts.mock.calls[0][0].skip).toEqual(false); - }); - it('toggleStatus=false, skip', () => { - mockUseQueryToggle.mockReturnValue({ toggleStatus: false, setToggleStatus: jest.fn() }); - render( - - - - ); - expect(mockUseHostsKpiHosts.mock.calls[0][0].skip).toEqual(true); - }); - it('Refetches data', () => { - mockUseQueryToggle.mockReturnValue({ toggleStatus: false, setToggleStatus: jest.fn() }); - render( - - - - ); - expect(MockKpiBaseComponentManage.mock.calls[0][0].refetch).toEqual(mockRefetch); - expect(MockKpiBaseComponentManage.mock.calls[0][0].session).toBeUndefined(); - }); - it('Refetch by restarting search session ID if isChartEmbeddablesEnabled = true', () => { - (useIsExperimentalFeatureEnabled as jest.Mock).mockReturnValue(true); - render( - - - - ); - - expect(MockKpiBaseComponentManage.mock.calls[0][0].refetch).toEqual( - mockRefetchByRestartingSession - ); - expect(MockKpiBaseComponentManage.mock.calls[0][0].session).toEqual(mockSession); + it('renders correctly', () => { + render(, { + wrapper: TestProviders, + }); + expect(MockKpiBaseComponent.mock.calls[0][0].statItems).toEqual(hostsStatItems); + expect(MockKpiBaseComponent.mock.calls[0][0].from).toEqual(from); + expect(MockKpiBaseComponent.mock.calls[0][0].to).toEqual(to); }); }); diff --git a/x-pack/plugins/security_solution/public/explore/hosts/components/kpi_hosts/hosts/index.tsx b/x-pack/plugins/security_solution/public/explore/hosts/components/kpi_hosts/hosts/index.tsx index 476aedd473586..04ceab7438059 100644 --- a/x-pack/plugins/security_solution/public/explore/hosts/components/kpi_hosts/hosts/index.tsx +++ b/x-pack/plugins/security_solution/public/explore/hosts/components/kpi_hosts/hosts/index.tsx @@ -5,28 +5,24 @@ * 2.0. */ -import React, { useEffect, useState } from 'react'; +import React from 'react'; import type { StatItems } from '../../../../components/stat_items'; import { kpiHostAreaLensAttributes } from '../../../../../common/components/visualization_actions/lens_attributes/hosts/kpi_host_area'; import { kpiHostMetricLensAttributes } from '../../../../../common/components/visualization_actions/lens_attributes/hosts/kpi_host_metric'; -import { useHostsKpiHosts, ID } from '../../../containers/kpi_hosts/hosts'; -import { KpiBaseComponentManage } from '../common'; +import { KpiBaseComponent } from '../../../../components/kpi'; import type { HostsKpiProps } from '../types'; import { HostsKpiChartColors } from '../types'; import * as i18n from './translations'; -import { useQueryToggle } from '../../../../../common/containers/query_toggle'; -import { useIsExperimentalFeatureEnabled } from '../../../../../common/hooks/use_experimental_features'; -import { InputsModelId } from '../../../../../common/store/inputs/constants'; -import { useRefetchByRestartingSession } from '../../../../../common/components/page/use_refetch_by_session'; -export const fieldsMapping: Readonly = [ +export const ID = 'hostsKpiHostsQuery'; + +export const hostsStatItems: Readonly = [ { key: 'hosts', fields: [ { key: 'hosts', - value: null, color: HostsKpiChartColors.hosts, icon: 'storage', lensAttributes: kpiHostMetricLensAttributes, @@ -38,52 +34,8 @@ export const fieldsMapping: Readonly = [ }, ]; -const HostsKpiHostsComponent: React.FC = ({ - filterQuery, - from, - indexNames, - to, - updateDateRange, - setQuery, - skip, -}) => { - const { toggleStatus } = useQueryToggle(ID); - const [querySkip, setQuerySkip] = useState(skip || !toggleStatus); - const isChartEmbeddablesEnabled = useIsExperimentalFeatureEnabled('chartEmbeddablesEnabled'); - - useEffect(() => { - setQuerySkip(skip || !toggleStatus); - }, [skip, toggleStatus]); - - const [loading, { refetch, id, inspect, ...data }] = useHostsKpiHosts({ - filterQuery, - endDate: to, - indexNames, - startDate: from, - skip: querySkip || isChartEmbeddablesEnabled, - }); - - const { session, refetchByRestartingSession } = useRefetchByRestartingSession({ - inputId: InputsModelId.global, - queryId: id, - }); - - return ( - - ); +const HostsKpiHostsComponent: React.FC = ({ from, to }) => { + return ; }; export const HostsKpiHosts = React.memo(HostsKpiHostsComponent); diff --git a/x-pack/plugins/security_solution/public/explore/hosts/components/kpi_hosts/index.tsx b/x-pack/plugins/security_solution/public/explore/hosts/components/kpi_hosts/index.tsx index 8c315de005691..556c71421b896 100644 --- a/x-pack/plugins/security_solution/public/explore/hosts/components/kpi_hosts/index.tsx +++ b/x-pack/plugins/security_solution/public/explore/hosts/components/kpi_hosts/index.tsx @@ -12,55 +12,15 @@ import { HostsKpiHosts } from './hosts'; import { HostsKpiUniqueIps } from './unique_ips'; import type { HostsKpiProps } from './types'; -export const HostsKpiComponent = React.memo( - ({ filterQuery, from, indexNames, to, setQuery, skip, updateDateRange }) => ( - - - - - - - - - ) -); +export const HostsKpiComponent = React.memo(({ from, to }) => ( + + + + + + + + +)); HostsKpiComponent.displayName = 'HostsKpiComponent'; - -export const HostsDetailsKpiComponent = React.memo( - ({ filterQuery, from, indexNames, to, setQuery, skip, updateDateRange }) => { - return ( - - - - - - ); - } -); - -HostsDetailsKpiComponent.displayName = 'HostsDetailsKpiComponent'; diff --git a/x-pack/plugins/security_solution/public/explore/hosts/components/kpi_hosts/types.ts b/x-pack/plugins/security_solution/public/explore/hosts/components/kpi_hosts/types.ts index 40e638bd645ce..b58367832f850 100644 --- a/x-pack/plugins/security_solution/public/explore/hosts/components/kpi_hosts/types.ts +++ b/x-pack/plugins/security_solution/public/explore/hosts/components/kpi_hosts/types.ts @@ -5,17 +5,9 @@ * 2.0. */ -import type { UpdateDateRange } from '../../../../common/components/charts/common'; -import type { GlobalTimeArgs } from '../../../../common/containers/use_global_time'; - export interface HostsKpiProps { - filterQuery?: string; from: string; to: string; - indexNames: string[]; - updateDateRange: UpdateDateRange; - setQuery: GlobalTimeArgs['setQuery']; - skip: boolean; } export enum HostsKpiChartColors { diff --git a/x-pack/plugins/security_solution/public/explore/hosts/components/kpi_hosts/unique_ips/index.test.tsx b/x-pack/plugins/security_solution/public/explore/hosts/components/kpi_hosts/unique_ips/index.test.tsx index 67d9aa0366c4f..2fbb35328286d 100644 --- a/x-pack/plugins/security_solution/public/explore/hosts/components/kpi_hosts/unique_ips/index.test.tsx +++ b/x-pack/plugins/security_solution/public/explore/hosts/components/kpi_hosts/unique_ips/index.test.tsx @@ -5,107 +5,29 @@ * 2.0. */ -import { useHostsKpiUniqueIps } from '../../../containers/kpi_hosts/unique_ips'; -import { useQueryToggle } from '../../../../../common/containers/query_toggle'; import { render } from '@testing-library/react'; import { TestProviders } from '../../../../../common/mock'; import React from 'react'; -import { HostsKpiUniqueIps } from '.'; -import { useIsExperimentalFeatureEnabled } from '../../../../../common/hooks/use_experimental_features'; -import { useRefetchByRestartingSession } from '../../../../../common/components/page/use_refetch_by_session'; -import { KpiBaseComponentManage } from '../common'; +import { uniqueIpsStatItems, HostsKpiUniqueIps } from '.'; +import { KpiBaseComponent } from '../../../../components/kpi'; -jest.mock('../../../../../common/containers/query_toggle'); -jest.mock('../../../containers/kpi_hosts/unique_ips'); -jest.mock('../common', () => ({ - KpiBaseComponentManage: jest - .fn() - .mockReturnValue(), -})); -jest.mock('../../../../../common/hooks/use_experimental_features', () => ({ - useIsExperimentalFeatureEnabled: jest.fn(), -})); -jest.mock('../../../../../common/components/page/use_refetch_by_session', () => ({ - useRefetchByRestartingSession: jest.fn(), -})); +jest.mock('../../../../components/kpi'); + +describe('Hosts KPI', () => { + const from = new Date('2023-12-30').toISOString(); + const to = new Date('2023-12-31').toISOString(); + const MockKpiBaseComponent = KpiBaseComponent as unknown as jest.Mock; -describe('KPI Unique IPs', () => { - const mockUseHostsKpiUniqueIps = useHostsKpiUniqueIps as jest.Mock; - const mockUseQueryToggle = useQueryToggle as jest.Mock; - const MockKpiBaseComponentManage = KpiBaseComponentManage as jest.Mock; - const mockRefetchByRestartingSession = jest.fn(); - const mockSession = { current: { start: jest.fn(() => 'mockNewSearchSessionId') } }; - const mockRefetch = jest.fn(); - const defaultProps = { - from: '2019-06-25T04:31:59.345Z', - to: '2019-06-25T06:31:59.345Z', - indexNames: [], - updateDateRange: jest.fn(), - setQuery: jest.fn(), - skip: false, - }; - beforeEach(() => { - mockUseQueryToggle.mockReturnValue({ toggleStatus: true, setToggleStatus: jest.fn() }); - mockUseHostsKpiUniqueIps.mockReturnValue([ - false, - { - id: '123', - inspect: { - dsl: [], - response: [], - }, - refetch: mockRefetch, - }, - ]); - (useIsExperimentalFeatureEnabled as jest.Mock).mockReturnValue(false); - (useRefetchByRestartingSession as jest.Mock).mockReturnValue({ - session: mockSession, - searchSessionId: 'mockSearchSessionId', - refetchByRestartingSession: mockRefetchByRestartingSession, - }); - }); afterEach(() => { jest.clearAllMocks(); }); - it('toggleStatus=true, do not skip', () => { - render( - - - - ); - expect(mockUseHostsKpiUniqueIps.mock.calls[0][0].skip).toEqual(false); - }); - it('toggleStatus=false, skip', () => { - mockUseQueryToggle.mockReturnValue({ toggleStatus: false, setToggleStatus: jest.fn() }); - render( - - - - ); - expect(mockUseHostsKpiUniqueIps.mock.calls[0][0].skip).toEqual(true); - }); - it('Refetches data', () => { - mockUseQueryToggle.mockReturnValue({ toggleStatus: false, setToggleStatus: jest.fn() }); - render( - - - - ); - expect(MockKpiBaseComponentManage.mock.calls[0][0].refetch).toEqual(mockRefetch); - expect(MockKpiBaseComponentManage.mock.calls[0][0].session).toBeUndefined(); - }); - it('Refetch by restarting search session ID if isChartEmbeddablesEnabled = true', () => { - (useIsExperimentalFeatureEnabled as jest.Mock).mockReturnValue(true); - render( - - - - ); - - expect(MockKpiBaseComponentManage.mock.calls[0][0].refetch).toEqual( - mockRefetchByRestartingSession - ); - expect(MockKpiBaseComponentManage.mock.calls[0][0].session).toEqual(mockSession); + it('renders correctly', () => { + render(, { + wrapper: TestProviders, + }); + expect(MockKpiBaseComponent.mock.calls[0][0].statItems).toEqual(uniqueIpsStatItems); + expect(MockKpiBaseComponent.mock.calls[0][0].from).toEqual(from); + expect(MockKpiBaseComponent.mock.calls[0][0].to).toEqual(to); }); }); diff --git a/x-pack/plugins/security_solution/public/explore/hosts/components/kpi_hosts/unique_ips/index.tsx b/x-pack/plugins/security_solution/public/explore/hosts/components/kpi_hosts/unique_ips/index.tsx index a5bf77d5d1f94..41e7cb5c12413 100644 --- a/x-pack/plugins/security_solution/public/explore/hosts/components/kpi_hosts/unique_ips/index.tsx +++ b/x-pack/plugins/security_solution/public/explore/hosts/components/kpi_hosts/unique_ips/index.tsx @@ -5,24 +5,21 @@ * 2.0. */ -import React, { useEffect, useState } from 'react'; +import React from 'react'; import type { StatItems } from '../../../../components/stat_items'; import { kpiUniqueIpsAreaLensAttributes } from '../../../../../common/components/visualization_actions/lens_attributes/hosts/kpi_unique_ips_area'; import { kpiUniqueIpsBarLensAttributes } from '../../../../../common/components/visualization_actions/lens_attributes/hosts/kpi_unique_ips_bar'; import { kpiUniqueIpsDestinationMetricLensAttributes } from '../../../../../common/components/visualization_actions/lens_attributes/hosts/kpi_unique_ips_destination_metric'; import { kpiUniqueIpsSourceMetricLensAttributes } from '../../../../../common/components/visualization_actions/lens_attributes/hosts/kpi_unique_ips_source_metric'; -import { useHostsKpiUniqueIps, ID } from '../../../containers/kpi_hosts/unique_ips'; -import { KpiBaseComponentManage } from '../common'; +import { KpiBaseComponent } from '../../../../components/kpi'; import type { HostsKpiProps } from '../types'; import { HostsKpiChartColors } from '../types'; import * as i18n from './translations'; -import { useQueryToggle } from '../../../../../common/containers/query_toggle'; -import { useIsExperimentalFeatureEnabled } from '../../../../../common/hooks/use_experimental_features'; -import { InputsModelId } from '../../../../../common/store/inputs/constants'; -import { useRefetchByRestartingSession } from '../../../../../common/components/page/use_refetch_by_session'; -export const fieldsMapping: Readonly = [ +export const ID = 'hostsKpiUniqueIpsQuery'; + +export const uniqueIpsStatItems: Readonly = [ { key: 'uniqueIps', fields: [ @@ -30,7 +27,6 @@ export const fieldsMapping: Readonly = [ key: 'uniqueSourceIps', name: i18n.SOURCE_CHART_LABEL, description: i18n.SOURCE_UNIT_LABEL, - value: null, color: HostsKpiChartColors.uniqueSourceIps, icon: 'visMapCoordinate', lensAttributes: kpiUniqueIpsSourceMetricLensAttributes, @@ -39,7 +35,6 @@ export const fieldsMapping: Readonly = [ key: 'uniqueDestinationIps', name: i18n.DESTINATION_CHART_LABEL, description: i18n.DESTINATION_UNIT_LABEL, - value: null, color: HostsKpiChartColors.uniqueDestinationIps, icon: 'visMapCoordinate', lensAttributes: kpiUniqueIpsDestinationMetricLensAttributes, @@ -53,52 +48,8 @@ export const fieldsMapping: Readonly = [ }, ]; -const HostsKpiUniqueIpsComponent: React.FC = ({ - filterQuery, - from, - indexNames, - to, - updateDateRange, - setQuery, - skip, -}) => { - const { toggleStatus } = useQueryToggle(ID); - const [querySkip, setQuerySkip] = useState(skip || !toggleStatus); - const isChartEmbeddablesEnabled = useIsExperimentalFeatureEnabled('chartEmbeddablesEnabled'); - - useEffect(() => { - setQuerySkip(skip || !toggleStatus); - }, [skip, toggleStatus]); - - const [loading, { refetch, id, inspect, ...data }] = useHostsKpiUniqueIps({ - filterQuery, - endDate: to, - indexNames, - startDate: from, - skip: querySkip || isChartEmbeddablesEnabled, - }); - - const { session, refetchByRestartingSession } = useRefetchByRestartingSession({ - inputId: InputsModelId.global, - queryId: id, - }); - - return ( - - ); +const HostsKpiUniqueIpsComponent: React.FC = ({ from, to }) => { + return ; }; export const HostsKpiUniqueIps = React.memo(HostsKpiUniqueIpsComponent); diff --git a/x-pack/plugins/security_solution/public/explore/hosts/containers/kpi_hosts/hosts/index.test.tsx b/x-pack/plugins/security_solution/public/explore/hosts/containers/kpi_hosts/hosts/index.test.tsx deleted file mode 100644 index 04ddb28a8c61c..0000000000000 --- a/x-pack/plugins/security_solution/public/explore/hosts/containers/kpi_hosts/hosts/index.test.tsx +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { act, renderHook } from '@testing-library/react-hooks'; -import { TestProviders } from '../../../../../common/mock'; -import { useHostsKpiHosts } from '.'; - -describe('kpi hosts - hosts', () => { - it('skip = true will cancel any running request', () => { - const abortSpy = jest.spyOn(AbortController.prototype, 'abort'); - const localProps = { - startDate: '2020-07-07T08:20:18.966Z', - endDate: '2020-07-08T08:20:18.966Z', - indexNames: ['cool'], - skip: false, - }; - const { rerender } = renderHook(() => useHostsKpiHosts(localProps), { - wrapper: TestProviders, - }); - localProps.skip = true; - act(() => rerender()); - expect(abortSpy).toHaveBeenCalledTimes(4); - }); -}); diff --git a/x-pack/plugins/security_solution/public/explore/hosts/containers/kpi_hosts/hosts/index.tsx b/x-pack/plugins/security_solution/public/explore/hosts/containers/kpi_hosts/hosts/index.tsx deleted file mode 100644 index d84fa8665b7ab..0000000000000 --- a/x-pack/plugins/security_solution/public/explore/hosts/containers/kpi_hosts/hosts/index.tsx +++ /dev/null @@ -1,157 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import deepEqual from 'fast-deep-equal'; -import { noop } from 'lodash/fp'; -import { useCallback, useEffect, useRef, useState } from 'react'; -import { Subscription } from 'rxjs'; - -import type { KpiHostsRequestOptionsInput } from '../../../../../../common/api/search_strategy'; -import { useAppToasts } from '../../../../../common/hooks/use_app_toasts'; -import type { inputsModel } from '../../../../../common/store'; -import { createFilter } from '../../../../../common/containers/helpers'; -import { useKibana } from '../../../../../common/lib/kibana'; -import type { HostsKpiHostsStrategyResponse } from '../../../../../../common/search_strategy'; -import { HostsKpiQueries } from '../../../../../../common/search_strategy'; -import type { ESTermQuery } from '../../../../../../common/typed_json'; - -import * as i18n from './translations'; -import { getInspectResponse } from '../../../../../helpers'; -import type { InspectResponse } from '../../../../../types'; - -export const ID = 'hostsKpiHostsQuery'; - -export interface HostsKpiHostsArgs extends Omit { - id: string; - inspect: InspectResponse; - isInspected: boolean; - refetch: inputsModel.Refetch; -} - -interface UseHostsKpiHosts { - filterQuery?: ESTermQuery | string; - endDate: string; - indexNames: string[]; - skip?: boolean; - startDate: string; -} - -export const useHostsKpiHosts = ({ - filterQuery, - endDate, - indexNames, - skip = false, - startDate, -}: UseHostsKpiHosts): [boolean, HostsKpiHostsArgs] => { - const { data } = useKibana().services; - const refetch = useRef(noop); - const abortCtrl = useRef(new AbortController()); - const searchSubscription$ = useRef(new Subscription()); - const [loading, setLoading] = useState(false); - const [hostsKpiHostsRequest, setHostsKpiHostsRequest] = - useState(null); - - const [hostsKpiHostsResponse, setHostsKpiHostsResponse] = useState({ - hosts: 0, - hostsHistogram: [], - id: ID, - inspect: { - dsl: [], - response: [], - }, - isInspected: false, - refetch: refetch.current, - }); - const { addError, addWarning } = useAppToasts(); - - const hostsKpiHostsSearch = useCallback( - (request: KpiHostsRequestOptionsInput | null) => { - if (request == null || skip) { - return; - } - const asyncSearch = async () => { - abortCtrl.current = new AbortController(); - setLoading(true); - - searchSubscription$.current = data.search - .search(request, { - strategy: 'securitySolutionSearchStrategy', - abortSignal: abortCtrl.current.signal, - }) - .subscribe({ - next: (response) => { - if (!response.isPartial && !response.isRunning) { - setLoading(false); - setHostsKpiHostsResponse((prevResponse) => ({ - ...prevResponse, - hosts: response.hosts, - hostsHistogram: response.hostsHistogram, - inspect: getInspectResponse(response, prevResponse.inspect), - refetch: refetch.current, - })); - searchSubscription$.current.unsubscribe(); - } else if (response.isPartial && !response.isRunning) { - setLoading(false); - addWarning(i18n.ERROR_HOSTS_KPI_HOSTS); - searchSubscription$.current.unsubscribe(); - } - }, - error: (msg) => { - setLoading(false); - addError(msg, { - title: i18n.FAIL_HOSTS_KPI_HOSTS, - }); - searchSubscription$.current.unsubscribe(); - }, - }); - }; - searchSubscription$.current.unsubscribe(); - abortCtrl.current.abort(); - asyncSearch(); - refetch.current = asyncSearch; - }, - [data.search, addError, addWarning, skip] - ); - - useEffect(() => { - setHostsKpiHostsRequest((prevRequest) => { - const myRequest: KpiHostsRequestOptionsInput = { - ...(prevRequest ?? {}), - defaultIndex: indexNames, - factoryQueryType: HostsKpiQueries.kpiHosts, - filterQuery: createFilter(filterQuery), - timerange: { - interval: '12h', - from: startDate, - to: endDate, - }, - }; - if (!deepEqual(prevRequest, myRequest)) { - return myRequest; - } - return prevRequest; - }); - }, [indexNames, endDate, filterQuery, startDate]); - - useEffect(() => { - hostsKpiHostsSearch(hostsKpiHostsRequest); - return () => { - searchSubscription$.current.unsubscribe(); - abortCtrl.current.abort(); - }; - }, [hostsKpiHostsRequest, hostsKpiHostsSearch]); - - useEffect(() => { - if (skip) { - setLoading(false); - searchSubscription$.current.unsubscribe(); - abortCtrl.current.abort(); - } - }, [skip]); - - return [loading, hostsKpiHostsResponse]; -}; diff --git a/x-pack/plugins/security_solution/public/explore/hosts/containers/kpi_hosts/hosts/translations.ts b/x-pack/plugins/security_solution/public/explore/hosts/containers/kpi_hosts/hosts/translations.ts deleted file mode 100644 index 6ce00635da881..0000000000000 --- a/x-pack/plugins/security_solution/public/explore/hosts/containers/kpi_hosts/hosts/translations.ts +++ /dev/null @@ -1,22 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { i18n } from '@kbn/i18n'; - -export const ERROR_HOSTS_KPI_HOSTS = i18n.translate( - 'xpack.securitySolution.hostsKpiHosts.errorSearchDescription', - { - defaultMessage: `An error has occurred on hosts kpi hosts search`, - } -); - -export const FAIL_HOSTS_KPI_HOSTS = i18n.translate( - 'xpack.securitySolution.hostsKpiHosts.failSearchDescription', - { - defaultMessage: `Failed to run search on hosts kpi hosts`, - } -); diff --git a/x-pack/plugins/security_solution/public/explore/hosts/containers/kpi_hosts/unique_ips/index.test.tsx b/x-pack/plugins/security_solution/public/explore/hosts/containers/kpi_hosts/unique_ips/index.test.tsx deleted file mode 100644 index 0050bde419807..0000000000000 --- a/x-pack/plugins/security_solution/public/explore/hosts/containers/kpi_hosts/unique_ips/index.test.tsx +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { act, renderHook } from '@testing-library/react-hooks'; -import { TestProviders } from '../../../../../common/mock'; -import { useHostsKpiUniqueIps } from '.'; - -describe('kpi hosts - Unique Ips', () => { - it('skip = true will cancel any running request', () => { - const abortSpy = jest.spyOn(AbortController.prototype, 'abort'); - const localProps = { - startDate: '2020-07-07T08:20:18.966Z', - endDate: '2020-07-08T08:20:18.966Z', - indexNames: ['cool'], - skip: false, - }; - const { rerender } = renderHook(() => useHostsKpiUniqueIps(localProps), { - wrapper: TestProviders, - }); - localProps.skip = true; - act(() => rerender()); - expect(abortSpy).toHaveBeenCalledTimes(4); - }); -}); diff --git a/x-pack/plugins/security_solution/public/explore/hosts/containers/kpi_hosts/unique_ips/index.tsx b/x-pack/plugins/security_solution/public/explore/hosts/containers/kpi_hosts/unique_ips/index.tsx deleted file mode 100644 index 740282030286c..0000000000000 --- a/x-pack/plugins/security_solution/public/explore/hosts/containers/kpi_hosts/unique_ips/index.tsx +++ /dev/null @@ -1,165 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import deepEqual from 'fast-deep-equal'; -import { noop } from 'lodash/fp'; -import { useCallback, useEffect, useRef, useState } from 'react'; -import { Subscription } from 'rxjs'; - -import type { KpiUniqueIpsRequestOptionsInput } from '../../../../../../common/api/search_strategy'; -import { useAppToasts } from '../../../../../common/hooks/use_app_toasts'; -import type { inputsModel } from '../../../../../common/store'; -import { createFilter } from '../../../../../common/containers/helpers'; -import { useKibana } from '../../../../../common/lib/kibana'; -import type { HostsKpiUniqueIpsStrategyResponse } from '../../../../../../common/search_strategy'; -import { HostsKpiQueries } from '../../../../../../common/search_strategy'; -import type { ESTermQuery } from '../../../../../../common/typed_json'; - -import * as i18n from './translations'; -import { getInspectResponse } from '../../../../../helpers'; -import type { InspectResponse } from '../../../../../types'; - -export const ID = 'hostsKpiUniqueIpsQuery'; - -export interface HostsKpiUniqueIpsArgs - extends Omit { - id: string; - inspect: InspectResponse; - isInspected: boolean; - refetch: inputsModel.Refetch; -} - -interface UseHostsKpiUniqueIps { - filterQuery?: ESTermQuery | string; - endDate: string; - indexNames: string[]; - skip?: boolean; - startDate: string; -} - -export const useHostsKpiUniqueIps = ({ - filterQuery, - endDate, - indexNames, - skip = false, - startDate, -}: UseHostsKpiUniqueIps): [boolean, HostsKpiUniqueIpsArgs] => { - const { data } = useKibana().services; - const refetch = useRef(noop); - const abortCtrl = useRef(new AbortController()); - const searchSubscription$ = useRef(new Subscription()); - const [loading, setLoading] = useState(false); - - const [hostsKpiUniqueIpsRequest, setHostsKpiUniqueIpsRequest] = - useState(null); - - const [hostsKpiUniqueIpsResponse, setHostsKpiUniqueIpsResponse] = useState( - { - uniqueSourceIps: 0, - uniqueSourceIpsHistogram: [], - uniqueDestinationIps: 0, - uniqueDestinationIpsHistogram: [], - id: ID, - inspect: { - dsl: [], - response: [], - }, - isInspected: false, - refetch: refetch.current, - } - ); - const { addError, addWarning } = useAppToasts(); - - const hostsKpiUniqueIpsSearch = useCallback( - (request: KpiUniqueIpsRequestOptionsInput | null) => { - if (request == null || skip) { - return; - } - - const asyncSearch = async () => { - abortCtrl.current = new AbortController(); - setLoading(true); - searchSubscription$.current = data.search - .search(request, { - strategy: 'securitySolutionSearchStrategy', - abortSignal: abortCtrl.current.signal, - }) - .subscribe({ - next: (response) => { - if (!response.isPartial && !response.isRunning) { - setLoading(false); - setHostsKpiUniqueIpsResponse((prevResponse) => ({ - ...prevResponse, - uniqueSourceIps: response.uniqueSourceIps, - uniqueSourceIpsHistogram: response.uniqueSourceIpsHistogram, - uniqueDestinationIps: response.uniqueDestinationIps, - uniqueDestinationIpsHistogram: response.uniqueDestinationIpsHistogram, - inspect: getInspectResponse(response, prevResponse.inspect), - refetch: refetch.current, - })); - searchSubscription$.current.unsubscribe(); - } else if (response.isPartial && !response.isRunning) { - setLoading(false); - addWarning(i18n.ERROR_HOSTS_KPI_UNIQUE_IPS); - searchSubscription$.current.unsubscribe(); - } - }, - error: (msg) => { - setLoading(false); - addError(msg, { - title: i18n.FAIL_HOSTS_KPI_UNIQUE_IPS, - }); - searchSubscription$.current.unsubscribe(); - }, - }); - }; - searchSubscription$.current.unsubscribe(); - abortCtrl.current.abort(); - asyncSearch(); - refetch.current = asyncSearch; - }, - [data.search, addError, addWarning, skip] - ); - - useEffect(() => { - setHostsKpiUniqueIpsRequest((prevRequest) => { - const myRequest: KpiUniqueIpsRequestOptionsInput = { - ...(prevRequest ?? {}), - defaultIndex: indexNames, - factoryQueryType: HostsKpiQueries.kpiUniqueIps, - filterQuery: createFilter(filterQuery), - timerange: { - interval: '12h', - from: startDate, - to: endDate, - }, - }; - if (!deepEqual(prevRequest, myRequest)) { - return myRequest; - } - return prevRequest; - }); - }, [indexNames, endDate, filterQuery, skip, startDate]); - - useEffect(() => { - hostsKpiUniqueIpsSearch(hostsKpiUniqueIpsRequest); - return () => { - searchSubscription$.current.unsubscribe(); - abortCtrl.current.abort(); - }; - }, [hostsKpiUniqueIpsRequest, hostsKpiUniqueIpsSearch]); - - useEffect(() => { - if (skip) { - setLoading(false); - searchSubscription$.current.unsubscribe(); - abortCtrl.current.abort(); - } - }, [skip]); - - return [loading, hostsKpiUniqueIpsResponse]; -}; diff --git a/x-pack/plugins/security_solution/public/explore/hosts/containers/kpi_hosts/unique_ips/translations.ts b/x-pack/plugins/security_solution/public/explore/hosts/containers/kpi_hosts/unique_ips/translations.ts deleted file mode 100644 index 1d80d6dd131e9..0000000000000 --- a/x-pack/plugins/security_solution/public/explore/hosts/containers/kpi_hosts/unique_ips/translations.ts +++ /dev/null @@ -1,22 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { i18n } from '@kbn/i18n'; - -export const ERROR_HOSTS_KPI_UNIQUE_IPS = i18n.translate( - 'xpack.securitySolution.hostsKpiUniqueIps.errorSearchDescription', - { - defaultMessage: `An error has occurred on hosts kpi unique ips search`, - } -); - -export const FAIL_HOSTS_KPI_UNIQUE_IPS = i18n.translate( - 'xpack.securitySolution.hostsKpiUniqueIps.failSearchDescription', - { - defaultMessage: `Failed to run search on hosts kpi unique ips`, - } -); diff --git a/x-pack/plugins/security_solution/public/explore/hosts/pages/hosts.tsx b/x-pack/plugins/security_solution/public/explore/hosts/pages/hosts.tsx index 850a814f1503f..81165ddc9a545 100644 --- a/x-pack/plugins/security_solution/public/explore/hosts/pages/hosts.tsx +++ b/x-pack/plugins/security_solution/public/explore/hosts/pages/hosts.tsx @@ -9,7 +9,6 @@ import { EuiSpacer, EuiWindowEvent } from '@elastic/eui'; import styled from 'styled-components'; import { noop } from 'lodash/fp'; import React, { useCallback, useMemo, useRef } from 'react'; -import { useDispatch } from 'react-redux'; import { useParams } from 'react-router-dom'; import type { Filter } from '@kbn/es-query'; import { isTab } from '@kbn/timelines-plugin/public'; @@ -17,7 +16,6 @@ import { getEsQueryConfig } from '@kbn/data-plugin/common'; import { dataTableSelectors, tableDefaults, TableId } from '@kbn/securitysolution-data-table'; import { InputsModelId } from '../../../common/store/inputs/constants'; import { SecurityPageName } from '../../../app/types'; -import type { UpdateDateRange } from '../../../common/components/charts/common'; import { FiltersGlobal } from '../../../common/components/filters_global'; import { HeaderPage } from '../../../common/components/header_page'; import { LastEventTime } from '../../../common/components/last_event_time'; @@ -33,7 +31,6 @@ import { useKibana } from '../../../common/lib/kibana'; import { convertToBuildEsQuery } from '../../../common/lib/kuery'; import type { State } from '../../../common/store'; import { inputsSelectors } from '../../../common/store'; -import { setAbsoluteRangeDatePicker } from '../../../common/store/inputs/actions'; import { SpyRoute } from '../../../common/utils/route/spy_routes'; import { useMlCapabilities } from '../../../common/components/ml/hooks/use_ml_capabilities'; @@ -68,7 +65,6 @@ const StyledFullHeightContainer = styled.div` `; const HostsComponent = () => { - const dispatch = useDispatch(); const containerElement = useRef(null); const getTable = useMemo(() => dataTableSelectors.getTableByIdSelector(), []); const graphEventId = useShallowEqualSelector( @@ -109,22 +105,6 @@ const HostsComponent = () => { return globalFilters; }, [globalFilters, severitySelection, tabName]); - const updateDateRange = useCallback( - ({ x }) => { - if (!x) { - return; - } - const [min, max] = x; - dispatch( - setAbsoluteRangeDatePicker({ - id: InputsModelId.global, - from: new Date(min).toISOString(), - to: new Date(max).toISOString(), - }) - ); - }, - [dispatch] - ); const { indicesExist, indexPattern, selectedPatterns, sourcererDataView } = useSourcererDataView(); const [globalFilterQuery, kqlError] = useMemo( @@ -203,15 +183,7 @@ const HostsComponent = () => { border /> - + diff --git a/x-pack/plugins/security_solution/public/explore/hosts/pages/navigation/authentications_query_tab_body.tsx b/x-pack/plugins/security_solution/public/explore/hosts/pages/navigation/authentications_query_tab_body.tsx index 2df170cd65b15..8a3ff93ceb245 100644 --- a/x-pack/plugins/security_solution/public/explore/hosts/pages/navigation/authentications_query_tab_body.tsx +++ b/x-pack/plugins/security_solution/public/explore/hosts/pages/navigation/authentications_query_tab_body.tsx @@ -29,7 +29,6 @@ const AuthenticationsQueryTabBodyComponent: React.FC endDate={endDate} filterQuery={filterQuery} id={HISTOGRAM_QUERY_ID} - indexNames={indexNames} setQuery={setQuery} startDate={startDate} {...histogramConfigs} diff --git a/x-pack/plugins/security_solution/public/explore/hosts/pages/navigation/uncommon_process_query_tab_body.tsx b/x-pack/plugins/security_solution/public/explore/hosts/pages/navigation/uncommon_process_query_tab_body.tsx index 1a3e7f31a03fc..d5a5043b9efcf 100644 --- a/x-pack/plugins/security_solution/public/explore/hosts/pages/navigation/uncommon_process_query_tab_body.tsx +++ b/x-pack/plugins/security_solution/public/explore/hosts/pages/navigation/uncommon_process_query_tab_body.tsx @@ -61,4 +61,4 @@ export const UncommonProcessQueryTabBody = ({ ); }; -UncommonProcessQueryTabBody.dispalyName = 'UncommonProcessQueryTabBody'; +UncommonProcessQueryTabBody.displayName = 'UncommonProcessQueryTabBody'; diff --git a/x-pack/plugins/security_solution/public/explore/network/components/kpi_network/dns/index.test.tsx b/x-pack/plugins/security_solution/public/explore/network/components/kpi_network/dns/index.test.tsx index 2945d3cc5d862..213de1f2d80e2 100644 --- a/x-pack/plugins/security_solution/public/explore/network/components/kpi_network/dns/index.test.tsx +++ b/x-pack/plugins/security_solution/public/explore/network/components/kpi_network/dns/index.test.tsx @@ -5,108 +5,29 @@ * 2.0. */ -import { useNetworkKpiDns } from '../../../containers/kpi_network/dns'; -import { useQueryToggle } from '../../../../../common/containers/query_toggle'; import { render } from '@testing-library/react'; import { TestProviders } from '../../../../../common/mock'; import React from 'react'; -import { NetworkKpiDns } from '.'; -import { useIsExperimentalFeatureEnabled } from '../../../../../common/hooks/use_experimental_features'; -import { useRefetchByRestartingSession } from '../../../../../common/components/page/use_refetch_by_session'; -import { KpiBaseComponentManage } from '../../../../hosts/components/kpi_hosts/common'; +import { dnsStatItems, NetworkKpiDns } from '.'; +import { KpiBaseComponent } from '../../../../components/kpi'; -jest.mock('../../../../../common/containers/query_toggle'); -jest.mock('../../../containers/kpi_network/dns'); -jest.mock('../../../../hosts/components/kpi_hosts/common', () => ({ - KpiBaseComponentManage: jest - .fn() - .mockReturnValue(), -})); -jest.mock('../../../../../common/hooks/use_experimental_features', () => ({ - useIsExperimentalFeatureEnabled: jest.fn(), -})); -jest.mock('../../../../../common/components/page/use_refetch_by_session', () => ({ - useRefetchByRestartingSession: jest.fn(), -})); +jest.mock('../../../../components/kpi'); describe('DNS KPI', () => { - const mockUseNetworkKpiDns = useNetworkKpiDns as jest.Mock; - const mockUseQueryToggle = useQueryToggle as jest.Mock; - const MockKpiBaseComponentManage = KpiBaseComponentManage as jest.Mock; - const mockRefetchByRestartingSession = jest.fn(); - const mockSession = { current: { start: jest.fn(() => 'mockNewSearchSessionId') } }; - const mockRefetch = jest.fn(); - const defaultProps = { - from: '2019-06-25T04:31:59.345Z', - to: '2019-06-25T06:31:59.345Z', - indexNames: [], - updateDateRange: jest.fn(), - setQuery: jest.fn(), - skip: false, - }; + const from = new Date('2023-12-30').toISOString(); + const to = new Date('2023-12-31').toISOString(); + const MockKpiBaseComponent = KpiBaseComponent as unknown as jest.Mock; - beforeEach(() => { - mockUseQueryToggle.mockReturnValue({ toggleStatus: true, setToggleStatus: jest.fn() }); - mockUseNetworkKpiDns.mockReturnValue([ - false, - { - id: '123', - inspect: { - dsl: [], - response: [], - }, - refetch: mockRefetch, - }, - ]); - (useIsExperimentalFeatureEnabled as jest.Mock).mockReturnValue(false); - (useRefetchByRestartingSession as jest.Mock).mockReturnValue({ - session: mockSession, - searchSessionId: 'mockSearchSessionId', - refetchByRestartingSession: mockRefetchByRestartingSession, - }); - }); afterEach(() => { jest.clearAllMocks(); }); - it('toggleStatus=true, do not skip', () => { - render( - - - - ); - expect(mockUseNetworkKpiDns.mock.calls[0][0].skip).toEqual(false); - }); - it('toggleStatus=false, skip', () => { - mockUseQueryToggle.mockReturnValue({ toggleStatus: false, setToggleStatus: jest.fn() }); - render( - - - - ); - expect(mockUseNetworkKpiDns.mock.calls[0][0].skip).toEqual(true); - }); - it('Refetches data', () => { - mockUseQueryToggle.mockReturnValue({ toggleStatus: false, setToggleStatus: jest.fn() }); - render( - - - - ); - expect(MockKpiBaseComponentManage.mock.calls[0][0].refetch).toEqual(mockRefetch); - expect(MockKpiBaseComponentManage.mock.calls[0][0].session).toBeUndefined(); - }); - it('Refetch by restarting search session ID if isChartEmbeddablesEnabled = true', () => { - (useIsExperimentalFeatureEnabled as jest.Mock).mockReturnValue(true); - - render( - - - - ); - expect(MockKpiBaseComponentManage.mock.calls[0][0].refetch).toEqual( - mockRefetchByRestartingSession - ); - expect(MockKpiBaseComponentManage.mock.calls[0][0].session).toEqual(mockSession); + it('renders correctly', () => { + render(, { + wrapper: TestProviders, + }); + expect(MockKpiBaseComponent.mock.calls[0][0].statItems).toEqual(dnsStatItems); + expect(MockKpiBaseComponent.mock.calls[0][0].from).toEqual(from); + expect(MockKpiBaseComponent.mock.calls[0][0].to).toEqual(to); }); }); diff --git a/x-pack/plugins/security_solution/public/explore/network/components/kpi_network/dns/index.tsx b/x-pack/plugins/security_solution/public/explore/network/components/kpi_network/dns/index.tsx index 9069c0b44276b..c23f76317217e 100644 --- a/x-pack/plugins/security_solution/public/explore/network/components/kpi_network/dns/index.tsx +++ b/x-pack/plugins/security_solution/public/explore/network/components/kpi_network/dns/index.tsx @@ -5,27 +5,23 @@ * 2.0. */ -import React, { useEffect, useState } from 'react'; +import React from 'react'; import type { StatItems } from '../../../../components/stat_items'; import { kpiDnsQueriesLensAttributes } from '../../../../../common/components/visualization_actions/lens_attributes/network/kpi_dns_queries'; -import { useNetworkKpiDns, ID } from '../../../containers/kpi_network/dns'; -import { KpiBaseComponentManage } from '../../../../hosts/components/kpi_hosts/common'; +import { KpiBaseComponent } from '../../../../components/kpi'; import type { NetworkKpiProps } from '../types'; import * as i18n from './translations'; -import { useQueryToggle } from '../../../../../common/containers/query_toggle'; -import { InputsModelId } from '../../../../../common/store/inputs/constants'; -import { useIsExperimentalFeatureEnabled } from '../../../../../common/hooks/use_experimental_features'; -import { useRefetchByRestartingSession } from '../../../../../common/components/page/use_refetch_by_session'; -export const fieldsMapping: Readonly = [ +export const ID = 'networkKpiDnsQuery'; + +export const dnsStatItems: Readonly = [ { key: 'dnsQueries', fields: [ { key: 'dnsQueries', - value: null, lensAttributes: kpiDnsQueriesLensAttributes, }, ], @@ -33,52 +29,8 @@ export const fieldsMapping: Readonly = [ }, ]; -const NetworkKpiDnsComponent: React.FC = ({ - filterQuery, - from, - indexNames, - to, - updateDateRange, - setQuery, - skip, -}) => { - const { toggleStatus } = useQueryToggle(ID); - const [querySkip, setQuerySkip] = useState(skip || !toggleStatus); - const isChartEmbeddablesEnabled = useIsExperimentalFeatureEnabled('chartEmbeddablesEnabled'); - - useEffect(() => { - setQuerySkip(skip || !toggleStatus); - }, [skip, toggleStatus]); - - const [loading, { refetch, id, inspect, ...data }] = useNetworkKpiDns({ - filterQuery, - endDate: to, - indexNames, - startDate: from, - skip: querySkip || isChartEmbeddablesEnabled, - }); - - const { session, refetchByRestartingSession } = useRefetchByRestartingSession({ - inputId: InputsModelId.global, - queryId: id, - }); - - return ( - - ); +const NetworkKpiDnsComponent: React.FC = ({ from, to }) => { + return ; }; export const NetworkKpiDns = React.memo(NetworkKpiDnsComponent); diff --git a/x-pack/plugins/security_solution/public/explore/network/components/kpi_network/index.tsx b/x-pack/plugins/security_solution/public/explore/network/components/kpi_network/index.tsx index b6b87e9193dd2..811d11da94bc5 100644 --- a/x-pack/plugins/security_solution/public/explore/network/components/kpi_network/index.tsx +++ b/x-pack/plugins/security_solution/public/explore/network/components/kpi_network/index.tsx @@ -15,73 +15,31 @@ import { NetworkKpiUniqueFlows } from './unique_flows'; import { NetworkKpiUniquePrivateIps } from './unique_private_ips'; import type { NetworkKpiProps } from './types'; -export const NetworkKpiComponent = React.memo( - ({ filterQuery, from, indexNames, to, setQuery, skip, updateDateRange }) => ( - - - - - - - - - - - - - - - - - - - - - - - - - ) -); +export const NetworkKpiComponent = React.memo(({ from, to }) => ( + + + + + + + + + + + + + + + + + + + + + + + + +)); NetworkKpiComponent.displayName = 'NetworkKpiComponent'; diff --git a/x-pack/plugins/security_solution/public/explore/network/components/kpi_network/mock.ts b/x-pack/plugins/security_solution/public/explore/network/components/kpi_network/mock.ts deleted file mode 100644 index 4f77abd79dfd4..0000000000000 --- a/x-pack/plugins/security_solution/public/explore/network/components/kpi_network/mock.ts +++ /dev/null @@ -1,158 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import type { NetworkKpiStrategyResponse } from '../../../../../common/search_strategy'; -import type { StatItems } from '../../../components/stat_items'; -import { kpiUniquePrivateIpsAreaLensAttributes } from '../../../../common/components/visualization_actions/lens_attributes/network/kpi_unique_private_ips_area'; -import { kpiUniquePrivateIpsBarLensAttributes } from '../../../../common/components/visualization_actions/lens_attributes/network/kpi_unique_private_ips_bar'; -import { kpiUniquePrivateIpsDestinationMetricLensAttributes } from '../../../../common/components/visualization_actions/lens_attributes/network/kpi_unique_private_ips_destination_metric'; -import { kpiUniquePrivateIpsSourceMetricLensAttributes } from '../../../../common/components/visualization_actions/lens_attributes/network/kpi_unique_private_ips_source_metric'; - -export const mockUpdateDateRange = jest.fn(); - -export const mockData: NetworkKpiStrategyResponse = { - networkEvents: 16, - uniqueFlowId: 10277307, - uniqueSourcePrivateIps: 383, - uniqueSourcePrivateIpsHistogram: [ - { - x: new Date('2019-02-09T16:00:00.000Z').valueOf(), - y: 8, - }, - { - x: new Date('2019-02-09T19:00:00.000Z').valueOf(), - y: 0, - }, - ], - uniqueDestinationPrivateIps: 18, - uniqueDestinationPrivateIpsHistogram: [ - { - x: new Date('2019-02-09T16:00:00.000Z').valueOf(), - y: 8, - }, - { - x: new Date('2019-02-09T19:00:00.000Z').valueOf(), - y: 0, - }, - ], - dnsQueries: 278, - tlsHandshakes: 10000, -}; - -const mockMappingItems: StatItems = { - key: 'UniqueIps', - fields: [ - { - key: 'uniqueSourcePrivateIps', - value: null, - name: 'Src.', - description: 'source', - color: '#D36086', - icon: 'visMapCoordinate', - }, - { - key: 'uniqueDestinationPrivateIps', - value: null, - name: 'Dest.', - description: 'destination', - color: '#9170B8', - icon: 'visMapCoordinate', - }, - ], - description: 'Unique private IPs', - enableAreaChart: true, - enableBarChart: true, -}; - -export const mockNoChartMappings: Readonly = [ - { - ...mockMappingItems, - enableAreaChart: false, - enableBarChart: false, - }, -]; - -export const mockEnableChartsData = { - areaChart: [ - { - key: 'uniqueSourcePrivateIpsHistogram', - value: [ - { x: new Date('2019-02-09T16:00:00.000Z').valueOf(), y: 8 }, - { - x: new Date('2019-02-09T19:00:00.000Z').valueOf(), - y: 0, - }, - ], - name: 'Src.', - description: 'source', - color: '#D36086', - icon: 'visMapCoordinate', - }, - { - key: 'uniqueDestinationPrivateIpsHistogram', - value: [ - { x: new Date('2019-02-09T16:00:00.000Z').valueOf(), y: 8 }, - { x: new Date('2019-02-09T19:00:00.000Z').valueOf(), y: 0 }, - ], - name: 'Dest.', - description: 'destination', - color: '#9170B8', - icon: 'visMapCoordinate', - }, - ], - barChart: [ - { - key: 'uniqueSourcePrivateIps', - color: '#D36086', - value: [ - { - x: 'Src.', - y: 383, - g: 'uniqueSourcePrivateIps', - y0: 0, - }, - ], - }, - { - key: 'uniqueDestinationPrivateIps', - color: '#9170B8', - value: [{ x: 'Dest.', y: 18, g: 'uniqueDestinationPrivateIps', y0: 0 }], - }, - ], - description: 'Unique private IPs', - enableAreaChart: true, - enableBarChart: true, - fields: [ - { - key: 'uniqueSourcePrivateIps', - value: 383, - name: 'Src.', - description: 'source', - color: '#D36086', - icon: 'visMapCoordinate', - lensAttributes: kpiUniquePrivateIpsSourceMetricLensAttributes, - }, - { - key: 'uniqueDestinationPrivateIps', - value: 18, - name: 'Dest.', - description: 'destination', - color: '#9170B8', - icon: 'visMapCoordinate', - lensAttributes: kpiUniquePrivateIpsDestinationMetricLensAttributes, - }, - ], - from: '2019-06-15T06:00:00.000Z', - id: 'statItem', - loading: false, - statKey: 'uniqueIps', - setQuerySkip: jest.fn(), - to: '2019-06-18T06:00:00.000Z', - updateDateRange: mockUpdateDateRange, - areaChartLensAttributes: kpiUniquePrivateIpsAreaLensAttributes, - barChartLensAttributes: kpiUniquePrivateIpsBarLensAttributes, -}; diff --git a/x-pack/plugins/security_solution/public/explore/network/components/kpi_network/network_events/index.test.tsx b/x-pack/plugins/security_solution/public/explore/network/components/kpi_network/network_events/index.test.tsx index bd1bc90855894..f0757a7c07cc4 100644 --- a/x-pack/plugins/security_solution/public/explore/network/components/kpi_network/network_events/index.test.tsx +++ b/x-pack/plugins/security_solution/public/explore/network/components/kpi_network/network_events/index.test.tsx @@ -5,107 +5,29 @@ * 2.0. */ -import { useNetworkKpiNetworkEvents } from '../../../containers/kpi_network/network_events'; -import { useQueryToggle } from '../../../../../common/containers/query_toggle'; import { render } from '@testing-library/react'; import { TestProviders } from '../../../../../common/mock'; import React from 'react'; -import { NetworkKpiNetworkEvents } from '.'; -import { useIsExperimentalFeatureEnabled } from '../../../../../common/hooks/use_experimental_features'; -import { useRefetchByRestartingSession } from '../../../../../common/components/page/use_refetch_by_session'; -import { KpiBaseComponentManage } from '../../../../hosts/components/kpi_hosts/common'; +import { networkEventsStatsItems, NetworkKpiNetworkEvents } from '.'; +import { KpiBaseComponent } from '../../../../components/kpi'; -jest.mock('../../../../../common/containers/query_toggle'); -jest.mock('../../../containers/kpi_network/network_events'); -jest.mock('../../../../hosts/components/kpi_hosts/common', () => ({ - KpiBaseComponentManage: jest - .fn() - .mockReturnValue(), -})); -jest.mock('../../../../../common/hooks/use_experimental_features', () => ({ - useIsExperimentalFeatureEnabled: jest.fn(), -})); -jest.mock('../../../../../common/components/page/use_refetch_by_session', () => ({ - useRefetchByRestartingSession: jest.fn(), -})); +jest.mock('../../../../components/kpi'); + +describe('Network events KPI', () => { + const from = new Date('2023-12-30').toISOString(); + const to = new Date('2023-12-31').toISOString(); + const MockKpiBaseComponent = KpiBaseComponent as unknown as jest.Mock; -describe('Network Events KPI', () => { - const mockUseNetworkKpiNetworkEvents = useNetworkKpiNetworkEvents as jest.Mock; - const mockUseQueryToggle = useQueryToggle as jest.Mock; - const MockKpiBaseComponentManage = KpiBaseComponentManage as jest.Mock; - const mockRefetchByRestartingSession = jest.fn(); - const mockSession = { current: { start: jest.fn(() => 'mockNewSearchSessionId') } }; - const mockRefetch = jest.fn(); - const defaultProps = { - from: '2019-06-25T04:31:59.345Z', - to: '2019-06-25T06:31:59.345Z', - indexNames: [], - updateDateRange: jest.fn(), - setQuery: jest.fn(), - skip: false, - }; - beforeEach(() => { - mockUseQueryToggle.mockReturnValue({ toggleStatus: true, setToggleStatus: jest.fn() }); - mockUseNetworkKpiNetworkEvents.mockReturnValue([ - false, - { - id: '123', - inspect: { - dsl: [], - response: [], - }, - refetch: mockRefetch, - }, - ]); - (useIsExperimentalFeatureEnabled as jest.Mock).mockReturnValue(false); - (useRefetchByRestartingSession as jest.Mock).mockReturnValue({ - session: mockSession, - searchSessionId: 'mockSearchSessionId', - refetchByRestartingSession: mockRefetchByRestartingSession, - }); - }); afterEach(() => { jest.clearAllMocks(); }); - it('toggleStatus=true, do not skip', () => { - render( - - - - ); - expect(mockUseNetworkKpiNetworkEvents.mock.calls[0][0].skip).toEqual(false); - }); - it('toggleStatus=false, skip', () => { - mockUseQueryToggle.mockReturnValue({ toggleStatus: false, setToggleStatus: jest.fn() }); - render( - - - - ); - expect(mockUseNetworkKpiNetworkEvents.mock.calls[0][0].skip).toEqual(true); - }); - it('Refetches data', () => { - mockUseQueryToggle.mockReturnValue({ toggleStatus: false, setToggleStatus: jest.fn() }); - render( - - - - ); - expect(MockKpiBaseComponentManage.mock.calls[0][0].refetch).toEqual(mockRefetch); - expect(MockKpiBaseComponentManage.mock.calls[0][0].session).toBeUndefined(); - }); - it('Refetch by restarting search session ID if isChartEmbeddablesEnabled = true', () => { - (useIsExperimentalFeatureEnabled as jest.Mock).mockReturnValue(true); - render( - - - - ); - - expect(MockKpiBaseComponentManage.mock.calls[0][0].refetch).toEqual( - mockRefetchByRestartingSession - ); - expect(MockKpiBaseComponentManage.mock.calls[0][0].session).toEqual(mockSession); + it('renders correctly', () => { + render(, { + wrapper: TestProviders, + }); + expect(MockKpiBaseComponent.mock.calls[0][0].statItems).toEqual(networkEventsStatsItems); + expect(MockKpiBaseComponent.mock.calls[0][0].from).toEqual(from); + expect(MockKpiBaseComponent.mock.calls[0][0].to).toEqual(to); }); }); diff --git a/x-pack/plugins/security_solution/public/explore/network/components/kpi_network/network_events/index.tsx b/x-pack/plugins/security_solution/public/explore/network/components/kpi_network/network_events/index.tsx index 08173486c5d10..31b3396a567d3 100644 --- a/x-pack/plugins/security_solution/public/explore/network/components/kpi_network/network_events/index.tsx +++ b/x-pack/plugins/security_solution/public/explore/network/components/kpi_network/network_events/index.tsx @@ -5,30 +5,26 @@ * 2.0. */ -import React, { useEffect, useState } from 'react'; +import React from 'react'; import { euiPaletteColorBlind } from '@elastic/eui'; import type { StatItems } from '../../../../components/stat_items'; -import { ID, useNetworkKpiNetworkEvents } from '../../../containers/kpi_network/network_events'; import type { NetworkKpiProps } from '../types'; import * as i18n from './translations'; import { kpiNetworkEventsLensAttributes } from '../../../../../common/components/visualization_actions/lens_attributes/network/kpi_network_events'; -import { KpiBaseComponentManage } from '../../../../hosts/components/kpi_hosts/common'; -import { useQueryToggle } from '../../../../../common/containers/query_toggle'; -import { InputsModelId } from '../../../../../common/store/inputs/constants'; -import { useRefetchByRestartingSession } from '../../../../../common/components/page/use_refetch_by_session'; -import { useIsExperimentalFeatureEnabled } from '../../../../../common/hooks/use_experimental_features'; +import { KpiBaseComponent } from '../../../../components/kpi'; + +export const ID = 'networkKpiNetworkEventsQuery'; const euiVisColorPalette = euiPaletteColorBlind(); const euiColorVis1 = euiVisColorPalette[1]; -export const fieldsMapping: Readonly = [ +export const networkEventsStatsItems: Readonly = [ { key: 'networkEvents', fields: [ { key: 'networkEvents', - value: null, color: euiColorVis1, lensAttributes: kpiNetworkEventsLensAttributes, }, @@ -37,52 +33,8 @@ export const fieldsMapping: Readonly = [ }, ]; -const NetworkKpiNetworkEventsComponent: React.FC = ({ - filterQuery, - from, - indexNames, - to, - updateDateRange, - setQuery, - skip, -}) => { - const { toggleStatus } = useQueryToggle(ID); - const [querySkip, setQuerySkip] = useState(skip || !toggleStatus); - const isChartEmbeddablesEnabled = useIsExperimentalFeatureEnabled('chartEmbeddablesEnabled'); - - useEffect(() => { - setQuerySkip(skip || !toggleStatus); - }, [skip, toggleStatus]); - - const [loading, { refetch, id, inspect, ...data }] = useNetworkKpiNetworkEvents({ - filterQuery, - endDate: to, - indexNames, - startDate: from, - skip: querySkip || isChartEmbeddablesEnabled, - }); - - const { session, refetchByRestartingSession } = useRefetchByRestartingSession({ - inputId: InputsModelId.global, - queryId: id, - }); - - return ( - - ); +const NetworkKpiNetworkEventsComponent: React.FC = ({ from, to }) => { + return ; }; export const NetworkKpiNetworkEvents = React.memo(NetworkKpiNetworkEventsComponent); diff --git a/x-pack/plugins/security_solution/public/explore/network/components/kpi_network/tls_handshakes/index.test.tsx b/x-pack/plugins/security_solution/public/explore/network/components/kpi_network/tls_handshakes/index.test.tsx index 965be78e4675f..37fc612b08cc5 100644 --- a/x-pack/plugins/security_solution/public/explore/network/components/kpi_network/tls_handshakes/index.test.tsx +++ b/x-pack/plugins/security_solution/public/explore/network/components/kpi_network/tls_handshakes/index.test.tsx @@ -5,107 +5,29 @@ * 2.0. */ -import { useNetworkKpiTlsHandshakes } from '../../../containers/kpi_network/tls_handshakes'; -import { useQueryToggle } from '../../../../../common/containers/query_toggle'; import { render } from '@testing-library/react'; import { TestProviders } from '../../../../../common/mock'; import React from 'react'; -import { NetworkKpiTlsHandshakes } from '.'; -import { useIsExperimentalFeatureEnabled } from '../../../../../common/hooks/use_experimental_features'; -import { useRefetchByRestartingSession } from '../../../../../common/components/page/use_refetch_by_session'; -import { KpiBaseComponentManage } from '../../../../hosts/components/kpi_hosts/common'; +import { tlsStatItems, NetworkKpiTlsHandshakes } from '.'; +import { KpiBaseComponent } from '../../../../components/kpi'; -jest.mock('../../../../../common/containers/query_toggle'); -jest.mock('../../../containers/kpi_network/tls_handshakes'); -jest.mock('../../../../hosts/components/kpi_hosts/common', () => ({ - KpiBaseComponentManage: jest - .fn() - .mockReturnValue(), -})); -jest.mock('../../../../../common/hooks/use_experimental_features', () => ({ - useIsExperimentalFeatureEnabled: jest.fn(), -})); -jest.mock('../../../../../common/components/page/use_refetch_by_session', () => ({ - useRefetchByRestartingSession: jest.fn(), -})); +jest.mock('../../../../components/kpi'); + +describe('TLS handshakes KPI', () => { + const from = new Date('2023-12-30').toISOString(); + const to = new Date('2023-12-31').toISOString(); + const MockKpiBaseComponent = KpiBaseComponent as unknown as jest.Mock; -describe('TLS Handshakes KPI', () => { - const mockUseNetworkKpiTlsHandshakes = useNetworkKpiTlsHandshakes as jest.Mock; - const mockUseQueryToggle = useQueryToggle as jest.Mock; - const MockKpiBaseComponentManage = KpiBaseComponentManage as jest.Mock; - const mockRefetchByRestartingSession = jest.fn(); - const mockSession = { current: { start: jest.fn(() => 'mockNewSearchSessionId') } }; - const mockRefetch = jest.fn(); - const defaultProps = { - from: '2019-06-25T04:31:59.345Z', - to: '2019-06-25T06:31:59.345Z', - indexNames: [], - updateDateRange: jest.fn(), - setQuery: jest.fn(), - skip: false, - }; - beforeEach(() => { - mockUseQueryToggle.mockReturnValue({ toggleStatus: true, setToggleStatus: jest.fn() }); - mockUseNetworkKpiTlsHandshakes.mockReturnValue([ - false, - { - id: '123', - inspect: { - dsl: [], - response: [], - }, - refetch: mockRefetch, - }, - ]); - (useIsExperimentalFeatureEnabled as jest.Mock).mockReturnValue(false); - (useRefetchByRestartingSession as jest.Mock).mockReturnValue({ - session: mockSession, - searchSessionId: 'mockSearchSessionId', - refetchByRestartingSession: mockRefetchByRestartingSession, - }); - }); afterEach(() => { jest.clearAllMocks(); }); - it('toggleStatus=true, do not skip', () => { - render( - - - - ); - expect(mockUseNetworkKpiTlsHandshakes.mock.calls[0][0].skip).toEqual(false); - }); - it('toggleStatus=false, skip', () => { - mockUseQueryToggle.mockReturnValue({ toggleStatus: false, setToggleStatus: jest.fn() }); - render( - - - - ); - expect(mockUseNetworkKpiTlsHandshakes.mock.calls[0][0].skip).toEqual(true); - }); - it('Refetches data', () => { - mockUseQueryToggle.mockReturnValue({ toggleStatus: false, setToggleStatus: jest.fn() }); - render( - - - - ); - expect(MockKpiBaseComponentManage.mock.calls[0][0].refetch).toEqual(mockRefetch); - expect(MockKpiBaseComponentManage.mock.calls[0][0].searchSessionId).toBeUndefined(); - }); - it('Refetch by restarting search session ID if isChartEmbeddablesEnabled = true', () => { - (useIsExperimentalFeatureEnabled as jest.Mock).mockReturnValue(true); - render( - - - - ); - - expect(MockKpiBaseComponentManage.mock.calls[0][0].refetch).toEqual( - mockRefetchByRestartingSession - ); - expect(MockKpiBaseComponentManage.mock.calls[0][0].session).toEqual(mockSession); + it('renders correctly', () => { + render(, { + wrapper: TestProviders, + }); + expect(MockKpiBaseComponent.mock.calls[0][0].statItems).toEqual(tlsStatItems); + expect(MockKpiBaseComponent.mock.calls[0][0].from).toEqual(from); + expect(MockKpiBaseComponent.mock.calls[0][0].to).toEqual(to); }); }); diff --git a/x-pack/plugins/security_solution/public/explore/network/components/kpi_network/tls_handshakes/index.tsx b/x-pack/plugins/security_solution/public/explore/network/components/kpi_network/tls_handshakes/index.tsx index 08d3d401307a6..a3d99613861f2 100644 --- a/x-pack/plugins/security_solution/public/explore/network/components/kpi_network/tls_handshakes/index.tsx +++ b/x-pack/plugins/security_solution/public/explore/network/components/kpi_network/tls_handshakes/index.tsx @@ -5,26 +5,22 @@ * 2.0. */ -import React, { useEffect, useState } from 'react'; +import React from 'react'; import type { StatItems } from '../../../../components/stat_items'; import { kpiTlsHandshakesLensAttributes } from '../../../../../common/components/visualization_actions/lens_attributes/network/kpi_tls_handshakes'; -import { useNetworkKpiTlsHandshakes, ID } from '../../../containers/kpi_network/tls_handshakes'; -import { KpiBaseComponentManage } from '../../../../hosts/components/kpi_hosts/common'; +import { KpiBaseComponent } from '../../../../components/kpi'; import type { NetworkKpiProps } from '../types'; import * as i18n from './translations'; -import { useQueryToggle } from '../../../../../common/containers/query_toggle'; -import { useIsExperimentalFeatureEnabled } from '../../../../../common/hooks/use_experimental_features'; -import { InputsModelId } from '../../../../../common/store/inputs/constants'; -import { useRefetchByRestartingSession } from '../../../../../common/components/page/use_refetch_by_session'; -export const fieldsMapping: Readonly = [ +export const ID = 'networkKpiTlsHandshakesQuery'; + +export const tlsStatItems: Readonly = [ { key: 'tlsHandshakes', fields: [ { key: 'tlsHandshakes', - value: null, lensAttributes: kpiTlsHandshakesLensAttributes, }, ], @@ -32,52 +28,8 @@ export const fieldsMapping: Readonly = [ }, ]; -const NetworkKpiTlsHandshakesComponent: React.FC = ({ - filterQuery, - from, - indexNames, - to, - updateDateRange, - setQuery, - skip, -}) => { - const { toggleStatus } = useQueryToggle(ID); - const [querySkip, setQuerySkip] = useState(skip || !toggleStatus); - const isChartEmbeddablesEnabled = useIsExperimentalFeatureEnabled('chartEmbeddablesEnabled'); - - useEffect(() => { - setQuerySkip(skip || !toggleStatus); - }, [skip, toggleStatus]); - - const [loading, { refetch, id, inspect, ...data }] = useNetworkKpiTlsHandshakes({ - filterQuery, - endDate: to, - indexNames, - startDate: from, - skip: querySkip || isChartEmbeddablesEnabled, - }); - - const { session, refetchByRestartingSession } = useRefetchByRestartingSession({ - inputId: InputsModelId.global, - queryId: id, - }); - - return ( - - ); +const NetworkKpiTlsHandshakesComponent: React.FC = ({ from, to }) => { + return ; }; export const NetworkKpiTlsHandshakes = React.memo(NetworkKpiTlsHandshakesComponent); diff --git a/x-pack/plugins/security_solution/public/explore/network/components/kpi_network/types.ts b/x-pack/plugins/security_solution/public/explore/network/components/kpi_network/types.ts index 84f28481a8c56..3a67e587c1ca8 100644 --- a/x-pack/plugins/security_solution/public/explore/network/components/kpi_network/types.ts +++ b/x-pack/plugins/security_solution/public/explore/network/components/kpi_network/types.ts @@ -5,15 +5,7 @@ * 2.0. */ -import type { UpdateDateRange } from '../../../../common/components/charts/common'; -import type { GlobalTimeArgs } from '../../../../common/containers/use_global_time'; - export interface NetworkKpiProps { - filterQuery?: string; from: string; - indexNames: string[]; to: string; - updateDateRange: UpdateDateRange; - setQuery: GlobalTimeArgs['setQuery']; - skip: boolean; } diff --git a/x-pack/plugins/security_solution/public/explore/network/components/kpi_network/unique_flows/index.test.tsx b/x-pack/plugins/security_solution/public/explore/network/components/kpi_network/unique_flows/index.test.tsx index 494c7e43abd5d..755af7b7425d7 100644 --- a/x-pack/plugins/security_solution/public/explore/network/components/kpi_network/unique_flows/index.test.tsx +++ b/x-pack/plugins/security_solution/public/explore/network/components/kpi_network/unique_flows/index.test.tsx @@ -5,107 +5,29 @@ * 2.0. */ -import { useNetworkKpiUniqueFlows } from '../../../containers/kpi_network/unique_flows'; -import { useQueryToggle } from '../../../../../common/containers/query_toggle'; import { render } from '@testing-library/react'; import { TestProviders } from '../../../../../common/mock'; import React from 'react'; -import { NetworkKpiUniqueFlows } from '.'; -import { useIsExperimentalFeatureEnabled } from '../../../../../common/hooks/use_experimental_features'; -import { useRefetchByRestartingSession } from '../../../../../common/components/page/use_refetch_by_session'; -import { KpiBaseComponentManage } from '../../../../hosts/components/kpi_hosts/common'; +import { uniqueFlowsStatItems, NetworkKpiUniqueFlows } from '.'; +import { KpiBaseComponent } from '../../../../components/kpi'; -jest.mock('../../../../../common/containers/query_toggle'); -jest.mock('../../../containers/kpi_network/unique_flows'); -jest.mock('../../../../hosts/components/kpi_hosts/common', () => ({ - KpiBaseComponentManage: jest - .fn() - .mockReturnValue(), -})); -jest.mock('../../../../../common/hooks/use_experimental_features', () => ({ - useIsExperimentalFeatureEnabled: jest.fn(), -})); -jest.mock('../../../../../common/components/page/use_refetch_by_session', () => ({ - useRefetchByRestartingSession: jest.fn(), -})); +jest.mock('../../../../components/kpi'); + +describe('Network unique flow KPI', () => { + const from = new Date('2023-12-30').toISOString(); + const to = new Date('2023-12-31').toISOString(); + const MockKpiBaseComponent = KpiBaseComponent as unknown as jest.Mock; -describe('Unique Flows KPI', () => { - const mockUseNetworkKpiUniqueFlows = useNetworkKpiUniqueFlows as jest.Mock; - const mockUseQueryToggle = useQueryToggle as jest.Mock; - const MockKpiBaseComponentManage = KpiBaseComponentManage as jest.Mock; - const mockRefetchByRestartingSession = jest.fn(); - const mockSession = { current: { start: jest.fn(() => 'mockNewSearchSessionId') } }; - const mockRefetch = jest.fn(); - const defaultProps = { - from: '2019-06-25T04:31:59.345Z', - to: '2019-06-25T06:31:59.345Z', - indexNames: [], - updateDateRange: jest.fn(), - setQuery: jest.fn(), - skip: false, - }; - beforeEach(() => { - mockUseQueryToggle.mockReturnValue({ toggleStatus: true, setToggleStatus: jest.fn() }); - mockUseNetworkKpiUniqueFlows.mockReturnValue([ - false, - { - id: '123', - inspect: { - dsl: [], - response: [], - }, - refetch: mockRefetch, - }, - ]); - (useIsExperimentalFeatureEnabled as jest.Mock).mockReturnValue(false); - (useRefetchByRestartingSession as jest.Mock).mockReturnValue({ - session: mockSession, - searchSessionId: 'mockSearchSessionId', - refetchByRestartingSession: mockRefetchByRestartingSession, - }); - }); afterEach(() => { jest.clearAllMocks(); }); - it('toggleStatus=true, do not skip', () => { - render( - - - - ); - expect(mockUseNetworkKpiUniqueFlows.mock.calls[0][0].skip).toEqual(false); - }); - it('toggleStatus=false, skip', () => { - mockUseQueryToggle.mockReturnValue({ toggleStatus: false, setToggleStatus: jest.fn() }); - render( - - - - ); - expect(mockUseNetworkKpiUniqueFlows.mock.calls[0][0].skip).toEqual(true); - }); - it('Refetches data', () => { - mockUseQueryToggle.mockReturnValue({ toggleStatus: false, setToggleStatus: jest.fn() }); - render( - - - - ); - expect(MockKpiBaseComponentManage.mock.calls[0][0].refetch).toEqual(mockRefetch); - expect(MockKpiBaseComponentManage.mock.calls[0][0].searchSessionId).toBeUndefined(); - }); - it('Refetch by restarting search session ID if isChartEmbeddablesEnabled = true', () => { - (useIsExperimentalFeatureEnabled as jest.Mock).mockReturnValue(true); - render( - - - - ); - - expect(MockKpiBaseComponentManage.mock.calls[0][0].refetch).toEqual( - mockRefetchByRestartingSession - ); - expect(MockKpiBaseComponentManage.mock.calls[0][0].session).toEqual(mockSession); + it('renders correctly', () => { + render(, { + wrapper: TestProviders, + }); + expect(MockKpiBaseComponent.mock.calls[0][0].statItems).toEqual(uniqueFlowsStatItems); + expect(MockKpiBaseComponent.mock.calls[0][0].from).toEqual(from); + expect(MockKpiBaseComponent.mock.calls[0][0].to).toEqual(to); }); }); diff --git a/x-pack/plugins/security_solution/public/explore/network/components/kpi_network/unique_flows/index.tsx b/x-pack/plugins/security_solution/public/explore/network/components/kpi_network/unique_flows/index.tsx index b7b145e9681ba..89ad0d18100f8 100644 --- a/x-pack/plugins/security_solution/public/explore/network/components/kpi_network/unique_flows/index.tsx +++ b/x-pack/plugins/security_solution/public/explore/network/components/kpi_network/unique_flows/index.tsx @@ -5,26 +5,22 @@ * 2.0. */ -import React, { useState, useEffect } from 'react'; +import React from 'react'; import type { StatItems } from '../../../../components/stat_items'; import { kpiUniqueFlowIdsLensAttributes } from '../../../../../common/components/visualization_actions/lens_attributes/network/kpi_unique_flow_ids'; -import { useNetworkKpiUniqueFlows, ID } from '../../../containers/kpi_network/unique_flows'; -import { KpiBaseComponentManage } from '../../../../hosts/components/kpi_hosts/common'; +import { KpiBaseComponent } from '../../../../components/kpi'; import type { NetworkKpiProps } from '../types'; import * as i18n from './translations'; -import { useQueryToggle } from '../../../../../common/containers/query_toggle'; -import { InputsModelId } from '../../../../../common/store/inputs/constants'; -import { useRefetchByRestartingSession } from '../../../../../common/components/page/use_refetch_by_session'; -import { useIsExperimentalFeatureEnabled } from '../../../../../common/hooks/use_experimental_features'; -export const fieldsMapping: Readonly = [ +export const ID = 'networkKpiUniqueFlowsQuery'; + +export const uniqueFlowsStatItems: Readonly = [ { key: 'uniqueFlowId', fields: [ { key: 'uniqueFlowId', - value: null, lensAttributes: kpiUniqueFlowIdsLensAttributes, }, ], @@ -32,52 +28,8 @@ export const fieldsMapping: Readonly = [ }, ]; -const NetworkKpiUniqueFlowsComponent: React.FC = ({ - filterQuery, - from, - indexNames, - to, - updateDateRange, - setQuery, - skip, -}) => { - const { toggleStatus } = useQueryToggle(ID); - const [querySkip, setQuerySkip] = useState(skip || !toggleStatus); - const isChartEmbeddablesEnabled = useIsExperimentalFeatureEnabled('chartEmbeddablesEnabled'); - - useEffect(() => { - setQuerySkip(skip || !toggleStatus); - }, [skip, toggleStatus]); - - const [loading, { refetch, id, inspect, ...data }] = useNetworkKpiUniqueFlows({ - filterQuery, - endDate: to, - indexNames, - startDate: from, - skip: querySkip || isChartEmbeddablesEnabled, - }); - - const { session, refetchByRestartingSession } = useRefetchByRestartingSession({ - inputId: InputsModelId.global, - queryId: id, - }); - - return ( - - ); +const NetworkKpiUniqueFlowsComponent: React.FC = ({ from, to }) => { + return ; }; export const NetworkKpiUniqueFlows = React.memo(NetworkKpiUniqueFlowsComponent); diff --git a/x-pack/plugins/security_solution/public/explore/network/components/kpi_network/unique_private_ips/index.test.tsx b/x-pack/plugins/security_solution/public/explore/network/components/kpi_network/unique_private_ips/index.test.tsx index 7e7309c85b48c..d19ae024fdaa4 100644 --- a/x-pack/plugins/security_solution/public/explore/network/components/kpi_network/unique_private_ips/index.test.tsx +++ b/x-pack/plugins/security_solution/public/explore/network/components/kpi_network/unique_private_ips/index.test.tsx @@ -5,107 +5,29 @@ * 2.0. */ -import { useNetworkKpiUniquePrivateIps } from '../../../containers/kpi_network/unique_private_ips'; -import { useQueryToggle } from '../../../../../common/containers/query_toggle'; import { render } from '@testing-library/react'; import { TestProviders } from '../../../../../common/mock'; import React from 'react'; -import { NetworkKpiUniquePrivateIps } from '.'; -import { useIsExperimentalFeatureEnabled } from '../../../../../common/hooks/use_experimental_features'; -import { useRefetchByRestartingSession } from '../../../../../common/components/page/use_refetch_by_session'; -import { KpiBaseComponentManage } from '../../../../hosts/components/kpi_hosts/common'; +import { uniquePrivateIpsStatItems, NetworkKpiUniquePrivateIps } from '.'; +import { KpiBaseComponent } from '../../../../components/kpi'; -jest.mock('../../../../../common/containers/query_toggle'); -jest.mock('../../../containers/kpi_network/unique_private_ips'); -jest.mock('../../../../hosts/components/kpi_hosts/common', () => ({ - KpiBaseComponentManage: jest - .fn() - .mockReturnValue(), -})); -jest.mock('../../../../../common/hooks/use_experimental_features', () => ({ - useIsExperimentalFeatureEnabled: jest.fn(), -})); -jest.mock('../../../../../common/components/page/use_refetch_by_session', () => ({ - useRefetchByRestartingSession: jest.fn(), -})); +jest.mock('../../../../components/kpi'); + +describe('Network unique private ips KPI', () => { + const from = new Date('2023-12-30').toISOString(); + const to = new Date('2023-12-31').toISOString(); + const MockKpiBaseComponent = KpiBaseComponent as unknown as jest.Mock; -describe('Unique Private IPs KPI', () => { - const mockUseNetworkKpiUniquePrivateIps = useNetworkKpiUniquePrivateIps as jest.Mock; - const mockUseQueryToggle = useQueryToggle as jest.Mock; - const MockKpiBaseComponentManage = KpiBaseComponentManage as jest.Mock; - const mockRefetchByRestartingSession = jest.fn(); - const mockSession = { current: { start: jest.fn(() => 'mockNewSearchSessionId') } }; - const mockRefetch = jest.fn(); - const defaultProps = { - from: '2019-06-25T04:31:59.345Z', - to: '2019-06-25T06:31:59.345Z', - indexNames: [], - updateDateRange: jest.fn(), - setQuery: jest.fn(), - skip: false, - }; - beforeEach(() => { - mockUseQueryToggle.mockReturnValue({ toggleStatus: true, setToggleStatus: jest.fn() }); - mockUseNetworkKpiUniquePrivateIps.mockReturnValue([ - false, - { - id: '123', - inspect: { - dsl: [], - response: [], - }, - refetch: mockRefetch, - }, - ]); - (useIsExperimentalFeatureEnabled as jest.Mock).mockReturnValue(false); - (useRefetchByRestartingSession as jest.Mock).mockReturnValue({ - session: mockSession, - searchSessionId: 'mockSearchSessionId', - refetchByRestartingSession: mockRefetchByRestartingSession, - }); - }); afterEach(() => { jest.clearAllMocks(); }); - it('toggleStatus=true, do not skip', () => { - render( - - - - ); - expect(mockUseNetworkKpiUniquePrivateIps.mock.calls[0][0].skip).toEqual(false); - }); - it('toggleStatus=false, skip', () => { - mockUseQueryToggle.mockReturnValue({ toggleStatus: false, setToggleStatus: jest.fn() }); - render( - - - - ); - expect(mockUseNetworkKpiUniquePrivateIps.mock.calls[0][0].skip).toEqual(true); - }); - it('Refetches data', () => { - mockUseQueryToggle.mockReturnValue({ toggleStatus: false, setToggleStatus: jest.fn() }); - render( - - - - ); - expect(MockKpiBaseComponentManage.mock.calls[0][0].refetch).toEqual(mockRefetch); - expect(MockKpiBaseComponentManage.mock.calls[0][0].searchSessionId).toBeUndefined(); - }); - it('Refetch by restarting search session ID if isChartEmbeddablesEnabled = true', () => { - (useIsExperimentalFeatureEnabled as jest.Mock).mockReturnValue(true); - render( - - - - ); - - expect(MockKpiBaseComponentManage.mock.calls[0][0].refetch).toEqual( - mockRefetchByRestartingSession - ); - expect(MockKpiBaseComponentManage.mock.calls[0][0].session).toEqual(mockSession); + it('renders correctly', () => { + render(, { + wrapper: TestProviders, + }); + expect(MockKpiBaseComponent.mock.calls[0][0].statItems).toEqual(uniquePrivateIpsStatItems); + expect(MockKpiBaseComponent.mock.calls[0][0].from).toEqual(from); + expect(MockKpiBaseComponent.mock.calls[0][0].to).toEqual(to); }); }); diff --git a/x-pack/plugins/security_solution/public/explore/network/components/kpi_network/unique_private_ips/index.tsx b/x-pack/plugins/security_solution/public/explore/network/components/kpi_network/unique_private_ips/index.tsx index e4e9b7fc7a0b8..2c84c27899084 100644 --- a/x-pack/plugins/security_solution/public/explore/network/components/kpi_network/unique_private_ips/index.tsx +++ b/x-pack/plugins/security_solution/public/explore/network/components/kpi_network/unique_private_ips/index.tsx @@ -5,37 +5,29 @@ * 2.0. */ -import React, { useEffect, useState } from 'react'; +import React from 'react'; import { euiPaletteColorBlind } from '@elastic/eui'; import type { StatItems } from '../../../../components/stat_items'; -import { - useNetworkKpiUniquePrivateIps, - ID, -} from '../../../containers/kpi_network/unique_private_ips'; import type { NetworkKpiProps } from '../types'; import * as i18n from './translations'; import { kpiUniquePrivateIpsSourceMetricLensAttributes } from '../../../../../common/components/visualization_actions/lens_attributes/network/kpi_unique_private_ips_source_metric'; import { kpiUniquePrivateIpsDestinationMetricLensAttributes } from '../../../../../common/components/visualization_actions/lens_attributes/network/kpi_unique_private_ips_destination_metric'; import { kpiUniquePrivateIpsAreaLensAttributes } from '../../../../../common/components/visualization_actions/lens_attributes/network/kpi_unique_private_ips_area'; import { kpiUniquePrivateIpsBarLensAttributes } from '../../../../../common/components/visualization_actions/lens_attributes/network/kpi_unique_private_ips_bar'; -import { KpiBaseComponentManage } from '../../../../hosts/components/kpi_hosts/common'; -import { useQueryToggle } from '../../../../../common/containers/query_toggle'; -import { useIsExperimentalFeatureEnabled } from '../../../../../common/hooks/use_experimental_features'; -import { InputsModelId } from '../../../../../common/store/inputs/constants'; -import { useRefetchByRestartingSession } from '../../../../../common/components/page/use_refetch_by_session'; +import { KpiBaseComponent } from '../../../../components/kpi'; const euiVisColorPalette = euiPaletteColorBlind(); const euiColorVis2 = euiVisColorPalette[2]; const euiColorVis3 = euiVisColorPalette[3]; +export const ID = 'networkKpiUniquePrivateIpsQuery'; -export const fieldsMapping: Readonly = [ +export const uniquePrivateIpsStatItems: Readonly = [ { key: 'uniqueIps', fields: [ { key: 'uniqueSourcePrivateIps', - value: null, name: i18n.SOURCE_CHART_LABEL, description: i18n.SOURCE_UNIT_LABEL, color: euiColorVis2, @@ -44,7 +36,6 @@ export const fieldsMapping: Readonly = [ }, { key: 'uniqueDestinationPrivateIps', - value: null, name: i18n.DESTINATION_CHART_LABEL, description: i18n.DESTINATION_UNIT_LABEL, color: euiColorVis3, @@ -60,52 +51,8 @@ export const fieldsMapping: Readonly = [ }, ]; -const NetworkKpiUniquePrivateIpsComponent: React.FC = ({ - filterQuery, - from, - indexNames, - to, - updateDateRange, - setQuery, - skip, -}) => { - const { toggleStatus } = useQueryToggle(ID); - const [querySkip, setQuerySkip] = useState(skip || !toggleStatus); - const isChartEmbeddablesEnabled = useIsExperimentalFeatureEnabled('chartEmbeddablesEnabled'); - - useEffect(() => { - setQuerySkip(skip || !toggleStatus); - }, [skip, toggleStatus]); - - const [loading, { refetch, id, inspect, ...data }] = useNetworkKpiUniquePrivateIps({ - filterQuery, - endDate: to, - indexNames, - startDate: from, - skip: querySkip || isChartEmbeddablesEnabled, - }); - - const { session, refetchByRestartingSession } = useRefetchByRestartingSession({ - inputId: InputsModelId.global, - queryId: id, - }); - - return ( - - ); +const NetworkKpiUniquePrivateIpsComponent: React.FC = ({ from, to }) => { + return ; }; export const NetworkKpiUniquePrivateIps = React.memo(NetworkKpiUniquePrivateIpsComponent); diff --git a/x-pack/plugins/security_solution/public/explore/network/containers/kpi_network/dns/index.test.tsx b/x-pack/plugins/security_solution/public/explore/network/containers/kpi_network/dns/index.test.tsx deleted file mode 100644 index 869baa2203f82..0000000000000 --- a/x-pack/plugins/security_solution/public/explore/network/containers/kpi_network/dns/index.test.tsx +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { act, renderHook } from '@testing-library/react-hooks'; -import { TestProviders } from '../../../../../common/mock'; -import { useNetworkKpiDns } from '.'; - -describe('kpi network - dns', () => { - it('skip = true will cancel any running request', () => { - const abortSpy = jest.spyOn(AbortController.prototype, 'abort'); - const localProps = { - startDate: '2020-07-07T08:20:18.966Z', - endDate: '2020-07-08T08:20:18.966Z', - indexNames: ['cool'], - skip: false, - }; - const { rerender } = renderHook(() => useNetworkKpiDns(localProps), { - wrapper: TestProviders, - }); - localProps.skip = true; - act(() => rerender()); - expect(abortSpy).toHaveBeenCalledTimes(4); - }); -}); diff --git a/x-pack/plugins/security_solution/public/explore/network/containers/kpi_network/dns/index.tsx b/x-pack/plugins/security_solution/public/explore/network/containers/kpi_network/dns/index.tsx deleted file mode 100644 index 417c3678fb06a..0000000000000 --- a/x-pack/plugins/security_solution/public/explore/network/containers/kpi_network/dns/index.tsx +++ /dev/null @@ -1,154 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import deepEqual from 'fast-deep-equal'; -import { noop } from 'lodash/fp'; -import { useCallback, useEffect, useRef, useState } from 'react'; -import { Subscription } from 'rxjs'; - -import { isRunningResponse } from '@kbn/data-plugin/common'; -import type { NetworkKpiDnsRequestOptionsInput } from '../../../../../../common/api/search_strategy'; -import { useAppToasts } from '../../../../../common/hooks/use_app_toasts'; -import type { inputsModel } from '../../../../../common/store'; -import { createFilter } from '../../../../../common/containers/helpers'; -import { useKibana } from '../../../../../common/lib/kibana'; -import type { NetworkKpiDnsStrategyResponse } from '../../../../../../common/search_strategy'; -import { NetworkKpiQueries } from '../../../../../../common/search_strategy'; -import type { ESTermQuery } from '../../../../../../common/typed_json'; - -import * as i18n from './translations'; -import { getInspectResponse } from '../../../../../helpers'; -import type { InspectResponse } from '../../../../../types'; - -export const ID = 'networkKpiDnsQuery'; - -export interface NetworkKpiDnsArgs { - dnsQueries: number; - id: string; - inspect: InspectResponse; - isInspected: boolean; - refetch: inputsModel.Refetch; -} - -interface UseNetworkKpiDns { - filterQuery?: ESTermQuery | string; - endDate: string; - indexNames: string[]; - skip?: boolean; - startDate: string; -} - -export const useNetworkKpiDns = ({ - filterQuery, - endDate, - indexNames, - skip = false, - startDate, -}: UseNetworkKpiDns): [boolean, NetworkKpiDnsArgs] => { - const { data } = useKibana().services; - const refetch = useRef(noop); - const abortCtrl = useRef(new AbortController()); - const searchSubscription$ = useRef(new Subscription()); - const [loading, setLoading] = useState(false); - const [networkKpiDnsRequest, setNetworkKpiDnsRequest] = - useState(null); - - const [networkKpiDnsResponse, setNetworkKpiDnsResponse] = useState({ - dnsQueries: 0, - id: ID, - inspect: { - dsl: [], - response: [], - }, - isInspected: false, - refetch: refetch.current, - }); - const { addError } = useAppToasts(); - - const networkKpiDnsSearch = useCallback( - (request: NetworkKpiDnsRequestOptionsInput | null) => { - if (request == null || skip) { - return; - } - - const asyncSearch = async () => { - abortCtrl.current = new AbortController(); - setLoading(true); - - searchSubscription$.current = data.search - .search(request, { - strategy: 'securitySolutionSearchStrategy', - abortSignal: abortCtrl.current.signal, - }) - .subscribe({ - next: (response) => { - if (!isRunningResponse(response)) { - setLoading(false); - setNetworkKpiDnsResponse((prevResponse) => ({ - ...prevResponse, - dnsQueries: response.dnsQueries, - inspect: getInspectResponse(response, prevResponse.inspect), - refetch: refetch.current, - })); - searchSubscription$.current.unsubscribe(); - } - }, - error: (msg) => { - setLoading(false); - addError(msg, { - title: i18n.FAIL_NETWORK_KPI_DNS, - }); - searchSubscription$.current.unsubscribe(); - }, - }); - }; - searchSubscription$.current.unsubscribe(); - abortCtrl.current.abort(); - asyncSearch(); - refetch.current = asyncSearch; - }, - [data.search, addError, skip] - ); - - useEffect(() => { - setNetworkKpiDnsRequest((prevRequest) => { - const myRequest: NetworkKpiDnsRequestOptionsInput = { - ...(prevRequest ?? {}), - defaultIndex: indexNames, - factoryQueryType: NetworkKpiQueries.dns, - filterQuery: createFilter(filterQuery), - timerange: { - interval: '12h', - from: startDate, - to: endDate, - }, - }; - if (!deepEqual(prevRequest, myRequest)) { - return myRequest; - } - return prevRequest; - }); - }, [indexNames, endDate, filterQuery, startDate]); - - useEffect(() => { - networkKpiDnsSearch(networkKpiDnsRequest); - return () => { - searchSubscription$.current.unsubscribe(); - abortCtrl.current.abort(); - }; - }, [networkKpiDnsRequest, networkKpiDnsSearch]); - - useEffect(() => { - if (skip) { - setLoading(false); - searchSubscription$.current.unsubscribe(); - abortCtrl.current.abort(); - } - }, [skip]); - - return [loading, networkKpiDnsResponse]; -}; diff --git a/x-pack/plugins/security_solution/public/explore/network/containers/kpi_network/dns/translations.ts b/x-pack/plugins/security_solution/public/explore/network/containers/kpi_network/dns/translations.ts deleted file mode 100644 index 2ba68b0939cb7..0000000000000 --- a/x-pack/plugins/security_solution/public/explore/network/containers/kpi_network/dns/translations.ts +++ /dev/null @@ -1,22 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { i18n } from '@kbn/i18n'; - -export const ERROR_NETWORK_KPI_DNS = i18n.translate( - 'xpack.securitySolution.networkKpiDns.errorSearchDescription', - { - defaultMessage: `An error has occurred on network kpi dns search`, - } -); - -export const FAIL_NETWORK_KPI_DNS = i18n.translate( - 'xpack.securitySolution.networkKpiDns.failSearchDescription', - { - defaultMessage: `Failed to run search on network kpi dns`, - } -); diff --git a/x-pack/plugins/security_solution/public/explore/network/containers/kpi_network/network_events/index.test.tsx b/x-pack/plugins/security_solution/public/explore/network/containers/kpi_network/network_events/index.test.tsx deleted file mode 100644 index 05f193dd5f8ac..0000000000000 --- a/x-pack/plugins/security_solution/public/explore/network/containers/kpi_network/network_events/index.test.tsx +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { act, renderHook } from '@testing-library/react-hooks'; -import { TestProviders } from '../../../../../common/mock'; -import { useNetworkKpiNetworkEvents } from '.'; - -describe('kpi network - network events', () => { - it('skip = true will cancel any running request', () => { - const abortSpy = jest.spyOn(AbortController.prototype, 'abort'); - const localProps = { - startDate: '2020-07-07T08:20:18.966Z', - endDate: '2020-07-08T08:20:18.966Z', - indexNames: ['cool'], - skip: false, - }; - const { rerender } = renderHook(() => useNetworkKpiNetworkEvents(localProps), { - wrapper: TestProviders, - }); - localProps.skip = true; - act(() => rerender()); - expect(abortSpy).toHaveBeenCalledTimes(4); - }); -}); diff --git a/x-pack/plugins/security_solution/public/explore/network/containers/kpi_network/network_events/index.tsx b/x-pack/plugins/security_solution/public/explore/network/containers/kpi_network/network_events/index.tsx deleted file mode 100644 index e675196aa0a80..0000000000000 --- a/x-pack/plugins/security_solution/public/explore/network/containers/kpi_network/network_events/index.tsx +++ /dev/null @@ -1,158 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import deepEqual from 'fast-deep-equal'; -import { noop } from 'lodash/fp'; -import { useCallback, useEffect, useRef, useState } from 'react'; -import { Subscription } from 'rxjs'; - -import { isRunningResponse } from '@kbn/data-plugin/common'; -import type { NetworkKpiEventsRequestOptionsInput } from '../../../../../../common/api/search_strategy'; -import { useAppToasts } from '../../../../../common/hooks/use_app_toasts'; -import type { inputsModel } from '../../../../../common/store'; -import { createFilter } from '../../../../../common/containers/helpers'; -import { useKibana } from '../../../../../common/lib/kibana'; -import type { NetworkKpiNetworkEventsStrategyResponse } from '../../../../../../common/search_strategy'; -import { NetworkKpiQueries } from '../../../../../../common/search_strategy'; -import type { ESTermQuery } from '../../../../../../common/typed_json'; - -import * as i18n from './translations'; -import { getInspectResponse } from '../../../../../helpers'; -import type { InspectResponse } from '../../../../../types'; - -export const ID = 'networkKpiNetworkEventsQuery'; - -export interface NetworkKpiNetworkEventsArgs { - networkEvents: number; - id: string; - inspect: InspectResponse; - isInspected: boolean; - refetch: inputsModel.Refetch; -} - -interface UseNetworkKpiNetworkEvents { - filterQuery?: ESTermQuery | string; - endDate: string; - indexNames: string[]; - skip?: boolean; - startDate: string; -} - -export const useNetworkKpiNetworkEvents = ({ - filterQuery, - endDate, - indexNames, - skip = false, - startDate, -}: UseNetworkKpiNetworkEvents): [boolean, NetworkKpiNetworkEventsArgs] => { - const { data } = useKibana().services; - const refetch = useRef(noop); - const abortCtrl = useRef(new AbortController()); - const searchSubscription$ = useRef(new Subscription()); - const [loading, setLoading] = useState(false); - const [networkKpiNetworkEventsRequest, setNetworkKpiNetworkEventsRequest] = - useState(null); - - const [networkKpiNetworkEventsResponse, setNetworkKpiNetworkEventsResponse] = - useState({ - networkEvents: 0, - id: ID, - inspect: { - dsl: [], - response: [], - }, - isInspected: false, - refetch: refetch.current, - }); - const { addError } = useAppToasts(); - - const networkKpiNetworkEventsSearch = useCallback( - (request: NetworkKpiEventsRequestOptionsInput | null) => { - if (request == null || skip) { - return; - } - - const asyncSearch = async () => { - abortCtrl.current = new AbortController(); - setLoading(true); - - searchSubscription$.current = data.search - .search( - request, - { - strategy: 'securitySolutionSearchStrategy', - abortSignal: abortCtrl.current.signal, - } - ) - .subscribe({ - next: (response) => { - if (!isRunningResponse(response)) { - setLoading(false); - setNetworkKpiNetworkEventsResponse((prevResponse) => ({ - ...prevResponse, - networkEvents: response.networkEvents, - inspect: getInspectResponse(response, prevResponse.inspect), - refetch: refetch.current, - })); - searchSubscription$.current.unsubscribe(); - } - }, - error: (msg) => { - setLoading(false); - addError(msg, { - title: i18n.FAIL_NETWORK_KPI_NETWORK_EVENTS, - }); - searchSubscription$.current.unsubscribe(); - }, - }); - }; - searchSubscription$.current.unsubscribe(); - abortCtrl.current.abort(); - asyncSearch(); - refetch.current = asyncSearch; - }, - [data.search, addError, skip] - ); - - useEffect(() => { - setNetworkKpiNetworkEventsRequest((prevRequest) => { - const myRequest: NetworkKpiEventsRequestOptionsInput = { - ...(prevRequest ?? {}), - defaultIndex: indexNames, - factoryQueryType: NetworkKpiQueries.networkEvents, - filterQuery: createFilter(filterQuery), - timerange: { - interval: '12h', - from: startDate, - to: endDate, - }, - }; - if (!deepEqual(prevRequest, myRequest)) { - return myRequest; - } - return prevRequest; - }); - }, [indexNames, endDate, filterQuery, startDate]); - - useEffect(() => { - networkKpiNetworkEventsSearch(networkKpiNetworkEventsRequest); - return () => { - searchSubscription$.current.unsubscribe(); - abortCtrl.current.abort(); - }; - }, [networkKpiNetworkEventsRequest, networkKpiNetworkEventsSearch]); - - useEffect(() => { - if (skip) { - setLoading(false); - searchSubscription$.current.unsubscribe(); - abortCtrl.current.abort(); - } - }, [skip]); - - return [loading, networkKpiNetworkEventsResponse]; -}; diff --git a/x-pack/plugins/security_solution/public/explore/network/containers/kpi_network/network_events/translations.ts b/x-pack/plugins/security_solution/public/explore/network/containers/kpi_network/network_events/translations.ts deleted file mode 100644 index 5067adf3768c7..0000000000000 --- a/x-pack/plugins/security_solution/public/explore/network/containers/kpi_network/network_events/translations.ts +++ /dev/null @@ -1,22 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { i18n } from '@kbn/i18n'; - -export const ERROR_NETWORK_KPI_NETWORK_EVENTS = i18n.translate( - 'xpack.securitySolution.networkKpiNetworkEvents.errorSearchDescription', - { - defaultMessage: `An error has occurred on network kpi network events search`, - } -); - -export const FAIL_NETWORK_KPI_NETWORK_EVENTS = i18n.translate( - 'xpack.securitySolution.networkKpiNetworkEvents.failSearchDescription', - { - defaultMessage: `Failed to run search on network kpi network events`, - } -); diff --git a/x-pack/plugins/security_solution/public/explore/network/containers/kpi_network/tls_handshakes/index.test.tsx b/x-pack/plugins/security_solution/public/explore/network/containers/kpi_network/tls_handshakes/index.test.tsx deleted file mode 100644 index c7e3b8c2f3aa5..0000000000000 --- a/x-pack/plugins/security_solution/public/explore/network/containers/kpi_network/tls_handshakes/index.test.tsx +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { act, renderHook } from '@testing-library/react-hooks'; -import { TestProviders } from '../../../../../common/mock'; -import { useNetworkKpiTlsHandshakes } from '.'; - -describe('kpi network - tls handshakes', () => { - it('skip = true will cancel any running request', () => { - const abortSpy = jest.spyOn(AbortController.prototype, 'abort'); - const localProps = { - startDate: '2020-07-07T08:20:18.966Z', - endDate: '2020-07-08T08:20:18.966Z', - indexNames: ['cool'], - skip: false, - }; - const { rerender } = renderHook(() => useNetworkKpiTlsHandshakes(localProps), { - wrapper: TestProviders, - }); - localProps.skip = true; - act(() => rerender()); - expect(abortSpy).toHaveBeenCalledTimes(4); - }); -}); diff --git a/x-pack/plugins/security_solution/public/explore/network/containers/kpi_network/tls_handshakes/index.tsx b/x-pack/plugins/security_solution/public/explore/network/containers/kpi_network/tls_handshakes/index.tsx deleted file mode 100644 index a94041f640d93..0000000000000 --- a/x-pack/plugins/security_solution/public/explore/network/containers/kpi_network/tls_handshakes/index.tsx +++ /dev/null @@ -1,157 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import deepEqual from 'fast-deep-equal'; -import { noop } from 'lodash/fp'; -import { useCallback, useEffect, useRef, useState } from 'react'; -import { Subscription } from 'rxjs'; - -import { isRunningResponse } from '@kbn/data-plugin/common'; -import type { NetworkKpiTlsHandshakesRequestOptionsInput } from '../../../../../../common/api/search_strategy'; -import { useAppToasts } from '../../../../../common/hooks/use_app_toasts'; -import type { inputsModel } from '../../../../../common/store'; -import { createFilter } from '../../../../../common/containers/helpers'; -import { useKibana } from '../../../../../common/lib/kibana'; -import type { NetworkKpiTlsHandshakesStrategyResponse } from '../../../../../../common/search_strategy'; -import { NetworkKpiQueries } from '../../../../../../common/search_strategy'; -import type { ESTermQuery } from '../../../../../../common/typed_json'; - -import * as i18n from './translations'; -import { getInspectResponse } from '../../../../../helpers'; -import type { InspectResponse } from '../../../../../types'; - -export const ID = 'networkKpiTlsHandshakesQuery'; - -export interface NetworkKpiTlsHandshakesArgs { - tlsHandshakes: number; - id: string; - inspect: InspectResponse; - isInspected: boolean; - refetch: inputsModel.Refetch; -} - -interface UseNetworkKpiTlsHandshakes { - filterQuery?: ESTermQuery | string; - endDate: string; - indexNames: string[]; - skip?: boolean; - startDate: string; -} - -export const useNetworkKpiTlsHandshakes = ({ - filterQuery, - endDate, - indexNames, - skip = false, - startDate, -}: UseNetworkKpiTlsHandshakes): [boolean, NetworkKpiTlsHandshakesArgs] => { - const { data } = useKibana().services; - const refetch = useRef(noop); - const abortCtrl = useRef(new AbortController()); - const searchSubscription$ = useRef(new Subscription()); - const [loading, setLoading] = useState(false); - const [networkKpiTlsHandshakesRequest, setNetworkKpiTlsHandshakesRequest] = - useState(null); - - const [networkKpiTlsHandshakesResponse, setNetworkKpiTlsHandshakesResponse] = - useState({ - tlsHandshakes: 0, - id: ID, - inspect: { - dsl: [], - response: [], - }, - isInspected: false, - refetch: refetch.current, - }); - const { addError } = useAppToasts(); - - const networkKpiTlsHandshakesSearch = useCallback( - (request: NetworkKpiTlsHandshakesRequestOptionsInput | null) => { - if (request == null || skip) { - return; - } - const asyncSearch = async () => { - abortCtrl.current = new AbortController(); - setLoading(true); - - searchSubscription$.current = data.search - .search< - NetworkKpiTlsHandshakesRequestOptionsInput, - NetworkKpiTlsHandshakesStrategyResponse - >(request, { - strategy: 'securitySolutionSearchStrategy', - abortSignal: abortCtrl.current.signal, - }) - .subscribe({ - next: (response) => { - if (!isRunningResponse(response)) { - setLoading(false); - setNetworkKpiTlsHandshakesResponse((prevResponse) => ({ - ...prevResponse, - tlsHandshakes: response.tlsHandshakes, - inspect: getInspectResponse(response, prevResponse.inspect), - refetch: refetch.current, - })); - searchSubscription$.current.unsubscribe(); - } - }, - error: (msg) => { - setLoading(false); - addError(msg, { - title: i18n.FAIL_NETWORK_KPI_TLS_HANDSHAKES, - }); - searchSubscription$.current.unsubscribe(); - }, - }); - }; - searchSubscription$.current.unsubscribe(); - abortCtrl.current.abort(); - asyncSearch(); - refetch.current = asyncSearch; - }, - [data.search, addError, skip] - ); - - useEffect(() => { - setNetworkKpiTlsHandshakesRequest((prevRequest) => { - const myRequest: NetworkKpiTlsHandshakesRequestOptionsInput = { - ...(prevRequest ?? {}), - defaultIndex: indexNames, - factoryQueryType: NetworkKpiQueries.tlsHandshakes, - filterQuery: createFilter(filterQuery), - timerange: { - interval: '12h', - from: startDate, - to: endDate, - }, - }; - if (!deepEqual(prevRequest, myRequest)) { - return myRequest; - } - return prevRequest; - }); - }, [indexNames, endDate, filterQuery, startDate]); - - useEffect(() => { - networkKpiTlsHandshakesSearch(networkKpiTlsHandshakesRequest); - return () => { - searchSubscription$.current.unsubscribe(); - abortCtrl.current.abort(); - }; - }, [networkKpiTlsHandshakesRequest, networkKpiTlsHandshakesSearch]); - - useEffect(() => { - if (skip) { - setLoading(false); - searchSubscription$.current.unsubscribe(); - abortCtrl.current.abort(); - } - }, [skip]); - - return [loading, networkKpiTlsHandshakesResponse]; -}; diff --git a/x-pack/plugins/security_solution/public/explore/network/containers/kpi_network/tls_handshakes/translations.ts b/x-pack/plugins/security_solution/public/explore/network/containers/kpi_network/tls_handshakes/translations.ts deleted file mode 100644 index eb9bd43b601c4..0000000000000 --- a/x-pack/plugins/security_solution/public/explore/network/containers/kpi_network/tls_handshakes/translations.ts +++ /dev/null @@ -1,22 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { i18n } from '@kbn/i18n'; - -export const ERROR_NETWORK_KPI_TLS_HANDSHAKES = i18n.translate( - 'xpack.securitySolution.networkKpiTlsHandshakes.errorSearchDescription', - { - defaultMessage: `An error has occurred on network kpi tls handshakes search`, - } -); - -export const FAIL_NETWORK_KPI_TLS_HANDSHAKES = i18n.translate( - 'xpack.securitySolution.networkKpiTlsHandshakes.failSearchDescription', - { - defaultMessage: `Failed to run search on network kpi tls handshakes`, - } -); diff --git a/x-pack/plugins/security_solution/public/explore/network/containers/kpi_network/unique_flows/index.test.tsx b/x-pack/plugins/security_solution/public/explore/network/containers/kpi_network/unique_flows/index.test.tsx deleted file mode 100644 index 75004d1b92ef2..0000000000000 --- a/x-pack/plugins/security_solution/public/explore/network/containers/kpi_network/unique_flows/index.test.tsx +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { act, renderHook } from '@testing-library/react-hooks'; -import { TestProviders } from '../../../../../common/mock'; -import { useNetworkKpiUniqueFlows } from '.'; - -describe('kpi network - unique flows', () => { - it('skip = true will cancel any running request', () => { - const abortSpy = jest.spyOn(AbortController.prototype, 'abort'); - const localProps = { - startDate: '2020-07-07T08:20:18.966Z', - endDate: '2020-07-08T08:20:18.966Z', - indexNames: ['cool'], - skip: false, - }; - const { rerender } = renderHook(() => useNetworkKpiUniqueFlows(localProps), { - wrapper: TestProviders, - }); - localProps.skip = true; - act(() => rerender()); - expect(abortSpy).toHaveBeenCalledTimes(4); - }); -}); diff --git a/x-pack/plugins/security_solution/public/explore/network/containers/kpi_network/unique_flows/index.tsx b/x-pack/plugins/security_solution/public/explore/network/containers/kpi_network/unique_flows/index.tsx deleted file mode 100644 index e997a9eb94e1d..0000000000000 --- a/x-pack/plugins/security_solution/public/explore/network/containers/kpi_network/unique_flows/index.tsx +++ /dev/null @@ -1,157 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import deepEqual from 'fast-deep-equal'; -import { noop } from 'lodash/fp'; -import { useCallback, useEffect, useRef, useState } from 'react'; -import { Subscription } from 'rxjs'; - -import { isRunningResponse } from '@kbn/data-plugin/common'; -import type { NetworkKpiUniqueFlowsRequestOptionsInput } from '../../../../../../common/api/search_strategy'; -import { useAppToasts } from '../../../../../common/hooks/use_app_toasts'; -import type { inputsModel } from '../../../../../common/store'; -import { createFilter } from '../../../../../common/containers/helpers'; -import { useKibana } from '../../../../../common/lib/kibana'; -import type { NetworkKpiUniqueFlowsStrategyResponse } from '../../../../../../common/search_strategy'; -import { NetworkKpiQueries } from '../../../../../../common/search_strategy'; -import type { ESTermQuery } from '../../../../../../common/typed_json'; - -import * as i18n from './translations'; -import { getInspectResponse } from '../../../../../helpers'; -import type { InspectResponse } from '../../../../../types'; - -export const ID = 'networkKpiUniqueFlowsQuery'; - -export interface NetworkKpiUniqueFlowsArgs { - uniqueFlowId: number; - id: string; - inspect: InspectResponse; - isInspected: boolean; - refetch: inputsModel.Refetch; -} - -interface UseNetworkKpiUniqueFlows { - filterQuery?: ESTermQuery | string; - endDate: string; - indexNames: string[]; - skip?: boolean; - startDate: string; -} - -export const useNetworkKpiUniqueFlows = ({ - filterQuery, - endDate, - indexNames, - skip = false, - startDate, -}: UseNetworkKpiUniqueFlows): [boolean, NetworkKpiUniqueFlowsArgs] => { - const { data } = useKibana().services; - const refetch = useRef(noop); - const abortCtrl = useRef(new AbortController()); - const searchSubscription$ = useRef(new Subscription()); - const [loading, setLoading] = useState(false); - const [networkKpiUniqueFlowsRequest, setNetworkKpiUniqueFlowsRequest] = - useState(null); - - const [networkKpiUniqueFlowsResponse, setNetworkKpiUniqueFlowsResponse] = - useState({ - uniqueFlowId: 0, - id: ID, - inspect: { - dsl: [], - response: [], - }, - isInspected: false, - refetch: refetch.current, - }); - const { addError } = useAppToasts(); - - const networkKpiUniqueFlowsSearch = useCallback( - (request: NetworkKpiUniqueFlowsRequestOptionsInput | null) => { - if (request == null || skip) { - return; - } - - const asyncSearch = async () => { - abortCtrl.current = new AbortController(); - setLoading(true); - searchSubscription$.current = data.search - .search( - request, - { - strategy: 'securitySolutionSearchStrategy', - abortSignal: abortCtrl.current.signal, - } - ) - .subscribe({ - next: (response) => { - if (!isRunningResponse(response)) { - setLoading(false); - setNetworkKpiUniqueFlowsResponse((prevResponse) => ({ - ...prevResponse, - uniqueFlowId: response.uniqueFlowId, - inspect: getInspectResponse(response, prevResponse.inspect), - refetch: refetch.current, - })); - searchSubscription$.current.unsubscribe(); - } - }, - error: (msg) => { - setLoading(false); - addError(msg, { - title: i18n.FAIL_NETWORK_KPI_UNIQUE_FLOWS, - }); - searchSubscription$.current.unsubscribe(); - }, - }); - }; - searchSubscription$.current.unsubscribe(); - abortCtrl.current.abort(); - asyncSearch(); - refetch.current = asyncSearch; - }, - [data.search, addError, skip] - ); - - useEffect(() => { - setNetworkKpiUniqueFlowsRequest((prevRequest) => { - const myRequest: NetworkKpiUniqueFlowsRequestOptionsInput = { - ...(prevRequest ?? {}), - defaultIndex: indexNames, - factoryQueryType: NetworkKpiQueries.uniqueFlows, - filterQuery: createFilter(filterQuery), - timerange: { - interval: '12h', - from: startDate, - to: endDate, - }, - }; - if (!deepEqual(prevRequest, myRequest)) { - return myRequest; - } - return prevRequest; - }); - }, [indexNames, endDate, filterQuery, startDate]); - - useEffect(() => { - networkKpiUniqueFlowsSearch(networkKpiUniqueFlowsRequest); - return () => { - searchSubscription$.current.unsubscribe(); - abortCtrl.current.abort(); - }; - }, [networkKpiUniqueFlowsRequest, networkKpiUniqueFlowsSearch]); - - useEffect(() => { - if (skip) { - setLoading(false); - searchSubscription$.current.unsubscribe(); - abortCtrl.current.abort(); - } - }, [skip]); - - return [loading, networkKpiUniqueFlowsResponse]; -}; diff --git a/x-pack/plugins/security_solution/public/explore/network/containers/kpi_network/unique_flows/translations.ts b/x-pack/plugins/security_solution/public/explore/network/containers/kpi_network/unique_flows/translations.ts deleted file mode 100644 index 5c882a00a03e9..0000000000000 --- a/x-pack/plugins/security_solution/public/explore/network/containers/kpi_network/unique_flows/translations.ts +++ /dev/null @@ -1,22 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { i18n } from '@kbn/i18n'; - -export const ERROR_NETWORK_KPI_UNIQUE_FLOWS = i18n.translate( - 'xpack.securitySolution.networkKpiUniqueFlows.errorSearchDescription', - { - defaultMessage: `An error has occurred on network kpi unique flows search`, - } -); - -export const FAIL_NETWORK_KPI_UNIQUE_FLOWS = i18n.translate( - 'xpack.securitySolution.networkKpiUniqueFlows.failSearchDescription', - { - defaultMessage: `Failed to run search on network kpi unique flows`, - } -); diff --git a/x-pack/plugins/security_solution/public/explore/network/containers/kpi_network/unique_private_ips/index.test.tsx b/x-pack/plugins/security_solution/public/explore/network/containers/kpi_network/unique_private_ips/index.test.tsx deleted file mode 100644 index 0d5ca709b31ee..0000000000000 --- a/x-pack/plugins/security_solution/public/explore/network/containers/kpi_network/unique_private_ips/index.test.tsx +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { act, renderHook } from '@testing-library/react-hooks'; -import { TestProviders } from '../../../../../common/mock'; -import { useNetworkKpiUniquePrivateIps } from '.'; - -describe('kpi network - unique private ips', () => { - it('skip = true will cancel any running request', () => { - const abortSpy = jest.spyOn(AbortController.prototype, 'abort'); - const localProps = { - startDate: '2020-07-07T08:20:18.966Z', - endDate: '2020-07-08T08:20:18.966Z', - indexNames: ['cool'], - skip: false, - }; - const { rerender } = renderHook(() => useNetworkKpiUniquePrivateIps(localProps), { - wrapper: TestProviders, - }); - localProps.skip = true; - act(() => rerender()); - expect(abortSpy).toHaveBeenCalledTimes(4); - }); -}); diff --git a/x-pack/plugins/security_solution/public/explore/network/containers/kpi_network/unique_private_ips/index.tsx b/x-pack/plugins/security_solution/public/explore/network/containers/kpi_network/unique_private_ips/index.tsx deleted file mode 100644 index a61d4a859082e..0000000000000 --- a/x-pack/plugins/security_solution/public/explore/network/containers/kpi_network/unique_private_ips/index.tsx +++ /dev/null @@ -1,171 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import deepEqual from 'fast-deep-equal'; -import { noop } from 'lodash/fp'; -import { useCallback, useEffect, useRef, useState } from 'react'; -import { Subscription } from 'rxjs'; - -import { isRunningResponse } from '@kbn/data-plugin/common'; -import type { NetworkKpiUniquePrivateIpsRequestOptionsInput } from '../../../../../../common/api/search_strategy'; -import { useAppToasts } from '../../../../../common/hooks/use_app_toasts'; -import type { inputsModel } from '../../../../../common/store'; -import { createFilter } from '../../../../../common/containers/helpers'; -import { useKibana } from '../../../../../common/lib/kibana'; -import type { - NetworkKpiHistogramData, - NetworkKpiUniquePrivateIpsStrategyResponse, -} from '../../../../../../common/search_strategy'; -import { NetworkKpiQueries } from '../../../../../../common/search_strategy'; -import type { ESTermQuery } from '../../../../../../common/typed_json'; - -import * as i18n from './translations'; -import { getInspectResponse } from '../../../../../helpers'; -import type { InspectResponse } from '../../../../../types'; - -export const ID = 'networkKpiUniquePrivateIpsQuery'; - -export interface NetworkKpiUniquePrivateIpsArgs { - uniqueDestinationPrivateIps: number; - uniqueDestinationPrivateIpsHistogram: NetworkKpiHistogramData[] | null; - uniqueSourcePrivateIps: number; - uniqueSourcePrivateIpsHistogram: NetworkKpiHistogramData[] | null; - id: string; - inspect: InspectResponse; - isInspected: boolean; - refetch: inputsModel.Refetch; -} - -interface UseNetworkKpiUniquePrivateIps { - filterQuery?: ESTermQuery | string; - endDate: string; - indexNames: string[]; - skip?: boolean; - startDate: string; -} - -export const useNetworkKpiUniquePrivateIps = ({ - filterQuery, - endDate, - indexNames, - skip = false, - startDate, -}: UseNetworkKpiUniquePrivateIps): [boolean, NetworkKpiUniquePrivateIpsArgs] => { - const { data } = useKibana().services; - const refetch = useRef(noop); - const abortCtrl = useRef(new AbortController()); - const searchSubscription$ = useRef(new Subscription()); - const [loading, setLoading] = useState(false); - const [networkKpiUniquePrivateIpsRequest, setNetworkKpiUniquePrivateIpsRequest] = - useState(null); - - const [networkKpiUniquePrivateIpsResponse, setNetworkKpiUniquePrivateIpsResponse] = - useState({ - uniqueDestinationPrivateIps: 0, - uniqueDestinationPrivateIpsHistogram: null, - uniqueSourcePrivateIps: 0, - uniqueSourcePrivateIpsHistogram: null, - id: ID, - inspect: { - dsl: [], - response: [], - }, - isInspected: false, - refetch: refetch.current, - }); - const { addError } = useAppToasts(); - - const networkKpiUniquePrivateIpsSearch = useCallback( - (request: NetworkKpiUniquePrivateIpsRequestOptionsInput | null) => { - if (request == null || skip) { - return; - } - - const asyncSearch = async () => { - abortCtrl.current = new AbortController(); - setLoading(true); - - searchSubscription$.current = data.search - .search< - NetworkKpiUniquePrivateIpsRequestOptionsInput, - NetworkKpiUniquePrivateIpsStrategyResponse - >(request, { - strategy: 'securitySolutionSearchStrategy', - abortSignal: abortCtrl.current.signal, - }) - .subscribe({ - next: (response) => { - if (!isRunningResponse(response)) { - setLoading(false); - setNetworkKpiUniquePrivateIpsResponse((prevResponse) => ({ - ...prevResponse, - uniqueDestinationPrivateIps: response.uniqueDestinationPrivateIps, - uniqueDestinationPrivateIpsHistogram: - response.uniqueDestinationPrivateIpsHistogram, - uniqueSourcePrivateIps: response.uniqueSourcePrivateIps, - uniqueSourcePrivateIpsHistogram: response.uniqueSourcePrivateIpsHistogram, - inspect: getInspectResponse(response, prevResponse.inspect), - refetch: refetch.current, - })); - searchSubscription$.current.unsubscribe(); - } - }, - error: (msg) => { - setLoading(false); - addError(msg, { - title: i18n.FAIL_NETWORK_KPI_UNIQUE_PRIVATE_IPS, - }); - searchSubscription$.current.unsubscribe(); - }, - }); - }; - searchSubscription$.current.unsubscribe(); - abortCtrl.current.abort(); - asyncSearch(); - refetch.current = asyncSearch; - }, - [data.search, addError, skip] - ); - - useEffect(() => { - setNetworkKpiUniquePrivateIpsRequest((prevRequest) => { - const myRequest: NetworkKpiUniquePrivateIpsRequestOptionsInput = { - ...(prevRequest ?? {}), - defaultIndex: indexNames, - factoryQueryType: NetworkKpiQueries.uniquePrivateIps, - filterQuery: createFilter(filterQuery), - timerange: { - interval: '12h', - from: startDate, - to: endDate, - }, - }; - if (!deepEqual(prevRequest, myRequest)) { - return myRequest; - } - return prevRequest; - }); - }, [indexNames, endDate, filterQuery, startDate]); - - useEffect(() => { - networkKpiUniquePrivateIpsSearch(networkKpiUniquePrivateIpsRequest); - return () => { - searchSubscription$.current.unsubscribe(); - abortCtrl.current.abort(); - }; - }, [networkKpiUniquePrivateIpsRequest, networkKpiUniquePrivateIpsSearch]); - - useEffect(() => { - if (skip) { - setLoading(false); - searchSubscription$.current.unsubscribe(); - abortCtrl.current.abort(); - } - }, [skip]); - - return [loading, networkKpiUniquePrivateIpsResponse]; -}; diff --git a/x-pack/plugins/security_solution/public/explore/network/containers/kpi_network/unique_private_ips/translations.ts b/x-pack/plugins/security_solution/public/explore/network/containers/kpi_network/unique_private_ips/translations.ts deleted file mode 100644 index f8d46c62d948c..0000000000000 --- a/x-pack/plugins/security_solution/public/explore/network/containers/kpi_network/unique_private_ips/translations.ts +++ /dev/null @@ -1,22 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { i18n } from '@kbn/i18n'; - -export const ERROR_NETWORK_KPI_UNIQUE_PRIVATE_IPS = i18n.translate( - 'xpack.securitySolution.networkKpiUniquePrivateIps.errorSearchDescription', - { - defaultMessage: `An error has occurred on network kpi unique private ips search`, - } -); - -export const FAIL_NETWORK_KPI_UNIQUE_PRIVATE_IPS = i18n.translate( - 'xpack.securitySolution.networkKpiUniquePrivateIps.failSearchDescription', - { - defaultMessage: `Failed to run search on network kpi unique private ips`, - } -); diff --git a/x-pack/plugins/security_solution/public/explore/network/pages/navigation/dns_query_tab_body.tsx b/x-pack/plugins/security_solution/public/explore/network/pages/navigation/dns_query_tab_body.tsx index c2db5e1794ff1..1e1870ee17594 100644 --- a/x-pack/plugins/security_solution/public/explore/network/pages/navigation/dns_query_tab_body.tsx +++ b/x-pack/plugins/security_solution/public/explore/network/pages/navigation/dns_query_tab_body.tsx @@ -20,7 +20,6 @@ import type { } from '../../../../common/components/matrix_histogram/types'; import * as i18n from './translations'; import { MatrixHistogram } from '../../../../common/components/matrix_histogram'; -import { MatrixHistogramType } from '../../../../../common/search_strategy/security_solution'; import { networkSelectors } from '../../store'; import { useShallowEqualSelector } from '../../../../common/hooks/use_selector'; import { getDnsTopDomainsLensAttributes } from '../../../../common/components/visualization_actions/lens_attributes/network/dns_top_domains'; @@ -42,8 +41,6 @@ const DEFAULT_STACK_BY = 'dns.question.registered_domain'; export const histogramConfigs: Omit = { defaultStackByOption: dnsStackByOptions.find((o) => o.text === DEFAULT_STACK_BY) ?? dnsStackByOptions[0], - errorMessage: i18n.ERROR_FETCHING_DNS_DATA, - histogramType: MatrixHistogramType.dns, stackByOptions: dnsStackByOptions, subtitle: undefined, getLensAttributes: getDnsTopDomainsLensAttributes, @@ -109,9 +106,7 @@ const DnsQueryTabBodyComponent: React.FC = ({ isPtrIncluded={isPtrIncluded} endDate={endDate} filterQuery={filterQuery} - indexNames={indexNames} setQuery={setQuery} - showLegend={true} startDate={startDate} {...dnsHistogramConfigs} /> diff --git a/x-pack/plugins/security_solution/public/explore/network/pages/network.tsx b/x-pack/plugins/security_solution/public/explore/network/pages/network.tsx index 3ca4d2c7a4d2b..5cb2d55f4d796 100644 --- a/x-pack/plugins/security_solution/public/explore/network/pages/network.tsx +++ b/x-pack/plugins/security_solution/public/explore/network/pages/network.tsx @@ -8,7 +8,6 @@ import { EuiPanel, EuiSpacer, EuiWindowEvent } from '@elastic/eui'; import { noop } from 'lodash/fp'; import React, { useCallback, useMemo, useRef } from 'react'; -import { useDispatch } from 'react-redux'; import { useParams } from 'react-router-dom'; import styled from 'styled-components'; @@ -17,7 +16,6 @@ import { getEsQueryConfig } from '@kbn/data-plugin/common'; import { dataTableSelectors, tableDefaults, TableId } from '@kbn/securitysolution-data-table'; import { InputsModelId } from '../../../common/store/inputs/constants'; import { SecurityPageName } from '../../../app/types'; -import type { UpdateDateRange } from '../../../common/components/charts/common'; import { EmbeddedMap } from '../components/embeddables/embedded_map'; import { FiltersGlobal } from '../../../common/components/filters_global'; import { HeaderPage } from '../../../common/components/header_page'; @@ -33,7 +31,6 @@ import { LastEventIndexKey } from '../../../../common/search_strategy'; import { useKibana } from '../../../common/lib/kibana'; import { convertToBuildEsQuery } from '../../../common/lib/kuery'; import { inputsSelectors } from '../../../common/store'; -import { setAbsoluteRangeDatePicker } from '../../../common/store/inputs/actions'; import { SpyRoute } from '../../../common/utils/route/spy_routes'; import { Display } from '../../hosts/pages/display'; import { networkModel } from '../store'; @@ -64,7 +61,6 @@ const ID = 'NetworkQueryId'; const NetworkComponent = React.memo( ({ hasMlUserPermissions, capabilitiesFetched }) => { - const dispatch = useDispatch(); const containerElement = useRef(null); const getTable = useMemo(() => dataTableSelectors.getTableByIdSelector(), []); const graphEventId = useShallowEqualSelector( @@ -92,23 +88,6 @@ const NetworkComponent = React.memo( return globalFilters; }, [tabName, globalFilters]); - const updateDateRange = useCallback( - ({ x }) => { - if (!x) { - return; - } - const [min, max] = x; - dispatch( - setAbsoluteRangeDatePicker({ - id: InputsModelId.global, - from: new Date(min).toISOString(), - to: new Date(max).toISOString(), - }) - ); - }, - [dispatch] - ); - const { indicesExist, indexPattern, selectedPatterns, sourcererDataView } = useSourcererDataView(); @@ -193,15 +172,7 @@ const NetworkComponent = React.memo( )} - + {capabilitiesFetched && !isInitializing ? ( diff --git a/x-pack/plugins/security_solution/public/explore/users/components/kpi_users/authentications/index.test.tsx b/x-pack/plugins/security_solution/public/explore/users/components/kpi_users/authentications/index.test.tsx index 68d03def9fd8d..2697e4675e4c3 100644 --- a/x-pack/plugins/security_solution/public/explore/users/components/kpi_users/authentications/index.test.tsx +++ b/x-pack/plugins/security_solution/public/explore/users/components/kpi_users/authentications/index.test.tsx @@ -5,106 +5,29 @@ * 2.0. */ -import { useUsersKpiAuthentications } from '../../../containers/users/authentications'; -import { useQueryToggle } from '../../../../../common/containers/query_toggle'; import { render } from '@testing-library/react'; import { TestProviders } from '../../../../../common/mock'; import React from 'react'; -import { UsersKpiAuthentications } from '.'; -import { useIsExperimentalFeatureEnabled } from '../../../../../common/hooks/use_experimental_features'; -import { useRefetchByRestartingSession } from '../../../../../common/components/page/use_refetch_by_session'; -import { KpiBaseComponentManage } from '../../../../hosts/components/kpi_hosts/common'; +import { authenticationsStatItems, UsersKpiAuthentications } from '.'; +import { KpiBaseComponent } from '../../../../components/kpi'; + +jest.mock('../../../../components/kpi'); + +describe('User authentications KPI', () => { + const from = new Date('2023-12-30').toISOString(); + const to = new Date('2023-12-31').toISOString(); + const MockKpiBaseComponent = KpiBaseComponent as unknown as jest.Mock; -jest.mock('../../../../../common/containers/query_toggle'); -jest.mock('../../../containers/users/authentications'); -jest.mock('../../../../hosts/components/kpi_hosts/common', () => ({ - KpiBaseComponentManage: jest - .fn() - .mockReturnValue(), -})); -jest.mock('../../../../../common/hooks/use_experimental_features', () => ({ - useIsExperimentalFeatureEnabled: jest.fn(), -})); -jest.mock('../../../../../common/components/page/use_refetch_by_session', () => ({ - useRefetchByRestartingSession: jest.fn(), -})); -describe('Authentications KPI', () => { - const mockUseHostsKpiAuthentications = useUsersKpiAuthentications as jest.Mock; - const mockUseQueryToggle = useQueryToggle as jest.Mock; - const MockKpiBaseComponentManage = KpiBaseComponentManage as jest.Mock; - const mockRefetchByRestartingSession = jest.fn(); - const mockSession = { current: { start: jest.fn(() => 'mockNewSearchSessionId') } }; - const mockRefetch = jest.fn(); - const defaultProps = { - from: '2019-06-25T04:31:59.345Z', - to: '2019-06-25T06:31:59.345Z', - indexNames: [], - updateDateRange: jest.fn(), - setQuery: jest.fn(), - skip: false, - }; - beforeEach(() => { - mockUseQueryToggle.mockReturnValue({ toggleStatus: true, setToggleStatus: jest.fn() }); - mockUseHostsKpiAuthentications.mockReturnValue([ - false, - { - id: '123', - inspect: { - dsl: [], - response: [], - }, - refetch: mockRefetch, - }, - ]); - (useIsExperimentalFeatureEnabled as jest.Mock).mockReturnValue(false); - (useRefetchByRestartingSession as jest.Mock).mockReturnValue({ - session: mockSession, - searchSessionId: 'mockSearchSessionId', - refetchByRestartingSession: mockRefetchByRestartingSession, - }); - }); afterEach(() => { jest.clearAllMocks(); }); - it('toggleStatus=true, do not skip', () => { - render( - - - - ); - expect(mockUseHostsKpiAuthentications.mock.calls[0][0].skip).toEqual(false); - }); - it('toggleStatus=false, skip', () => { - mockUseQueryToggle.mockReturnValue({ toggleStatus: false, setToggleStatus: jest.fn() }); - render( - - - - ); - expect(mockUseHostsKpiAuthentications.mock.calls[0][0].skip).toEqual(true); - }); - it('Refetches data', () => { - mockUseQueryToggle.mockReturnValue({ toggleStatus: false, setToggleStatus: jest.fn() }); - render( - - - - ); - expect(MockKpiBaseComponentManage.mock.calls[0][0].refetch).toEqual(mockRefetch); - expect(MockKpiBaseComponentManage.mock.calls[0][0].session).toBeUndefined(); - }); - it('Refetch by restarting search session ID if isChartEmbeddablesEnabled = true', () => { - (useIsExperimentalFeatureEnabled as jest.Mock).mockReturnValue(true); - render( - - - - ); - - expect(MockKpiBaseComponentManage.mock.calls[0][0].refetch).toEqual( - mockRefetchByRestartingSession - ); - expect(MockKpiBaseComponentManage.mock.calls[0][0].session).toEqual(mockSession); + it('renders correctly', () => { + render(, { + wrapper: TestProviders, + }); + expect(MockKpiBaseComponent.mock.calls[0][0].statItems).toEqual(authenticationsStatItems); + expect(MockKpiBaseComponent.mock.calls[0][0].from).toEqual(from); + expect(MockKpiBaseComponent.mock.calls[0][0].to).toEqual(to); }); }); diff --git a/x-pack/plugins/security_solution/public/explore/users/components/kpi_users/authentications/index.tsx b/x-pack/plugins/security_solution/public/explore/users/components/kpi_users/authentications/index.tsx index 4cd4e4fbfd07f..a1b9066a721ac 100644 --- a/x-pack/plugins/security_solution/public/explore/users/components/kpi_users/authentications/index.tsx +++ b/x-pack/plugins/security_solution/public/explore/users/components/kpi_users/authentications/index.tsx @@ -5,28 +5,25 @@ * 2.0. */ -import React, { useEffect, useState } from 'react'; +import React from 'react'; import type { StatItems } from '../../../../components/stat_items'; import { kpiUserAuthenticationsAreaLensAttributes } from '../../../../../common/components/visualization_actions/lens_attributes/users/kpi_user_authentications_area'; import { kpiUserAuthenticationsBarLensAttributes } from '../../../../../common/components/visualization_actions/lens_attributes/users/kpi_user_authentications_bar'; import { kpiUserAuthenticationsMetricSuccessLensAttributes } from '../../../../../common/components/visualization_actions/lens_attributes/users/kpi_user_authentications_metric_success'; import { kpiUserAuthenticationsMetricFailureLensAttributes } from '../../../../../common/components/visualization_actions/lens_attributes/users/kpi_user_authentication_metric_failure'; -import { useUsersKpiAuthentications, ID } from '../../../containers/users/authentications'; -import { KpiBaseComponentManage } from '../../../../hosts/components/kpi_hosts/common'; +import { KpiBaseComponent } from '../../../../components/kpi'; import * as i18n from './translations'; -import { useQueryToggle } from '../../../../../common/containers/query_toggle'; import type { UsersKpiProps } from '../types'; -import { InputsModelId } from '../../../../../common/store/inputs/constants'; -import { useRefetchByRestartingSession } from '../../../../../common/components/page/use_refetch_by_session'; -import { useIsExperimentalFeatureEnabled } from '../../../../../common/hooks/use_experimental_features'; + +const ID = 'usersKpiAuthentications'; enum ChartColors { authenticationsSuccess = '#54B399', authenticationsFailure = '#E7664C', } -export const fieldsMapping: Readonly = [ +export const authenticationsStatItems: Readonly = [ { key: 'authentication', fields: [ @@ -34,7 +31,6 @@ export const fieldsMapping: Readonly = [ key: 'authenticationsSuccess', name: i18n.SUCCESS_CHART_LABEL, description: i18n.SUCCESS_UNIT_LABEL, - value: null, color: ChartColors.authenticationsSuccess, icon: 'check', lensAttributes: kpiUserAuthenticationsMetricSuccessLensAttributes, @@ -43,7 +39,6 @@ export const fieldsMapping: Readonly = [ key: 'authenticationsFailure', name: i18n.FAIL_CHART_LABEL, description: i18n.FAIL_UNIT_LABEL, - value: null, color: ChartColors.authenticationsFailure, icon: 'cross', lensAttributes: kpiUserAuthenticationsMetricFailureLensAttributes, @@ -57,52 +52,8 @@ export const fieldsMapping: Readonly = [ }, ]; -const UsersKpiAuthenticationsComponent: React.FC = ({ - filterQuery, - from, - indexNames, - to, - updateDateRange, - setQuery, - skip, -}) => { - const { toggleStatus } = useQueryToggle(ID); - const [querySkip, setQuerySkip] = useState(skip || !toggleStatus); - const isChartEmbeddablesEnabled = useIsExperimentalFeatureEnabled('chartEmbeddablesEnabled'); - - useEffect(() => { - setQuerySkip(skip || !toggleStatus); - }, [skip, toggleStatus]); - - const [loading, { refetch, id, inspect, ...data }] = useUsersKpiAuthentications({ - filterQuery, - endDate: to, - indexNames, - startDate: from, - skip: querySkip || isChartEmbeddablesEnabled, - }); - - const { session, refetchByRestartingSession } = useRefetchByRestartingSession({ - inputId: InputsModelId.global, - queryId: id, - }); - - return ( - - ); +const UsersKpiAuthenticationsComponent: React.FC = ({ from, to }) => { + return ; }; UsersKpiAuthenticationsComponent.displayName = 'UsersKpiAuthenticationsComponent'; diff --git a/x-pack/plugins/security_solution/public/explore/users/components/kpi_users/index.tsx b/x-pack/plugins/security_solution/public/explore/users/components/kpi_users/index.tsx index b7052bef14ba2..3870e56fc9e60 100644 --- a/x-pack/plugins/security_solution/public/explore/users/components/kpi_users/index.tsx +++ b/x-pack/plugins/security_solution/public/explore/users/components/kpi_users/index.tsx @@ -11,34 +11,16 @@ import type { UsersKpiProps } from './types'; import { UsersKpiAuthentications } from './authentications'; import { TotalUsersKpi } from './total_users'; -export const UsersKpiComponent = React.memo( - ({ filterQuery, from, indexNames, to, setQuery, skip, updateDateRange }) => ( - - - - +export const UsersKpiComponent = React.memo(({ from, to }) => ( + + + + - - - - - ) -); + + + + +)); UsersKpiComponent.displayName = 'UsersKpiComponent'; diff --git a/x-pack/plugins/security_solution/public/explore/users/components/kpi_users/total_users/index.test.tsx b/x-pack/plugins/security_solution/public/explore/users/components/kpi_users/total_users/index.test.tsx index a02b27d06ac99..30bb37782889f 100644 --- a/x-pack/plugins/security_solution/public/explore/users/components/kpi_users/total_users/index.test.tsx +++ b/x-pack/plugins/security_solution/public/explore/users/components/kpi_users/total_users/index.test.tsx @@ -5,109 +5,29 @@ * 2.0. */ -import { useQueryToggle } from '../../../../../common/containers/query_toggle'; import { render } from '@testing-library/react'; import { TestProviders } from '../../../../../common/mock'; import React from 'react'; -import { TotalUsersKpi } from '.'; -import { useSearchStrategy } from '../../../../../common/containers/use_search_strategy'; -import { useIsExperimentalFeatureEnabled } from '../../../../../common/hooks/use_experimental_features'; -import { useRefetchByRestartingSession } from '../../../../../common/components/page/use_refetch_by_session'; -import { KpiBaseComponentManage } from '../../../../hosts/components/kpi_hosts/common'; +import { usersStatItems, TotalUsersKpi } from '.'; +import { KpiBaseComponent } from '../../../../components/kpi'; -jest.mock('../../../../../common/containers/query_toggle'); -jest.mock('../../../../../common/containers/use_search_strategy'); -jest.mock('../../../../hosts/components/kpi_hosts/common', () => ({ - KpiBaseComponentManage: jest - .fn() - .mockReturnValue(), -})); -jest.mock('../../../../../common/hooks/use_experimental_features', () => ({ - useIsExperimentalFeatureEnabled: jest.fn(), -})); -jest.mock('../../../../../common/components/page/use_refetch_by_session', () => ({ - useRefetchByRestartingSession: jest.fn(), -})); +jest.mock('../../../../components/kpi'); + +describe('Users KPI', () => { + const from = new Date('2023-12-30').toISOString(); + const to = new Date('2023-12-31').toISOString(); + const MockKpiBaseComponent = KpiBaseComponent as unknown as jest.Mock; -describe('Total Users KPI', () => { - const mockUseSearchStrategy = useSearchStrategy as jest.Mock; - const mockUseQueryToggle = useQueryToggle as jest.Mock; - const MockKpiBaseComponentManage = KpiBaseComponentManage as jest.Mock; - const mockRefetchByRestartingSession = jest.fn(); - const mockSession = { current: { start: jest.fn(() => 'mockNewSearchSessionId') } }; - const mockRefetch = jest.fn(); - const defaultProps = { - from: '2019-06-25T04:31:59.345Z', - to: '2019-06-25T06:31:59.345Z', - indexNames: [], - updateDateRange: jest.fn(), - setQuery: jest.fn(), - skip: false, - }; - const mockSearch = jest.fn(); - beforeEach(() => { - mockUseQueryToggle.mockReturnValue({ toggleStatus: true, setToggleStatus: jest.fn() }); - mockUseSearchStrategy.mockReturnValue({ - result: [], - loading: false, - inspect: { - dsl: [], - response: [], - }, - search: mockSearch, - refetch: mockRefetch, - }); - (useIsExperimentalFeatureEnabled as jest.Mock).mockReturnValue(false); - (useRefetchByRestartingSession as jest.Mock).mockReturnValue({ - session: mockSession, - searchSessionId: 'mockSearchSessionId', - refetchByRestartingSession: mockRefetchByRestartingSession, - }); - }); afterEach(() => { jest.clearAllMocks(); }); - it('toggleStatus=true, do not skip', () => { - render( - - - - ); - expect(mockUseSearchStrategy.mock.calls[0][0].abort).toEqual(false); - expect(mockSearch).toHaveBeenCalled(); - }); - it('toggleStatus=false, skip', () => { - mockUseQueryToggle.mockReturnValue({ toggleStatus: false, setToggleStatus: jest.fn() }); - render( - - - - ); - expect(mockUseSearchStrategy.mock.calls[0][0].abort).toEqual(true); - expect(mockSearch).not.toHaveBeenCalled(); - }); - it('Refetches data', () => { - mockUseQueryToggle.mockReturnValue({ toggleStatus: false, setToggleStatus: jest.fn() }); - render( - - - - ); - expect(MockKpiBaseComponentManage.mock.calls[0][0].refetch).toEqual(mockRefetch); - expect(MockKpiBaseComponentManage.mock.calls[0][0].session).toBeUndefined(); - }); - it('Refetch by restarting search session ID if isChartEmbeddablesEnabled = true', () => { - (useIsExperimentalFeatureEnabled as jest.Mock).mockReturnValue(true); - render( - - - - ); - - expect(MockKpiBaseComponentManage.mock.calls[0][0].refetch).toEqual( - mockRefetchByRestartingSession - ); - expect(MockKpiBaseComponentManage.mock.calls[0][0].session).toEqual(mockSession); + it('renders correctly', () => { + render(, { + wrapper: TestProviders, + }); + expect(MockKpiBaseComponent.mock.calls[0][0].statItems).toEqual(usersStatItems); + expect(MockKpiBaseComponent.mock.calls[0][0].from).toEqual(from); + expect(MockKpiBaseComponent.mock.calls[0][0].to).toEqual(to); }); }); diff --git a/x-pack/plugins/security_solution/public/explore/users/components/kpi_users/total_users/index.tsx b/x-pack/plugins/security_solution/public/explore/users/components/kpi_users/total_users/index.tsx index 25326c38b1346..195bc43337f9d 100644 --- a/x-pack/plugins/security_solution/public/explore/users/components/kpi_users/total_users/index.tsx +++ b/x-pack/plugins/security_solution/public/explore/users/components/kpi_users/total_users/index.tsx @@ -6,30 +6,23 @@ */ import { euiPaletteColorBlind } from '@elastic/eui'; -import React, { useEffect, useState } from 'react'; -import { UsersQueries } from '../../../../../../common/search_strategy/security_solution/users'; +import React from 'react'; import type { StatItems } from '../../../../components/stat_items'; -import { useSearchStrategy } from '../../../../../common/containers/use_search_strategy'; -import { KpiBaseComponentManage } from '../../../../hosts/components/kpi_hosts/common'; +import { KpiBaseComponent } from '../../../../components/kpi'; import { kpiTotalUsersMetricLensAttributes } from '../../../../../common/components/visualization_actions/lens_attributes/users/kpi_total_users_metric'; import { kpiTotalUsersAreaLensAttributes } from '../../../../../common/components/visualization_actions/lens_attributes/users/kpi_total_users_area'; import * as i18n from './translations'; -import { useQueryToggle } from '../../../../../common/containers/query_toggle'; import type { UsersKpiProps } from '../types'; -import { useIsExperimentalFeatureEnabled } from '../../../../../common/hooks/use_experimental_features'; -import { useRefetchByRestartingSession } from '../../../../../common/components/page/use_refetch_by_session'; -import { InputsModelId } from '../../../../../common/store/inputs/constants'; const euiVisColorPalette = euiPaletteColorBlind(); const euiColorVis1 = euiVisColorPalette[1]; -export const fieldsMapping: Readonly = [ +export const usersStatItems: Readonly = [ { key: 'users', fields: [ { key: 'users', - value: null, color: euiColorVis1, icon: 'storage', lensAttributes: kpiTotalUsersMetricLensAttributes, @@ -41,68 +34,10 @@ export const fieldsMapping: Readonly = [ }, ]; -const QUERY_ID = 'TotalUsersKpiQuery'; +const ID = 'TotalUsersKpiQuery'; -const TotalUsersKpiComponent: React.FC = ({ - filterQuery, - from, - indexNames, - to, - updateDateRange, - setQuery, - skip, -}) => { - const { toggleStatus } = useQueryToggle(QUERY_ID); - const [querySkip, setQuerySkip] = useState(skip || !toggleStatus); - const isChartEmbeddablesEnabled = useIsExperimentalFeatureEnabled('chartEmbeddablesEnabled'); - - useEffect(() => { - setQuerySkip(skip || !toggleStatus); - }, [skip, toggleStatus]); - - const { loading, result, search, refetch, inspect } = - useSearchStrategy({ - factoryQueryType: UsersQueries.kpiTotalUsers, - initialResult: { users: 0, usersHistogram: [] }, - errorMessage: i18n.ERROR_USERS_KPI, - abort: querySkip || isChartEmbeddablesEnabled, - }); - - const { session, refetchByRestartingSession } = useRefetchByRestartingSession({ - inputId: InputsModelId.global, - queryId: QUERY_ID, - }); - - useEffect(() => { - if (!querySkip) { - search({ - filterQuery, - defaultIndex: indexNames, - timerange: { - interval: '12h', - from, - to, - }, - }); - } - }, [search, from, to, filterQuery, indexNames, querySkip]); - - return ( - - ); +const TotalUsersKpiComponent: React.FC = ({ from, to }) => { + return ; }; export const TotalUsersKpi = React.memo(TotalUsersKpiComponent); diff --git a/x-pack/plugins/security_solution/public/explore/users/components/kpi_users/types.ts b/x-pack/plugins/security_solution/public/explore/users/components/kpi_users/types.ts index d9bf1487877df..764cf05521357 100644 --- a/x-pack/plugins/security_solution/public/explore/users/components/kpi_users/types.ts +++ b/x-pack/plugins/security_solution/public/explore/users/components/kpi_users/types.ts @@ -5,15 +5,7 @@ * 2.0. */ -import type { UpdateDateRange } from '../../../../common/components/charts/common'; -import type { GlobalTimeArgs } from '../../../../common/containers/use_global_time'; - export interface UsersKpiProps { - filterQuery?: string; from: string; to: string; - indexNames: string[]; - updateDateRange: UpdateDateRange; - setQuery: GlobalTimeArgs['setQuery']; - skip: boolean; } diff --git a/x-pack/plugins/security_solution/public/explore/users/containers/users/authentications/index.test.tsx b/x-pack/plugins/security_solution/public/explore/users/containers/users/authentications/index.test.tsx deleted file mode 100644 index 50fcad8301f1e..0000000000000 --- a/x-pack/plugins/security_solution/public/explore/users/containers/users/authentications/index.test.tsx +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { act, renderHook } from '@testing-library/react-hooks'; -import { TestProviders } from '../../../../../common/mock'; -import { useUsersKpiAuthentications } from '.'; - -describe('kpi users - authentications', () => { - it('skip = true will cancel any running request', () => { - const abortSpy = jest.spyOn(AbortController.prototype, 'abort'); - const localProps = { - startDate: '2020-07-07T08:20:18.966Z', - endDate: '2020-07-08T08:20:18.966Z', - indexNames: ['cool'], - skip: false, - }; - const { rerender } = renderHook(() => useUsersKpiAuthentications(localProps), { - wrapper: TestProviders, - }); - localProps.skip = true; - act(() => rerender()); - expect(abortSpy).toHaveBeenCalledTimes(4); - }); -}); diff --git a/x-pack/plugins/security_solution/public/explore/users/containers/users/authentications/index.tsx b/x-pack/plugins/security_solution/public/explore/users/containers/users/authentications/index.tsx deleted file mode 100644 index 29798d69da399..0000000000000 --- a/x-pack/plugins/security_solution/public/explore/users/containers/users/authentications/index.tsx +++ /dev/null @@ -1,167 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import deepEqual from 'fast-deep-equal'; -import { noop } from 'lodash/fp'; -import { useCallback, useEffect, useRef, useState } from 'react'; -import { Subscription } from 'rxjs'; - -import type { AuthenticationsKpiRequestOptionsInput } from '../../../../../../common/api/search_strategy'; -import { useAppToasts } from '../../../../../common/hooks/use_app_toasts'; -import type { inputsModel } from '../../../../../common/store'; -import { createFilter } from '../../../../../common/containers/helpers'; -import { useKibana } from '../../../../../common/lib/kibana'; -import type { UsersKpiAuthenticationsStrategyResponse } from '../../../../../../common/search_strategy'; -import { UsersQueries } from '../../../../../../common/search_strategy'; -import type { ESTermQuery } from '../../../../../../common/typed_json'; - -import * as i18n from './translations'; -import { getInspectResponse } from '../../../../../helpers'; -import type { InspectResponse } from '../../../../../types'; - -export const ID = 'usersKpiAuthenticationsQuery'; - -export interface UsersKpiAuthenticationsArgs - extends Omit { - id: string; - inspect: InspectResponse; - isInspected: boolean; - refetch: inputsModel.Refetch; -} - -interface UseUsersKpiAuthentications { - filterQuery?: ESTermQuery | string; - endDate: string; - indexNames: string[]; - skip?: boolean; - startDate: string; -} - -export const useUsersKpiAuthentications = ({ - filterQuery, - endDate, - indexNames, - skip = false, - startDate, -}: UseUsersKpiAuthentications): [boolean, UsersKpiAuthenticationsArgs] => { - const { data } = useKibana().services; - const refetch = useRef(noop); - const abortCtrl = useRef(new AbortController()); - const searchSubscription$ = useRef(new Subscription()); - const [loading, setLoading] = useState(false); - const [usersKpiAuthenticationsRequest, setUsersKpiAuthenticationsRequest] = - useState(null); - - const [usersKpiAuthenticationsResponse, setUsersKpiAuthenticationsResponse] = - useState({ - authenticationsSuccess: 0, - authenticationsSuccessHistogram: [], - authenticationsFailure: 0, - authenticationsFailureHistogram: [], - id: ID, - inspect: { - dsl: [], - response: [], - }, - isInspected: false, - refetch: refetch.current, - }); - const { addError, addWarning } = useAppToasts(); - - const usersKpiAuthenticationsSearch = useCallback( - (request: AuthenticationsKpiRequestOptionsInput | null) => { - if (request == null || skip) { - return; - } - - const asyncSearch = async () => { - abortCtrl.current = new AbortController(); - setLoading(true); - - searchSubscription$.current = data.search - .search( - request, - { - strategy: 'securitySolutionSearchStrategy', - abortSignal: abortCtrl.current.signal, - } - ) - .subscribe({ - next: (response) => { - if (!response.isPartial && !response.isRunning) { - setLoading(false); - setUsersKpiAuthenticationsResponse((prevResponse) => ({ - ...prevResponse, - authenticationsSuccess: response.authenticationsSuccess, - authenticationsSuccessHistogram: response.authenticationsSuccessHistogram, - authenticationsFailure: response.authenticationsFailure, - authenticationsFailureHistogram: response.authenticationsFailureHistogram, - inspect: getInspectResponse(response, prevResponse.inspect), - refetch: refetch.current, - })); - searchSubscription$.current.unsubscribe(); - } else if (response.isPartial && !response.isRunning) { - setLoading(false); - addWarning(i18n.ERROR_USERS_KPI_AUTHENTICATIONS); - searchSubscription$.current.unsubscribe(); - } - }, - error: (msg) => { - setLoading(false); - addError(msg, { - title: i18n.FAIL_USERS_KPI_AUTHENTICATIONS, - }); - searchSubscription$.current.unsubscribe(); - }, - }); - }; - searchSubscription$.current.unsubscribe(); - abortCtrl.current.abort(); - asyncSearch(); - refetch.current = asyncSearch; - }, - [data.search, addError, addWarning, skip] - ); - - useEffect(() => { - setUsersKpiAuthenticationsRequest((prevRequest) => { - const myRequest: AuthenticationsKpiRequestOptionsInput = { - ...(prevRequest ?? {}), - defaultIndex: indexNames, - factoryQueryType: UsersQueries.kpiAuthentications, - filterQuery: createFilter(filterQuery), - timerange: { - interval: '12h', - from: startDate, - to: endDate, - }, - }; - if (!deepEqual(prevRequest, myRequest)) { - return myRequest; - } - return prevRequest; - }); - }, [indexNames, endDate, filterQuery, startDate]); - - useEffect(() => { - usersKpiAuthenticationsSearch(usersKpiAuthenticationsRequest); - return () => { - searchSubscription$.current.unsubscribe(); - abortCtrl.current.abort(); - }; - }, [usersKpiAuthenticationsRequest, usersKpiAuthenticationsSearch]); - - useEffect(() => { - if (skip) { - setLoading(false); - searchSubscription$.current.unsubscribe(); - abortCtrl.current.abort(); - } - }, [skip]); - - return [loading, usersKpiAuthenticationsResponse]; -}; diff --git a/x-pack/plugins/security_solution/public/explore/users/containers/users/authentications/translations.ts b/x-pack/plugins/security_solution/public/explore/users/containers/users/authentications/translations.ts deleted file mode 100644 index 7c434563d384b..0000000000000 --- a/x-pack/plugins/security_solution/public/explore/users/containers/users/authentications/translations.ts +++ /dev/null @@ -1,22 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { i18n } from '@kbn/i18n'; - -export const ERROR_USERS_KPI_AUTHENTICATIONS = i18n.translate( - 'xpack.securitySolution.usersKpiAuthentications.errorSearchDescription', - { - defaultMessage: `An error has occurred on users kpi authentications search`, - } -); - -export const FAIL_USERS_KPI_AUTHENTICATIONS = i18n.translate( - 'xpack.securitySolution.usersKpiAuthentications.failSearchDescription', - { - defaultMessage: `Failed to run search on users kpi authentications`, - } -); diff --git a/x-pack/plugins/security_solution/public/explore/users/pages/navigation/authentications_query_tab_body.tsx b/x-pack/plugins/security_solution/public/explore/users/pages/navigation/authentications_query_tab_body.tsx index 296424b759e9d..db286f63d5cd0 100644 --- a/x-pack/plugins/security_solution/public/explore/users/pages/navigation/authentications_query_tab_body.tsx +++ b/x-pack/plugins/security_solution/public/explore/users/pages/navigation/authentications_query_tab_body.tsx @@ -31,7 +31,6 @@ export const AuthenticationsQueryTabBody = ({ endDate={endDate} filterQuery={filterQuery} id={HISTOGRAM_QUERY_ID} - indexNames={indexNames} setQuery={setQuery} startDate={startDate} {...histogramConfigs} diff --git a/x-pack/plugins/security_solution/public/explore/users/pages/users.tsx b/x-pack/plugins/security_solution/public/explore/users/pages/users.tsx index fd0f7deff446c..41f974971b0e1 100644 --- a/x-pack/plugins/security_solution/public/explore/users/pages/users.tsx +++ b/x-pack/plugins/security_solution/public/explore/users/pages/users.tsx @@ -9,7 +9,6 @@ import { EuiSpacer, EuiWindowEvent } from '@elastic/eui'; import styled from 'styled-components'; import { noop } from 'lodash/fp'; import React, { useCallback, useMemo, useRef } from 'react'; -import { useDispatch } from 'react-redux'; import { useParams } from 'react-router-dom'; import type { Filter } from '@kbn/es-query'; import { isTab } from '@kbn/timelines-plugin/public'; @@ -29,7 +28,6 @@ import { useKibana } from '../../../common/lib/kibana'; import { convertToBuildEsQuery } from '../../../common/lib/kuery'; import type { State } from '../../../common/store'; import { inputsSelectors } from '../../../common/store'; -import { setAbsoluteRangeDatePicker } from '../../../common/store/inputs/actions'; import { SpyRoute } from '../../../common/utils/route/spy_routes'; import { UsersTabs } from './users_tabs'; @@ -44,7 +42,6 @@ import { useSourcererDataView } from '../../../common/containers/sourcerer'; import { useDeepEqualSelector } from '../../../common/hooks/use_selector'; import { useInvalidFilterQuery } from '../../../common/hooks/use_invalid_filter_query'; import { UsersKpiComponent } from '../components/kpi_users'; -import type { UpdateDateRange } from '../../../common/components/charts/common'; import { LastEventIndexKey, RiskScoreEntity } from '../../../../common/search_strategy'; import { generateSeverityFilter } from '../../hosts/store/helpers'; import { UsersTableType } from '../store/model'; @@ -66,7 +63,6 @@ const StyledFullHeightContainer = styled.div` `; const UsersComponent = () => { - const dispatch = useDispatch(); const containerElement = useRef(null); const getGlobalFiltersQuerySelector = useMemo( @@ -159,23 +155,6 @@ const UsersComponent = () => { [containerElement, onSkipFocusBeforeEventsTable, onSkipFocusAfterEventsTable] ); - const updateDateRange = useCallback( - ({ x }) => { - if (!x) { - return; - } - const [min, max] = x; - dispatch( - setAbsoluteRangeDatePicker({ - id: InputsModelId.global, - from: new Date(min).toISOString(), - to: new Date(max).toISOString(), - }) - ); - }, - [dispatch] - ); - const capabilities = useMlCapabilities(); const hasEntityAnalyticsCapability = useHasSecurityCapability('entity-analytics'); const navTabs = useMemo( @@ -201,15 +180,7 @@ const UsersComponent = () => { title={i18n.PAGE_TITLE} /> - + diff --git a/x-pack/plugins/security_solution/public/overview/components/detection_response/alerts_by_status/use_alerts_by_status_visualization_data.ts b/x-pack/plugins/security_solution/public/overview/components/detection_response/alerts_by_status/use_alerts_by_status_visualization_data.ts index 218d69b4183a7..441528836358a 100644 --- a/x-pack/plugins/security_solution/public/overview/components/detection_response/alerts_by_status/use_alerts_by_status_visualization_data.ts +++ b/x-pack/plugins/security_solution/public/overview/components/detection_response/alerts_by_status/use_alerts_by_status_visualization_data.ts @@ -13,24 +13,24 @@ export const acknowledgedAlertsVisualizationId = `${DETECTION_RESPONSE_ALERTS_BY export const closedAlertsVisualizationId = `${DETECTION_RESPONSE_ALERTS_BY_STATUS_ID}-closed`; export const useAlertsByStatusVisualizationData = () => { - const { responses: openAlertsResponse } = useVisualizationResponse({ + const { responses: openAlertsResponses } = useVisualizationResponse({ visualizationId: openAlertsVisualizationId, }); - const { responses: acknowledgedAlertsResponse } = useVisualizationResponse({ + const { responses: acknowledgedAlertsResponses } = useVisualizationResponse({ visualizationId: acknowledgedAlertsVisualizationId, }); - const { responses: closedAlertsResponse } = useVisualizationResponse({ + const { responses: closedAlertsResponses } = useVisualizationResponse({ visualizationId: closedAlertsVisualizationId, }); const visualizationOpenAlertsData = - openAlertsResponse != null ? openAlertsResponse[0].hits.total : 0; + openAlertsResponses != null ? openAlertsResponses[0].hits.total : 0; const visualizationAcknowledgedAlertsData = - acknowledgedAlertsResponse != null ? acknowledgedAlertsResponse[0].hits.total : 0; + acknowledgedAlertsResponses != null ? acknowledgedAlertsResponses[0].hits.total : 0; const visualizationClosedAlertsData = - closedAlertsResponse != null ? closedAlertsResponse[0].hits.total : 0; + closedAlertsResponses != null ? closedAlertsResponses[0].hits.total : 0; const visualizationTotalAlertsData = visualizationOpenAlertsData + diff --git a/x-pack/plugins/security_solution/public/overview/components/events_by_dataset/index.tsx b/x-pack/plugins/security_solution/public/overview/components/events_by_dataset/index.tsx index 9a62b29aa411c..5d673674225fd 100644 --- a/x-pack/plugins/security_solution/public/overview/components/events_by_dataset/index.tsx +++ b/x-pack/plugins/security_solution/public/overview/components/events_by_dataset/index.tsx @@ -14,7 +14,6 @@ import type { DataViewBase, Filter, Query } from '@kbn/es-query'; import styled from 'styled-components'; import { EuiButton } from '@elastic/eui'; import { getEsQueryConfig } from '@kbn/data-plugin/common'; -import type { RunTimeMappings } from '@kbn/timelines-plugin/common/api/search_strategy'; import { DEFAULT_NUMBER_FORMAT, APP_UI_ID } from '../../../../common/constants'; import { SHOWING, UNIT } from '../../../common/components/events_viewer/translations'; import { getTabsOnHostsUrl } from '../../../common/components/link_to/redirect_to_hosts'; @@ -196,17 +195,10 @@ const EventsByDatasetComponent: React.FC = ({ filterQuery={filterQuery} headerChildren={headerContent} id={uniqueQueryId} - indexNames={indexNames} - runtimeMappings={runtimeMappings as RunTimeMappings} - onError={toggleTopN} paddingSize={paddingSize} - setAbsoluteRangeDatePickerTarget={setAbsoluteRangeDatePickerTarget} setQuery={setQuery} showSpacer={showSpacer} - showLegend={showLegend} - skip={filterQuery === undefined} startDate={from} - scopeId={scopeId} sourcererScopeId={sourcererScopeId} {...eventsByDatasetHistogramConfigs} title={onlyField != null ? i18n.TOP(onlyField) : eventsByDatasetHistogramConfigs.title} diff --git a/x-pack/plugins/security_solution/public/overview/components/signals_by_category/signals_by_category.tsx b/x-pack/plugins/security_solution/public/overview/components/signals_by_category/signals_by_category.tsx index f03058683f2a7..f25ef25081d05 100644 --- a/x-pack/plugins/security_solution/public/overview/components/signals_by_category/signals_by_category.tsx +++ b/x-pack/plugins/security_solution/public/overview/components/signals_by_category/signals_by_category.tsx @@ -7,8 +7,7 @@ import React, { useCallback } from 'react'; import { useDispatch } from 'react-redux'; -import type { Filter, Query } from '@kbn/es-query'; -import type { MappingRuntimeFields } from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; +import type { Filter } from '@kbn/es-query'; import { AlertsHistogramPanel } from '../../../detections/components/alerts_kpis/alerts_histogram_panel'; import { useSignalIndex } from '../../../detections/containers/detection_engine/alerts/use_signal_index'; @@ -24,29 +23,21 @@ import * as i18n from '../../pages/translations'; import { useFiltersForSignalsByCategory } from './use_filters_for_signals_by_category'; interface Props { - combinedQueries?: string; filters: Filter[]; headerChildren?: React.ReactNode; /** Override all defaults, and only display this field */ onlyField?: AlertsStackByField; paddingSize?: 's' | 'm' | 'l' | 'none'; - query?: Query; setAbsoluteRangeDatePickerTarget?: InputsModelId; - showLegend?: boolean; - runtimeMappings?: MappingRuntimeFields; hideQueryToggle?: boolean; } const SignalsByCategoryComponent: React.FC = ({ - combinedQueries, filters, headerChildren, onlyField, paddingSize, - query, - showLegend, setAbsoluteRangeDatePickerTarget = InputsModelId.global, - runtimeMappings, hideQueryToggle = false, }) => { const dispatch = useDispatch(); @@ -72,19 +63,14 @@ const SignalsByCategoryComponent: React.FC = ({ return ( { {hasIndexRead && hasKibanaREAD && ( - + )} diff --git a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/common/format_general_histogram_data.test.ts b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/common/format_general_histogram_data.test.ts deleted file mode 100644 index a646a73079704..0000000000000 --- a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/common/format_general_histogram_data.test.ts +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import type { KpiGeneralHistogramCount, KpiHistogram } from '../../../../../common/search_strategy'; -import { formatGeneralHistogramData } from './format_general_histogram_data'; - -describe('formatGeneralHistogramData', () => { - test('Picks up data from count.value', () => { - const mockHistogramData = [ - { - key_as_string: '2022-12-01T00:00:00.000Z', - key: 1669852800000, - doc_count: 4, - count: { - doc_count: 4, - }, - } as KpiHistogram, - ]; - const result = formatGeneralHistogramData(mockHistogramData); - - expect(result).toMatchInlineSnapshot(` - Array [ - Object { - "x": 1669852800000, - "y": 4, - }, - ] - `); - }); - - test('Picks up data from count.doc_count - userAuthentications', () => { - const mockUserAuthentications = [ - { - key_as_string: '2022-12-01T04:00:00.000Z', - key: 1669867200000, - doc_count: 4, - count: { - value: 1, - }, - }, - ]; - const result = formatGeneralHistogramData(mockUserAuthentications); - - expect(result).toMatchInlineSnapshot(` - Array [ - Object { - "x": 1669867200000, - "y": 1, - }, - ] - `); - }); -}); diff --git a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/common/format_general_histogram_data.ts b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/common/format_general_histogram_data.ts deleted file mode 100644 index c52db5b74b8fd..0000000000000 --- a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/common/format_general_histogram_data.ts +++ /dev/null @@ -1,22 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import type { - KpiHistogramData, - KpiGeneralHistogramCount, - KpiHistogram, -} from '../../../../../common/search_strategy'; - -export const formatGeneralHistogramData = ( - data: Array> -): KpiHistogramData[] | null => - data && data.length > 0 - ? data.map(({ key, count }) => ({ - x: key, - y: count.doc_count ?? count.value, - })) - : null; diff --git a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/hosts/index.test.ts b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/hosts/index.test.ts index 193bc524d84fa..130da9b5baf57 100644 --- a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/hosts/index.test.ts +++ b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/hosts/index.test.ts @@ -6,21 +6,17 @@ */ import { hostsFactory } from '.'; -import { HostsQueries, HostsKpiQueries } from '../../../../../common/search_strategy'; +import { HostsQueries } from '../../../../../common/search_strategy'; import { allHosts } from './all'; import { hostDetails } from './details'; import { hostOverview } from './overview'; import { uncommonProcesses } from './uncommon_processes'; -import { hostsKpiHosts } from './kpi/hosts'; -import { hostsKpiUniqueIps } from './kpi/unique_ips'; jest.mock('./all'); jest.mock('./details'); jest.mock('./overview'); jest.mock('./uncommon_processes'); -jest.mock('./kpi/hosts'); -jest.mock('./kpi/unique_ips'); describe('hostsFactory', () => { test('should include correct apis', () => { @@ -29,8 +25,6 @@ describe('hostsFactory', () => { [HostsQueries.hosts]: allHosts, [HostsQueries.overview]: hostOverview, [HostsQueries.uncommonProcesses]: uncommonProcesses, - [HostsKpiQueries.kpiHosts]: hostsKpiHosts, - [HostsKpiQueries.kpiUniqueIps]: hostsKpiUniqueIps, }; expect(hostsFactory).toEqual(expectedHostsFactory); }); diff --git a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/hosts/index.ts b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/hosts/index.ts index d776754eab064..fd1394add6031 100644 --- a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/hosts/index.ts +++ b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/hosts/index.ts @@ -6,27 +6,17 @@ */ import type { FactoryQueryTypes } from '../../../../../common/search_strategy/security_solution'; -import { - HostsQueries, - HostsKpiQueries, -} from '../../../../../common/search_strategy/security_solution'; +import { HostsQueries } from '../../../../../common/search_strategy/security_solution'; import type { SecuritySolutionFactory } from '../types'; import { allHosts } from './all'; import { hostDetails } from './details'; import { hostOverview } from './overview'; import { uncommonProcesses } from './uncommon_processes'; -import { hostsKpiHosts } from './kpi/hosts'; -import { hostsKpiUniqueIps } from './kpi/unique_ips'; -export const hostsFactory: Record< - HostsQueries | HostsKpiQueries, - SecuritySolutionFactory -> = { +export const hostsFactory: Record> = { [HostsQueries.details]: hostDetails, [HostsQueries.hosts]: allHosts, [HostsQueries.overview]: hostOverview, [HostsQueries.uncommonProcesses]: uncommonProcesses, - [HostsKpiQueries.kpiHosts]: hostsKpiHosts, - [HostsKpiQueries.kpiUniqueIps]: hostsKpiUniqueIps, }; diff --git a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/hosts/kpi/hosts/index.ts b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/hosts/kpi/hosts/index.ts deleted file mode 100644 index f38e0f7b401aa..0000000000000 --- a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/hosts/kpi/hosts/index.ts +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { getOr } from 'lodash/fp'; - -import type { IEsSearchResponse } from '@kbn/data-plugin/common'; -import type { - HostsKpiQueries, - HostsKpiHostsStrategyResponse, -} from '../../../../../../../common/search_strategy/security_solution/hosts'; -import { inspectStringifyObject } from '../../../../../../utils/build_query'; -import type { SecuritySolutionFactory } from '../../../types'; -import { buildHostsKpiHostsQuery } from './query.hosts_kpi_hosts.dsl'; -import { formatGeneralHistogramData } from '../../../common/format_general_histogram_data'; - -export const hostsKpiHosts: SecuritySolutionFactory = { - buildDsl: (options) => buildHostsKpiHostsQuery(options), - parse: async ( - options, - response: IEsSearchResponse - ): Promise => { - const inspect = { - dsl: [inspectStringifyObject(buildHostsKpiHostsQuery(options))], - }; - - const hostsHistogram = getOr( - null, - 'aggregations.hosts_histogram.buckets', - response.rawResponse - ); - return { - ...response, - inspect, - hosts: getOr(null, 'aggregations.hosts.value', response.rawResponse), - hostsHistogram: formatGeneralHistogramData(hostsHistogram), - }; - }, -}; diff --git a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/hosts/kpi/hosts/query.hosts_kpi_hosts.dsl.ts b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/hosts/kpi/hosts/query.hosts_kpi_hosts.dsl.ts deleted file mode 100644 index 73e5c25e53683..0000000000000 --- a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/hosts/kpi/hosts/query.hosts_kpi_hosts.dsl.ts +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import type { KpiHostsRequestOptions } from '../../../../../../../common/api/search_strategy'; -import { createQueryFilterClauses } from '../../../../../../utils/build_query'; - -export const buildHostsKpiHostsQuery = ({ - filterQuery, - timerange: { from, to }, - defaultIndex, -}: KpiHostsRequestOptions) => { - const filter = [ - ...createQueryFilterClauses(filterQuery), - { - range: { - '@timestamp': { - gte: from, - lte: to, - format: 'strict_date_optional_time', - }, - }, - }, - ]; - - const dslQuery = { - index: defaultIndex, - allow_no_indices: true, - ignore_unavailable: true, - track_total_hits: false, - body: { - aggregations: { - hosts: { - cardinality: { - field: 'host.name', - }, - }, - hosts_histogram: { - auto_date_histogram: { - field: '@timestamp', - buckets: 6, - }, - aggs: { - count: { - cardinality: { - field: 'host.name', - }, - }, - }, - }, - }, - query: { - bool: { - filter, - }, - }, - _source: false, - fields: [ - 'host.name', - { - field: '@timestamp', - format: 'strict_date_optional_time', - }, - ], - size: 0, - }, - }; - - return dslQuery; -}; diff --git a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/hosts/kpi/unique_ips/index.ts b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/hosts/kpi/unique_ips/index.ts deleted file mode 100644 index 8d0eef56b75b9..0000000000000 --- a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/hosts/kpi/unique_ips/index.ts +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { getOr } from 'lodash/fp'; - -import type { IEsSearchResponse } from '@kbn/data-plugin/common'; -import type { - HostsKpiQueries, - HostsKpiUniqueIpsStrategyResponse, -} from '../../../../../../../common/search_strategy/security_solution/hosts'; -import { inspectStringifyObject } from '../../../../../../utils/build_query'; -import type { SecuritySolutionFactory } from '../../../types'; -import { buildHostsKpiUniqueIpsQuery } from './query.hosts_kpi_unique_ips.dsl'; -import { formatGeneralHistogramData } from '../../../common/format_general_histogram_data'; - -export const hostsKpiUniqueIps: SecuritySolutionFactory = { - buildDsl: (options) => buildHostsKpiUniqueIpsQuery(options), - parse: async ( - options, - response: IEsSearchResponse - ): Promise => { - const inspect = { - dsl: [inspectStringifyObject(buildHostsKpiUniqueIpsQuery(options))], - }; - - const uniqueSourceIpsHistogram = getOr( - null, - 'aggregations.unique_source_ips_histogram.buckets', - response.rawResponse - ); - - const uniqueDestinationIpsHistogram = getOr( - null, - 'aggregations.unique_destination_ips_histogram.buckets', - response.rawResponse - ); - - return { - ...response, - inspect, - uniqueSourceIps: getOr(null, 'aggregations.unique_source_ips.value', response.rawResponse), - uniqueSourceIpsHistogram: formatGeneralHistogramData(uniqueSourceIpsHistogram), - uniqueDestinationIps: getOr( - null, - 'aggregations.unique_destination_ips.value', - response.rawResponse - ), - uniqueDestinationIpsHistogram: formatGeneralHistogramData(uniqueDestinationIpsHistogram), - }; - }, -}; diff --git a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/hosts/kpi/unique_ips/query.hosts_kpi_unique_ips.dsl.ts b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/hosts/kpi/unique_ips/query.hosts_kpi_unique_ips.dsl.ts deleted file mode 100644 index 0d18765a1b6a4..0000000000000 --- a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/hosts/kpi/unique_ips/query.hosts_kpi_unique_ips.dsl.ts +++ /dev/null @@ -1,92 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import type { KpiUniqueIpsRequestOptions } from '../../../../../../../common/api/search_strategy'; -import { createQueryFilterClauses } from '../../../../../../utils/build_query'; - -export const buildHostsKpiUniqueIpsQuery = ({ - filterQuery, - timerange: { from, to }, - defaultIndex, -}: KpiUniqueIpsRequestOptions) => { - const filter = [ - ...createQueryFilterClauses(filterQuery), - { - range: { - '@timestamp': { - gte: from, - lte: to, - format: 'strict_date_optional_time', - }, - }, - }, - ]; - - const dslQuery = { - index: defaultIndex, - allow_no_indices: true, - ignore_unavailable: true, - track_total_hits: false, - body: { - aggregations: { - unique_source_ips: { - cardinality: { - field: 'source.ip', - }, - }, - unique_source_ips_histogram: { - auto_date_histogram: { - field: '@timestamp', - buckets: 6, - }, - aggs: { - count: { - cardinality: { - field: 'source.ip', - }, - }, - }, - }, - unique_destination_ips: { - cardinality: { - field: 'destination.ip', - }, - }, - unique_destination_ips_histogram: { - auto_date_histogram: { - field: '@timestamp', - buckets: 6, - }, - aggs: { - count: { - cardinality: { - field: 'destination.ip', - }, - }, - }, - }, - }, - query: { - bool: { - filter, - }, - }, - _source: false, - fields: [ - 'destination.ip', - 'source.ip', - { - field: '@timestamp', - format: 'strict_date_optional_time', - }, - ], - size: 0, - }, - }; - - return dslQuery; -}; diff --git a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/index.ts b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/index.ts index af94f47be89de..46ef72464dd1b 100644 --- a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/index.ts +++ b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/index.ts @@ -9,7 +9,6 @@ import type { FactoryQueryTypes } from '../../../../common/search_strategy/secur import type { SecuritySolutionFactory } from './types'; import { hostsFactory } from './hosts'; -import { matrixHistogramFactory } from './matrix_histogram'; import { networkFactory } from './network'; import { ctiFactoryTypes } from './cti'; import { riskScoreFactory } from './risk_score'; @@ -23,7 +22,6 @@ export const securitySolutionFactory: Record< > = { ...hostsFactory, ...usersFactory, - ...matrixHistogramFactory, ...networkFactory, ...ctiFactoryTypes, ...riskScoreFactory, diff --git a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/matrix_histogram/__mocks__/index.ts b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/matrix_histogram/__mocks__/index.ts deleted file mode 100644 index 5f0b69ba6dc87..0000000000000 --- a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/matrix_histogram/__mocks__/index.ts +++ /dev/null @@ -1,2180 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import type { IEsSearchResponse } from '@kbn/data-plugin/common'; - -import type { MatrixHistogramStrategyResponse } from '../../../../../../common/search_strategy'; - -export const mockAlertsSearchStrategyResponse: IEsSearchResponse = { - isPartial: false, - isRunning: false, - rawResponse: { - took: 11, - timed_out: false, - _shards: { total: 21, successful: 21, skipped: 0, failed: 0 }, - hits: { total: 0, max_score: 0, hits: [] }, - aggregations: { - alertsGroup: { doc_count_error_upper_bound: 0, sum_other_doc_count: 0, buckets: [] }, - }, - }, - total: 21, - loaded: 21, -}; - -export const formattedAlertsSearchStrategyResponse: MatrixHistogramStrategyResponse = { - ...mockAlertsSearchStrategyResponse, - inspect: { - dsl: [ - JSON.stringify( - { - index: [ - 'apm-*-transaction*', - 'traces-apm*', - 'auditbeat-*', - 'endgame-*', - 'filebeat-*', - 'logs-*', - 'packetbeat-*', - 'winlogbeat-*', - ], - allow_no_indices: true, - ignore_unavailable: true, - track_total_hits: true, - body: { - aggregations: { - alertsGroup: { - terms: { - field: 'event.module', - missing: 'All others', - order: { _count: 'desc' }, - size: 10, - }, - aggs: { - alerts: { - date_histogram: { - field: '@timestamp', - fixed_interval: '2700000ms', - min_doc_count: 0, - extended_bounds: { min: 1599574984482, max: 1599661384482 }, - }, - }, - }, - }, - }, - query: { - bool: { - filter: [ - { - bool: { - must: [], - filter: [ - { match_all: {} }, - { - bool: { - filter: [ - { - bool: { - should: [{ exists: { field: 'host.name' } }], - minimum_should_match: 1, - }, - }, - ], - }, - }, - ], - should: [], - must_not: [], - }, - }, - { - bool: { - filter: [ - { - bool: { - should: [{ match: { 'event.kind': 'alert' } }], - minimum_should_match: 1, - }, - }, - ], - }, - }, - { - range: { - '@timestamp': { - gte: '2020-09-08T14:23:04.482Z', - lte: '2020-09-09T14:23:04.482Z', - format: 'strict_date_optional_time', - }, - }, - }, - ], - }, - }, - size: 0, - }, - }, - null, - 2 - ), - ], - }, - matrixHistogramData: [], - totalCount: 0, -}; - -export const expectedDsl = { - allow_no_indices: true, - track_total_hits: false, - body: { - aggregations: { - host_count: { cardinality: { field: 'host.name' } }, - host_data: { - aggs: { - lastSeen: { max: { field: '@timestamp' } }, - os: { - top_hits: { - _source: { includes: ['host.os.*'] }, - size: 1, - sort: [{ '@timestamp': { order: 'desc' } }], - }, - }, - }, - terms: { field: 'host.name', order: { lastSeen: 'desc' }, size: 10 }, - }, - }, - query: { - bool: { - filter: [ - { bool: { filter: [{ match_all: {} }], must: [], must_not: [], should: [] } }, - { - range: { - '@timestamp': { - format: 'strict_date_optional_time', - gte: '2020-09-03T09:15:21.415Z', - lte: '2020-09-04T09:15:21.415Z', - }, - }, - }, - ], - }, - }, - size: 0, - }, - ignore_unavailable: true, - index: [ - 'apm-*-transaction*', - 'traces-apm*', - 'auditbeat-*', - 'endgame-*', - 'filebeat-*', - 'logs-*', - 'packetbeat-*', - 'winlogbeat-*', - ], -}; - -export const mockAnomaliesSearchStrategyResponse: IEsSearchResponse = { - isPartial: false, - isRunning: false, - rawResponse: { - took: 9, - timed_out: false, - _shards: { total: 21, successful: 21, skipped: 0, failed: 0 }, - hits: { total: 0, max_score: 0, hits: [] }, - aggregations: { - anomalyActionGroup: { doc_count_error_upper_bound: 0, sum_other_doc_count: 0, buckets: [] }, - }, - }, - total: 21, - loaded: 21, -}; - -export const formattedAnomaliesSearchStrategyResponse: MatrixHistogramStrategyResponse = { - ...mockAnomaliesSearchStrategyResponse, - inspect: { - dsl: [ - JSON.stringify( - { - index: [ - 'apm-*-transaction*', - 'traces-apm*', - 'auditbeat-*', - 'endgame-*', - 'filebeat-*', - 'logs-*', - 'packetbeat-*', - 'winlogbeat-*', - ], - allow_no_indices: true, - ignore_unavailable: true, - track_total_hits: true, - body: { - aggs: { - anomalyActionGroup: { - terms: { field: 'job_id', order: { _count: 'desc' }, size: 10 }, - aggs: { - anomalies: { - date_histogram: { - field: 'timestamp', - fixed_interval: '2700000ms', - min_doc_count: 0, - extended_bounds: { min: 1599578075566, max: 1599664475566 }, - }, - }, - }, - }, - }, - query: { - bool: { - filter: [ - { - bool: { - must: [], - filter: [ - { match_all: {} }, - { bool: { should: [], minimum_should_match: 1 } }, - { match_phrase: { result_type: 'record' } }, - null, - { range: { record_score: { gte: 50 } } }, - ], - should: [ - { exists: { field: 'source.ip' } }, - { exists: { field: 'destination.ip' } }, - ], - must_not: [], - minimum_should_match: 1, - }, - }, - { - range: { - timestamp: { - gte: '2020-09-08T15:14:35.566Z', - lte: '2020-09-09T15:14:35.566Z', - format: 'strict_date_optional_time', - }, - }, - }, - ], - }, - }, - size: 0, - }, - }, - null, - 2 - ), - ], - }, - matrixHistogramData: [], - totalCount: 0, -}; - -export const mockAuthenticationsSearchStrategyResponse: IEsSearchResponse = { - isPartial: false, - isRunning: false, - rawResponse: { - took: 6, - timed_out: false, - _shards: { total: 21, successful: 21, skipped: 0, failed: 0 }, - hits: { total: 0, max_score: 0, hits: [] }, - aggregations: { - eventActionGroup: { - doc_count_error_upper_bound: 0, - sum_other_doc_count: 0, - buckets: [ - { - key: 'failure', - doc_count: 379, - events: { - buckets: [ - { key_as_string: '2020-09-08T15:00:00.000Z', key: 1599577200000, doc_count: 1 }, - { key_as_string: '2020-09-08T15:45:00.000Z', key: 1599579900000, doc_count: 4 }, - { key_as_string: '2020-09-08T16:30:00.000Z', key: 1599582600000, doc_count: 34 }, - { key_as_string: '2020-09-08T17:15:00.000Z', key: 1599585300000, doc_count: 1 }, - { key_as_string: '2020-09-08T18:00:00.000Z', key: 1599588000000, doc_count: 3 }, - { key_as_string: '2020-09-08T18:45:00.000Z', key: 1599590700000, doc_count: 20 }, - { key_as_string: '2020-09-08T19:30:00.000Z', key: 1599593400000, doc_count: 24 }, - { key_as_string: '2020-09-08T20:15:00.000Z', key: 1599596100000, doc_count: 37 }, - { key_as_string: '2020-09-08T21:00:00.000Z', key: 1599598800000, doc_count: 4 }, - { key_as_string: '2020-09-08T21:45:00.000Z', key: 1599601500000, doc_count: 22 }, - { key_as_string: '2020-09-08T22:30:00.000Z', key: 1599604200000, doc_count: 3 }, - { key_as_string: '2020-09-08T23:15:00.000Z', key: 1599606900000, doc_count: 0 }, - { key_as_string: '2020-09-09T00:00:00.000Z', key: 1599609600000, doc_count: 2 }, - { key_as_string: '2020-09-09T00:45:00.000Z', key: 1599612300000, doc_count: 21 }, - { key_as_string: '2020-09-09T01:30:00.000Z', key: 1599615000000, doc_count: 28 }, - { key_as_string: '2020-09-09T02:15:00.000Z', key: 1599617700000, doc_count: 30 }, - { key_as_string: '2020-09-09T03:00:00.000Z', key: 1599620400000, doc_count: 19 }, - { key_as_string: '2020-09-09T03:45:00.000Z', key: 1599623100000, doc_count: 4 }, - { key_as_string: '2020-09-09T04:30:00.000Z', key: 1599625800000, doc_count: 1 }, - { key_as_string: '2020-09-09T05:15:00.000Z', key: 1599628500000, doc_count: 6 }, - { key_as_string: '2020-09-09T06:00:00.000Z', key: 1599631200000, doc_count: 18 }, - { key_as_string: '2020-09-09T06:45:00.000Z', key: 1599633900000, doc_count: 5 }, - { key_as_string: '2020-09-09T07:30:00.000Z', key: 1599636600000, doc_count: 23 }, - { key_as_string: '2020-09-09T08:15:00.000Z', key: 1599639300000, doc_count: 15 }, - { key_as_string: '2020-09-09T09:00:00.000Z', key: 1599642000000, doc_count: 2 }, - { key_as_string: '2020-09-09T09:45:00.000Z', key: 1599644700000, doc_count: 0 }, - { key_as_string: '2020-09-09T10:30:00.000Z', key: 1599647400000, doc_count: 5 }, - { key_as_string: '2020-09-09T11:15:00.000Z', key: 1599650100000, doc_count: 2 }, - { key_as_string: '2020-09-09T12:00:00.000Z', key: 1599652800000, doc_count: 4 }, - { key_as_string: '2020-09-09T12:45:00.000Z', key: 1599655500000, doc_count: 6 }, - { key_as_string: '2020-09-09T13:30:00.000Z', key: 1599658200000, doc_count: 11 }, - { key_as_string: '2020-09-09T14:15:00.000Z', key: 1599660900000, doc_count: 0 }, - { key_as_string: '2020-09-09T15:00:00.000Z', key: 1599663600000, doc_count: 24 }, - ], - }, - }, - { - key: 'success', - doc_count: 191, - events: { - buckets: [ - { key_as_string: '2020-09-08T15:00:00.000Z', key: 1599577200000, doc_count: 2 }, - { key_as_string: '2020-09-08T15:45:00.000Z', key: 1599579900000, doc_count: 5 }, - { key_as_string: '2020-09-08T16:30:00.000Z', key: 1599582600000, doc_count: 5 }, - { key_as_string: '2020-09-08T17:15:00.000Z', key: 1599585300000, doc_count: 2 }, - { key_as_string: '2020-09-08T18:00:00.000Z', key: 1599588000000, doc_count: 4 }, - { key_as_string: '2020-09-08T18:45:00.000Z', key: 1599590700000, doc_count: 6 }, - { key_as_string: '2020-09-08T19:30:00.000Z', key: 1599593400000, doc_count: 4 }, - { key_as_string: '2020-09-08T20:15:00.000Z', key: 1599596100000, doc_count: 13 }, - { key_as_string: '2020-09-08T21:00:00.000Z', key: 1599598800000, doc_count: 6 }, - { key_as_string: '2020-09-08T21:45:00.000Z', key: 1599601500000, doc_count: 3 }, - { key_as_string: '2020-09-08T22:30:00.000Z', key: 1599604200000, doc_count: 1 }, - { key_as_string: '2020-09-08T23:15:00.000Z', key: 1599606900000, doc_count: 9 }, - { key_as_string: '2020-09-09T00:00:00.000Z', key: 1599609600000, doc_count: 5 }, - { key_as_string: '2020-09-09T00:45:00.000Z', key: 1599612300000, doc_count: 6 }, - { key_as_string: '2020-09-09T01:30:00.000Z', key: 1599615000000, doc_count: 8 }, - { key_as_string: '2020-09-09T02:15:00.000Z', key: 1599617700000, doc_count: 2 }, - { key_as_string: '2020-09-09T03:00:00.000Z', key: 1599620400000, doc_count: 9 }, - { key_as_string: '2020-09-09T03:45:00.000Z', key: 1599623100000, doc_count: 2 }, - { key_as_string: '2020-09-09T04:30:00.000Z', key: 1599625800000, doc_count: 5 }, - { key_as_string: '2020-09-09T05:15:00.000Z', key: 1599628500000, doc_count: 2 }, - { key_as_string: '2020-09-09T06:00:00.000Z', key: 1599631200000, doc_count: 14 }, - { key_as_string: '2020-09-09T06:45:00.000Z', key: 1599633900000, doc_count: 7 }, - { key_as_string: '2020-09-09T07:30:00.000Z', key: 1599636600000, doc_count: 13 }, - { key_as_string: '2020-09-09T08:15:00.000Z', key: 1599639300000, doc_count: 10 }, - { key_as_string: '2020-09-09T09:00:00.000Z', key: 1599642000000, doc_count: 5 }, - { key_as_string: '2020-09-09T09:45:00.000Z', key: 1599644700000, doc_count: 2 }, - { key_as_string: '2020-09-09T10:30:00.000Z', key: 1599647400000, doc_count: 6 }, - { key_as_string: '2020-09-09T11:15:00.000Z', key: 1599650100000, doc_count: 7 }, - { key_as_string: '2020-09-09T12:00:00.000Z', key: 1599652800000, doc_count: 5 }, - { key_as_string: '2020-09-09T12:45:00.000Z', key: 1599655500000, doc_count: 6 }, - { key_as_string: '2020-09-09T13:30:00.000Z', key: 1599658200000, doc_count: 5 }, - { key_as_string: '2020-09-09T14:15:00.000Z', key: 1599660900000, doc_count: 10 }, - { key_as_string: '2020-09-09T15:00:00.000Z', key: 1599663600000, doc_count: 2 }, - ], - }, - }, - ], - }, - }, - }, - total: 21, - loaded: 21, -}; - -export const formattedAuthenticationsSearchStrategyResponse: MatrixHistogramStrategyResponse = { - ...mockAuthenticationsSearchStrategyResponse, - inspect: { - dsl: [ - JSON.stringify( - { - index: [ - 'apm-*-transaction*', - 'traces-apm*', - 'auditbeat-*', - 'endgame-*', - 'filebeat-*', - 'logs-*', - 'packetbeat-*', - 'winlogbeat-*', - ], - allow_no_indices: true, - ignore_unavailable: true, - track_total_hits: true, - body: { - aggregations: { - eventActionGroup: { - terms: { - field: 'event.outcome', - include: ['success', 'failure'], - order: { _count: 'desc' }, - size: 2, - }, - aggs: { - events: { - date_histogram: { - field: '@timestamp', - fixed_interval: '2700000ms', - min_doc_count: 0, - extended_bounds: { min: 1599578520325, max: 1599664920325 }, - }, - }, - }, - }, - }, - query: { - bool: { - filter: [ - { bool: { must: [], filter: [{ match_all: {} }], should: [], must_not: [] } }, - { bool: { must: [{ term: { 'event.category': 'authentication' } }] } }, - { - range: { - '@timestamp': { - gte: '2020-09-08T15:22:00.325Z', - lte: '2020-09-09T15:22:00.325Z', - format: 'strict_date_optional_time', - }, - }, - }, - ], - }, - }, - size: 0, - }, - }, - null, - 2 - ), - ], - }, - matrixHistogramData: [ - { x: 1599577200000, y: 1, g: 'failure' }, - { x: 1599579900000, y: 4, g: 'failure' }, - { x: 1599582600000, y: 34, g: 'failure' }, - { x: 1599585300000, y: 1, g: 'failure' }, - { x: 1599588000000, y: 3, g: 'failure' }, - { x: 1599590700000, y: 20, g: 'failure' }, - { x: 1599593400000, y: 24, g: 'failure' }, - { x: 1599596100000, y: 37, g: 'failure' }, - { x: 1599598800000, y: 4, g: 'failure' }, - { x: 1599601500000, y: 22, g: 'failure' }, - { x: 1599604200000, y: 3, g: 'failure' }, - { x: 1599606900000, y: 0, g: 'failure' }, - { x: 1599609600000, y: 2, g: 'failure' }, - { x: 1599612300000, y: 21, g: 'failure' }, - { x: 1599615000000, y: 28, g: 'failure' }, - { x: 1599617700000, y: 30, g: 'failure' }, - { x: 1599620400000, y: 19, g: 'failure' }, - { x: 1599623100000, y: 4, g: 'failure' }, - { x: 1599625800000, y: 1, g: 'failure' }, - { x: 1599628500000, y: 6, g: 'failure' }, - { x: 1599631200000, y: 18, g: 'failure' }, - { x: 1599633900000, y: 5, g: 'failure' }, - { x: 1599636600000, y: 23, g: 'failure' }, - { x: 1599639300000, y: 15, g: 'failure' }, - { x: 1599642000000, y: 2, g: 'failure' }, - { x: 1599644700000, y: 0, g: 'failure' }, - { x: 1599647400000, y: 5, g: 'failure' }, - { x: 1599650100000, y: 2, g: 'failure' }, - { x: 1599652800000, y: 4, g: 'failure' }, - { x: 1599655500000, y: 6, g: 'failure' }, - { x: 1599658200000, y: 11, g: 'failure' }, - { x: 1599660900000, y: 0, g: 'failure' }, - { x: 1599663600000, y: 24, g: 'failure' }, - { x: 1599577200000, y: 2, g: 'success' }, - { x: 1599579900000, y: 5, g: 'success' }, - { x: 1599582600000, y: 5, g: 'success' }, - { x: 1599585300000, y: 2, g: 'success' }, - { x: 1599588000000, y: 4, g: 'success' }, - { x: 1599590700000, y: 6, g: 'success' }, - { x: 1599593400000, y: 4, g: 'success' }, - { x: 1599596100000, y: 13, g: 'success' }, - { x: 1599598800000, y: 6, g: 'success' }, - { x: 1599601500000, y: 3, g: 'success' }, - { x: 1599604200000, y: 1, g: 'success' }, - { x: 1599606900000, y: 9, g: 'success' }, - { x: 1599609600000, y: 5, g: 'success' }, - { x: 1599612300000, y: 6, g: 'success' }, - { x: 1599615000000, y: 8, g: 'success' }, - { x: 1599617700000, y: 2, g: 'success' }, - { x: 1599620400000, y: 9, g: 'success' }, - { x: 1599623100000, y: 2, g: 'success' }, - { x: 1599625800000, y: 5, g: 'success' }, - { x: 1599628500000, y: 2, g: 'success' }, - { x: 1599631200000, y: 14, g: 'success' }, - { x: 1599633900000, y: 7, g: 'success' }, - { x: 1599636600000, y: 13, g: 'success' }, - { x: 1599639300000, y: 10, g: 'success' }, - { x: 1599642000000, y: 5, g: 'success' }, - { x: 1599644700000, y: 2, g: 'success' }, - { x: 1599647400000, y: 6, g: 'success' }, - { x: 1599650100000, y: 7, g: 'success' }, - { x: 1599652800000, y: 5, g: 'success' }, - { x: 1599655500000, y: 6, g: 'success' }, - { x: 1599658200000, y: 5, g: 'success' }, - { x: 1599660900000, y: 10, g: 'success' }, - { x: 1599663600000, y: 2, g: 'success' }, - ], - totalCount: 0, -}; - -export const mockEventsSearchStrategyResponse: IEsSearchResponse = { - isPartial: false, - isRunning: false, - rawResponse: { - took: 198, - timed_out: false, - _shards: { total: 21, successful: 21, skipped: 0, failed: 0 }, - hits: { total: 0, max_score: 0, hits: [] }, - aggregations: { - eventActionGroup: { - doc_count_error_upper_bound: 3, - sum_other_doc_count: 4090, - buckets: [ - { - key: 'All others', - doc_count: 1556741, - events: { - buckets: [ - { key_as_string: '2020-09-08T15:45:00.000Z', key: 1599579900000, doc_count: 26124 }, - { key_as_string: '2020-09-08T16:30:00.000Z', key: 1599582600000, doc_count: 62910 }, - { key_as_string: '2020-09-08T17:15:00.000Z', key: 1599585300000, doc_count: 60326 }, - { key_as_string: '2020-09-08T18:00:00.000Z', key: 1599588000000, doc_count: 56144 }, - { key_as_string: '2020-09-08T18:45:00.000Z', key: 1599590700000, doc_count: 53614 }, - { key_as_string: '2020-09-08T19:30:00.000Z', key: 1599593400000, doc_count: 53228 }, - { key_as_string: '2020-09-08T20:15:00.000Z', key: 1599596100000, doc_count: 61195 }, - { key_as_string: '2020-09-08T21:00:00.000Z', key: 1599598800000, doc_count: 52082 }, - { key_as_string: '2020-09-08T21:45:00.000Z', key: 1599601500000, doc_count: 52697 }, - { key_as_string: '2020-09-08T22:30:00.000Z', key: 1599604200000, doc_count: 41094 }, - { key_as_string: '2020-09-08T23:15:00.000Z', key: 1599606900000, doc_count: 50164 }, - { key_as_string: '2020-09-09T00:00:00.000Z', key: 1599609600000, doc_count: 41500 }, - { key_as_string: '2020-09-09T00:45:00.000Z', key: 1599612300000, doc_count: 42373 }, - { key_as_string: '2020-09-09T01:30:00.000Z', key: 1599615000000, doc_count: 49785 }, - { key_as_string: '2020-09-09T02:15:00.000Z', key: 1599617700000, doc_count: 42237 }, - { key_as_string: '2020-09-09T03:00:00.000Z', key: 1599620400000, doc_count: 43114 }, - { key_as_string: '2020-09-09T03:45:00.000Z', key: 1599623100000, doc_count: 40716 }, - { key_as_string: '2020-09-09T04:30:00.000Z', key: 1599625800000, doc_count: 39248 }, - { key_as_string: '2020-09-09T05:15:00.000Z', key: 1599628500000, doc_count: 37674 }, - { key_as_string: '2020-09-09T06:00:00.000Z', key: 1599631200000, doc_count: 41072 }, - { key_as_string: '2020-09-09T06:45:00.000Z', key: 1599633900000, doc_count: 37049 }, - { key_as_string: '2020-09-09T07:30:00.000Z', key: 1599636600000, doc_count: 38561 }, - { key_as_string: '2020-09-09T08:15:00.000Z', key: 1599639300000, doc_count: 40895 }, - { key_as_string: '2020-09-09T09:00:00.000Z', key: 1599642000000, doc_count: 45490 }, - { key_as_string: '2020-09-09T09:45:00.000Z', key: 1599644700000, doc_count: 46559 }, - { key_as_string: '2020-09-09T10:30:00.000Z', key: 1599647400000, doc_count: 40020 }, - { key_as_string: '2020-09-09T11:15:00.000Z', key: 1599650100000, doc_count: 44335 }, - { key_as_string: '2020-09-09T12:00:00.000Z', key: 1599652800000, doc_count: 47252 }, - { key_as_string: '2020-09-09T12:45:00.000Z', key: 1599655500000, doc_count: 48744 }, - { key_as_string: '2020-09-09T13:30:00.000Z', key: 1599658200000, doc_count: 55756 }, - { key_as_string: '2020-09-09T14:15:00.000Z', key: 1599660900000, doc_count: 56887 }, - { key_as_string: '2020-09-09T15:00:00.000Z', key: 1599663600000, doc_count: 66920 }, - { key_as_string: '2020-09-09T15:45:00.000Z', key: 1599666300000, doc_count: 40976 }, - ], - }, - }, - { - key: 'end', - doc_count: 18413, - events: { - buckets: [ - { key_as_string: '2020-09-08T15:45:00.000Z', key: 1599579900000, doc_count: 226 }, - { key_as_string: '2020-09-08T16:30:00.000Z', key: 1599582600000, doc_count: 547 }, - { key_as_string: '2020-09-08T17:15:00.000Z', key: 1599585300000, doc_count: 532 }, - { key_as_string: '2020-09-08T18:00:00.000Z', key: 1599588000000, doc_count: 551 }, - { key_as_string: '2020-09-08T18:45:00.000Z', key: 1599590700000, doc_count: 543 }, - { key_as_string: '2020-09-08T19:30:00.000Z', key: 1599593400000, doc_count: 547 }, - { key_as_string: '2020-09-08T20:15:00.000Z', key: 1599596100000, doc_count: 656 }, - { key_as_string: '2020-09-08T21:00:00.000Z', key: 1599598800000, doc_count: 543 }, - { key_as_string: '2020-09-08T21:45:00.000Z', key: 1599601500000, doc_count: 616 }, - { key_as_string: '2020-09-08T22:30:00.000Z', key: 1599604200000, doc_count: 539 }, - { key_as_string: '2020-09-08T23:15:00.000Z', key: 1599606900000, doc_count: 539 }, - { key_as_string: '2020-09-09T00:00:00.000Z', key: 1599609600000, doc_count: 547 }, - { key_as_string: '2020-09-09T00:45:00.000Z', key: 1599612300000, doc_count: 616 }, - { key_as_string: '2020-09-09T01:30:00.000Z', key: 1599615000000, doc_count: 640 }, - { key_as_string: '2020-09-09T02:15:00.000Z', key: 1599617700000, doc_count: 614 }, - { key_as_string: '2020-09-09T03:00:00.000Z', key: 1599620400000, doc_count: 545 }, - { key_as_string: '2020-09-09T03:45:00.000Z', key: 1599623100000, doc_count: 537 }, - { key_as_string: '2020-09-09T04:30:00.000Z', key: 1599625800000, doc_count: 544 }, - { key_as_string: '2020-09-09T05:15:00.000Z', key: 1599628500000, doc_count: 571 }, - { key_as_string: '2020-09-09T06:00:00.000Z', key: 1599631200000, doc_count: 743 }, - { key_as_string: '2020-09-09T06:45:00.000Z', key: 1599633900000, doc_count: 560 }, - { key_as_string: '2020-09-09T07:30:00.000Z', key: 1599636600000, doc_count: 598 }, - { key_as_string: '2020-09-09T08:15:00.000Z', key: 1599639300000, doc_count: 613 }, - { key_as_string: '2020-09-09T09:00:00.000Z', key: 1599642000000, doc_count: 563 }, - { key_as_string: '2020-09-09T09:45:00.000Z', key: 1599644700000, doc_count: 540 }, - { key_as_string: '2020-09-09T10:30:00.000Z', key: 1599647400000, doc_count: 538 }, - { key_as_string: '2020-09-09T11:15:00.000Z', key: 1599650100000, doc_count: 549 }, - { key_as_string: '2020-09-09T12:00:00.000Z', key: 1599652800000, doc_count: 561 }, - { key_as_string: '2020-09-09T12:45:00.000Z', key: 1599655500000, doc_count: 554 }, - { key_as_string: '2020-09-09T13:30:00.000Z', key: 1599658200000, doc_count: 561 }, - { key_as_string: '2020-09-09T14:15:00.000Z', key: 1599660900000, doc_count: 542 }, - { key_as_string: '2020-09-09T15:00:00.000Z', key: 1599663600000, doc_count: 712 }, - { key_as_string: '2020-09-09T15:45:00.000Z', key: 1599666300000, doc_count: 326 }, - ], - }, - }, - { - key: 'fork', - doc_count: 18412, - events: { - buckets: [ - { key_as_string: '2020-09-08T15:45:00.000Z', key: 1599579900000, doc_count: 226 }, - { key_as_string: '2020-09-08T16:30:00.000Z', key: 1599582600000, doc_count: 546 }, - { key_as_string: '2020-09-08T17:15:00.000Z', key: 1599585300000, doc_count: 532 }, - { key_as_string: '2020-09-08T18:00:00.000Z', key: 1599588000000, doc_count: 551 }, - { key_as_string: '2020-09-08T18:45:00.000Z', key: 1599590700000, doc_count: 543 }, - { key_as_string: '2020-09-08T19:30:00.000Z', key: 1599593400000, doc_count: 547 }, - { key_as_string: '2020-09-08T20:15:00.000Z', key: 1599596100000, doc_count: 656 }, - { key_as_string: '2020-09-08T21:00:00.000Z', key: 1599598800000, doc_count: 543 }, - { key_as_string: '2020-09-08T21:45:00.000Z', key: 1599601500000, doc_count: 616 }, - { key_as_string: '2020-09-08T22:30:00.000Z', key: 1599604200000, doc_count: 539 }, - { key_as_string: '2020-09-08T23:15:00.000Z', key: 1599606900000, doc_count: 539 }, - { key_as_string: '2020-09-09T00:00:00.000Z', key: 1599609600000, doc_count: 547 }, - { key_as_string: '2020-09-09T00:45:00.000Z', key: 1599612300000, doc_count: 616 }, - { key_as_string: '2020-09-09T01:30:00.000Z', key: 1599615000000, doc_count: 640 }, - { key_as_string: '2020-09-09T02:15:00.000Z', key: 1599617700000, doc_count: 614 }, - { key_as_string: '2020-09-09T03:00:00.000Z', key: 1599620400000, doc_count: 545 }, - { key_as_string: '2020-09-09T03:45:00.000Z', key: 1599623100000, doc_count: 537 }, - { key_as_string: '2020-09-09T04:30:00.000Z', key: 1599625800000, doc_count: 544 }, - { key_as_string: '2020-09-09T05:15:00.000Z', key: 1599628500000, doc_count: 571 }, - { key_as_string: '2020-09-09T06:00:00.000Z', key: 1599631200000, doc_count: 743 }, - { key_as_string: '2020-09-09T06:45:00.000Z', key: 1599633900000, doc_count: 560 }, - { key_as_string: '2020-09-09T07:30:00.000Z', key: 1599636600000, doc_count: 598 }, - { key_as_string: '2020-09-09T08:15:00.000Z', key: 1599639300000, doc_count: 613 }, - { key_as_string: '2020-09-09T09:00:00.000Z', key: 1599642000000, doc_count: 563 }, - { key_as_string: '2020-09-09T09:45:00.000Z', key: 1599644700000, doc_count: 540 }, - { key_as_string: '2020-09-09T10:30:00.000Z', key: 1599647400000, doc_count: 538 }, - { key_as_string: '2020-09-09T11:15:00.000Z', key: 1599650100000, doc_count: 549 }, - { key_as_string: '2020-09-09T12:00:00.000Z', key: 1599652800000, doc_count: 561 }, - { key_as_string: '2020-09-09T12:45:00.000Z', key: 1599655500000, doc_count: 554 }, - { key_as_string: '2020-09-09T13:30:00.000Z', key: 1599658200000, doc_count: 561 }, - { key_as_string: '2020-09-09T14:15:00.000Z', key: 1599660900000, doc_count: 542 }, - { key_as_string: '2020-09-09T15:00:00.000Z', key: 1599663600000, doc_count: 712 }, - { key_as_string: '2020-09-09T15:45:00.000Z', key: 1599666300000, doc_count: 326 }, - ], - }, - }, - { - key: 'exec', - doc_count: 15183, - events: { - buckets: [ - { key_as_string: '2020-09-08T15:45:00.000Z', key: 1599579900000, doc_count: 189 }, - { key_as_string: '2020-09-08T16:30:00.000Z', key: 1599582600000, doc_count: 456 }, - { key_as_string: '2020-09-08T17:15:00.000Z', key: 1599585300000, doc_count: 445 }, - { key_as_string: '2020-09-08T18:00:00.000Z', key: 1599588000000, doc_count: 458 }, - { key_as_string: '2020-09-08T18:45:00.000Z', key: 1599590700000, doc_count: 455 }, - { key_as_string: '2020-09-08T19:30:00.000Z', key: 1599593400000, doc_count: 457 }, - { key_as_string: '2020-09-08T20:15:00.000Z', key: 1599596100000, doc_count: 511 }, - { key_as_string: '2020-09-08T21:00:00.000Z', key: 1599598800000, doc_count: 455 }, - { key_as_string: '2020-09-08T21:45:00.000Z', key: 1599601500000, doc_count: 493 }, - { key_as_string: '2020-09-08T22:30:00.000Z', key: 1599604200000, doc_count: 451 }, - { key_as_string: '2020-09-08T23:15:00.000Z', key: 1599606900000, doc_count: 453 }, - { key_as_string: '2020-09-09T00:00:00.000Z', key: 1599609600000, doc_count: 460 }, - { key_as_string: '2020-09-09T00:45:00.000Z', key: 1599612300000, doc_count: 521 }, - { key_as_string: '2020-09-09T01:30:00.000Z', key: 1599615000000, doc_count: 504 }, - { key_as_string: '2020-09-09T02:15:00.000Z', key: 1599617700000, doc_count: 490 }, - { key_as_string: '2020-09-09T03:00:00.000Z', key: 1599620400000, doc_count: 457 }, - { key_as_string: '2020-09-09T03:45:00.000Z', key: 1599623100000, doc_count: 447 }, - { key_as_string: '2020-09-09T04:30:00.000Z', key: 1599625800000, doc_count: 454 }, - { key_as_string: '2020-09-09T05:15:00.000Z', key: 1599628500000, doc_count: 469 }, - { key_as_string: '2020-09-09T06:00:00.000Z', key: 1599631200000, doc_count: 642 }, - { key_as_string: '2020-09-09T06:45:00.000Z', key: 1599633900000, doc_count: 465 }, - { key_as_string: '2020-09-09T07:30:00.000Z', key: 1599636600000, doc_count: 481 }, - { key_as_string: '2020-09-09T08:15:00.000Z', key: 1599639300000, doc_count: 489 }, - { key_as_string: '2020-09-09T09:00:00.000Z', key: 1599642000000, doc_count: 466 }, - { key_as_string: '2020-09-09T09:45:00.000Z', key: 1599644700000, doc_count: 452 }, - { key_as_string: '2020-09-09T10:30:00.000Z', key: 1599647400000, doc_count: 448 }, - { key_as_string: '2020-09-09T11:15:00.000Z', key: 1599650100000, doc_count: 457 }, - { key_as_string: '2020-09-09T12:00:00.000Z', key: 1599652800000, doc_count: 471 }, - { key_as_string: '2020-09-09T12:45:00.000Z', key: 1599655500000, doc_count: 460 }, - { key_as_string: '2020-09-09T13:30:00.000Z', key: 1599658200000, doc_count: 463 }, - { key_as_string: '2020-09-09T14:15:00.000Z', key: 1599660900000, doc_count: 455 }, - { key_as_string: '2020-09-09T15:00:00.000Z', key: 1599663600000, doc_count: 547 }, - { key_as_string: '2020-09-09T15:45:00.000Z', key: 1599666300000, doc_count: 262 }, - ], - }, - }, - { - key: 'disconnect_received', - doc_count: 4998, - events: { - buckets: [ - { key_as_string: '2020-09-08T15:45:00.000Z', key: 1599579900000, doc_count: 59 }, - { key_as_string: '2020-09-08T16:30:00.000Z', key: 1599582600000, doc_count: 151 }, - { key_as_string: '2020-09-08T17:15:00.000Z', key: 1599585300000, doc_count: 139 }, - { key_as_string: '2020-09-08T18:00:00.000Z', key: 1599588000000, doc_count: 144 }, - { key_as_string: '2020-09-08T18:45:00.000Z', key: 1599590700000, doc_count: 143 }, - { key_as_string: '2020-09-08T19:30:00.000Z', key: 1599593400000, doc_count: 144 }, - { key_as_string: '2020-09-08T20:15:00.000Z', key: 1599596100000, doc_count: 202 }, - { key_as_string: '2020-09-08T21:00:00.000Z', key: 1599598800000, doc_count: 142 }, - { key_as_string: '2020-09-08T21:45:00.000Z', key: 1599601500000, doc_count: 180 }, - { key_as_string: '2020-09-08T22:30:00.000Z', key: 1599604200000, doc_count: 144 }, - { key_as_string: '2020-09-08T23:15:00.000Z', key: 1599606900000, doc_count: 143 }, - { key_as_string: '2020-09-09T00:00:00.000Z', key: 1599609600000, doc_count: 137 }, - { key_as_string: '2020-09-09T00:45:00.000Z', key: 1599612300000, doc_count: 150 }, - { key_as_string: '2020-09-09T01:30:00.000Z', key: 1599615000000, doc_count: 195 }, - { key_as_string: '2020-09-09T02:15:00.000Z', key: 1599617700000, doc_count: 178 }, - { key_as_string: '2020-09-09T03:00:00.000Z', key: 1599620400000, doc_count: 144 }, - { key_as_string: '2020-09-09T03:45:00.000Z', key: 1599623100000, doc_count: 143 }, - { key_as_string: '2020-09-09T04:30:00.000Z', key: 1599625800000, doc_count: 142 }, - { key_as_string: '2020-09-09T05:15:00.000Z', key: 1599628500000, doc_count: 157 }, - { key_as_string: '2020-09-09T06:00:00.000Z', key: 1599631200000, doc_count: 166 }, - { key_as_string: '2020-09-09T06:45:00.000Z', key: 1599633900000, doc_count: 153 }, - { key_as_string: '2020-09-09T07:30:00.000Z', key: 1599636600000, doc_count: 168 }, - { key_as_string: '2020-09-09T08:15:00.000Z', key: 1599639300000, doc_count: 175 }, - { key_as_string: '2020-09-09T09:00:00.000Z', key: 1599642000000, doc_count: 158 }, - { key_as_string: '2020-09-09T09:45:00.000Z', key: 1599644700000, doc_count: 142 }, - { key_as_string: '2020-09-09T10:30:00.000Z', key: 1599647400000, doc_count: 144 }, - { key_as_string: '2020-09-09T11:15:00.000Z', key: 1599650100000, doc_count: 147 }, - { key_as_string: '2020-09-09T12:00:00.000Z', key: 1599652800000, doc_count: 139 }, - { key_as_string: '2020-09-09T12:45:00.000Z', key: 1599655500000, doc_count: 145 }, - { key_as_string: '2020-09-09T13:30:00.000Z', key: 1599658200000, doc_count: 158 }, - { key_as_string: '2020-09-09T14:15:00.000Z', key: 1599660900000, doc_count: 137 }, - { key_as_string: '2020-09-09T15:00:00.000Z', key: 1599663600000, doc_count: 234 }, - { key_as_string: '2020-09-09T15:45:00.000Z', key: 1599666300000, doc_count: 95 }, - ], - }, - }, - { - key: 'connection_attempted', - doc_count: 4534, - events: { - buckets: [ - { key_as_string: '2020-09-08T15:45:00.000Z', key: 1599579900000, doc_count: 60 }, - { key_as_string: '2020-09-08T16:30:00.000Z', key: 1599582600000, doc_count: 145 }, - { key_as_string: '2020-09-08T17:15:00.000Z', key: 1599585300000, doc_count: 138 }, - { key_as_string: '2020-09-08T18:00:00.000Z', key: 1599588000000, doc_count: 144 }, - { key_as_string: '2020-09-08T18:45:00.000Z', key: 1599590700000, doc_count: 140 }, - { key_as_string: '2020-09-08T19:30:00.000Z', key: 1599593400000, doc_count: 144 }, - { key_as_string: '2020-09-08T20:15:00.000Z', key: 1599596100000, doc_count: 145 }, - { key_as_string: '2020-09-08T21:00:00.000Z', key: 1599598800000, doc_count: 137 }, - { key_as_string: '2020-09-08T21:45:00.000Z', key: 1599601500000, doc_count: 142 }, - { key_as_string: '2020-09-08T22:30:00.000Z', key: 1599604200000, doc_count: 142 }, - { key_as_string: '2020-09-08T23:15:00.000Z', key: 1599606900000, doc_count: 143 }, - { key_as_string: '2020-09-09T00:00:00.000Z', key: 1599609600000, doc_count: 132 }, - { key_as_string: '2020-09-09T00:45:00.000Z', key: 1599612300000, doc_count: 153 }, - { key_as_string: '2020-09-09T01:30:00.000Z', key: 1599615000000, doc_count: 143 }, - { key_as_string: '2020-09-09T02:15:00.000Z', key: 1599617700000, doc_count: 142 }, - { key_as_string: '2020-09-09T03:00:00.000Z', key: 1599620400000, doc_count: 143 }, - { key_as_string: '2020-09-09T03:45:00.000Z', key: 1599623100000, doc_count: 142 }, - { key_as_string: '2020-09-09T04:30:00.000Z', key: 1599625800000, doc_count: 140 }, - { key_as_string: '2020-09-09T05:15:00.000Z', key: 1599628500000, doc_count: 140 }, - { key_as_string: '2020-09-09T06:00:00.000Z', key: 1599631200000, doc_count: 148 }, - { key_as_string: '2020-09-09T06:45:00.000Z', key: 1599633900000, doc_count: 142 }, - { key_as_string: '2020-09-09T07:30:00.000Z', key: 1599636600000, doc_count: 139 }, - { key_as_string: '2020-09-09T08:15:00.000Z', key: 1599639300000, doc_count: 139 }, - { key_as_string: '2020-09-09T09:00:00.000Z', key: 1599642000000, doc_count: 142 }, - { key_as_string: '2020-09-09T09:45:00.000Z', key: 1599644700000, doc_count: 142 }, - { key_as_string: '2020-09-09T10:30:00.000Z', key: 1599647400000, doc_count: 143 }, - { key_as_string: '2020-09-09T11:15:00.000Z', key: 1599650100000, doc_count: 141 }, - { key_as_string: '2020-09-09T12:00:00.000Z', key: 1599652800000, doc_count: 137 }, - { key_as_string: '2020-09-09T12:45:00.000Z', key: 1599655500000, doc_count: 141 }, - { key_as_string: '2020-09-09T13:30:00.000Z', key: 1599658200000, doc_count: 144 }, - { key_as_string: '2020-09-09T14:15:00.000Z', key: 1599660900000, doc_count: 138 }, - { key_as_string: '2020-09-09T15:00:00.000Z', key: 1599663600000, doc_count: 145 }, - { key_as_string: '2020-09-09T15:45:00.000Z', key: 1599666300000, doc_count: 78 }, - ], - }, - }, - { - key: 'creation', - doc_count: 1880, - events: { - buckets: [ - { key_as_string: '2020-09-08T15:45:00.000Z', key: 1599579900000, doc_count: 24 }, - { key_as_string: '2020-09-08T16:30:00.000Z', key: 1599582600000, doc_count: 53 }, - { key_as_string: '2020-09-08T17:15:00.000Z', key: 1599585300000, doc_count: 50 }, - { key_as_string: '2020-09-08T18:00:00.000Z', key: 1599588000000, doc_count: 54 }, - { key_as_string: '2020-09-08T18:45:00.000Z', key: 1599590700000, doc_count: 55 }, - { key_as_string: '2020-09-08T19:30:00.000Z', key: 1599593400000, doc_count: 53 }, - { key_as_string: '2020-09-08T20:15:00.000Z', key: 1599596100000, doc_count: 54 }, - { key_as_string: '2020-09-08T21:00:00.000Z', key: 1599598800000, doc_count: 54 }, - { key_as_string: '2020-09-08T21:45:00.000Z', key: 1599601500000, doc_count: 55 }, - { key_as_string: '2020-09-08T22:30:00.000Z', key: 1599604200000, doc_count: 52 }, - { key_as_string: '2020-09-08T23:15:00.000Z', key: 1599606900000, doc_count: 51 }, - { key_as_string: '2020-09-09T00:00:00.000Z', key: 1599609600000, doc_count: 58 }, - { key_as_string: '2020-09-09T00:45:00.000Z', key: 1599612300000, doc_count: 122 }, - { key_as_string: '2020-09-09T01:30:00.000Z', key: 1599615000000, doc_count: 54 }, - { key_as_string: '2020-09-09T02:15:00.000Z', key: 1599617700000, doc_count: 54 }, - { key_as_string: '2020-09-09T03:00:00.000Z', key: 1599620400000, doc_count: 56 }, - { key_as_string: '2020-09-09T03:45:00.000Z', key: 1599623100000, doc_count: 53 }, - { key_as_string: '2020-09-09T04:30:00.000Z', key: 1599625800000, doc_count: 55 }, - { key_as_string: '2020-09-09T05:15:00.000Z', key: 1599628500000, doc_count: 51 }, - { key_as_string: '2020-09-09T06:00:00.000Z', key: 1599631200000, doc_count: 144 }, - { key_as_string: '2020-09-09T06:45:00.000Z', key: 1599633900000, doc_count: 54 }, - { key_as_string: '2020-09-09T07:30:00.000Z', key: 1599636600000, doc_count: 53 }, - { key_as_string: '2020-09-09T08:15:00.000Z', key: 1599639300000, doc_count: 51 }, - { key_as_string: '2020-09-09T09:00:00.000Z', key: 1599642000000, doc_count: 57 }, - { key_as_string: '2020-09-09T09:45:00.000Z', key: 1599644700000, doc_count: 55 }, - { key_as_string: '2020-09-09T10:30:00.000Z', key: 1599647400000, doc_count: 52 }, - { key_as_string: '2020-09-09T11:15:00.000Z', key: 1599650100000, doc_count: 52 }, - { key_as_string: '2020-09-09T12:00:00.000Z', key: 1599652800000, doc_count: 57 }, - { key_as_string: '2020-09-09T12:45:00.000Z', key: 1599655500000, doc_count: 56 }, - { key_as_string: '2020-09-09T13:30:00.000Z', key: 1599658200000, doc_count: 53 }, - { key_as_string: '2020-09-09T14:15:00.000Z', key: 1599660900000, doc_count: 51 }, - { key_as_string: '2020-09-09T15:00:00.000Z', key: 1599663600000, doc_count: 56 }, - { key_as_string: '2020-09-09T15:45:00.000Z', key: 1599666300000, doc_count: 31 }, - ], - }, - }, - { - key: 'deletion', - doc_count: 1869, - events: { - buckets: [ - { key_as_string: '2020-09-08T15:45:00.000Z', key: 1599579900000, doc_count: 23 }, - { key_as_string: '2020-09-08T16:30:00.000Z', key: 1599582600000, doc_count: 53 }, - { key_as_string: '2020-09-08T17:15:00.000Z', key: 1599585300000, doc_count: 50 }, - { key_as_string: '2020-09-08T18:00:00.000Z', key: 1599588000000, doc_count: 54 }, - { key_as_string: '2020-09-08T18:45:00.000Z', key: 1599590700000, doc_count: 54 }, - { key_as_string: '2020-09-08T19:30:00.000Z', key: 1599593400000, doc_count: 53 }, - { key_as_string: '2020-09-08T20:15:00.000Z', key: 1599596100000, doc_count: 53 }, - { key_as_string: '2020-09-08T21:00:00.000Z', key: 1599598800000, doc_count: 54 }, - { key_as_string: '2020-09-08T21:45:00.000Z', key: 1599601500000, doc_count: 55 }, - { key_as_string: '2020-09-08T22:30:00.000Z', key: 1599604200000, doc_count: 52 }, - { key_as_string: '2020-09-08T23:15:00.000Z', key: 1599606900000, doc_count: 51 }, - { key_as_string: '2020-09-09T00:00:00.000Z', key: 1599609600000, doc_count: 55 }, - { key_as_string: '2020-09-09T00:45:00.000Z', key: 1599612300000, doc_count: 121 }, - { key_as_string: '2020-09-09T01:30:00.000Z', key: 1599615000000, doc_count: 54 }, - { key_as_string: '2020-09-09T02:15:00.000Z', key: 1599617700000, doc_count: 53 }, - { key_as_string: '2020-09-09T03:00:00.000Z', key: 1599620400000, doc_count: 55 }, - { key_as_string: '2020-09-09T03:45:00.000Z', key: 1599623100000, doc_count: 53 }, - { key_as_string: '2020-09-09T04:30:00.000Z', key: 1599625800000, doc_count: 54 }, - { key_as_string: '2020-09-09T05:15:00.000Z', key: 1599628500000, doc_count: 51 }, - { key_as_string: '2020-09-09T06:00:00.000Z', key: 1599631200000, doc_count: 146 }, - { key_as_string: '2020-09-09T06:45:00.000Z', key: 1599633900000, doc_count: 54 }, - { key_as_string: '2020-09-09T07:30:00.000Z', key: 1599636600000, doc_count: 53 }, - { key_as_string: '2020-09-09T08:15:00.000Z', key: 1599639300000, doc_count: 51 }, - { key_as_string: '2020-09-09T09:00:00.000Z', key: 1599642000000, doc_count: 55 }, - { key_as_string: '2020-09-09T09:45:00.000Z', key: 1599644700000, doc_count: 55 }, - { key_as_string: '2020-09-09T10:30:00.000Z', key: 1599647400000, doc_count: 52 }, - { key_as_string: '2020-09-09T11:15:00.000Z', key: 1599650100000, doc_count: 55 }, - { key_as_string: '2020-09-09T12:00:00.000Z', key: 1599652800000, doc_count: 55 }, - { key_as_string: '2020-09-09T12:45:00.000Z', key: 1599655500000, doc_count: 55 }, - { key_as_string: '2020-09-09T13:30:00.000Z', key: 1599658200000, doc_count: 53 }, - { key_as_string: '2020-09-09T14:15:00.000Z', key: 1599660900000, doc_count: 51 }, - { key_as_string: '2020-09-09T15:00:00.000Z', key: 1599663600000, doc_count: 55 }, - { key_as_string: '2020-09-09T15:45:00.000Z', key: 1599666300000, doc_count: 31 }, - ], - }, - }, - { - key: 'File Delete (rule: FileDelete)', - doc_count: 1831, - events: { - buckets: [ - { key_as_string: '2020-09-08T15:45:00.000Z', key: 1599579900000, doc_count: 19 }, - { key_as_string: '2020-09-08T16:30:00.000Z', key: 1599582600000, doc_count: 46 }, - { key_as_string: '2020-09-08T17:15:00.000Z', key: 1599585300000, doc_count: 47 }, - { key_as_string: '2020-09-08T18:00:00.000Z', key: 1599588000000, doc_count: 47 }, - { key_as_string: '2020-09-08T18:45:00.000Z', key: 1599590700000, doc_count: 47 }, - { key_as_string: '2020-09-08T19:30:00.000Z', key: 1599593400000, doc_count: 45 }, - { key_as_string: '2020-09-08T20:15:00.000Z', key: 1599596100000, doc_count: 48 }, - { key_as_string: '2020-09-08T21:00:00.000Z', key: 1599598800000, doc_count: 46 }, - { key_as_string: '2020-09-08T21:45:00.000Z', key: 1599601500000, doc_count: 45 }, - { key_as_string: '2020-09-08T22:30:00.000Z', key: 1599604200000, doc_count: 47 }, - { key_as_string: '2020-09-08T23:15:00.000Z', key: 1599606900000, doc_count: 47 }, - { key_as_string: '2020-09-09T00:00:00.000Z', key: 1599609600000, doc_count: 60 }, - { key_as_string: '2020-09-09T00:45:00.000Z', key: 1599612300000, doc_count: 45 }, - { key_as_string: '2020-09-09T01:30:00.000Z', key: 1599615000000, doc_count: 46 }, - { key_as_string: '2020-09-09T02:15:00.000Z', key: 1599617700000, doc_count: 46 }, - { key_as_string: '2020-09-09T03:00:00.000Z', key: 1599620400000, doc_count: 47 }, - { key_as_string: '2020-09-09T03:45:00.000Z', key: 1599623100000, doc_count: 88 }, - { key_as_string: '2020-09-09T04:30:00.000Z', key: 1599625800000, doc_count: 53 }, - { key_as_string: '2020-09-09T05:15:00.000Z', key: 1599628500000, doc_count: 46 }, - { key_as_string: '2020-09-09T06:00:00.000Z', key: 1599631200000, doc_count: 49 }, - { key_as_string: '2020-09-09T06:45:00.000Z', key: 1599633900000, doc_count: 45 }, - { key_as_string: '2020-09-09T07:30:00.000Z', key: 1599636600000, doc_count: 48 }, - { key_as_string: '2020-09-09T08:15:00.000Z', key: 1599639300000, doc_count: 46 }, - { key_as_string: '2020-09-09T09:00:00.000Z', key: 1599642000000, doc_count: 46 }, - { key_as_string: '2020-09-09T09:45:00.000Z', key: 1599644700000, doc_count: 45 }, - { key_as_string: '2020-09-09T10:30:00.000Z', key: 1599647400000, doc_count: 47 }, - { key_as_string: '2020-09-09T11:15:00.000Z', key: 1599650100000, doc_count: 47 }, - { key_as_string: '2020-09-09T12:00:00.000Z', key: 1599652800000, doc_count: 45 }, - { key_as_string: '2020-09-09T12:45:00.000Z', key: 1599655500000, doc_count: 331 }, - { key_as_string: '2020-09-09T13:30:00.000Z', key: 1599658200000, doc_count: 45 }, - { key_as_string: '2020-09-09T14:15:00.000Z', key: 1599660900000, doc_count: 47 }, - { key_as_string: '2020-09-09T15:00:00.000Z', key: 1599663600000, doc_count: 47 }, - { key_as_string: '2020-09-09T15:45:00.000Z', key: 1599666300000, doc_count: 28 }, - ], - }, - }, - { - key: 'session_id_change', - doc_count: 647, - events: { - buckets: [ - { key_as_string: '2020-09-08T15:45:00.000Z', key: 1599579900000, doc_count: 3 }, - { key_as_string: '2020-09-08T16:30:00.000Z', key: 1599582600000, doc_count: 9 }, - { key_as_string: '2020-09-08T17:15:00.000Z', key: 1599585300000, doc_count: 7 }, - { key_as_string: '2020-09-08T18:00:00.000Z', key: 1599588000000, doc_count: 10 }, - { key_as_string: '2020-09-08T18:45:00.000Z', key: 1599590700000, doc_count: 7 }, - { key_as_string: '2020-09-08T19:30:00.000Z', key: 1599593400000, doc_count: 10 }, - { key_as_string: '2020-09-08T20:15:00.000Z', key: 1599596100000, doc_count: 63 }, - { key_as_string: '2020-09-08T21:00:00.000Z', key: 1599598800000, doc_count: 7 }, - { key_as_string: '2020-09-08T21:45:00.000Z', key: 1599601500000, doc_count: 45 }, - { key_as_string: '2020-09-08T22:30:00.000Z', key: 1599604200000, doc_count: 4 }, - { key_as_string: '2020-09-08T23:15:00.000Z', key: 1599606900000, doc_count: 5 }, - { key_as_string: '2020-09-09T00:00:00.000Z', key: 1599609600000, doc_count: 6 }, - { key_as_string: '2020-09-09T00:45:00.000Z', key: 1599612300000, doc_count: 6 }, - { key_as_string: '2020-09-09T01:30:00.000Z', key: 1599615000000, doc_count: 55 }, - { key_as_string: '2020-09-09T02:15:00.000Z', key: 1599617700000, doc_count: 43 }, - { key_as_string: '2020-09-09T03:00:00.000Z', key: 1599620400000, doc_count: 8 }, - { key_as_string: '2020-09-09T03:45:00.000Z', key: 1599623100000, doc_count: 9 }, - { key_as_string: '2020-09-09T04:30:00.000Z', key: 1599625800000, doc_count: 7 }, - { key_as_string: '2020-09-09T05:15:00.000Z', key: 1599628500000, doc_count: 21 }, - { key_as_string: '2020-09-09T06:00:00.000Z', key: 1599631200000, doc_count: 26 }, - { key_as_string: '2020-09-09T06:45:00.000Z', key: 1599633900000, doc_count: 17 }, - { key_as_string: '2020-09-09T07:30:00.000Z', key: 1599636600000, doc_count: 34 }, - { key_as_string: '2020-09-09T08:15:00.000Z', key: 1599639300000, doc_count: 41 }, - { key_as_string: '2020-09-09T09:00:00.000Z', key: 1599642000000, doc_count: 18 }, - { key_as_string: '2020-09-09T09:45:00.000Z', key: 1599644700000, doc_count: 4 }, - { key_as_string: '2020-09-09T10:30:00.000Z', key: 1599647400000, doc_count: 11 }, - { key_as_string: '2020-09-09T11:15:00.000Z', key: 1599650100000, doc_count: 9 }, - { key_as_string: '2020-09-09T12:00:00.000Z', key: 1599652800000, doc_count: 7 }, - { key_as_string: '2020-09-09T12:45:00.000Z', key: 1599655500000, doc_count: 12 }, - { key_as_string: '2020-09-09T13:30:00.000Z', key: 1599658200000, doc_count: 16 }, - { key_as_string: '2020-09-09T14:15:00.000Z', key: 1599660900000, doc_count: 7 }, - { key_as_string: '2020-09-09T15:00:00.000Z', key: 1599663600000, doc_count: 99 }, - { key_as_string: '2020-09-09T15:45:00.000Z', key: 1599666300000, doc_count: 21 }, - ], - }, - }, - ], - }, - }, - }, - total: 21, - loaded: 21, -}; - -export const formattedEventsSearchStrategyResponse: MatrixHistogramStrategyResponse = { - ...mockEventsSearchStrategyResponse, - inspect: { - dsl: [ - JSON.stringify( - { - index: [ - 'apm-*-transaction*', - 'traces-apm*', - 'auditbeat-*', - 'endgame-*', - 'filebeat-*', - 'logs-*', - 'packetbeat-*', - 'winlogbeat-*', - ], - allow_no_indices: true, - ignore_unavailable: true, - track_total_hits: true, - body: { - aggregations: { - eventActionGroup: { - terms: { - field: 'event.action', - missing: 'All others', - order: { _count: 'desc' }, - size: 10, - }, - aggs: { - events: { - date_histogram: { - field: '@timestamp', - fixed_interval: '2700000ms', - min_doc_count: 0, - extended_bounds: { min: 1599581486215, max: 1599667886215 }, - }, - }, - }, - }, - }, - query: { - bool: { - filter: [ - { bool: { must: [], filter: [{ match_all: {} }], should: [], must_not: [] } }, - { - range: { - '@timestamp': { - gte: '2020-09-08T16:11:26.215Z', - lte: '2020-09-09T16:11:26.215Z', - format: 'strict_date_optional_time', - }, - }, - }, - ], - }, - }, - runtime_mappings: { - '@a.runtime.field': { - script: { - source: 'emit("Radically mocked dude: " + doc[\'host.name\'].value)', - }, - type: 'keyword', - }, - }, - size: 0, - }, - }, - null, - 2 - ), - ], - }, - totalCount: 0, - matrixHistogramData: [ - { x: 1599579900000, y: 26124, g: 'All others' }, - { x: 1599582600000, y: 62910, g: 'All others' }, - { x: 1599585300000, y: 60326, g: 'All others' }, - { x: 1599588000000, y: 56144, g: 'All others' }, - { x: 1599590700000, y: 53614, g: 'All others' }, - { x: 1599593400000, y: 53228, g: 'All others' }, - { x: 1599596100000, y: 61195, g: 'All others' }, - { x: 1599598800000, y: 52082, g: 'All others' }, - { x: 1599601500000, y: 52697, g: 'All others' }, - { x: 1599604200000, y: 41094, g: 'All others' }, - { x: 1599606900000, y: 50164, g: 'All others' }, - { x: 1599609600000, y: 41500, g: 'All others' }, - { x: 1599612300000, y: 42373, g: 'All others' }, - { x: 1599615000000, y: 49785, g: 'All others' }, - { x: 1599617700000, y: 42237, g: 'All others' }, - { x: 1599620400000, y: 43114, g: 'All others' }, - { x: 1599623100000, y: 40716, g: 'All others' }, - { x: 1599625800000, y: 39248, g: 'All others' }, - { x: 1599628500000, y: 37674, g: 'All others' }, - { x: 1599631200000, y: 41072, g: 'All others' }, - { x: 1599633900000, y: 37049, g: 'All others' }, - { x: 1599636600000, y: 38561, g: 'All others' }, - { x: 1599639300000, y: 40895, g: 'All others' }, - { x: 1599642000000, y: 45490, g: 'All others' }, - { x: 1599644700000, y: 46559, g: 'All others' }, - { x: 1599647400000, y: 40020, g: 'All others' }, - { x: 1599650100000, y: 44335, g: 'All others' }, - { x: 1599652800000, y: 47252, g: 'All others' }, - { x: 1599655500000, y: 48744, g: 'All others' }, - { x: 1599658200000, y: 55756, g: 'All others' }, - { x: 1599660900000, y: 56887, g: 'All others' }, - { x: 1599663600000, y: 66920, g: 'All others' }, - { x: 1599666300000, y: 40976, g: 'All others' }, - { x: 1599579900000, y: 226, g: 'end' }, - { x: 1599582600000, y: 547, g: 'end' }, - { x: 1599585300000, y: 532, g: 'end' }, - { x: 1599588000000, y: 551, g: 'end' }, - { x: 1599590700000, y: 543, g: 'end' }, - { x: 1599593400000, y: 547, g: 'end' }, - { x: 1599596100000, y: 656, g: 'end' }, - { x: 1599598800000, y: 543, g: 'end' }, - { x: 1599601500000, y: 616, g: 'end' }, - { x: 1599604200000, y: 539, g: 'end' }, - { x: 1599606900000, y: 539, g: 'end' }, - { x: 1599609600000, y: 547, g: 'end' }, - { x: 1599612300000, y: 616, g: 'end' }, - { x: 1599615000000, y: 640, g: 'end' }, - { x: 1599617700000, y: 614, g: 'end' }, - { x: 1599620400000, y: 545, g: 'end' }, - { x: 1599623100000, y: 537, g: 'end' }, - { x: 1599625800000, y: 544, g: 'end' }, - { x: 1599628500000, y: 571, g: 'end' }, - { x: 1599631200000, y: 743, g: 'end' }, - { x: 1599633900000, y: 560, g: 'end' }, - { x: 1599636600000, y: 598, g: 'end' }, - { x: 1599639300000, y: 613, g: 'end' }, - { x: 1599642000000, y: 563, g: 'end' }, - { x: 1599644700000, y: 540, g: 'end' }, - { x: 1599647400000, y: 538, g: 'end' }, - { x: 1599650100000, y: 549, g: 'end' }, - { x: 1599652800000, y: 561, g: 'end' }, - { x: 1599655500000, y: 554, g: 'end' }, - { x: 1599658200000, y: 561, g: 'end' }, - { x: 1599660900000, y: 542, g: 'end' }, - { x: 1599663600000, y: 712, g: 'end' }, - { x: 1599666300000, y: 326, g: 'end' }, - { x: 1599579900000, y: 226, g: 'fork' }, - { x: 1599582600000, y: 546, g: 'fork' }, - { x: 1599585300000, y: 532, g: 'fork' }, - { x: 1599588000000, y: 551, g: 'fork' }, - { x: 1599590700000, y: 543, g: 'fork' }, - { x: 1599593400000, y: 547, g: 'fork' }, - { x: 1599596100000, y: 656, g: 'fork' }, - { x: 1599598800000, y: 543, g: 'fork' }, - { x: 1599601500000, y: 616, g: 'fork' }, - { x: 1599604200000, y: 539, g: 'fork' }, - { x: 1599606900000, y: 539, g: 'fork' }, - { x: 1599609600000, y: 547, g: 'fork' }, - { x: 1599612300000, y: 616, g: 'fork' }, - { x: 1599615000000, y: 640, g: 'fork' }, - { x: 1599617700000, y: 614, g: 'fork' }, - { x: 1599620400000, y: 545, g: 'fork' }, - { x: 1599623100000, y: 537, g: 'fork' }, - { x: 1599625800000, y: 544, g: 'fork' }, - { x: 1599628500000, y: 571, g: 'fork' }, - { x: 1599631200000, y: 743, g: 'fork' }, - { x: 1599633900000, y: 560, g: 'fork' }, - { x: 1599636600000, y: 598, g: 'fork' }, - { x: 1599639300000, y: 613, g: 'fork' }, - { x: 1599642000000, y: 563, g: 'fork' }, - { x: 1599644700000, y: 540, g: 'fork' }, - { x: 1599647400000, y: 538, g: 'fork' }, - { x: 1599650100000, y: 549, g: 'fork' }, - { x: 1599652800000, y: 561, g: 'fork' }, - { x: 1599655500000, y: 554, g: 'fork' }, - { x: 1599658200000, y: 561, g: 'fork' }, - { x: 1599660900000, y: 542, g: 'fork' }, - { x: 1599663600000, y: 712, g: 'fork' }, - { x: 1599666300000, y: 326, g: 'fork' }, - { x: 1599579900000, y: 189, g: 'exec' }, - { x: 1599582600000, y: 456, g: 'exec' }, - { x: 1599585300000, y: 445, g: 'exec' }, - { x: 1599588000000, y: 458, g: 'exec' }, - { x: 1599590700000, y: 455, g: 'exec' }, - { x: 1599593400000, y: 457, g: 'exec' }, - { x: 1599596100000, y: 511, g: 'exec' }, - { x: 1599598800000, y: 455, g: 'exec' }, - { x: 1599601500000, y: 493, g: 'exec' }, - { x: 1599604200000, y: 451, g: 'exec' }, - { x: 1599606900000, y: 453, g: 'exec' }, - { x: 1599609600000, y: 460, g: 'exec' }, - { x: 1599612300000, y: 521, g: 'exec' }, - { x: 1599615000000, y: 504, g: 'exec' }, - { x: 1599617700000, y: 490, g: 'exec' }, - { x: 1599620400000, y: 457, g: 'exec' }, - { x: 1599623100000, y: 447, g: 'exec' }, - { x: 1599625800000, y: 454, g: 'exec' }, - { x: 1599628500000, y: 469, g: 'exec' }, - { x: 1599631200000, y: 642, g: 'exec' }, - { x: 1599633900000, y: 465, g: 'exec' }, - { x: 1599636600000, y: 481, g: 'exec' }, - { x: 1599639300000, y: 489, g: 'exec' }, - { x: 1599642000000, y: 466, g: 'exec' }, - { x: 1599644700000, y: 452, g: 'exec' }, - { x: 1599647400000, y: 448, g: 'exec' }, - { x: 1599650100000, y: 457, g: 'exec' }, - { x: 1599652800000, y: 471, g: 'exec' }, - { x: 1599655500000, y: 460, g: 'exec' }, - { x: 1599658200000, y: 463, g: 'exec' }, - { x: 1599660900000, y: 455, g: 'exec' }, - { x: 1599663600000, y: 547, g: 'exec' }, - { x: 1599666300000, y: 262, g: 'exec' }, - { x: 1599579900000, y: 59, g: 'disconnect_received' }, - { x: 1599582600000, y: 151, g: 'disconnect_received' }, - { x: 1599585300000, y: 139, g: 'disconnect_received' }, - { x: 1599588000000, y: 144, g: 'disconnect_received' }, - { x: 1599590700000, y: 143, g: 'disconnect_received' }, - { x: 1599593400000, y: 144, g: 'disconnect_received' }, - { x: 1599596100000, y: 202, g: 'disconnect_received' }, - { x: 1599598800000, y: 142, g: 'disconnect_received' }, - { x: 1599601500000, y: 180, g: 'disconnect_received' }, - { x: 1599604200000, y: 144, g: 'disconnect_received' }, - { x: 1599606900000, y: 143, g: 'disconnect_received' }, - { x: 1599609600000, y: 137, g: 'disconnect_received' }, - { x: 1599612300000, y: 150, g: 'disconnect_received' }, - { x: 1599615000000, y: 195, g: 'disconnect_received' }, - { x: 1599617700000, y: 178, g: 'disconnect_received' }, - { x: 1599620400000, y: 144, g: 'disconnect_received' }, - { x: 1599623100000, y: 143, g: 'disconnect_received' }, - { x: 1599625800000, y: 142, g: 'disconnect_received' }, - { x: 1599628500000, y: 157, g: 'disconnect_received' }, - { x: 1599631200000, y: 166, g: 'disconnect_received' }, - { x: 1599633900000, y: 153, g: 'disconnect_received' }, - { x: 1599636600000, y: 168, g: 'disconnect_received' }, - { x: 1599639300000, y: 175, g: 'disconnect_received' }, - { x: 1599642000000, y: 158, g: 'disconnect_received' }, - { x: 1599644700000, y: 142, g: 'disconnect_received' }, - { x: 1599647400000, y: 144, g: 'disconnect_received' }, - { x: 1599650100000, y: 147, g: 'disconnect_received' }, - { x: 1599652800000, y: 139, g: 'disconnect_received' }, - { x: 1599655500000, y: 145, g: 'disconnect_received' }, - { x: 1599658200000, y: 158, g: 'disconnect_received' }, - { x: 1599660900000, y: 137, g: 'disconnect_received' }, - { x: 1599663600000, y: 234, g: 'disconnect_received' }, - { x: 1599666300000, y: 95, g: 'disconnect_received' }, - { x: 1599579900000, y: 60, g: 'connection_attempted' }, - { x: 1599582600000, y: 145, g: 'connection_attempted' }, - { x: 1599585300000, y: 138, g: 'connection_attempted' }, - { x: 1599588000000, y: 144, g: 'connection_attempted' }, - { x: 1599590700000, y: 140, g: 'connection_attempted' }, - { x: 1599593400000, y: 144, g: 'connection_attempted' }, - { x: 1599596100000, y: 145, g: 'connection_attempted' }, - { x: 1599598800000, y: 137, g: 'connection_attempted' }, - { x: 1599601500000, y: 142, g: 'connection_attempted' }, - { x: 1599604200000, y: 142, g: 'connection_attempted' }, - { x: 1599606900000, y: 143, g: 'connection_attempted' }, - { x: 1599609600000, y: 132, g: 'connection_attempted' }, - { x: 1599612300000, y: 153, g: 'connection_attempted' }, - { x: 1599615000000, y: 143, g: 'connection_attempted' }, - { x: 1599617700000, y: 142, g: 'connection_attempted' }, - { x: 1599620400000, y: 143, g: 'connection_attempted' }, - { x: 1599623100000, y: 142, g: 'connection_attempted' }, - { x: 1599625800000, y: 140, g: 'connection_attempted' }, - { x: 1599628500000, y: 140, g: 'connection_attempted' }, - { x: 1599631200000, y: 148, g: 'connection_attempted' }, - { x: 1599633900000, y: 142, g: 'connection_attempted' }, - { x: 1599636600000, y: 139, g: 'connection_attempted' }, - { x: 1599639300000, y: 139, g: 'connection_attempted' }, - { x: 1599642000000, y: 142, g: 'connection_attempted' }, - { x: 1599644700000, y: 142, g: 'connection_attempted' }, - { x: 1599647400000, y: 143, g: 'connection_attempted' }, - { x: 1599650100000, y: 141, g: 'connection_attempted' }, - { x: 1599652800000, y: 137, g: 'connection_attempted' }, - { x: 1599655500000, y: 141, g: 'connection_attempted' }, - { x: 1599658200000, y: 144, g: 'connection_attempted' }, - { x: 1599660900000, y: 138, g: 'connection_attempted' }, - { x: 1599663600000, y: 145, g: 'connection_attempted' }, - { x: 1599666300000, y: 78, g: 'connection_attempted' }, - { x: 1599579900000, y: 24, g: 'creation' }, - { x: 1599582600000, y: 53, g: 'creation' }, - { x: 1599585300000, y: 50, g: 'creation' }, - { x: 1599588000000, y: 54, g: 'creation' }, - { x: 1599590700000, y: 55, g: 'creation' }, - { x: 1599593400000, y: 53, g: 'creation' }, - { x: 1599596100000, y: 54, g: 'creation' }, - { x: 1599598800000, y: 54, g: 'creation' }, - { x: 1599601500000, y: 55, g: 'creation' }, - { x: 1599604200000, y: 52, g: 'creation' }, - { x: 1599606900000, y: 51, g: 'creation' }, - { x: 1599609600000, y: 58, g: 'creation' }, - { x: 1599612300000, y: 122, g: 'creation' }, - { x: 1599615000000, y: 54, g: 'creation' }, - { x: 1599617700000, y: 54, g: 'creation' }, - { x: 1599620400000, y: 56, g: 'creation' }, - { x: 1599623100000, y: 53, g: 'creation' }, - { x: 1599625800000, y: 55, g: 'creation' }, - { x: 1599628500000, y: 51, g: 'creation' }, - { x: 1599631200000, y: 144, g: 'creation' }, - { x: 1599633900000, y: 54, g: 'creation' }, - { x: 1599636600000, y: 53, g: 'creation' }, - { x: 1599639300000, y: 51, g: 'creation' }, - { x: 1599642000000, y: 57, g: 'creation' }, - { x: 1599644700000, y: 55, g: 'creation' }, - { x: 1599647400000, y: 52, g: 'creation' }, - { x: 1599650100000, y: 52, g: 'creation' }, - { x: 1599652800000, y: 57, g: 'creation' }, - { x: 1599655500000, y: 56, g: 'creation' }, - { x: 1599658200000, y: 53, g: 'creation' }, - { x: 1599660900000, y: 51, g: 'creation' }, - { x: 1599663600000, y: 56, g: 'creation' }, - { x: 1599666300000, y: 31, g: 'creation' }, - { x: 1599579900000, y: 23, g: 'deletion' }, - { x: 1599582600000, y: 53, g: 'deletion' }, - { x: 1599585300000, y: 50, g: 'deletion' }, - { x: 1599588000000, y: 54, g: 'deletion' }, - { x: 1599590700000, y: 54, g: 'deletion' }, - { x: 1599593400000, y: 53, g: 'deletion' }, - { x: 1599596100000, y: 53, g: 'deletion' }, - { x: 1599598800000, y: 54, g: 'deletion' }, - { x: 1599601500000, y: 55, g: 'deletion' }, - { x: 1599604200000, y: 52, g: 'deletion' }, - { x: 1599606900000, y: 51, g: 'deletion' }, - { x: 1599609600000, y: 55, g: 'deletion' }, - { x: 1599612300000, y: 121, g: 'deletion' }, - { x: 1599615000000, y: 54, g: 'deletion' }, - { x: 1599617700000, y: 53, g: 'deletion' }, - { x: 1599620400000, y: 55, g: 'deletion' }, - { x: 1599623100000, y: 53, g: 'deletion' }, - { x: 1599625800000, y: 54, g: 'deletion' }, - { x: 1599628500000, y: 51, g: 'deletion' }, - { x: 1599631200000, y: 146, g: 'deletion' }, - { x: 1599633900000, y: 54, g: 'deletion' }, - { x: 1599636600000, y: 53, g: 'deletion' }, - { x: 1599639300000, y: 51, g: 'deletion' }, - { x: 1599642000000, y: 55, g: 'deletion' }, - { x: 1599644700000, y: 55, g: 'deletion' }, - { x: 1599647400000, y: 52, g: 'deletion' }, - { x: 1599650100000, y: 55, g: 'deletion' }, - { x: 1599652800000, y: 55, g: 'deletion' }, - { x: 1599655500000, y: 55, g: 'deletion' }, - { x: 1599658200000, y: 53, g: 'deletion' }, - { x: 1599660900000, y: 51, g: 'deletion' }, - { x: 1599663600000, y: 55, g: 'deletion' }, - { x: 1599666300000, y: 31, g: 'deletion' }, - { x: 1599579900000, y: 19, g: 'File Delete (rule: FileDelete)' }, - { x: 1599582600000, y: 46, g: 'File Delete (rule: FileDelete)' }, - { x: 1599585300000, y: 47, g: 'File Delete (rule: FileDelete)' }, - { x: 1599588000000, y: 47, g: 'File Delete (rule: FileDelete)' }, - { x: 1599590700000, y: 47, g: 'File Delete (rule: FileDelete)' }, - { x: 1599593400000, y: 45, g: 'File Delete (rule: FileDelete)' }, - { x: 1599596100000, y: 48, g: 'File Delete (rule: FileDelete)' }, - { x: 1599598800000, y: 46, g: 'File Delete (rule: FileDelete)' }, - { x: 1599601500000, y: 45, g: 'File Delete (rule: FileDelete)' }, - { x: 1599604200000, y: 47, g: 'File Delete (rule: FileDelete)' }, - { x: 1599606900000, y: 47, g: 'File Delete (rule: FileDelete)' }, - { x: 1599609600000, y: 60, g: 'File Delete (rule: FileDelete)' }, - { x: 1599612300000, y: 45, g: 'File Delete (rule: FileDelete)' }, - { x: 1599615000000, y: 46, g: 'File Delete (rule: FileDelete)' }, - { x: 1599617700000, y: 46, g: 'File Delete (rule: FileDelete)' }, - { x: 1599620400000, y: 47, g: 'File Delete (rule: FileDelete)' }, - { x: 1599623100000, y: 88, g: 'File Delete (rule: FileDelete)' }, - { x: 1599625800000, y: 53, g: 'File Delete (rule: FileDelete)' }, - { x: 1599628500000, y: 46, g: 'File Delete (rule: FileDelete)' }, - { x: 1599631200000, y: 49, g: 'File Delete (rule: FileDelete)' }, - { x: 1599633900000, y: 45, g: 'File Delete (rule: FileDelete)' }, - { x: 1599636600000, y: 48, g: 'File Delete (rule: FileDelete)' }, - { x: 1599639300000, y: 46, g: 'File Delete (rule: FileDelete)' }, - { x: 1599642000000, y: 46, g: 'File Delete (rule: FileDelete)' }, - { x: 1599644700000, y: 45, g: 'File Delete (rule: FileDelete)' }, - { x: 1599647400000, y: 47, g: 'File Delete (rule: FileDelete)' }, - { x: 1599650100000, y: 47, g: 'File Delete (rule: FileDelete)' }, - { x: 1599652800000, y: 45, g: 'File Delete (rule: FileDelete)' }, - { x: 1599655500000, y: 331, g: 'File Delete (rule: FileDelete)' }, - { x: 1599658200000, y: 45, g: 'File Delete (rule: FileDelete)' }, - { x: 1599660900000, y: 47, g: 'File Delete (rule: FileDelete)' }, - { x: 1599663600000, y: 47, g: 'File Delete (rule: FileDelete)' }, - { x: 1599666300000, y: 28, g: 'File Delete (rule: FileDelete)' }, - { x: 1599579900000, y: 3, g: 'session_id_change' }, - { x: 1599582600000, y: 9, g: 'session_id_change' }, - { x: 1599585300000, y: 7, g: 'session_id_change' }, - { x: 1599588000000, y: 10, g: 'session_id_change' }, - { x: 1599590700000, y: 7, g: 'session_id_change' }, - { x: 1599593400000, y: 10, g: 'session_id_change' }, - { x: 1599596100000, y: 63, g: 'session_id_change' }, - { x: 1599598800000, y: 7, g: 'session_id_change' }, - { x: 1599601500000, y: 45, g: 'session_id_change' }, - { x: 1599604200000, y: 4, g: 'session_id_change' }, - { x: 1599606900000, y: 5, g: 'session_id_change' }, - { x: 1599609600000, y: 6, g: 'session_id_change' }, - { x: 1599612300000, y: 6, g: 'session_id_change' }, - { x: 1599615000000, y: 55, g: 'session_id_change' }, - { x: 1599617700000, y: 43, g: 'session_id_change' }, - { x: 1599620400000, y: 8, g: 'session_id_change' }, - { x: 1599623100000, y: 9, g: 'session_id_change' }, - { x: 1599625800000, y: 7, g: 'session_id_change' }, - { x: 1599628500000, y: 21, g: 'session_id_change' }, - { x: 1599631200000, y: 26, g: 'session_id_change' }, - { x: 1599633900000, y: 17, g: 'session_id_change' }, - { x: 1599636600000, y: 34, g: 'session_id_change' }, - { x: 1599639300000, y: 41, g: 'session_id_change' }, - { x: 1599642000000, y: 18, g: 'session_id_change' }, - { x: 1599644700000, y: 4, g: 'session_id_change' }, - { x: 1599647400000, y: 11, g: 'session_id_change' }, - { x: 1599650100000, y: 9, g: 'session_id_change' }, - { x: 1599652800000, y: 7, g: 'session_id_change' }, - { x: 1599655500000, y: 12, g: 'session_id_change' }, - { x: 1599658200000, y: 16, g: 'session_id_change' }, - { x: 1599660900000, y: 7, g: 'session_id_change' }, - { x: 1599663600000, y: 99, g: 'session_id_change' }, - { x: 1599666300000, y: 21, g: 'session_id_change' }, - ], -}; - -export const mockDnsSearchStrategyResponse: IEsSearchResponse = { - isPartial: false, - isRunning: false, - rawResponse: { - took: 36, - timed_out: false, - _shards: { - total: 55, - successful: 55, - skipped: 38, - failed: 0, - }, - hits: { - max_score: 0, - hits: [], - total: 0, - }, - aggregations: { - dns_count: { - value: 3, - }, - dns_name_query_count: { - doc_count_error_upper_bound: 0, - sum_other_doc_count: 0, - buckets: [ - { - key: 'google.com', - doc_count: 1, - unique_domains: { - value: 1, - }, - dns_question_name: { - buckets: [ - { - key_as_string: '2020-11-12T01:13:31.395Z', - key: 1605143611395, - doc_count: 0, - }, - { - key_as_string: '2020-11-12T01:21:48.492Z', - key: 1605144108492, - doc_count: 0, - }, - { - key_as_string: '2020-11-12T01:30:05.589Z', - key: 1605144605589, - doc_count: 0, - }, - { - key_as_string: '2020-11-12T01:38:22.686Z', - key: 1605145102686, - doc_count: 0, - }, - { - key_as_string: '2020-11-12T01:46:39.783Z', - key: 1605145599783, - doc_count: 0, - }, - { - key_as_string: '2020-11-12T01:54:56.880Z', - key: 1605146096880, - doc_count: 0, - }, - { - key_as_string: '2020-11-12T02:03:13.977Z', - key: 1605146593977, - doc_count: 0, - }, - { - key_as_string: '2020-11-12T02:11:31.074Z', - key: 1605147091074, - doc_count: 0, - }, - { - key_as_string: '2020-11-12T02:19:48.171Z', - key: 1605147588171, - doc_count: 0, - }, - { - key_as_string: '2020-11-12T02:28:05.268Z', - key: 1605148085268, - doc_count: 0, - }, - { - key_as_string: '2020-11-12T02:36:22.365Z', - key: 1605148582365, - doc_count: 0, - }, - { - key_as_string: '2020-11-12T02:44:39.462Z', - key: 1605149079462, - doc_count: 0, - }, - { - key_as_string: '2020-11-12T02:52:56.559Z', - key: 1605149576559, - doc_count: 0, - }, - { - key_as_string: '2020-11-12T03:01:13.656Z', - key: 1605150073656, - doc_count: 0, - }, - { - key_as_string: '2020-11-12T03:09:30.753Z', - key: 1605150570753, - doc_count: 0, - }, - { - key_as_string: '2020-11-12T03:17:47.850Z', - key: 1605151067850, - doc_count: 0, - }, - { - key_as_string: '2020-11-12T03:26:04.947Z', - key: 1605151564947, - doc_count: 0, - }, - { - key_as_string: '2020-11-12T03:34:22.044Z', - key: 1605152062044, - doc_count: 0, - }, - { - key_as_string: '2020-11-12T03:42:39.141Z', - key: 1605152559141, - doc_count: 0, - }, - { - key_as_string: '2020-11-12T03:50:56.238Z', - key: 1605153056238, - doc_count: 1, - }, - { - key_as_string: '2020-11-12T03:59:13.335Z', - key: 1605153553335, - doc_count: 0, - }, - { - key_as_string: '2020-11-12T04:07:30.432Z', - key: 1605154050432, - doc_count: 0, - }, - { - key_as_string: '2020-11-12T04:15:47.529Z', - key: 1605154547529, - doc_count: 0, - }, - { - key_as_string: '2020-11-12T04:24:04.626Z', - key: 1605155044626, - doc_count: 0, - }, - { - key_as_string: '2020-11-12T04:32:21.723Z', - key: 1605155541723, - doc_count: 0, - }, - { - key_as_string: '2020-11-12T04:40:38.820Z', - key: 1605156038820, - doc_count: 0, - }, - { - key_as_string: '2020-11-12T04:48:55.917Z', - key: 1605156535917, - doc_count: 0, - }, - { - key_as_string: '2020-11-12T04:57:13.014Z', - key: 1605157033014, - doc_count: 0, - }, - { - key_as_string: '2020-11-12T05:05:30.111Z', - key: 1605157530111, - doc_count: 0, - }, - { - key_as_string: '2020-11-12T05:13:47.208Z', - key: 1605158027208, - doc_count: 0, - }, - { - key_as_string: '2020-11-12T05:22:04.305Z', - key: 1605158524305, - doc_count: 0, - }, - { - key_as_string: '2020-11-12T05:30:21.402Z', - key: 1605159021402, - doc_count: 0, - }, - { - key_as_string: '2020-11-12T05:38:38.499Z', - key: 1605159518499, - doc_count: 0, - }, - ], - }, - dns_bytes_in: { - value: 0, - }, - dns_bytes_out: { - value: 0, - }, - }, - { - key: 'google.internal', - doc_count: 1, - unique_domains: { - value: 1, - }, - dns_question_name: { - buckets: [ - { - key_as_string: '2020-11-12T01:13:31.395Z', - key: 1605143611395, - doc_count: 0, - }, - { - key_as_string: '2020-11-12T01:21:48.492Z', - key: 1605144108492, - doc_count: 0, - }, - { - key_as_string: '2020-11-12T01:30:05.589Z', - key: 1605144605589, - doc_count: 0, - }, - { - key_as_string: '2020-11-12T01:38:22.686Z', - key: 1605145102686, - doc_count: 0, - }, - { - key_as_string: '2020-11-12T01:46:39.783Z', - key: 1605145599783, - doc_count: 0, - }, - { - key_as_string: '2020-11-12T01:54:56.880Z', - key: 1605146096880, - doc_count: 0, - }, - { - key_as_string: '2020-11-12T02:03:13.977Z', - key: 1605146593977, - doc_count: 0, - }, - { - key_as_string: '2020-11-12T02:11:31.074Z', - key: 1605147091074, - doc_count: 0, - }, - { - key_as_string: '2020-11-12T02:19:48.171Z', - key: 1605147588171, - doc_count: 0, - }, - { - key_as_string: '2020-11-12T02:28:05.268Z', - key: 1605148085268, - doc_count: 0, - }, - { - key_as_string: '2020-11-12T02:36:22.365Z', - key: 1605148582365, - doc_count: 0, - }, - { - key_as_string: '2020-11-12T02:44:39.462Z', - key: 1605149079462, - doc_count: 0, - }, - { - key_as_string: '2020-11-12T02:52:56.559Z', - key: 1605149576559, - doc_count: 0, - }, - { - key_as_string: '2020-11-12T03:01:13.656Z', - key: 1605150073656, - doc_count: 0, - }, - { - key_as_string: '2020-11-12T03:09:30.753Z', - key: 1605150570753, - doc_count: 0, - }, - { - key_as_string: '2020-11-12T03:17:47.850Z', - key: 1605151067850, - doc_count: 0, - }, - { - key_as_string: '2020-11-12T03:26:04.947Z', - key: 1605151564947, - doc_count: 0, - }, - { - key_as_string: '2020-11-12T03:34:22.044Z', - key: 1605152062044, - doc_count: 0, - }, - { - key_as_string: '2020-11-12T03:42:39.141Z', - key: 1605152559141, - doc_count: 0, - }, - { - key_as_string: '2020-11-12T03:50:56.238Z', - key: 1605153056238, - doc_count: 1, - }, - { - key_as_string: '2020-11-12T03:59:13.335Z', - key: 1605153553335, - doc_count: 0, - }, - { - key_as_string: '2020-11-12T04:07:30.432Z', - key: 1605154050432, - doc_count: 0, - }, - { - key_as_string: '2020-11-12T04:15:47.529Z', - key: 1605154547529, - doc_count: 0, - }, - { - key_as_string: '2020-11-12T04:24:04.626Z', - key: 1605155044626, - doc_count: 0, - }, - { - key_as_string: '2020-11-12T04:32:21.723Z', - key: 1605155541723, - doc_count: 0, - }, - { - key_as_string: '2020-11-12T04:40:38.820Z', - key: 1605156038820, - doc_count: 0, - }, - { - key_as_string: '2020-11-12T04:48:55.917Z', - key: 1605156535917, - doc_count: 0, - }, - { - key_as_string: '2020-11-12T04:57:13.014Z', - key: 1605157033014, - doc_count: 0, - }, - { - key_as_string: '2020-11-12T05:05:30.111Z', - key: 1605157530111, - doc_count: 0, - }, - { - key_as_string: '2020-11-12T05:13:47.208Z', - key: 1605158027208, - doc_count: 0, - }, - { - key_as_string: '2020-11-12T05:22:04.305Z', - key: 1605158524305, - doc_count: 0, - }, - { - key_as_string: '2020-11-12T05:30:21.402Z', - key: 1605159021402, - doc_count: 0, - }, - { - key_as_string: '2020-11-12T05:38:38.499Z', - key: 1605159518499, - doc_count: 0, - }, - ], - }, - dns_bytes_in: { - value: 0, - }, - dns_bytes_out: { - value: 0, - }, - }, - { - key: 'windows.net', - doc_count: 1, - unique_domains: { - value: 1, - }, - dns_question_name: { - buckets: [ - { - key_as_string: '2020-11-12T01:13:31.395Z', - key: 1605143611395, - doc_count: 0, - }, - { - key_as_string: '2020-11-12T01:21:48.492Z', - key: 1605144108492, - doc_count: 0, - }, - { - key_as_string: '2020-11-12T01:30:05.589Z', - key: 1605144605589, - doc_count: 0, - }, - { - key_as_string: '2020-11-12T01:38:22.686Z', - key: 1605145102686, - doc_count: 0, - }, - { - key_as_string: '2020-11-12T01:46:39.783Z', - key: 1605145599783, - doc_count: 0, - }, - { - key_as_string: '2020-11-12T01:54:56.880Z', - key: 1605146096880, - doc_count: 0, - }, - { - key_as_string: '2020-11-12T02:03:13.977Z', - key: 1605146593977, - doc_count: 0, - }, - { - key_as_string: '2020-11-12T02:11:31.074Z', - key: 1605147091074, - doc_count: 0, - }, - { - key_as_string: '2020-11-12T02:19:48.171Z', - key: 1605147588171, - doc_count: 0, - }, - { - key_as_string: '2020-11-12T02:28:05.268Z', - key: 1605148085268, - doc_count: 0, - }, - { - key_as_string: '2020-11-12T02:36:22.365Z', - key: 1605148582365, - doc_count: 0, - }, - { - key_as_string: '2020-11-12T02:44:39.462Z', - key: 1605149079462, - doc_count: 0, - }, - { - key_as_string: '2020-11-12T02:52:56.559Z', - key: 1605149576559, - doc_count: 0, - }, - { - key_as_string: '2020-11-12T03:01:13.656Z', - key: 1605150073656, - doc_count: 1, - }, - { - key_as_string: '2020-11-12T03:09:30.753Z', - key: 1605150570753, - doc_count: 0, - }, - { - key_as_string: '2020-11-12T03:17:47.850Z', - key: 1605151067850, - doc_count: 0, - }, - { - key_as_string: '2020-11-12T03:26:04.947Z', - key: 1605151564947, - doc_count: 0, - }, - { - key_as_string: '2020-11-12T03:34:22.044Z', - key: 1605152062044, - doc_count: 0, - }, - { - key_as_string: '2020-11-12T03:42:39.141Z', - key: 1605152559141, - doc_count: 0, - }, - { - key_as_string: '2020-11-12T03:50:56.238Z', - key: 1605153056238, - doc_count: 0, - }, - { - key_as_string: '2020-11-12T03:59:13.335Z', - key: 1605153553335, - doc_count: 0, - }, - { - key_as_string: '2020-11-12T04:07:30.432Z', - key: 1605154050432, - doc_count: 0, - }, - { - key_as_string: '2020-11-12T04:15:47.529Z', - key: 1605154547529, - doc_count: 0, - }, - { - key_as_string: '2020-11-12T04:24:04.626Z', - key: 1605155044626, - doc_count: 0, - }, - { - key_as_string: '2020-11-12T04:32:21.723Z', - key: 1605155541723, - doc_count: 0, - }, - { - key_as_string: '2020-11-12T04:40:38.820Z', - key: 1605156038820, - doc_count: 0, - }, - { - key_as_string: '2020-11-12T04:48:55.917Z', - key: 1605156535917, - doc_count: 0, - }, - { - key_as_string: '2020-11-12T04:57:13.014Z', - key: 1605157033014, - doc_count: 0, - }, - { - key_as_string: '2020-11-12T05:05:30.111Z', - key: 1605157530111, - doc_count: 0, - }, - { - key_as_string: '2020-11-12T05:13:47.208Z', - key: 1605158027208, - doc_count: 0, - }, - { - key_as_string: '2020-11-12T05:22:04.305Z', - key: 1605158524305, - doc_count: 0, - }, - { - key_as_string: '2020-11-12T05:30:21.402Z', - key: 1605159021402, - doc_count: 0, - }, - { - key_as_string: '2020-11-12T05:38:38.499Z', - key: 1605159518499, - doc_count: 0, - }, - ], - }, - dns_bytes_in: { - value: 0, - }, - dns_bytes_out: { - value: 0, - }, - }, - ], - }, - }, - }, - total: 21, - loaded: 21, -}; - -export const formattedDnsSearchStrategyResponse: MatrixHistogramStrategyResponse = { - ...mockDnsSearchStrategyResponse, - inspect: { - dsl: [ - JSON.stringify( - { - allow_no_indices: true, - index: [ - 'apm-*-transaction*', - 'traces-apm*', - 'auditbeat-*', - 'endgame-*', - 'filebeat-*', - 'logs-*', - 'packetbeat-*', - 'winlogbeat-*', - ], - ignore_unavailable: true, - body: { - aggregations: { - dns_count: { cardinality: { field: 'dns.question.registered_domain' } }, - dns_name_query_count: { - terms: { - field: 'dns.question.registered_domain', - order: { unique_domains: 'desc' }, - size: 10, - }, - aggs: { - unique_domains: { cardinality: { field: 'dns.question.name' } }, - dns_question_name: { - date_histogram: { - field: '@timestamp', - fixed_interval: '2700000ms', - min_doc_count: 0, - extended_bounds: { min: 1599579675528, max: 1599666075529 }, - }, - }, - }, - }, - }, - query: { - bool: { - filter: [ - { bool: { must: [], filter: [{ match_all: {} }], should: [], must_not: [] } }, - { - range: { - '@timestamp': { - gte: '2020-09-08T15:41:15.528Z', - lte: '2020-09-09T15:41:15.529Z', - format: 'strict_date_optional_time', - }, - }, - }, - ], - must_not: [{ term: { 'dns.question.type': { value: 'PTR' } } }], - }, - }, - }, - size: 0, - track_total_hits: false, - }, - null, - 2 - ), - ], - }, - matrixHistogramData: [ - { x: 1605143611395, y: 0, g: 'google.com' }, - { x: 1605144108492, y: 0, g: 'google.com' }, - { x: 1605144605589, y: 0, g: 'google.com' }, - { x: 1605145102686, y: 0, g: 'google.com' }, - { x: 1605145599783, y: 0, g: 'google.com' }, - { x: 1605146096880, y: 0, g: 'google.com' }, - { x: 1605146593977, y: 0, g: 'google.com' }, - { x: 1605147091074, y: 0, g: 'google.com' }, - { x: 1605147588171, y: 0, g: 'google.com' }, - { x: 1605148085268, y: 0, g: 'google.com' }, - { x: 1605148582365, y: 0, g: 'google.com' }, - { x: 1605149079462, y: 0, g: 'google.com' }, - { x: 1605149576559, y: 0, g: 'google.com' }, - { x: 1605150073656, y: 0, g: 'google.com' }, - { x: 1605150570753, y: 0, g: 'google.com' }, - { x: 1605151067850, y: 0, g: 'google.com' }, - { x: 1605151564947, y: 0, g: 'google.com' }, - { x: 1605152062044, y: 0, g: 'google.com' }, - { x: 1605152559141, y: 0, g: 'google.com' }, - { x: 1605153056238, y: 1, g: 'google.com' }, - { x: 1605153553335, y: 0, g: 'google.com' }, - { x: 1605154050432, y: 0, g: 'google.com' }, - { x: 1605154547529, y: 0, g: 'google.com' }, - { x: 1605155044626, y: 0, g: 'google.com' }, - { x: 1605155541723, y: 0, g: 'google.com' }, - { x: 1605156038820, y: 0, g: 'google.com' }, - { x: 1605156535917, y: 0, g: 'google.com' }, - { x: 1605157033014, y: 0, g: 'google.com' }, - { x: 1605157530111, y: 0, g: 'google.com' }, - { x: 1605158027208, y: 0, g: 'google.com' }, - { x: 1605158524305, y: 0, g: 'google.com' }, - { x: 1605159021402, y: 0, g: 'google.com' }, - { x: 1605159518499, y: 0, g: 'google.com' }, - { x: 1605143611395, y: 0, g: 'google.internal' }, - { x: 1605144108492, y: 0, g: 'google.internal' }, - { x: 1605144605589, y: 0, g: 'google.internal' }, - { x: 1605145102686, y: 0, g: 'google.internal' }, - { x: 1605145599783, y: 0, g: 'google.internal' }, - { x: 1605146096880, y: 0, g: 'google.internal' }, - { x: 1605146593977, y: 0, g: 'google.internal' }, - { x: 1605147091074, y: 0, g: 'google.internal' }, - { x: 1605147588171, y: 0, g: 'google.internal' }, - { x: 1605148085268, y: 0, g: 'google.internal' }, - { x: 1605148582365, y: 0, g: 'google.internal' }, - { x: 1605149079462, y: 0, g: 'google.internal' }, - { x: 1605149576559, y: 0, g: 'google.internal' }, - { x: 1605150073656, y: 0, g: 'google.internal' }, - { x: 1605150570753, y: 0, g: 'google.internal' }, - { x: 1605151067850, y: 0, g: 'google.internal' }, - { x: 1605151564947, y: 0, g: 'google.internal' }, - { x: 1605152062044, y: 0, g: 'google.internal' }, - { x: 1605152559141, y: 0, g: 'google.internal' }, - { x: 1605153056238, y: 1, g: 'google.internal' }, - { x: 1605153553335, y: 0, g: 'google.internal' }, - { x: 1605154050432, y: 0, g: 'google.internal' }, - { x: 1605154547529, y: 0, g: 'google.internal' }, - { x: 1605155044626, y: 0, g: 'google.internal' }, - { x: 1605155541723, y: 0, g: 'google.internal' }, - { x: 1605156038820, y: 0, g: 'google.internal' }, - { x: 1605156535917, y: 0, g: 'google.internal' }, - { x: 1605157033014, y: 0, g: 'google.internal' }, - { x: 1605157530111, y: 0, g: 'google.internal' }, - { x: 1605158027208, y: 0, g: 'google.internal' }, - { x: 1605158524305, y: 0, g: 'google.internal' }, - { x: 1605159021402, y: 0, g: 'google.internal' }, - { x: 1605159518499, y: 0, g: 'google.internal' }, - { x: 1605143611395, y: 0, g: 'windows.net' }, - { x: 1605144108492, y: 0, g: 'windows.net' }, - { x: 1605144605589, y: 0, g: 'windows.net' }, - { x: 1605145102686, y: 0, g: 'windows.net' }, - { x: 1605145599783, y: 0, g: 'windows.net' }, - { x: 1605146096880, y: 0, g: 'windows.net' }, - { x: 1605146593977, y: 0, g: 'windows.net' }, - { x: 1605147091074, y: 0, g: 'windows.net' }, - { x: 1605147588171, y: 0, g: 'windows.net' }, - { x: 1605148085268, y: 0, g: 'windows.net' }, - { x: 1605148582365, y: 0, g: 'windows.net' }, - { x: 1605149079462, y: 0, g: 'windows.net' }, - { x: 1605149576559, y: 0, g: 'windows.net' }, - { x: 1605150073656, y: 1, g: 'windows.net' }, - { x: 1605150570753, y: 0, g: 'windows.net' }, - { x: 1605151067850, y: 0, g: 'windows.net' }, - { x: 1605151564947, y: 0, g: 'windows.net' }, - { x: 1605152062044, y: 0, g: 'windows.net' }, - { x: 1605152559141, y: 0, g: 'windows.net' }, - { x: 1605153056238, y: 0, g: 'windows.net' }, - { x: 1605153553335, y: 0, g: 'windows.net' }, - { x: 1605154050432, y: 0, g: 'windows.net' }, - { x: 1605154547529, y: 0, g: 'windows.net' }, - { x: 1605155044626, y: 0, g: 'windows.net' }, - { x: 1605155541723, y: 0, g: 'windows.net' }, - { x: 1605156038820, y: 0, g: 'windows.net' }, - { x: 1605156535917, y: 0, g: 'windows.net' }, - { x: 1605157033014, y: 0, g: 'windows.net' }, - { x: 1605157530111, y: 0, g: 'windows.net' }, - { x: 1605158027208, y: 0, g: 'windows.net' }, - { x: 1605158524305, y: 0, g: 'windows.net' }, - { x: 1605159021402, y: 0, g: 'windows.net' }, - { x: 1605159518499, y: 0, g: 'windows.net' }, - ], - totalCount: 0, -}; - -export const formattedPreviewStrategyResponse = { - ...mockAlertsSearchStrategyResponse, - inspect: { - dsl: [ - JSON.stringify( - { - index: ['.siem-preview-signals-default'], - allow_no_indices: true, - ignore_unavailable: true, - track_total_hits: true, - body: { - aggregations: { - preview: { - terms: { - field: 'event.category', - missing: 'All others', - order: { _count: 'desc' }, - size: 10, - }, - aggs: { - preview: { - date_histogram: { - field: '@timestamp', - fixed_interval: '2700000ms', - min_doc_count: 0, - extended_bounds: { min: 1599574984482, max: 1599661384482 }, - }, - }, - }, - }, - }, - query: { - bool: { - filter: [ - { - bool: { - must: [], - filter: [ - { match_all: {} }, - { - bool: { - filter: [ - { - bool: { - should: [{ match: { 'signal.rule.id': 'test-preview-id' } }], - minimum_should_match: 1, - }, - }, - ], - }, - }, - ], - should: [], - must_not: [], - }, - }, - { - range: { - '@timestamp': { - gte: '2020-09-08T14:23:04.482Z', - lte: '2020-09-09T14:23:04.482Z', - format: 'strict_date_optional_time', - }, - }, - }, - ], - }, - }, - size: 0, - }, - }, - null, - 2 - ), - ], - }, - matrixHistogramData: [], - totalCount: 0, -}; diff --git a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/matrix_histogram/alerts/__mocks__/index.ts b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/matrix_histogram/alerts/__mocks__/index.ts deleted file mode 100644 index dda3395b54c1a..0000000000000 --- a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/matrix_histogram/alerts/__mocks__/index.ts +++ /dev/null @@ -1,116 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import type { MatrixHistogramRequestOptions } from '../../../../../../../common/api/search_strategy'; -import { MatrixHistogramQuery } from '../../../../../../../common/api/search_strategy'; -import { MatrixHistogramType } from '../../../../../../../common/search_strategy'; - -export const mockOptions: MatrixHistogramRequestOptions = { - defaultIndex: [ - 'apm-*-transaction*', - 'traces-apm*', - 'auditbeat-*', - 'endgame-*', - 'filebeat-*', - 'logs-*', - 'packetbeat-*', - 'winlogbeat-*', - ], - filterQuery: - '{"bool":{"must":[],"filter":[{"match_all":{}},{"bool":{"filter":[{"bool":{"should":[{"exists":{"field":"host.name"}}],"minimum_should_match":1}}]}}],"should":[],"must_not":[]}}', - histogramType: MatrixHistogramType.alerts, - timerange: { interval: '12h', from: '2020-09-08T14:23:04.482Z', to: '2020-09-09T14:23:04.482Z' }, - stackByField: 'event.module', - includeMissingData: false, - isPtrIncluded: false, - factoryQueryType: MatrixHistogramQuery, -}; - -export const expectedDsl = { - index: [ - 'apm-*-transaction*', - 'traces-apm*', - 'auditbeat-*', - 'endgame-*', - 'filebeat-*', - 'logs-*', - 'packetbeat-*', - 'winlogbeat-*', - ], - allow_no_indices: true, - ignore_unavailable: true, - track_total_hits: true, - body: { - aggregations: { - alertsGroup: { - terms: { - field: 'event.module', - missing: 'All others', - order: { _count: 'desc' }, - size: 10, - }, - aggs: { - alerts: { - date_histogram: { - field: '@timestamp', - fixed_interval: '2700000ms', - min_doc_count: 0, - extended_bounds: { min: 1599574984482, max: 1599661384482 }, - }, - }, - }, - }, - }, - query: { - bool: { - filter: [ - { - bool: { - must: [], - filter: [ - { match_all: {} }, - { - bool: { - filter: [ - { - bool: { - should: [{ exists: { field: 'host.name' } }], - minimum_should_match: 1, - }, - }, - ], - }, - }, - ], - should: [], - must_not: [], - }, - }, - { - bool: { - filter: [ - { - bool: { should: [{ match: { 'event.kind': 'alert' } }], minimum_should_match: 1 }, - }, - ], - }, - }, - { - range: { - '@timestamp': { - gte: '2020-09-08T14:23:04.482Z', - lte: '2020-09-09T14:23:04.482Z', - format: 'strict_date_optional_time', - }, - }, - }, - ], - }, - }, - size: 0, - }, -}; diff --git a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/matrix_histogram/alerts/index.test.ts b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/matrix_histogram/alerts/index.test.ts deleted file mode 100644 index 310161d13d25c..0000000000000 --- a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/matrix_histogram/alerts/index.test.ts +++ /dev/null @@ -1,23 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { alertsMatrixHistogramConfig } from '.'; -import { buildAlertsHistogramQuery } from './query.alerts_histogram.dsl'; - -jest.mock('./query.alerts_histogram.dsl', () => ({ - buildAlertsHistogramQuery: jest.fn(), -})); - -describe('alertsMatrixHistogramConfig', () => { - test('should export alertsMatrixHistogramConfig corrrectly', () => { - expect(alertsMatrixHistogramConfig).toEqual({ - aggName: 'aggregations.alertsGroup.buckets', - parseKey: 'alerts.buckets', - buildDsl: buildAlertsHistogramQuery, - }); - }); -}); diff --git a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/matrix_histogram/alerts/index.ts b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/matrix_histogram/alerts/index.ts deleted file mode 100644 index 59985a927aa8f..0000000000000 --- a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/matrix_histogram/alerts/index.ts +++ /dev/null @@ -1,15 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { MatrixHistogramTypeToAggName } from '../../../../../../common/search_strategy'; -import { buildAlertsHistogramQuery } from './query.alerts_histogram.dsl'; - -export const alertsMatrixHistogramConfig = { - buildDsl: buildAlertsHistogramQuery, - aggName: MatrixHistogramTypeToAggName.alerts, - parseKey: 'alerts.buckets', -}; diff --git a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/matrix_histogram/alerts/query.alerts_histogram.dsl.test.ts b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/matrix_histogram/alerts/query.alerts_histogram.dsl.test.ts deleted file mode 100644 index 19f6dc202824a..0000000000000 --- a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/matrix_histogram/alerts/query.alerts_histogram.dsl.test.ts +++ /dev/null @@ -1,15 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { buildAlertsHistogramQuery } from './query.alerts_histogram.dsl'; -import { mockOptions, expectedDsl } from './__mocks__'; - -describe('buildAlertsHistogramQuery', () => { - test('build query from options correctly', () => { - expect(buildAlertsHistogramQuery(mockOptions)).toEqual(expectedDsl); - }); -}); diff --git a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/matrix_histogram/alerts/query.alerts_histogram.dsl.ts b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/matrix_histogram/alerts/query.alerts_histogram.dsl.ts deleted file mode 100644 index bee0f1ac7f457..0000000000000 --- a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/matrix_histogram/alerts/query.alerts_histogram.dsl.ts +++ /dev/null @@ -1,101 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import moment from 'moment'; -import type { MatrixHistogramRequestOptions } from '../../../../../../common/api/search_strategy'; - -import { - createQueryFilterClauses, - calculateTimeSeriesInterval, -} from '../../../../../utils/build_query'; - -export const buildAlertsHistogramQuery = ({ - filterQuery, - timerange: { from, to }, - defaultIndex, - stackByField, -}: MatrixHistogramRequestOptions) => { - const filter = [ - ...createQueryFilterClauses(filterQuery), - { - bool: { - filter: [ - { - bool: { - should: [ - { - match: { - 'event.kind': 'alert', - }, - }, - ], - minimum_should_match: 1, - }, - }, - ], - }, - }, - { - range: { - '@timestamp': { - gte: from, - lte: to, - format: 'strict_date_optional_time', - }, - }, - }, - ]; - - const getHistogramAggregation = () => { - const interval = calculateTimeSeriesInterval(from, to); - const histogramTimestampField = '@timestamp'; - const dateHistogram = { - date_histogram: { - field: histogramTimestampField, - fixed_interval: interval, - min_doc_count: 0, - extended_bounds: { - min: moment(from).valueOf(), - max: moment(to).valueOf(), - }, - }, - }; - return { - alertsGroup: { - terms: { - field: stackByField, - missing: 'All others', - order: { - _count: 'desc', - }, - size: 10, - }, - aggs: { - alerts: dateHistogram, - }, - }, - }; - }; - - const dslQuery = { - index: defaultIndex, - allow_no_indices: true, - ignore_unavailable: true, - track_total_hits: true, - body: { - aggregations: getHistogramAggregation(), - query: { - bool: { - filter, - }, - }, - size: 0, - }, - }; - - return dslQuery; -}; diff --git a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/matrix_histogram/anomalies/__mocks__/index.ts b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/matrix_histogram/anomalies/__mocks__/index.ts deleted file mode 100644 index 69b1977f17083..0000000000000 --- a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/matrix_histogram/anomalies/__mocks__/index.ts +++ /dev/null @@ -1,95 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import type { MatrixHistogramRequestOptions } from '../../../../../../../common/api/search_strategy'; -import { MatrixHistogramQuery } from '../../../../../../../common/api/search_strategy'; -import { MatrixHistogramType } from '../../../../../../../common/search_strategy'; - -export const mockOptions: MatrixHistogramRequestOptions = { - defaultIndex: [ - 'apm-*-transaction*', - 'traces-apm*', - 'auditbeat-*', - 'endgame-*', - 'filebeat-*', - 'logs-*', - 'packetbeat-*', - 'winlogbeat-*', - ], - filterQuery: - '{"bool":{"must":[],"filter":[{"match_all":{}},{"bool":{"should":[],"minimum_should_match":1}},{"match_phrase":{"result_type":"record"}},null,{"range":{"record_score":{"gte":50}}}],"should":[{"exists":{"field":"source.ip"}},{"exists":{"field":"destination.ip"}}],"must_not":[],"minimum_should_match":1}}', - histogramType: MatrixHistogramType.anomalies, - timerange: { interval: '12h', from: '2020-09-08T15:14:35.566Z', to: '2020-09-09T15:14:35.566Z' }, - stackByField: 'job_id', - includeMissingData: false, - isPtrIncluded: false, - factoryQueryType: MatrixHistogramQuery, -}; - -export const expectedDsl = { - index: [ - 'apm-*-transaction*', - 'traces-apm*', - 'auditbeat-*', - 'endgame-*', - 'filebeat-*', - 'logs-*', - 'packetbeat-*', - 'winlogbeat-*', - ], - allow_no_indices: true, - ignore_unavailable: true, - track_total_hits: true, - body: { - aggs: { - anomalyActionGroup: { - terms: { field: 'job_id', order: { _count: 'desc' }, size: 10 }, - aggs: { - anomalies: { - date_histogram: { - field: 'timestamp', - fixed_interval: '2700000ms', - min_doc_count: 0, - extended_bounds: { min: 1599578075566, max: 1599664475566 }, - }, - }, - }, - }, - }, - query: { - bool: { - filter: [ - { - bool: { - must: [], - filter: [ - { match_all: {} }, - { bool: { should: [], minimum_should_match: 1 } }, - { match_phrase: { result_type: 'record' } }, - null, - { range: { record_score: { gte: 50 } } }, - ], - should: [{ exists: { field: 'source.ip' } }, { exists: { field: 'destination.ip' } }], - must_not: [], - minimum_should_match: 1, - }, - }, - { - range: { - timestamp: { - gte: '2020-09-08T15:14:35.566Z', - lte: '2020-09-09T15:14:35.566Z', - format: 'strict_date_optional_time', - }, - }, - }, - ], - }, - }, - size: 0, - }, -}; diff --git a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/matrix_histogram/anomalies/index.test.ts b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/matrix_histogram/anomalies/index.test.ts deleted file mode 100644 index 8664d967c5884..0000000000000 --- a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/matrix_histogram/anomalies/index.test.ts +++ /dev/null @@ -1,23 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { anomaliesMatrixHistogramConfig } from '.'; -import { buildAnomaliesHistogramQuery } from './query.anomalies_histogram.dsl'; - -jest.mock('./query.anomalies_histogram.dsl', () => ({ - buildAnomaliesHistogramQuery: jest.fn(), -})); - -describe('anomaliesMatrixHistogramConfig', () => { - test('should export anomaliesMatrixHistogramConfig corrrectly', () => { - expect(anomaliesMatrixHistogramConfig).toEqual({ - aggName: 'aggregations.anomalyActionGroup.buckets', - parseKey: 'anomalies.buckets', - buildDsl: buildAnomaliesHistogramQuery, - }); - }); -}); diff --git a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/matrix_histogram/anomalies/index.ts b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/matrix_histogram/anomalies/index.ts deleted file mode 100644 index c7e67566acfc2..0000000000000 --- a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/matrix_histogram/anomalies/index.ts +++ /dev/null @@ -1,15 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { MatrixHistogramTypeToAggName } from '../../../../../../common/search_strategy'; -import { buildAnomaliesHistogramQuery } from './query.anomalies_histogram.dsl'; - -export const anomaliesMatrixHistogramConfig = { - buildDsl: buildAnomaliesHistogramQuery, - aggName: MatrixHistogramTypeToAggName.anomalies, - parseKey: 'anomalies.buckets', -}; diff --git a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/matrix_histogram/anomalies/query.anomalies_histogram.dsl.test.ts b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/matrix_histogram/anomalies/query.anomalies_histogram.dsl.test.ts deleted file mode 100644 index ddf3a1f43b1b8..0000000000000 --- a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/matrix_histogram/anomalies/query.anomalies_histogram.dsl.test.ts +++ /dev/null @@ -1,15 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { buildAnomaliesHistogramQuery } from './query.anomalies_histogram.dsl'; -import { mockOptions, expectedDsl } from './__mocks__'; - -describe('buildAnomaliesHistogramQuery', () => { - test('build query from options correctly', () => { - expect(buildAnomaliesHistogramQuery(mockOptions)).toEqual(expectedDsl); - }); -}); diff --git a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/matrix_histogram/anomalies/query.anomalies_histogram.dsl.ts b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/matrix_histogram/anomalies/query.anomalies_histogram.dsl.ts deleted file mode 100644 index da1b72341c71a..0000000000000 --- a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/matrix_histogram/anomalies/query.anomalies_histogram.dsl.ts +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import moment from 'moment'; - -import { - createQueryFilterClauses, - calculateTimeSeriesInterval, -} from '../../../../../utils/build_query'; -import type { MatrixHistogramRequestOptions } from '../../../../../../common/api/search_strategy'; - -export const buildAnomaliesHistogramQuery = ({ - filterQuery, - timerange: { from, to }, - defaultIndex, - stackByField = 'job_id', -}: MatrixHistogramRequestOptions) => { - const filter = [ - ...createQueryFilterClauses(filterQuery), - { - range: { - timestamp: { - gte: from, - lte: to, - format: 'strict_date_optional_time', - }, - }, - }, - ]; - - const getHistogramAggregation = () => { - const interval = calculateTimeSeriesInterval(from, to); - const histogramTimestampField = 'timestamp'; - const dateHistogram = { - date_histogram: { - field: histogramTimestampField, - fixed_interval: interval, - min_doc_count: 0, - extended_bounds: { - min: moment(from).valueOf(), - max: moment(to).valueOf(), - }, - }, - }; - return { - anomalyActionGroup: { - terms: { - field: stackByField, - order: { - _count: 'desc', - }, - size: 10, - }, - aggs: { - anomalies: dateHistogram, - }, - }, - }; - }; - - const dslQuery = { - index: defaultIndex, - allow_no_indices: true, - ignore_unavailable: true, - track_total_hits: true, - body: { - aggs: getHistogramAggregation(), - query: { - bool: { - filter, - }, - }, - size: 0, - }, - }; - - return dslQuery; -}; diff --git a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/matrix_histogram/authentications/__mocks__/index.ts b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/matrix_histogram/authentications/__mocks__/index.ts deleted file mode 100644 index 0f7145dc95320..0000000000000 --- a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/matrix_histogram/authentications/__mocks__/index.ts +++ /dev/null @@ -1,86 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import type { MatrixHistogramRequestOptions } from '../../../../../../../common/api/search_strategy'; -import { MatrixHistogramQuery } from '../../../../../../../common/api/search_strategy'; -import { MatrixHistogramType } from '../../../../../../../common/search_strategy'; - -export const mockOptions: MatrixHistogramRequestOptions = { - defaultIndex: [ - 'apm-*-transaction*', - 'traces-apm*', - 'auditbeat-*', - 'endgame-*', - 'filebeat-*', - 'logs-*', - 'packetbeat-*', - 'winlogbeat-*', - ], - filterQuery: '{"bool":{"must":[],"filter":[{"match_all":{}}],"should":[],"must_not":[]}}', - histogramType: MatrixHistogramType.authentications, - timerange: { interval: '12h', from: '2020-09-08T15:22:00.325Z', to: '2020-09-09T15:22:00.325Z' }, - stackByField: 'event.outcome', - includeMissingData: false, - isPtrIncluded: false, - factoryQueryType: MatrixHistogramQuery, -}; - -export const expectedDsl = { - index: [ - 'apm-*-transaction*', - 'traces-apm*', - 'auditbeat-*', - 'endgame-*', - 'filebeat-*', - 'logs-*', - 'packetbeat-*', - 'winlogbeat-*', - ], - allow_no_indices: true, - ignore_unavailable: true, - track_total_hits: true, - body: { - aggregations: { - eventActionGroup: { - terms: { - field: 'event.outcome', - include: ['success', 'failure'], - order: { _count: 'desc' }, - size: 2, - }, - aggs: { - events: { - date_histogram: { - field: '@timestamp', - fixed_interval: '2700000ms', - min_doc_count: 0, - extended_bounds: { min: 1599578520325, max: 1599664920325 }, - }, - }, - }, - }, - }, - query: { - bool: { - filter: [ - { bool: { must: [], filter: [{ match_all: {} }], should: [], must_not: [] } }, - { bool: { must: [{ term: { 'event.category': 'authentication' } }] } }, - { - range: { - '@timestamp': { - gte: '2020-09-08T15:22:00.325Z', - lte: '2020-09-09T15:22:00.325Z', - format: 'strict_date_optional_time', - }, - }, - }, - ], - }, - }, - size: 0, - }, -}; diff --git a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/matrix_histogram/authentications/index.test.ts b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/matrix_histogram/authentications/index.test.ts deleted file mode 100644 index 553c833adc295..0000000000000 --- a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/matrix_histogram/authentications/index.test.ts +++ /dev/null @@ -1,23 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { authenticationsMatrixHistogramConfig } from '.'; -import { buildAuthenticationsHistogramQuery } from './query.authentications_histogram.dsl'; - -jest.mock('./query.authentications_histogram.dsl', () => ({ - buildAuthenticationsHistogramQuery: jest.fn(), -})); - -describe('authenticationsMatrixHistogramConfig', () => { - test('should export authenticationsMatrixHistogramConfig corrrectly', () => { - expect(authenticationsMatrixHistogramConfig).toEqual({ - aggName: 'aggregations.eventActionGroup.buckets', - parseKey: 'events.buckets', - buildDsl: buildAuthenticationsHistogramQuery, - }); - }); -}); diff --git a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/matrix_histogram/authentications/index.ts b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/matrix_histogram/authentications/index.ts deleted file mode 100644 index 377cd0a019d3f..0000000000000 --- a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/matrix_histogram/authentications/index.ts +++ /dev/null @@ -1,15 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { MatrixHistogramTypeToAggName } from '../../../../../../common/search_strategy'; -import { buildAuthenticationsHistogramQuery } from './query.authentications_histogram.dsl'; - -export const authenticationsMatrixHistogramConfig = { - buildDsl: buildAuthenticationsHistogramQuery, - aggName: MatrixHistogramTypeToAggName.authentications, - parseKey: 'events.buckets', -}; diff --git a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/matrix_histogram/authentications/query.authentications_histogram.dsl.test.ts b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/matrix_histogram/authentications/query.authentications_histogram.dsl.test.ts deleted file mode 100644 index 80e5a64137ae6..0000000000000 --- a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/matrix_histogram/authentications/query.authentications_histogram.dsl.test.ts +++ /dev/null @@ -1,15 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { buildAuthenticationsHistogramQuery } from './query.authentications_histogram.dsl'; -import { mockOptions, expectedDsl } from './__mocks__'; - -describe('buildAuthenticationsHistogramQuery', () => { - test('build query from options correctly', () => { - expect(buildAuthenticationsHistogramQuery(mockOptions)).toEqual(expectedDsl); - }); -}); diff --git a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/matrix_histogram/authentications/query.authentications_histogram.dsl.ts b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/matrix_histogram/authentications/query.authentications_histogram.dsl.ts deleted file mode 100644 index a0bae6ad6d322..0000000000000 --- a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/matrix_histogram/authentications/query.authentications_histogram.dsl.ts +++ /dev/null @@ -1,94 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import moment from 'moment'; - -import { - createQueryFilterClauses, - calculateTimeSeriesInterval, -} from '../../../../../utils/build_query'; -import type { MatrixHistogramRequestOptions } from '../../../../../../common/api/search_strategy'; - -export const buildAuthenticationsHistogramQuery = ({ - filterQuery, - timerange: { from, to }, - defaultIndex, - stackByField = 'event.outcome', -}: MatrixHistogramRequestOptions) => { - const filter = [ - ...createQueryFilterClauses(filterQuery), - { - bool: { - must: [ - { - term: { - 'event.category': 'authentication', - }, - }, - ], - }, - }, - { - range: { - '@timestamp': { - gte: from, - lte: to, - format: 'strict_date_optional_time', - }, - }, - }, - ]; - - const getHistogramAggregation = () => { - const interval = calculateTimeSeriesInterval(from, to); - const histogramTimestampField = '@timestamp'; - const dateHistogram = { - date_histogram: { - field: histogramTimestampField, - fixed_interval: interval, - min_doc_count: 0, - extended_bounds: { - min: moment(from).valueOf(), - max: moment(to).valueOf(), - }, - }, - }; - return { - eventActionGroup: { - terms: { - field: stackByField, - include: ['success', 'failure'], - order: { - _count: 'desc', - }, - size: 2, - }, - aggs: { - events: dateHistogram, - }, - }, - }; - }; - - const dslQuery = { - index: defaultIndex, - allow_no_indices: true, - ignore_unavailable: true, - track_total_hits: true, - body: { - aggregations: getHistogramAggregation(), - query: { - bool: { - filter, - }, - }, - size: 0, - }, - }; - - return dslQuery; -}; diff --git a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/matrix_histogram/dns/__mocks__/index.ts b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/matrix_histogram/dns/__mocks__/index.ts deleted file mode 100644 index 5823206d58b63..0000000000000 --- a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/matrix_histogram/dns/__mocks__/index.ts +++ /dev/null @@ -1,87 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import type { MatrixHistogramRequestOptions } from '../../../../../../../common/api/search_strategy'; -import { MatrixHistogramQuery } from '../../../../../../../common/api/search_strategy'; -import { MatrixHistogramType } from '../../../../../../../common/search_strategy'; - -export const mockOptions: MatrixHistogramRequestOptions = { - defaultIndex: [ - 'apm-*-transaction*', - 'traces-apm*', - 'auditbeat-*', - 'endgame-*', - 'filebeat-*', - 'logs-*', - 'packetbeat-*', - 'winlogbeat-*', - ], - filterQuery: '{"bool":{"must":[],"filter":[{"match_all":{}}],"should":[],"must_not":[]}}', - histogramType: MatrixHistogramType.dns, - isPtrIncluded: false, - timerange: { interval: '12h', from: '2020-09-08T15:41:15.528Z', to: '2020-09-09T15:41:15.529Z' }, - stackByField: 'dns.question.registered_domain', - includeMissingData: false, - factoryQueryType: MatrixHistogramQuery, -}; - -export const expectedDsl = { - allow_no_indices: true, - index: [ - 'apm-*-transaction*', - 'traces-apm*', - 'auditbeat-*', - 'endgame-*', - 'filebeat-*', - 'logs-*', - 'packetbeat-*', - 'winlogbeat-*', - ], - ignore_unavailable: true, - body: { - aggregations: { - dns_count: { cardinality: { field: 'dns.question.registered_domain' } }, - dns_name_query_count: { - terms: { - field: 'dns.question.registered_domain', - order: { unique_domains: 'desc' }, - size: 10, - }, - aggs: { - unique_domains: { cardinality: { field: 'dns.question.name' } }, - dns_question_name: { - date_histogram: { - field: '@timestamp', - fixed_interval: '2700000ms', - min_doc_count: 0, - extended_bounds: { min: 1599579675528, max: 1599666075529 }, - }, - }, - }, - }, - }, - query: { - bool: { - filter: [ - { bool: { must: [], filter: [{ match_all: {} }], should: [], must_not: [] } }, - { - range: { - '@timestamp': { - gte: '2020-09-08T15:41:15.528Z', - lte: '2020-09-09T15:41:15.529Z', - format: 'strict_date_optional_time', - }, - }, - }, - ], - must_not: [{ term: { 'dns.question.type': { value: 'PTR' } } }], - }, - }, - }, - size: 0, - track_total_hits: false, -}; diff --git a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/matrix_histogram/dns/helpers.ts b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/matrix_histogram/dns/helpers.ts deleted file mode 100644 index 3e5cd71241422..0000000000000 --- a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/matrix_histogram/dns/helpers.ts +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { get, getOr } from 'lodash/fp'; -import type { - MatrixHistogramData, - MatrixHistogramParseData, - DnsHistogramSubBucket, -} from '../../../../../../common/search_strategy/security_solution/matrix_histogram'; - -export const getDnsParsedData = ( - data: MatrixHistogramParseData, - keyBucket: string -): MatrixHistogramData[] => { - let result: MatrixHistogramData[] = []; - data.forEach((bucketData: unknown) => { - const questionName = get('key', bucketData); - const histData = getOr([], keyBucket, bucketData).map( - // eslint-disable-next-line @typescript-eslint/naming-convention - ({ key, doc_count }: DnsHistogramSubBucket) => ({ - x: key, - y: doc_count, - g: questionName, - }) - ); - - result = [...result, ...histData]; - }); - return result; -}; diff --git a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/matrix_histogram/dns/index.test.ts b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/matrix_histogram/dns/index.test.ts deleted file mode 100644 index 1ee38fc5e6728..0000000000000 --- a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/matrix_histogram/dns/index.test.ts +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { dnsMatrixHistogramConfig } from '.'; -import { buildDnsHistogramQuery } from './query.dns_histogram.dsl'; -import { getDnsParsedData } from './helpers'; - -jest.mock('./query.dns_histogram.dsl', () => ({ - buildDnsHistogramQuery: jest.fn(), -})); - -jest.mock('./helpers', () => ({ - getDnsParsedData: jest.fn(), -})); - -describe('dnsMatrixHistogramConfig', () => { - test('should export dnsMatrixHistogramConfig corrrectly', () => { - expect(dnsMatrixHistogramConfig).toEqual({ - aggName: 'aggregations.dns_name_query_count.buckets', - parseKey: 'dns_question_name.buckets', - buildDsl: buildDnsHistogramQuery, - parser: getDnsParsedData, - }); - }); -}); diff --git a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/matrix_histogram/dns/index.ts b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/matrix_histogram/dns/index.ts deleted file mode 100644 index f52a760db842e..0000000000000 --- a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/matrix_histogram/dns/index.ts +++ /dev/null @@ -1,17 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { buildDnsHistogramQuery } from './query.dns_histogram.dsl'; -import { getDnsParsedData } from './helpers'; -import { MatrixHistogramTypeToAggName } from '../../../../../../common/search_strategy'; - -export const dnsMatrixHistogramConfig = { - buildDsl: buildDnsHistogramQuery, - aggName: MatrixHistogramTypeToAggName.dns, - parseKey: 'dns_question_name.buckets', - parser: getDnsParsedData, -}; diff --git a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/matrix_histogram/dns/query.dns_histogram.dsl.test.ts b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/matrix_histogram/dns/query.dns_histogram.dsl.test.ts deleted file mode 100644 index 024bbec987f9f..0000000000000 --- a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/matrix_histogram/dns/query.dns_histogram.dsl.test.ts +++ /dev/null @@ -1,15 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { buildDnsHistogramQuery } from './query.dns_histogram.dsl'; -import { mockOptions, expectedDsl } from './__mocks__'; - -describe('buildDnsHistogramQuery', () => { - test('build query from options correctly', () => { - expect(buildDnsHistogramQuery(mockOptions)).toEqual(expectedDsl); - }); -}); diff --git a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/matrix_histogram/dns/query.dns_histogram.dsl.ts b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/matrix_histogram/dns/query.dns_histogram.dsl.ts deleted file mode 100644 index 825f121c87fb3..0000000000000 --- a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/matrix_histogram/dns/query.dns_histogram.dsl.ts +++ /dev/null @@ -1,113 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import moment from 'moment'; - -import type { MatrixHistogramRequestOptions } from '../../../../../../common/api/search_strategy'; -import { - calculateTimeSeriesInterval, - createQueryFilterClauses, -} from '../../../../../utils/build_query'; - -const getCountAgg = () => ({ - dns_count: { - cardinality: { - field: 'dns.question.registered_domain', - }, - }, -}); - -const createIncludePTRFilter = (isPtrIncluded: boolean) => - isPtrIncluded - ? {} - : { - must_not: [ - { - term: { - 'dns.question.type': { - value: 'PTR', - }, - }, - }, - ], - }; - -const getHistogramAggregation = ({ from, to }: { from: string; to: string }) => { - const interval = calculateTimeSeriesInterval(from, to); - const histogramTimestampField = '@timestamp'; - - return { - date_histogram: { - field: histogramTimestampField, - fixed_interval: interval, - min_doc_count: 0, - extended_bounds: { - min: moment(from).valueOf(), - max: moment(to).valueOf(), - }, - }, - }; -}; - -export const buildDnsHistogramQuery = ({ - defaultIndex, - filterQuery, - isPtrIncluded = false, - stackByField = 'dns.question.registered_domain', - timerange: { from, to }, -}: MatrixHistogramRequestOptions) => { - const filter = [ - ...createQueryFilterClauses(filterQuery), - { - range: { - '@timestamp': { - gte: from, - lte: to, - format: 'strict_date_optional_time', - }, - }, - }, - ]; - - const dslQuery = { - allow_no_indices: true, - index: defaultIndex, - ignore_unavailable: true, - body: { - aggregations: { - ...getCountAgg(), - dns_name_query_count: { - terms: { - field: stackByField, - order: { - unique_domains: 'desc', - }, - size: 10, - }, - aggs: { - unique_domains: { - cardinality: { - field: 'dns.question.name', - }, - }, - dns_question_name: getHistogramAggregation({ from, to }), - }, - }, - }, - query: { - bool: { - filter, - ...createIncludePTRFilter(isPtrIncluded), - }, - }, - }, - size: 0, - track_total_hits: false, - }; - - return dslQuery; -}; diff --git a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/matrix_histogram/events/__mocks__/index.ts b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/matrix_histogram/events/__mocks__/index.ts deleted file mode 100644 index e1b25916ec978..0000000000000 --- a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/matrix_histogram/events/__mocks__/index.ts +++ /dev/null @@ -1,463 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import type { MatrixHistogramRequestOptions } from '../../../../../../../common/api/search_strategy'; -import { - MatrixHistogramQuery, - 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*', - 'traces-apm*', - 'auditbeat-*', - 'endgame-*', - 'filebeat-*', - 'logs-*', - 'packetbeat-*', - 'winlogbeat-*', - ], - factoryQueryType: MatrixHistogramQuery, - filterQuery: '{"bool":{"must":[],"filter":[{"match_all":{}}],"should":[],"must_not":[]}}', - histogramType: MatrixHistogramType.events, - timerange: { interval: '12h', from: '2020-09-08T16:11:26.215Z', to: '2020-09-09T16:11:26.215Z' }, - stackByField: 'event.action', - runtimeMappings, - includeMissingData: true, - isPtrIncluded: false, -}; - -export const expectedDsl = { - index: [ - 'apm-*-transaction*', - 'traces-apm*', - 'auditbeat-*', - 'endgame-*', - 'filebeat-*', - 'logs-*', - 'packetbeat-*', - 'winlogbeat-*', - ], - allow_no_indices: true, - ignore_unavailable: true, - track_total_hits: true, - body: { - aggregations: { - eventActionGroup: { - terms: { - field: 'event.action', - missing: 'All others', - order: { _count: 'desc' }, - size: 10, - }, - aggs: { - events: { - date_histogram: { - field: '@timestamp', - fixed_interval: '2700000ms', - min_doc_count: 0, - extended_bounds: { min: 1599581486215, max: 1599667886215 }, - }, - }, - }, - }, - }, - query: { - bool: { - filter: [ - { bool: { must: [], filter: [{ match_all: {} }], should: [], must_not: [] } }, - { - range: { - '@timestamp': { - gte: '2020-09-08T16:11:26.215Z', - lte: '2020-09-09T16:11:26.215Z', - format: 'strict_date_optional_time', - }, - }, - }, - ], - }, - }, - runtime_mappings: runtimeMappings, - size: 0, - }, -}; - -export const expectedThresholdDsl = { - index: [ - 'apm-*-transaction*', - 'traces-apm*', - 'auditbeat-*', - 'endgame-*', - 'filebeat-*', - 'logs-*', - 'packetbeat-*', - 'winlogbeat-*', - ], - allow_no_indices: true, - ignore_unavailable: true, - track_total_hits: true, - body: { - aggregations: { - eventActionGroup: { - terms: { - script: { - lang: 'painless', - source: "doc['host.name'].value + ':' + doc['agent.name'].value", - }, - order: { _count: 'desc' }, - size: 10, - }, - aggs: { - events: { - date_histogram: { - field: '@timestamp', - fixed_interval: '2700000ms', - min_doc_count: 200, - extended_bounds: { min: 1599581486215, max: 1599667886215 }, - }, - }, - }, - }, - }, - query: { - bool: { - filter: [ - { bool: { must: [], filter: [{ match_all: {} }], should: [], must_not: [] } }, - { - range: { - '@timestamp': { - gte: '2020-09-08T16:11:26.215Z', - lte: '2020-09-09T16:11:26.215Z', - format: 'strict_date_optional_time', - }, - }, - }, - ], - }, - }, - runtime_mappings: runtimeMappings, - size: 0, - }, -}; - -export const expectedThresholdMissingFieldDsl = { - index: [ - 'apm-*-transaction*', - 'traces-apm*', - 'auditbeat-*', - 'endgame-*', - 'filebeat-*', - 'logs-*', - 'packetbeat-*', - 'winlogbeat-*', - ], - allow_no_indices: true, - ignore_unavailable: true, - track_total_hits: true, - body: { - aggregations: { - eventActionGroup: { - terms: { - field: 'event.action', - missing: 'All others', - order: { _count: 'desc' }, - size: 10, - }, - aggs: { - events: { - date_histogram: { - field: '@timestamp', - fixed_interval: '2700000ms', - min_doc_count: 200, - extended_bounds: { min: 1599581486215, max: 1599667886215 }, - }, - }, - }, - }, - }, - query: { - bool: { - filter: [ - { bool: { must: [], filter: [{ match_all: {} }], should: [], must_not: [] } }, - { - range: { - '@timestamp': { - gte: '2020-09-08T16:11:26.215Z', - lte: '2020-09-09T16:11:26.215Z', - format: 'strict_date_optional_time', - }, - }, - }, - ], - }, - }, - runtime_mappings: runtimeMappings, - size: 0, - }, -}; - -export const expectedThresholdWithCardinalityDsl = { - allow_no_indices: true, - body: { - aggregations: { - eventActionGroup: { - aggs: { - cardinality_check: { - bucket_selector: { - buckets_path: { cardinalityCount: 'cardinality_count' }, - script: 'params.cardinalityCount >= 10', - }, - }, - cardinality_count: { cardinality: { field: 'agent.name' } }, - events: { - date_histogram: { - extended_bounds: { max: 1599667886215, min: 1599581486215 }, - field: '@timestamp', - fixed_interval: '2700000ms', - min_doc_count: 200, - }, - }, - }, - terms: { - field: 'event.action', - missing: 'All others', - order: { _count: 'desc' }, - size: 10, - }, - }, - }, - query: { - bool: { - filter: [ - { bool: { filter: [{ match_all: {} }], must: [], must_not: [], should: [] } }, - { - range: { - '@timestamp': { - format: 'strict_date_optional_time', - gte: '2020-09-08T16:11:26.215Z', - lte: '2020-09-09T16:11:26.215Z', - }, - }, - }, - ], - }, - }, - runtime_mappings: runtimeMappings, - size: 0, - }, - ignore_unavailable: true, - index: [ - 'apm-*-transaction*', - 'traces-apm*', - 'auditbeat-*', - 'endgame-*', - 'filebeat-*', - 'logs-*', - 'packetbeat-*', - 'winlogbeat-*', - ], - track_total_hits: true, -}; - -export const expectedThresholdGroupWithCardinalityDsl = { - allow_no_indices: true, - body: { - aggregations: { - eventActionGroup: { - aggs: { - cardinality_check: { - bucket_selector: { - buckets_path: { cardinalityCount: 'cardinality_count' }, - script: 'params.cardinalityCount >= 10', - }, - }, - cardinality_count: { cardinality: { field: 'agent.name' } }, - events: { - date_histogram: { - extended_bounds: { max: 1599667886215, min: 1599581486215 }, - field: '@timestamp', - fixed_interval: '2700000ms', - min_doc_count: 200, - }, - }, - }, - terms: { - order: { _count: 'desc' }, - script: { - lang: 'painless', - source: "doc['host.name'].value + ':' + doc['agent.name'].value", - }, - size: 10, - }, - }, - }, - query: { - bool: { - filter: [ - { bool: { filter: [{ match_all: {} }], must: [], must_not: [], should: [] } }, - { - range: { - '@timestamp': { - format: 'strict_date_optional_time', - gte: '2020-09-08T16:11:26.215Z', - lte: '2020-09-09T16:11:26.215Z', - }, - }, - }, - ], - }, - }, - runtime_mappings: runtimeMappings, - size: 0, - }, - ignore_unavailable: true, - index: [ - 'apm-*-transaction*', - 'traces-apm*', - 'auditbeat-*', - 'endgame-*', - 'filebeat-*', - 'logs-*', - 'packetbeat-*', - 'winlogbeat-*', - ], - track_total_hits: true, -}; - -export const expectedIpIncludingMissingDataDsl = { - index: [ - 'apm-*-transaction*', - 'traces-apm*', - 'auditbeat-*', - 'endgame-*', - 'filebeat-*', - 'logs-*', - 'packetbeat-*', - 'winlogbeat-*', - ], - allow_no_indices: true, - ignore_unavailable: true, - track_total_hits: true, - body: { - aggregations: { - eventActionGroup: { - terms: { - field: 'source.ip', - missing: '0.0.0.0', - value_type: 'ip', - order: { _count: 'desc' }, - size: 10, - }, - aggs: { - events: { - date_histogram: { - field: '@timestamp', - fixed_interval: '2700000ms', - min_doc_count: 0, - extended_bounds: { min: 1599581486215, max: 1599667886215 }, - }, - }, - }, - }, - }, - query: { - bool: { - filter: [ - { - bool: { - must: [], - filter: [{ match_all: {} }], - should: [], - must_not: [{ exists: { field: 'source.ip' } }], - }, - }, - { - range: { - '@timestamp': { - gte: '2020-09-08T16:11:26.215Z', - lte: '2020-09-09T16:11:26.215Z', - format: 'strict_date_optional_time', - }, - }, - }, - ], - }, - }, - runtime_mappings: runtimeMappings, - size: 0, - }, -}; - -export const expectedIpNotIncludingMissingDataDsl = { - index: [ - 'apm-*-transaction*', - 'traces-apm*', - 'auditbeat-*', - 'endgame-*', - 'filebeat-*', - 'logs-*', - 'packetbeat-*', - 'winlogbeat-*', - ], - allow_no_indices: true, - ignore_unavailable: true, - track_total_hits: true, - body: { - aggregations: { - eventActionGroup: { - terms: { field: 'source.ip', order: { _count: 'desc' }, size: 10, value_type: 'ip' }, - aggs: { - events: { - date_histogram: { - field: '@timestamp', - fixed_interval: '2700000ms', - min_doc_count: 0, - extended_bounds: { min: 1599581486215, max: 1599667886215 }, - }, - }, - }, - }, - }, - query: { - bool: { - filter: [ - { - bool: { - must: [], - filter: [{ match_all: {} }], - should: [], - must_not: [], - }, - }, - { exists: { field: 'source.ip' } }, - { - range: { - '@timestamp': { - gte: '2020-09-08T16:11:26.215Z', - lte: '2020-09-09T16:11:26.215Z', - format: 'strict_date_optional_time', - }, - }, - }, - ], - }, - }, - runtime_mappings: runtimeMappings, - size: 0, - }, -}; diff --git a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/matrix_histogram/events/helpers.test.ts b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/matrix_histogram/events/helpers.test.ts deleted file mode 100644 index 477381778a367..0000000000000 --- a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/matrix_histogram/events/helpers.test.ts +++ /dev/null @@ -1,175 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import type { BaseQuery } from './helpers'; -import { buildThresholdTermsQuery, buildThresholdCardinalityQuery } from './helpers'; - -const BASE_QUERY: BaseQuery = { - eventActionGroup: { - terms: { - order: { - _count: 'desc', - }, - size: 10, - }, - aggs: { - events: { - date_histogram: { - field: '@timestamp', - fixed_interval: '5000ms', - min_doc_count: 0, - extended_bounds: { - min: 1599581486215, - max: 1599667886215, - }, - }, - }, - }, - }, -}; - -const STACK_BY_FIELD = 'event.action'; - -describe('buildEventsHistogramQuery - helpers', () => { - describe('buildThresholdTermsQuery', () => { - test('it builds a terms query using script if threshold field/s exist', () => { - const query = buildThresholdTermsQuery({ - query: BASE_QUERY, - fields: ['agent.name', 'host.name'], - stackByField: STACK_BY_FIELD, - missing: {}, - }); - expect(query).toEqual({ - eventActionGroup: { - aggs: { - events: { - date_histogram: { - extended_bounds: { max: 1599667886215, min: 1599581486215 }, - field: '@timestamp', - fixed_interval: '5000ms', - min_doc_count: 0, - }, - }, - }, - terms: { - order: { _count: 'desc' }, - script: { - lang: 'painless', - source: "doc['agent.name'].value + ':' + doc['host.name'].value", - }, - size: 10, - }, - }, - }); - }); - - test('it builds a terms query using default stackByField if threshold field/s do not exist', () => { - const query = buildThresholdTermsQuery({ - query: BASE_QUERY, - fields: [], - stackByField: STACK_BY_FIELD, - missing: { missing: 'All others' }, - }); - expect(query).toEqual({ - eventActionGroup: { - aggs: { - events: { - date_histogram: { - extended_bounds: { max: 1599667886215, min: 1599581486215 }, - field: '@timestamp', - fixed_interval: '5000ms', - min_doc_count: 0, - }, - }, - }, - terms: { - field: 'event.action', - missing: 'All others', - order: { _count: 'desc' }, - size: 10, - }, - }, - }); - }); - }); - - describe('buildThresholdCardinalityQuery', () => { - const TERMS_QUERY = { - eventActionGroup: { - terms: { - field: 'host.name', - order: { _count: 'desc' }, - size: 10, - min_doc_count: 200, - }, - aggs: { - events: { - date_histogram: { - field: '@timestamp', - fixed_interval: '2700000ms', - min_doc_count: 0, - extended_bounds: { min: 1599581486215, max: 1599667886215 }, - }, - }, - }, - }, - }; - - test('it builds query with cardinality', () => { - const query = buildThresholdCardinalityQuery({ - query: TERMS_QUERY, - cardinalityField: 'agent.name', - cardinalityValue: '100', - }); - expect(query).toEqual({ - eventActionGroup: { - aggs: { - cardinality_check: { - bucket_selector: { - buckets_path: { cardinalityCount: 'cardinality_count' }, - script: 'params.cardinalityCount >= 100', - }, - }, - cardinality_count: { cardinality: { field: 'agent.name' } }, - events: { - date_histogram: { - extended_bounds: { max: 1599667886215, min: 1599581486215 }, - field: '@timestamp', - fixed_interval: '2700000ms', - min_doc_count: 0, - }, - }, - }, - terms: { field: 'host.name', min_doc_count: 200, order: { _count: 'desc' }, size: 10 }, - }, - }); - }); - - test('it builds a terms query using default stackByField if threshold field/s do not exist', () => { - const query = buildThresholdCardinalityQuery({ - query: TERMS_QUERY, - cardinalityField: '', - cardinalityValue: '', - }); - expect(query).toEqual({ - eventActionGroup: { - aggs: { - events: { - date_histogram: { - extended_bounds: { max: 1599667886215, min: 1599581486215 }, - field: '@timestamp', - fixed_interval: '2700000ms', - min_doc_count: 0, - }, - }, - }, - terms: { field: 'host.name', min_doc_count: 200, order: { _count: 'desc' }, size: 10 }, - }, - }); - }); - }); -}); diff --git a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/matrix_histogram/events/helpers.ts b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/matrix_histogram/events/helpers.ts deleted file mode 100644 index 6aed879371a0a..0000000000000 --- a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/matrix_histogram/events/helpers.ts +++ /dev/null @@ -1,114 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -export interface BaseQuery { - eventActionGroup: { - terms: { - min_doc_count?: number; - order?: { - _count?: string; - }; - size?: number; - field?: string | string[]; - script?: { - lang: string; - source: string; - }; - missing?: string; - }; - aggs: { - events?: unknown; - cardinality_count?: { - cardinality?: { - field?: string; - }; - }; - cardinality_check?: { - bucket_selector?: { - buckets_path?: { - cardinalityCount?: string; - }; - script?: string; - }; - }; - }; - }; -} - -export const buildThresholdTermsQuery = ({ - query, - fields, - stackByField, - missing, -}: { - query: BaseQuery; - fields: string[]; - stackByField: string; - missing: { missing?: string }; -}): BaseQuery => { - if (fields.length > 1) { - return { - eventActionGroup: { - ...query.eventActionGroup, - terms: { - ...query.eventActionGroup.terms, - script: { - lang: 'painless', - source: fields.map((f) => `doc['${f}'].value`).join(` + ':' + `), - }, - }, - }, - }; - } else { - return { - eventActionGroup: { - ...query.eventActionGroup, - terms: { - ...query.eventActionGroup.terms, - field: fields[0] ?? stackByField, - ...missing, - }, - }, - }; - } -}; - -export const buildThresholdCardinalityQuery = ({ - query, - cardinalityField, - cardinalityValue, -}: { - query: BaseQuery; - cardinalityField: string | undefined; - cardinalityValue: string; -}): BaseQuery => { - if (cardinalityField != null && cardinalityField !== '' && cardinalityValue !== '') { - return { - eventActionGroup: { - ...query.eventActionGroup, - aggs: { - ...query.eventActionGroup.aggs, - cardinality_count: { - cardinality: { - field: cardinalityField, - }, - }, - cardinality_check: { - bucket_selector: { - buckets_path: { - cardinalityCount: 'cardinality_count', - }, - script: `params.cardinalityCount >= ${cardinalityValue}`, - }, - }, - }, - }, - }; - } else { - return query; - } -}; diff --git a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/matrix_histogram/events/index.test.ts b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/matrix_histogram/events/index.test.ts deleted file mode 100644 index 6d52262c047d6..0000000000000 --- a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/matrix_histogram/events/index.test.ts +++ /dev/null @@ -1,23 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { eventsMatrixHistogramConfig } from '.'; -import { buildEventsHistogramQuery } from './query.events_histogram.dsl'; - -jest.mock('./query.events_histogram.dsl', () => ({ - buildEventsHistogramQuery: jest.fn(), -})); - -describe('eventsMatrixHistogramConfig', () => { - test('should export eventsMatrixHistogramConfig corrrectly', () => { - expect(eventsMatrixHistogramConfig).toEqual({ - aggName: 'aggregations.eventActionGroup.buckets', - parseKey: 'events.buckets', - buildDsl: buildEventsHistogramQuery, - }); - }); -}); diff --git a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/matrix_histogram/events/index.ts b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/matrix_histogram/events/index.ts deleted file mode 100644 index 954cd6509e2b0..0000000000000 --- a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/matrix_histogram/events/index.ts +++ /dev/null @@ -1,15 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { MatrixHistogramTypeToAggName } from '../../../../../../common/search_strategy'; -import { buildEventsHistogramQuery } from './query.events_histogram.dsl'; - -export const eventsMatrixHistogramConfig = { - buildDsl: buildEventsHistogramQuery, - aggName: MatrixHistogramTypeToAggName.events, - parseKey: 'events.buckets', -}; diff --git a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/matrix_histogram/events/query.events_histogram.dsl.test.ts b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/matrix_histogram/events/query.events_histogram.dsl.test.ts deleted file mode 100644 index 472b0eb23b0ee..0000000000000 --- a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/matrix_histogram/events/query.events_histogram.dsl.test.ts +++ /dev/null @@ -1,90 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { buildEventsHistogramQuery } from './query.events_histogram.dsl'; -import { - mockOptions, - expectedDsl, - expectedThresholdDsl, - expectedThresholdMissingFieldDsl, - expectedThresholdWithCardinalityDsl, - expectedThresholdGroupWithCardinalityDsl, - expectedIpIncludingMissingDataDsl, - expectedIpNotIncludingMissingDataDsl, -} from './__mocks__'; - -describe('buildEventsHistogramQuery', () => { - test('build query from options correctly', () => { - expect(buildEventsHistogramQuery(mockOptions)).toEqual(expectedDsl); - }); - - test('builds query with just min doc if "threshold.field" is empty array and "missing" param included', () => { - expect( - buildEventsHistogramQuery({ - ...mockOptions, - threshold: { field: [], value: '200', cardinality: { field: [], value: '0' } }, - }) - ).toEqual(expectedThresholdMissingFieldDsl); - }); - - test('builds query with specified threshold fields and without "missing" param if "threshold.field" is multi field', () => { - expect( - buildEventsHistogramQuery({ - ...mockOptions, - threshold: { - field: ['host.name', 'agent.name'], - value: '200', - }, - }) - ).toEqual(expectedThresholdDsl); - }); - - test('builds query with specified threshold cardinality if defined', () => { - expect( - buildEventsHistogramQuery({ - ...mockOptions, - threshold: { - field: [], - value: '200', - cardinality: { field: ['agent.name'], value: '10' }, - }, - }) - ).toEqual(expectedThresholdWithCardinalityDsl); - }); - - test('builds query with specified threshold group fields and cardinality if defined', () => { - expect( - buildEventsHistogramQuery({ - ...mockOptions, - threshold: { - field: ['host.name', 'agent.name'], - value: '200', - cardinality: { field: ['agent.name'], value: '10' }, - }, - }) - ).toEqual(expectedThresholdGroupWithCardinalityDsl); - }); - - test('builds query with stack by ip and including missing data', () => { - expect( - buildEventsHistogramQuery({ - ...mockOptions, - stackByField: 'source.ip', - }) - ).toEqual(expectedIpIncludingMissingDataDsl); - }); - - test('builds query with stack by ip and not including missing data', () => { - expect( - buildEventsHistogramQuery({ - ...mockOptions, - includeMissingData: false, - stackByField: 'source.ip', - }) - ).toEqual(expectedIpNotIncludingMissingDataDsl); - }); -}); diff --git a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/matrix_histogram/events/query.events_histogram.dsl.ts b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/matrix_histogram/events/query.events_histogram.dsl.ts deleted file mode 100644 index fe09a005770fe..0000000000000 --- a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/matrix_histogram/events/query.events_histogram.dsl.ts +++ /dev/null @@ -1,173 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import moment from 'moment'; - -import { showAllOthersBucket } from '../../../../../../common/constants'; -import { - createQueryFilterClauses, - calculateTimeSeriesInterval, -} from '../../../../../utils/build_query'; -import type { MatrixHistogramRequestOptions } from '../../../../../../common/api/search_strategy'; -import * as i18n from './translations'; -import type { BaseQuery } from './helpers'; -import { buildThresholdCardinalityQuery, buildThresholdTermsQuery } from './helpers'; - -export const buildEventsHistogramQuery = ({ - filterQuery, - timerange: { from, to }, - defaultIndex, - stackByField = 'event.action', - threshold, - includeMissingData, - runtimeMappings, -}: MatrixHistogramRequestOptions) => { - const [queryFilterFirstClause, ...queryFilterClauses] = createQueryFilterClauses(filterQuery); - const stackByIpField = - stackByField != null && - showAllOthersBucket.includes(stackByField) && - stackByField.endsWith('.ip'); - - const filter = [ - ...[ - { - ...queryFilterFirstClause, - bool: { - ...(queryFilterFirstClause.bool || {}), - must_not: [ - ...(queryFilterFirstClause.bool?.must_not || []), - ...(stackByIpField && includeMissingData - ? [ - { - exists: { - field: stackByField, - }, - }, - ] - : []), - ], - }, - }, - ...queryFilterClauses, - ], - ...(stackByIpField && !includeMissingData - ? [ - { - exists: { - field: stackByField, - }, - }, - ] - : []), - { - range: { - '@timestamp': { - gte: from, - lte: to, - format: 'strict_date_optional_time', - }, - }, - }, - ]; - - const getHistogramAggregation = () => { - const interval = calculateTimeSeriesInterval(from, to); - const histogramTimestampField = '@timestamp'; - const dateHistogram = { - date_histogram: { - field: histogramTimestampField, - fixed_interval: interval, - min_doc_count: threshold != null ? Number(threshold?.value) : 0, - extended_bounds: { - min: moment(from).valueOf(), - max: moment(to).valueOf(), - }, - }, - }; - - const missing = - stackByField != null && showAllOthersBucket.includes(stackByField) - ? { - ...(includeMissingData - ? stackByField?.endsWith('.ip') - ? { missing: '0.0.0.0' } - : { missing: i18n.ALL_OTHERS } - : {}), - ...(stackByField?.endsWith('.ip') ? { value_type: 'ip' } : {}), - } - : {}; - - if (threshold != null) { - const query: BaseQuery = { - eventActionGroup: { - terms: { - order: { - _count: 'desc', - }, - size: 10, - }, - aggs: { - events: dateHistogram, - }, - }, - }; - const baseQuery = buildThresholdTermsQuery({ - query, - fields: threshold.field ?? [], - stackByField, - missing, - }); - - if (threshold.cardinality != null) { - const enrichedQuery = buildThresholdCardinalityQuery({ - query: baseQuery, - cardinalityField: threshold.cardinality.field[0], - cardinalityValue: threshold.cardinality.value, - }); - - return enrichedQuery; - } - - return baseQuery; - } - - return { - eventActionGroup: { - terms: { - field: stackByField, - ...missing, - order: { - _count: 'desc', - }, - size: 10, - }, - aggs: { - events: dateHistogram, - }, - }, - }; - }; - - const dslQuery = { - index: defaultIndex, - allow_no_indices: true, - ignore_unavailable: true, - track_total_hits: true, - body: { - aggregations: getHistogramAggregation(), - query: { - bool: { - filter, - }, - }, - runtime_mappings: runtimeMappings, - size: 0, - }, - }; - - return dslQuery; -}; diff --git a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/matrix_histogram/events/translations.ts b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/matrix_histogram/events/translations.ts deleted file mode 100644 index fd3356d4ac6af..0000000000000 --- a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/matrix_histogram/events/translations.ts +++ /dev/null @@ -1,15 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { i18n } from '@kbn/i18n'; - -export const ALL_OTHERS = i18n.translate( - 'xpack.securitySolution.detectionEngine.alerts.histogram.allOthersGroupingLabel', - { - defaultMessage: 'All others', - } -); diff --git a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/matrix_histogram/helpers.test.ts b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/matrix_histogram/helpers.test.ts deleted file mode 100644 index 3492f8097f676..0000000000000 --- a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/matrix_histogram/helpers.test.ts +++ /dev/null @@ -1,22 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import type { MatrixHistogramType } from '../../../../../common/search_strategy'; -import { getGenericData } from './helpers'; -import { stackedByBooleanField, stackedByTextField, result, textResult } from './mock_data'; - -describe('getGenericData', () => { - test('stack by a boolean field', () => { - const res = getGenericData(stackedByBooleanField, 'events.bucket'); - expect(res).toEqual(result); - }); - - test('stack by a text field', () => { - const res = getGenericData(stackedByTextField, 'events.bucket'); - expect(res).toEqual(textResult); - }); -}); diff --git a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/matrix_histogram/helpers.ts b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/matrix_histogram/helpers.ts deleted file mode 100644 index 7e0950d746b4d..0000000000000 --- a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/matrix_histogram/helpers.ts +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { get, getOr } from 'lodash/fp'; -import type { - MatrixHistogramParseData, - MatrixHistogramBucket, - MatrixHistogramData, -} from '../../../../../common/search_strategy/security_solution/matrix_histogram'; - -export const getGenericData = ( - data: MatrixHistogramParseData, - keyBucket: string -): MatrixHistogramData[] => { - let result: MatrixHistogramData[] = []; - data.forEach((bucketData: unknown) => { - // if key_as_string is present use it, else default to the existing key - const group = get('key_as_string', bucketData) ?? get('key', bucketData); - const histData = getOr([], keyBucket, bucketData).map( - // eslint-disable-next-line @typescript-eslint/naming-convention - ({ key, doc_count }: MatrixHistogramBucket) => ({ - x: key, - y: doc_count, - g: group, - }) - ); - result = [...result, ...histData]; - }); - - return result; -}; diff --git a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/matrix_histogram/index.test.ts b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/matrix_histogram/index.test.ts deleted file mode 100644 index 4b09dcf1971d9..0000000000000 --- a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/matrix_histogram/index.test.ts +++ /dev/null @@ -1,249 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import type { MatrixHistogramType } from '../../../../../common/search_strategy/security_solution'; -import { matrixHistogram } from '.'; -import { - formattedAlertsSearchStrategyResponse, - formattedAnomaliesSearchStrategyResponse, - formattedAuthenticationsSearchStrategyResponse, - formattedEventsSearchStrategyResponse, - formattedDnsSearchStrategyResponse, - mockAlertsSearchStrategyResponse, - mockAnomaliesSearchStrategyResponse, - mockAuthenticationsSearchStrategyResponse, - mockEventsSearchStrategyResponse, - mockDnsSearchStrategyResponse, - formattedPreviewStrategyResponse, -} from './__mocks__'; -import { alertsMatrixHistogramConfig } from './alerts'; -import { anomaliesMatrixHistogramConfig } from './anomalies'; -import { authenticationsMatrixHistogramConfig } from './authentications'; -import { eventsMatrixHistogramConfig } from './events'; -import { dnsMatrixHistogramConfig } from './dns'; -import { previewMatrixHistogramConfig } from './preview'; - -import { mockOptions as mockAlertsOptions } from './alerts/__mocks__'; -import { mockOptions as mockAnomaliesOptions } from './anomalies/__mocks__'; -import { mockOptions as mockAuthenticationsOptions } from './authentications/__mocks__'; -import { mockOptions as mockEventsOptions } from './events/__mocks__'; -import { mockOptions as mockDnsOptions } from './dns/__mocks__'; -import { mockOptions as mockPreviewOptions } from './preview/__mocks__'; -import type { MatrixHistogramRequestOptions } from '../../../../../common/api/search_strategy/matrix_histogram/matrix_histogram'; - -describe('Alerts matrixHistogram search strategy', () => { - const buildMatrixHistogramQuery = jest.spyOn(alertsMatrixHistogramConfig, 'buildDsl'); - - afterEach(() => { - buildMatrixHistogramQuery.mockClear(); - }); - - describe('buildDsl', () => { - test('should build dsl query', () => { - matrixHistogram.buildDsl(mockAlertsOptions); - expect(buildMatrixHistogramQuery).toHaveBeenCalledWith(mockAlertsOptions); - }); - - test('should throw error if histogramType is invalid', () => { - const invalidOptions: MatrixHistogramRequestOptions = { - ...mockAlertsOptions, - histogramType: 'xxx' as MatrixHistogramType, - } as MatrixHistogramRequestOptions; - - expect(() => { - matrixHistogram.buildDsl(invalidOptions); - }).toThrowError(/This histogram type xxx is unknown to the server side/); - }); - }); - - describe('parse', () => { - test('should parse data correctly', async () => { - const result = await matrixHistogram.parse( - mockAlertsOptions, - mockAlertsSearchStrategyResponse - ); - expect(result).toMatchObject(formattedAlertsSearchStrategyResponse); - }); - }); -}); - -describe('Anomalies matrixHistogram search strategy', () => { - const buildMatrixHistogramQuery = jest.spyOn(anomaliesMatrixHistogramConfig, 'buildDsl'); - - afterEach(() => { - buildMatrixHistogramQuery.mockClear(); - }); - - describe('buildDsl', () => { - test('should build dsl query', () => { - matrixHistogram.buildDsl(mockAnomaliesOptions); - expect(buildMatrixHistogramQuery).toHaveBeenCalledWith(mockAnomaliesOptions); - }); - - test('should throw error if histogramType is invalid', () => { - const invalidOptions: MatrixHistogramRequestOptions = { - ...mockAnomaliesOptions, - histogramType: 'xxx' as MatrixHistogramType, - } as MatrixHistogramRequestOptions; - - expect(() => { - matrixHistogram.buildDsl(invalidOptions); - }).toThrowError(/This histogram type xxx is unknown to the server side/); - }); - }); - - describe('parse', () => { - test('should parse data correctly', async () => { - const result = await matrixHistogram.parse( - mockAnomaliesOptions, - mockAnomaliesSearchStrategyResponse - ); - expect(result).toMatchObject(formattedAnomaliesSearchStrategyResponse); - }); - }); -}); - -describe('Authentications matrixHistogram search strategy', () => { - const buildMatrixHistogramQuery = jest.spyOn(authenticationsMatrixHistogramConfig, 'buildDsl'); - - afterEach(() => { - buildMatrixHistogramQuery.mockClear(); - }); - - describe('buildDsl', () => { - test('should build dsl query', () => { - matrixHistogram.buildDsl(mockAuthenticationsOptions); - expect(buildMatrixHistogramQuery).toHaveBeenCalledWith(mockAuthenticationsOptions); - }); - - test('should throw error if histogramType is invalid', () => { - const invalidOptions = { - ...mockAuthenticationsOptions, - histogramType: 'xxx' as MatrixHistogramType, - } as MatrixHistogramRequestOptions; - - expect(() => { - matrixHistogram.buildDsl(invalidOptions); - }).toThrowError(/This histogram type xxx is unknown to the server side/); - }); - }); - - describe('parse', () => { - test('should parse data correctly', async () => { - const result = await matrixHistogram.parse( - mockAuthenticationsOptions, - mockAuthenticationsSearchStrategyResponse - ); - expect(result).toMatchObject(formattedAuthenticationsSearchStrategyResponse); - }); - }); -}); - -describe('Events matrixHistogram search strategy', () => { - const buildMatrixHistogramQuery = jest.spyOn(eventsMatrixHistogramConfig, 'buildDsl'); - - afterEach(() => { - buildMatrixHistogramQuery.mockClear(); - }); - - describe('buildDsl', () => { - test('should build dsl query', () => { - matrixHistogram.buildDsl(mockEventsOptions); - expect(buildMatrixHistogramQuery).toHaveBeenCalledWith(mockEventsOptions); - }); - - test('should throw error if histogramType is invalid', () => { - const invalidOptions = { - ...mockEventsOptions, - histogramType: 'xxx' as MatrixHistogramType, - } as MatrixHistogramRequestOptions; - - expect(() => { - matrixHistogram.buildDsl(invalidOptions); - }).toThrowError(/This histogram type xxx is unknown to the server side/); - }); - }); - - describe('parse', () => { - test('should parse data correctly', async () => { - const result = await matrixHistogram.parse( - mockEventsOptions, - mockEventsSearchStrategyResponse - ); - expect(result).toMatchObject(formattedEventsSearchStrategyResponse); - }); - }); -}); - -describe('Dns matrixHistogram search strategy', () => { - const buildMatrixHistogramQuery = jest.spyOn(dnsMatrixHistogramConfig, 'buildDsl'); - - afterEach(() => { - buildMatrixHistogramQuery.mockClear(); - }); - - describe('buildDsl', () => { - test('should build dsl query', () => { - matrixHistogram.buildDsl(mockDnsOptions); - expect(buildMatrixHistogramQuery).toHaveBeenCalledWith(mockDnsOptions); - }); - - test('should throw error if histogramType is invalid', () => { - const invalidOptions = { - ...mockDnsOptions, - histogramType: 'xxx' as MatrixHistogramType, - } as MatrixHistogramRequestOptions; - - expect(() => { - matrixHistogram.buildDsl(invalidOptions); - }).toThrowError(/This histogram type xxx is unknown to the server side/); - }); - }); - - describe('parse', () => { - test('should parse data correctly', async () => { - const result = await matrixHistogram.parse(mockDnsOptions, mockDnsSearchStrategyResponse); - expect(result).toMatchObject(formattedDnsSearchStrategyResponse); - }); - }); -}); - -describe('Preview matrixHistogram search strategy', () => { - const buildMatrixHistogramQuery = jest.spyOn(previewMatrixHistogramConfig, 'buildDsl'); - - afterEach(() => { - buildMatrixHistogramQuery.mockClear(); - }); - - describe('buildDsl', () => { - test('should build dsl query', () => { - matrixHistogram.buildDsl(mockPreviewOptions); - expect(buildMatrixHistogramQuery).toHaveBeenCalledWith(mockPreviewOptions); - }); - - test('should throw error if histogramType is invalid', () => { - const invalidOptions: MatrixHistogramRequestOptions = { - ...mockPreviewOptions, - histogramType: 'xxx' as MatrixHistogramType, - } as MatrixHistogramRequestOptions; - - expect(() => { - matrixHistogram.buildDsl(invalidOptions); - }).toThrowError(/This histogram type xxx is unknown to the server side/); - }); - }); - - describe('parse', () => { - test('should parse data correctly', async () => { - const result = await matrixHistogram.parse( - mockPreviewOptions, - mockAlertsSearchStrategyResponse - ); - expect(result).toMatchObject(formattedPreviewStrategyResponse); - }); - }); -}); diff --git a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/matrix_histogram/index.ts b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/matrix_histogram/index.ts deleted file mode 100644 index 567bdcbd1f78b..0000000000000 --- a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/matrix_histogram/index.ts +++ /dev/null @@ -1,80 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { getOr } from 'lodash/fp'; - -import type { IEsSearchResponse } from '@kbn/data-plugin/common'; -import type { - FactoryQueryTypes, - MatrixHistogramStrategyResponse, - MatrixHistogramDataConfig, -} from '../../../../../common/search_strategy/security_solution'; -import { - MatrixHistogramQuery, - MatrixHistogramType, -} from '../../../../../common/search_strategy/security_solution'; -import { inspectStringifyObject } from '../../../../utils/build_query'; -import type { SecuritySolutionFactory } from '../types'; -import { getGenericData } from './helpers'; -import { alertsMatrixHistogramConfig } from './alerts'; -import { anomaliesMatrixHistogramConfig } from './anomalies'; -import { authenticationsMatrixHistogramConfig } from './authentications'; -import { dnsMatrixHistogramConfig } from './dns'; -import { eventsMatrixHistogramConfig } from './events'; -import { previewMatrixHistogramConfig } from './preview'; - -const matrixHistogramConfig: MatrixHistogramDataConfig = { - [MatrixHistogramType.alerts]: alertsMatrixHistogramConfig, - [MatrixHistogramType.anomalies]: anomaliesMatrixHistogramConfig, - [MatrixHistogramType.authentications]: authenticationsMatrixHistogramConfig, - [MatrixHistogramType.dns]: dnsMatrixHistogramConfig, - [MatrixHistogramType.events]: eventsMatrixHistogramConfig, - [MatrixHistogramType.preview]: previewMatrixHistogramConfig, -}; - -export const matrixHistogram: SecuritySolutionFactory = { - buildDsl: (options) => { - const myConfig = getOr(null, options.histogramType, matrixHistogramConfig); - if (myConfig == null) { - throw new Error(`This histogram type ${options.histogramType} is unknown to the server side`); - } - return myConfig.buildDsl(options); - }, - parse: async ( - options, - response: IEsSearchResponse - ): Promise => { - const myConfig = getOr(null, options.histogramType, matrixHistogramConfig); - if (myConfig == null) { - throw new Error(`This histogram type ${options.histogramType} is unknown to the server side`); - } - const totalCount = response.rawResponse.hits.total || 0; - const matrixHistogramData = getOr([], myConfig.aggName, response.rawResponse); - const inspect = { - dsl: [inspectStringifyObject(myConfig.buildDsl(options))], - }; - const dataParser = myConfig.parser ?? getGenericData; - - return { - ...response, - inspect, - matrixHistogramData: dataParser( - matrixHistogramData, - myConfig.parseKey - ), - // @ts-expect-error code doesn't handle TotalHits - totalCount, - }; - }, -}; - -export const matrixHistogramFactory: Record< - typeof MatrixHistogramQuery, - SecuritySolutionFactory -> = { - [MatrixHistogramQuery]: matrixHistogram, -}; diff --git a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/matrix_histogram/mock_data.ts b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/matrix_histogram/mock_data.ts deleted file mode 100644 index 9a938846826a1..0000000000000 --- a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/matrix_histogram/mock_data.ts +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -export const stackedByBooleanField = [ - { - key: 1, - key_as_string: 'true', - doc_count: 7125, - events: { - bucket: [ - { key_as_string: '2022-05-10T15:34:48.075Z', key: 1652196888075, doc_count: 0 }, - { key_as_string: '2022-05-10T16:19:48.074Z', key: 1652199588074, doc_count: 774 }, - { key_as_string: '2022-05-10T17:04:48.073Z', key: 1652202288073, doc_count: 415 }, - ], - }, - }, -]; -export const result = [ - { x: 1652196888075, y: 0, g: 'true' }, - { x: 1652199588074, y: 774, g: 'true' }, - { x: 1652202288073, y: 415, g: 'true' }, -]; - -export const stackedByTextField = [ - { - key: 'MacBook-Pro.local', - doc_count: 7103, - events: { - bucket: [ - { key_as_string: '2022-05-10T15:34:48.075Z', key: 1652196888075, doc_count: 0 }, - { key_as_string: '2022-05-10T16:19:48.074Z', key: 1652199588074, doc_count: 774 }, - { key_as_string: '2022-05-10T17:04:48.073Z', key: 1652202288073, doc_count: 415 }, - ], - }, - }, -]; - -export const textResult = [ - { x: 1652196888075, y: 0, g: 'MacBook-Pro.local' }, - { x: 1652199588074, y: 774, g: 'MacBook-Pro.local' }, - { x: 1652202288073, y: 415, g: 'MacBook-Pro.local' }, -]; diff --git a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/matrix_histogram/preview/__mocks__/index.ts b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/matrix_histogram/preview/__mocks__/index.ts deleted file mode 100644 index 4b7ef376b8cd3..0000000000000 --- a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/matrix_histogram/preview/__mocks__/index.ts +++ /dev/null @@ -1,89 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import type { MatrixHistogramRequestOptions } from '../../../../../../../common/api/search_strategy'; -import { MatrixHistogramQuery } from '../../../../../../../common/api/search_strategy'; -import { MatrixHistogramType } from '../../../../../../../common/search_strategy'; - -export const mockOptions: MatrixHistogramRequestOptions = { - defaultIndex: ['.siem-preview-signals-default'], - filterQuery: - '{"bool":{"must":[],"filter":[{"match_all":{}},{"bool":{"filter":[{"bool":{"should":[{"match":{"signal.rule.id":"test-preview-id"}}],"minimum_should_match":1}}]}}],"should":[],"must_not":[]}}', - histogramType: MatrixHistogramType.preview, - timerange: { interval: '12h', from: '2020-09-08T14:23:04.482Z', to: '2020-09-09T14:23:04.482Z' }, - stackByField: 'event.category', - includeMissingData: false, - isPtrIncluded: false, - factoryQueryType: MatrixHistogramQuery, -}; - -export const expectedDsl = { - index: ['.siem-preview-signals-default'], - allow_no_indices: true, - ignore_unavailable: true, - track_total_hits: true, - body: { - aggregations: { - preview: { - terms: { - field: 'event.category', - missing: 'All others', - order: { _count: 'desc' }, - size: 10, - }, - aggs: { - preview: { - date_histogram: { - field: '@timestamp', - fixed_interval: '2700000ms', - min_doc_count: 0, - extended_bounds: { min: 1599574984482, max: 1599661384482 }, - }, - }, - }, - }, - }, - query: { - bool: { - filter: [ - { - bool: { - must: [], - filter: [ - { match_all: {} }, - { - bool: { - filter: [ - { - bool: { - should: [{ match: { 'signal.rule.id': 'test-preview-id' } }], - minimum_should_match: 1, - }, - }, - ], - }, - }, - ], - should: [], - must_not: [], - }, - }, - { - range: { - '@timestamp': { - gte: '2020-09-08T14:23:04.482Z', - lte: '2020-09-09T14:23:04.482Z', - format: 'strict_date_optional_time', - }, - }, - }, - ], - }, - }, - size: 0, - }, -}; diff --git a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/matrix_histogram/preview/index.ts b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/matrix_histogram/preview/index.ts deleted file mode 100644 index 0ca14c5489c56..0000000000000 --- a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/matrix_histogram/preview/index.ts +++ /dev/null @@ -1,15 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { MatrixHistogramTypeToAggName } from '../../../../../../common/search_strategy'; -import { buildPreviewHistogramQuery } from './query.preview_histogram.dsl'; - -export const previewMatrixHistogramConfig = { - buildDsl: buildPreviewHistogramQuery, - aggName: MatrixHistogramTypeToAggName.preview, - parseKey: 'preview.buckets', -}; diff --git a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/matrix_histogram/preview/query.preview_histogram.dsl.test.ts b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/matrix_histogram/preview/query.preview_histogram.dsl.test.ts deleted file mode 100644 index e12142e21a156..0000000000000 --- a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/matrix_histogram/preview/query.preview_histogram.dsl.test.ts +++ /dev/null @@ -1,15 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { buildPreviewHistogramQuery } from './query.preview_histogram.dsl'; -import { mockOptions, expectedDsl } from './__mocks__'; - -describe('buildAlertsHistogramQuery', () => { - test('build query from options correctly', () => { - expect(buildPreviewHistogramQuery(mockOptions)).toEqual(expectedDsl); - }); -}); diff --git a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/matrix_histogram/preview/query.preview_histogram.dsl.ts b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/matrix_histogram/preview/query.preview_histogram.dsl.ts deleted file mode 100644 index 56f1ce122bfd0..0000000000000 --- a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/matrix_histogram/preview/query.preview_histogram.dsl.ts +++ /dev/null @@ -1,84 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import moment from 'moment'; - -import { TIMESTAMP } from '@kbn/rule-data-utils'; -import { - createQueryFilterClauses, - calculateTimeSeriesInterval, -} from '../../../../../utils/build_query'; -import type { MatrixHistogramRequestOptions } from '../../../../../../common/api/search_strategy'; - -export const buildPreviewHistogramQuery = ({ - filterQuery, - timerange: { from, to }, - defaultIndex, - stackByField, -}: MatrixHistogramRequestOptions) => { - const filter = [ - ...createQueryFilterClauses(filterQuery), - { - range: { - [TIMESTAMP]: { - gte: from, - lte: to, - format: 'strict_date_optional_time', - }, - }, - }, - ]; - - const getHistogramAggregation = () => { - const interval = calculateTimeSeriesInterval(from, to); - const histogramTimestampField = TIMESTAMP; - const dateHistogram = { - date_histogram: { - field: histogramTimestampField, - fixed_interval: interval, - min_doc_count: 0, - extended_bounds: { - min: moment(from).valueOf(), - max: moment(to).valueOf(), - }, - }, - }; - return { - preview: { - terms: { - field: stackByField, - missing: 'All others', - order: { - _count: 'desc', - }, - size: 10, - }, - aggs: { - preview: dateHistogram, - }, - }, - }; - }; - - const dslQuery = { - index: defaultIndex, - allow_no_indices: true, - ignore_unavailable: true, - track_total_hits: true, - body: { - aggregations: getHistogramAggregation(), - query: { - bool: { - filter, - }, - }, - size: 0, - }, - }; - - return dslQuery; -}; diff --git a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/index.test.ts b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/index.test.ts index d3621ef22bf2a..82edc9d89156b 100644 --- a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/index.test.ts +++ b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/index.test.ts @@ -5,10 +5,7 @@ * 2.0. */ -import { - NetworkQueries, - NetworkKpiQueries, -} from '../../../../../common/search_strategy/security_solution'; +import { NetworkQueries } from '../../../../../common/search_strategy/security_solution'; import { networkFactory } from '.'; import { networkDetails } from './details'; @@ -19,11 +16,6 @@ import { networkTls } from './tls'; import { networkTopCountries } from './top_countries'; import { networkTopNFlow } from './top_n_flow'; import { networkUsers } from './users'; -import { networkKpiDns } from './kpi/dns'; -import { networkKpiNetworkEvents } from './kpi/network_events'; -import { networkKpiTlsHandshakes } from './kpi/tls_handshakes'; -import { networkKpiUniqueFlows } from './kpi/unique_flows'; -import { networkKpiUniquePrivateIps } from './kpi/unique_private_ips'; jest.mock('./details'); jest.mock('./dns'); @@ -33,11 +25,6 @@ jest.mock('./tls'); jest.mock('./top_countries'); jest.mock('./top_n_flow'); jest.mock('./users'); -jest.mock('./kpi/dns'); -jest.mock('./kpi/network_events'); -jest.mock('./kpi/tls_handshakes'); -jest.mock('./kpi/unique_flows'); -jest.mock('./kpi/unique_private_ips'); describe('networkFactory', () => { test('should include correct apis', () => { @@ -50,11 +37,6 @@ describe('networkFactory', () => { [NetworkQueries.topCountries]: networkTopCountries, [NetworkQueries.topNFlow]: networkTopNFlow, [NetworkQueries.users]: networkUsers, - [NetworkKpiQueries.dns]: networkKpiDns, - [NetworkKpiQueries.networkEvents]: networkKpiNetworkEvents, - [NetworkKpiQueries.tlsHandshakes]: networkKpiTlsHandshakes, - [NetworkKpiQueries.uniqueFlows]: networkKpiUniqueFlows, - [NetworkKpiQueries.uniquePrivateIps]: networkKpiUniquePrivateIps, }; expect(networkFactory).toEqual(expectedNetworkFactory); }); diff --git a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/index.ts b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/index.ts index 71a671efcdfef..6c32d9b5d51eb 100644 --- a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/index.ts +++ b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/index.ts @@ -5,16 +5,8 @@ * 2.0. */ -import { - NetworkQueries, - NetworkKpiQueries, -} from '../../../../../common/search_strategy/security_solution'; +import { NetworkQueries } from '../../../../../common/search_strategy/security_solution'; -import { networkKpiDns } from './kpi/dns'; -import { networkKpiNetworkEvents } from './kpi/network_events'; -import { networkKpiTlsHandshakes } from './kpi/tls_handshakes'; -import { networkKpiUniqueFlows } from './kpi/unique_flows'; -import { networkKpiUniquePrivateIps } from './kpi/unique_private_ips'; import { networkDetails } from './details'; import { networkDns } from './dns'; import { networkHttp } from './http'; @@ -26,7 +18,7 @@ import { networkUsers } from './users'; // TODO: add safer type for the strategy map // eslint-disable-next-line @typescript-eslint/no-explicit-any -export const networkFactory: Record = { +export const networkFactory: Record = { [NetworkQueries.details]: networkDetails, [NetworkQueries.dns]: networkDns, [NetworkQueries.http]: networkHttp, @@ -36,9 +28,4 @@ export const networkFactory: Record = { [NetworkQueries.topNFlowCount]: networkTopNFlowCount, [NetworkQueries.topNFlow]: networkTopNFlow, [NetworkQueries.users]: networkUsers, - [NetworkKpiQueries.dns]: networkKpiDns, - [NetworkKpiQueries.networkEvents]: networkKpiNetworkEvents, - [NetworkKpiQueries.tlsHandshakes]: networkKpiTlsHandshakes, - [NetworkKpiQueries.uniqueFlows]: networkKpiUniqueFlows, - [NetworkKpiQueries.uniquePrivateIps]: networkKpiUniquePrivateIps, }; diff --git a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/kpi/common/index.ts b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/kpi/common/index.ts deleted file mode 100644 index c0d681e60a442..0000000000000 --- a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/kpi/common/index.ts +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { getOr } from 'lodash/fp'; -import type { NetworkKpiHistogramData } from '../../../../../../../common/search_strategy/security_solution/network'; - -export const getIpFilter = () => [ - { - bool: { - should: [ - { - exists: { - field: 'source.ip', - }, - }, - { - exists: { - field: 'destination.ip', - }, - }, - ], - minimum_should_match: 1, - }, - }, -]; - -export const formatHistogramData = ( - data: Array<{ key: number; count: { value: number } }> -): NetworkKpiHistogramData[] | null => - data && data.length > 0 - ? data.map(({ key, count }) => ({ - x: key, - y: getOr(null, 'value', count), - })) - : null; diff --git a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/kpi/dns/index.ts b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/kpi/dns/index.ts deleted file mode 100644 index 09dcc714b444c..0000000000000 --- a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/kpi/dns/index.ts +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import type { IEsSearchResponse } from '@kbn/data-plugin/common'; -import type { - NetworkKpiQueries, - NetworkKpiDnsStrategyResponse, -} from '../../../../../../../common/search_strategy/security_solution/network'; -import { inspectStringifyObject } from '../../../../../../utils/build_query'; -import type { SecuritySolutionFactory } from '../../../types'; -import { buildDnsQuery } from './query.network_kpi_dns.dsl'; - -export const networkKpiDns: SecuritySolutionFactory = { - buildDsl: (options) => buildDnsQuery(options), - parse: async ( - options, - response: IEsSearchResponse - ): Promise => { - const inspect = { - dsl: [inspectStringifyObject(buildDnsQuery(options))], - }; - - return { - ...response, - inspect, - // @ts-expect-error code doesn't handle TotalHits - dnsQueries: response.rawResponse.hits.total, - }; - }, -}; diff --git a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/kpi/dns/query.network_kpi_dns.dsl.ts b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/kpi/dns/query.network_kpi_dns.dsl.ts deleted file mode 100644 index a55cb8f026664..0000000000000 --- a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/kpi/dns/query.network_kpi_dns.dsl.ts +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import type { NetworkKpiDnsRequestOptions } from '../../../../../../../common/api/search_strategy'; - -import { createQueryFilterClauses } from '../../../../../../utils/build_query'; - -const getDnsQueryFilter = () => [ - { - bool: { - should: [ - { - exists: { - field: 'dns.question.name', - }, - }, - { - term: { - 'suricata.eve.dns.type': { - value: 'query', - }, - }, - }, - { - exists: { - field: 'zeek.dns.query', - }, - }, - ], - minimum_should_match: 1, - }, - }, -]; - -export const buildDnsQuery = ({ - filterQuery, - timerange: { from, to }, - defaultIndex, -}: NetworkKpiDnsRequestOptions) => { - const filter = [ - ...createQueryFilterClauses(filterQuery), - ...getDnsQueryFilter(), - { - range: { - '@timestamp': { - gte: from, - lte: to, - format: 'strict_date_optional_time', - }, - }, - }, - ]; - - const dslQuery = { - index: defaultIndex, - allow_no_indices: true, - ignore_unavailable: true, - track_total_hits: true, - body: { - query: { - bool: { - filter, - }, - }, - size: 0, - }, - }; - - return dslQuery; -}; diff --git a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/kpi/network_events/index.ts b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/kpi/network_events/index.ts deleted file mode 100644 index 6751c829cc350..0000000000000 --- a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/kpi/network_events/index.ts +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import type { IEsSearchResponse } from '@kbn/data-plugin/common'; -import type { - NetworkKpiQueries, - NetworkKpiNetworkEventsStrategyResponse, -} from '../../../../../../../common/search_strategy/security_solution/network'; -import { inspectStringifyObject } from '../../../../../../utils/build_query'; -import type { SecuritySolutionFactory } from '../../../types'; -import { buildNetworkEventsQuery } from './query.network_kpi_network_events.dsl'; - -export const networkKpiNetworkEvents: SecuritySolutionFactory = { - buildDsl: (options) => buildNetworkEventsQuery(options), - parse: async ( - options, - response: IEsSearchResponse - ): Promise => { - const inspect = { - dsl: [inspectStringifyObject(buildNetworkEventsQuery(options))], - }; - - return { - ...response, - inspect, - // @ts-expect-error code doesn't handle TotalHits - networkEvents: response.rawResponse.hits.total, - }; - }, -}; diff --git a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/kpi/network_events/query.network_kpi_network_events.dsl.ts b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/kpi/network_events/query.network_kpi_network_events.dsl.ts deleted file mode 100644 index 96f67b8e17600..0000000000000 --- a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/kpi/network_events/query.network_kpi_network_events.dsl.ts +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import type { NetworkKpiEventsRequestOptions } from '../../../../../../../common/api/search_strategy'; -import { createQueryFilterClauses } from '../../../../../../utils/build_query'; -import { getIpFilter } from '../common'; - -export const buildNetworkEventsQuery = ({ - filterQuery, - timerange: { from, to }, - defaultIndex, -}: NetworkKpiEventsRequestOptions) => { - const filter = [ - ...createQueryFilterClauses(filterQuery), - ...getIpFilter(), - { - range: { - '@timestamp': { - gte: from, - lte: to, - format: 'strict_date_optional_time', - }, - }, - }, - ]; - - const dslQuery = { - index: defaultIndex, - allow_no_indices: true, - ignore_unavailable: true, - track_total_hits: true, - body: { - query: { - bool: { - filter, - }, - }, - size: 0, - }, - }; - - return dslQuery; -}; diff --git a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/kpi/tls_handshakes/index.ts b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/kpi/tls_handshakes/index.ts deleted file mode 100644 index 3b8e65fb163af..0000000000000 --- a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/kpi/tls_handshakes/index.ts +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import type { IEsSearchResponse } from '@kbn/data-plugin/common'; -import type { - NetworkKpiQueries, - NetworkKpiTlsHandshakesStrategyResponse, -} from '../../../../../../../common/search_strategy/security_solution/network'; -import { inspectStringifyObject } from '../../../../../../utils/build_query'; -import type { SecuritySolutionFactory } from '../../../types'; -import { buildTlsHandshakeQuery } from './query.network_kpi_tls_handshakes.dsl'; - -export const networkKpiTlsHandshakes: SecuritySolutionFactory = { - buildDsl: (options) => buildTlsHandshakeQuery(options), - parse: async ( - options, - response: IEsSearchResponse - ): Promise => { - const inspect = { - dsl: [inspectStringifyObject(buildTlsHandshakeQuery(options))], - }; - - return { - ...response, - inspect, - // @ts-expect-error code doesn't handle TotalHits - tlsHandshakes: response.rawResponse.hits.total, - }; - }, -}; diff --git a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/kpi/tls_handshakes/query.network_kpi_tls_handshakes.dsl.ts b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/kpi/tls_handshakes/query.network_kpi_tls_handshakes.dsl.ts deleted file mode 100644 index 2797a2e814506..0000000000000 --- a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/kpi/tls_handshakes/query.network_kpi_tls_handshakes.dsl.ts +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import type { NetworkKpiTlsHandshakesRequestOptions } from '../../../../../../../common/api/search_strategy'; -import { createQueryFilterClauses } from '../../../../../../utils/build_query'; -import { getIpFilter } from '../common'; - -const getTlsHandshakesQueryFilter = () => [ - { - bool: { - should: [ - { - exists: { - field: 'tls.version', - }, - }, - { - exists: { - field: 'suricata.eve.tls.version', - }, - }, - { - exists: { - field: 'zeek.ssl.version', - }, - }, - ], - minimum_should_match: 1, - }, - }, -]; - -export const buildTlsHandshakeQuery = ({ - filterQuery, - timerange: { from, to }, - defaultIndex, -}: NetworkKpiTlsHandshakesRequestOptions) => { - const filter = [ - ...getIpFilter(), - ...createQueryFilterClauses(filterQuery), - ...getTlsHandshakesQueryFilter(), - { - range: { - '@timestamp': { - gte: from, - lte: to, - format: 'strict_date_optional_time', - }, - }, - }, - ]; - - const dslQuery = { - index: defaultIndex, - allow_no_indices: true, - ignore_unavailable: true, - track_total_hits: true, - body: { - query: { - bool: { - filter, - }, - }, - size: 0, - }, - }; - - return dslQuery; -}; diff --git a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/kpi/unique_flows/index.ts b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/kpi/unique_flows/index.ts deleted file mode 100644 index e245d1af846f8..0000000000000 --- a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/kpi/unique_flows/index.ts +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { getOr } from 'lodash/fp'; - -import type { IEsSearchResponse } from '@kbn/data-plugin/common'; -import type { - NetworkKpiQueries, - NetworkKpiUniqueFlowsStrategyResponse, -} from '../../../../../../../common/search_strategy/security_solution/network'; -import { inspectStringifyObject } from '../../../../../../utils/build_query'; -import type { SecuritySolutionFactory } from '../../../types'; -import { buildUniqueFlowsQuery } from './query.network_kpi_unique_flows.dsl'; - -export const networkKpiUniqueFlows: SecuritySolutionFactory = { - buildDsl: (options) => buildUniqueFlowsQuery(options), - parse: async ( - options, - response: IEsSearchResponse - ): Promise => { - const inspect = { - dsl: [inspectStringifyObject(buildUniqueFlowsQuery(options))], - }; - - return { - ...response, - inspect, - uniqueFlowId: getOr(null, 'aggregations.unique_flow_id.value', response.rawResponse), - }; - }, -}; diff --git a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/kpi/unique_flows/query.network_kpi_unique_flows.dsl.ts b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/kpi/unique_flows/query.network_kpi_unique_flows.dsl.ts deleted file mode 100644 index 29e4c386fc348..0000000000000 --- a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/kpi/unique_flows/query.network_kpi_unique_flows.dsl.ts +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import type { NetworkKpiUniqueFlowsRequestOptions } from '../../../../../../../common/api/search_strategy'; - -import { createQueryFilterClauses } from '../../../../../../utils/build_query'; -import { getIpFilter } from '../common'; - -export const buildUniqueFlowsQuery = ({ - filterQuery, - timerange: { from, to }, - defaultIndex, -}: NetworkKpiUniqueFlowsRequestOptions) => { - const filter = [ - ...createQueryFilterClauses(filterQuery), - ...getIpFilter(), - { - range: { - '@timestamp': { - gte: from, - lte: to, - format: 'strict_date_optional_time', - }, - }, - }, - ]; - - const dslQuery = { - index: defaultIndex, - allow_no_indices: true, - ignore_unavailable: true, - track_total_hits: false, - body: { - aggregations: { - unique_flow_id: { - cardinality: { - field: 'network.community_id', - }, - }, - }, - query: { - bool: { - filter, - }, - }, - size: 0, - }, - }; - - return dslQuery; -}; diff --git a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/kpi/unique_private_ips/index.ts b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/kpi/unique_private_ips/index.ts deleted file mode 100644 index a3d72e6e15898..0000000000000 --- a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/kpi/unique_private_ips/index.ts +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { getOr } from 'lodash/fp'; - -import type { IEsSearchResponse } from '@kbn/data-plugin/common'; -import type { - NetworkKpiQueries, - NetworkKpiUniquePrivateIpsStrategyResponse, -} from '../../../../../../../common/search_strategy/security_solution/network'; -import { inspectStringifyObject } from '../../../../../../utils/build_query'; -import type { SecuritySolutionFactory } from '../../../types'; -import { formatHistogramData } from '../common'; -import { buildUniquePrivateIpsQuery } from './query.network_kpi_unique_private_ips.dsl'; - -export const networkKpiUniquePrivateIps: SecuritySolutionFactory = - { - // @ts-expect-error auto_date_histogram.buckets is incompatible - buildDsl: (options) => buildUniquePrivateIpsQuery(options), - parse: async ( - options, - response: IEsSearchResponse - ): Promise => { - const inspect = { - dsl: [inspectStringifyObject(buildUniquePrivateIpsQuery(options))], - }; - - const uniqueSourcePrivateIpsHistogram = getOr( - null, - 'aggregations.source.histogram.buckets', - response.rawResponse - ); - const uniqueDestinationPrivateIpsHistogram = getOr( - null, - 'aggregations.destination.histogram.buckets', - response.rawResponse - ); - - return { - ...response, - inspect, - uniqueSourcePrivateIps: getOr( - null, - 'aggregations.source.unique_private_ips.value', - response.rawResponse - ), - uniqueDestinationPrivateIps: getOr( - null, - 'aggregations.destination.unique_private_ips.value', - response.rawResponse - ), - uniqueSourcePrivateIpsHistogram: formatHistogramData(uniqueSourcePrivateIpsHistogram), - uniqueDestinationPrivateIpsHistogram: formatHistogramData( - uniqueDestinationPrivateIpsHistogram - ), - }; - }, - }; diff --git a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/kpi/unique_private_ips/query.network_kpi_unique_private_ips.dsl.ts b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/kpi/unique_private_ips/query.network_kpi_unique_private_ips.dsl.ts deleted file mode 100644 index 6b31e5af05797..0000000000000 --- a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/kpi/unique_private_ips/query.network_kpi_unique_private_ips.dsl.ts +++ /dev/null @@ -1,104 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import type { NetworkKpiUniquePrivateIpsRequestOptions } from '../../../../../../../common/api/search_strategy'; -import type { UniquePrivateAttributeQuery } from '../../../../../../../common/search_strategy/security_solution/network'; -import { createQueryFilterClauses } from '../../../../../../utils/build_query'; - -const getUniquePrivateIpsFilter = (attrQuery: UniquePrivateAttributeQuery) => ({ - bool: { - should: [ - { - term: { - [`${attrQuery}.ip`]: '10.0.0.0/8', - }, - }, - { - term: { - [`${attrQuery}.ip`]: '192.168.0.0/16', - }, - }, - { - term: { - [`${attrQuery}.ip`]: '172.16.0.0/12', - }, - }, - { - term: { - [`${attrQuery}.ip`]: 'fd00::/8', - }, - }, - ], - minimum_should_match: 1, - }, -}); - -const getAggs = (attrQuery: 'source' | 'destination') => ({ - [attrQuery]: { - filter: getUniquePrivateIpsFilter(attrQuery), - aggs: { - unique_private_ips: { - cardinality: { - field: `${attrQuery}.ip`, - }, - }, - histogram: { - auto_date_histogram: { - field: '@timestamp', - buckets: '6', - }, - aggs: { - count: { - cardinality: { - field: `${attrQuery}.ip`, - }, - }, - }, - }, - }, - }, -}); - -export const buildUniquePrivateIpsQuery = ({ - filterQuery, - timerange: { from, to }, - defaultIndex, -}: NetworkKpiUniquePrivateIpsRequestOptions) => { - const filter = [ - ...createQueryFilterClauses(filterQuery), - { - range: { - '@timestamp': { - gte: from, - lte: to, - format: 'strict_date_optional_time', - }, - }, - }, - ]; - - const dslQuery = { - allow_no_indices: true, - index: defaultIndex, - ignore_unavailable: true, - track_total_hits: false, - body: { - aggregations: { - ...getAggs('source'), - ...getAggs('destination'), - }, - query: { - bool: { - filter, - }, - }, - size: 0, - }, - }; - - return dslQuery; -}; diff --git a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/users/index.ts b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/users/index.ts index ea4038e53730d..6c3df1aef56a6 100644 --- a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/users/index.ts +++ b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/users/index.ts @@ -12,15 +12,12 @@ import type { SecuritySolutionFactory } from '../types'; import { allUsers } from './all'; import { authentications } from './authentications'; import { managedUserDetails } from './managed_details'; -import { usersKpiAuthentications } from './kpi/authentications'; -import { totalUsersKpi } from './kpi/total_users'; + import { observedUserDetails } from './observed_details'; export const usersFactory: Record> = { [UsersQueries.observedDetails]: observedUserDetails, [UsersQueries.managedDetails]: managedUserDetails, - [UsersQueries.kpiTotalUsers]: totalUsersKpi, [UsersQueries.users]: allUsers, [UsersQueries.authentications]: authentications, - [UsersQueries.kpiAuthentications]: usersKpiAuthentications, }; diff --git a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/users/kpi/authentications/index.ts b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/users/kpi/authentications/index.ts deleted file mode 100644 index d8b8d3ba827f2..0000000000000 --- a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/users/kpi/authentications/index.ts +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { getOr } from 'lodash/fp'; - -import type { IEsSearchResponse } from '@kbn/data-plugin/common'; -import { inspectStringifyObject } from '../../../../../../utils/build_query'; -import type { SecuritySolutionFactory } from '../../../types'; -import { buildUsersKpiAuthenticationsQuery } from './query.users_kpi_authentications.dsl'; -import type { - UsersKpiAuthenticationsStrategyResponse, - UsersQueries, -} from '../../../../../../../common/search_strategy'; -import { formatGeneralHistogramData } from '../../../common/format_general_histogram_data'; - -export const usersKpiAuthentications: SecuritySolutionFactory = { - buildDsl: (options) => buildUsersKpiAuthenticationsQuery(options), - parse: async ( - options, - response: IEsSearchResponse - ): Promise => { - const inspect = { - dsl: [inspectStringifyObject(buildUsersKpiAuthenticationsQuery(options))], - }; - - const authenticationsSuccessHistogram = getOr( - null, - 'aggregations.authentication_success_histogram.buckets', - response.rawResponse - ); - const authenticationsFailureHistogram = getOr( - null, - 'aggregations.authentication_failure_histogram.buckets', - response.rawResponse - ); - - return { - ...response, - inspect, - authenticationsSuccess: getOr( - null, - 'aggregations.authentication_success.doc_count', - response.rawResponse - ), - authenticationsSuccessHistogram: formatGeneralHistogramData(authenticationsSuccessHistogram), - authenticationsFailure: getOr( - null, - 'aggregations.authentication_failure.doc_count', - response.rawResponse - ), - authenticationsFailureHistogram: formatGeneralHistogramData(authenticationsFailureHistogram), - }; - }, -}; diff --git a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/users/kpi/authentications/query.users_kpi_authentications.dsl.ts b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/users/kpi/authentications/query.users_kpi_authentications.dsl.ts deleted file mode 100644 index e3e5af4a32a5e..0000000000000 --- a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/users/kpi/authentications/query.users_kpi_authentications.dsl.ts +++ /dev/null @@ -1,111 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import type { AuthenticationsKpiRequestOptions } from '../../../../../../../common/api/search_strategy/users/kpi/authentications'; -import { createQueryFilterClauses } from '../../../../../../utils/build_query'; - -export const buildUsersKpiAuthenticationsQuery = ({ - filterQuery, - timerange: { from, to }, - defaultIndex, -}: AuthenticationsKpiRequestOptions) => { - const filter = [ - ...createQueryFilterClauses(filterQuery), - { - bool: { - filter: [ - { - term: { - 'event.category': 'authentication', - }, - }, - ], - }, - }, - { - range: { - '@timestamp': { - gte: from, - lte: to, - format: 'strict_date_optional_time', - }, - }, - }, - ]; - - const dslQuery = { - index: defaultIndex, - allow_no_indices: true, - ignore_unavailable: true, - track_total_hits: false, - body: { - aggs: { - authentication_success: { - filter: { - term: { - 'event.outcome': 'success', - }, - }, - }, - authentication_success_histogram: { - auto_date_histogram: { - field: '@timestamp', - buckets: 6, - }, - aggs: { - count: { - filter: { - term: { - 'event.outcome': 'success', - }, - }, - }, - }, - }, - authentication_failure: { - filter: { - term: { - 'event.outcome': 'failure', - }, - }, - }, - authentication_failure_histogram: { - auto_date_histogram: { - field: '@timestamp', - buckets: 6, - }, - aggs: { - count: { - filter: { - term: { - 'event.outcome': 'failure', - }, - }, - }, - }, - }, - }, - query: { - bool: { - filter, - }, - }, - size: 0, - _source: false, - fields: [ - 'event.outcome', - 'event.category', - { - field: '@timestamp', - format: 'strict_date_optional_time', - }, - ], - }, - }; - - return dslQuery; -}; diff --git a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/users/kpi/total_users/index.ts b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/users/kpi/total_users/index.ts deleted file mode 100644 index 7086b1c6f4f45..0000000000000 --- a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/users/kpi/total_users/index.ts +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { getOr } from 'lodash/fp'; - -import type { IEsSearchResponse } from '@kbn/data-plugin/common'; -import type { UsersQueries } from '../../../../../../../common/search_strategy/security_solution/users'; -import type { TotalUsersKpiStrategyResponse } from '../../../../../../../common/search_strategy/security_solution/users/kpi/total_users'; - -import { inspectStringifyObject } from '../../../../../../utils/build_query'; -import type { SecuritySolutionFactory } from '../../../types'; -import { buildTotalUsersKpiQuery } from './query.build_total_users_kpi.dsl'; -import { formatGeneralHistogramData } from '../../../common/format_general_histogram_data'; - -export const totalUsersKpi: SecuritySolutionFactory = { - buildDsl: (options) => buildTotalUsersKpiQuery(options), - parse: async ( - options, - response: IEsSearchResponse - ): Promise => { - const inspect = { - dsl: [inspectStringifyObject(buildTotalUsersKpiQuery(options))], - }; - - const usersHistogram = getOr( - null, - 'aggregations.users_histogram.buckets', - response.rawResponse - ); - return { - ...response, - inspect, - users: getOr(null, 'aggregations.users.value', response.rawResponse), - usersHistogram: formatGeneralHistogramData(usersHistogram), - }; - }, -}; diff --git a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/users/kpi/total_users/query.build_total_users_kpi.dsl.ts b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/users/kpi/total_users/query.build_total_users_kpi.dsl.ts deleted file mode 100644 index 9ff10bd22cb1f..0000000000000 --- a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/users/kpi/total_users/query.build_total_users_kpi.dsl.ts +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import type { TotalUsersKpiRequestOptions } from '../../../../../../../common/api/search_strategy'; -import { createQueryFilterClauses } from '../../../../../../utils/build_query'; - -export const buildTotalUsersKpiQuery = ({ - filterQuery, - timerange: { from, to }, - defaultIndex, -}: TotalUsersKpiRequestOptions) => { - const filter = [ - ...createQueryFilterClauses(filterQuery), - { - range: { - '@timestamp': { - gte: from, - lte: to, - format: 'strict_date_optional_time', - }, - }, - }, - ]; - - const dslQuery = { - index: defaultIndex, - allow_no_indices: true, - ignore_unavailable: true, - track_total_hits: false, - body: { - aggregations: { - users: { - cardinality: { - field: 'user.name', - }, - }, - users_histogram: { - auto_date_histogram: { - field: '@timestamp', - buckets: 6, - }, - aggs: { - count: { - cardinality: { - field: 'user.name', - }, - }, - }, - }, - }, - query: { - bool: { - filter, - }, - }, - size: 0, - }, - }; - - return dslQuery; -}; diff --git a/x-pack/plugins/translations/translations/fr-FR.json b/x-pack/plugins/translations/translations/fr-FR.json index fe8eeb773ad9f..11f2e54d59534 100644 --- a/x-pack/plugins/translations/translations/fr-FR.json +++ b/x-pack/plugins/translations/translations/fr-FR.json @@ -34008,7 +34008,6 @@ "xpack.securitySolution.detectionEngine.alerts.createThresholdTimelineFailureTitle": "Impossible de créer une chronologie d'alerte de seuil", "xpack.securitySolution.detectionEngine.alerts.documentTypeTitle": "Alertes", "xpack.securitySolution.detectionEngine.alerts.fetchExceptionFilterFailure": "Erreur lors de la récupération du filtre d'exception.", - "xpack.securitySolution.detectionEngine.alerts.histogram.allOthersGroupingLabel": "Toutes les autres", "xpack.securitySolution.detectionEngine.alerts.histogram.headerTitle": "Tendance", "xpack.securitySolution.detectionEngine.alerts.histogram.notAvailableTooltip": "Non disponible pour la vue de tendance", "xpack.securitySolution.detectionEngine.alerts.histogram.stackByOptions.groupByLabel": "Regrouper par", @@ -36700,10 +36699,6 @@ "xpack.securitySolution.hosts.topRiskScoreContributors.ruleNameColumnTitle": "Nom de règle", "xpack.securitySolution.hosts.topRiskScoreContributors.title": "Principaux contributeurs de score de risque", "xpack.securitySolution.hosts.topRiskScoreContributorsTable.title": "Principaux contributeurs de score de risque", - "xpack.securitySolution.hostsKpiHosts.errorSearchDescription": "Une erreur s'est produite lors de la recherche du KPI des hôtes", - "xpack.securitySolution.hostsKpiHosts.failSearchDescription": "Impossible de lancer une recherche sur le KPI des hôtes", - "xpack.securitySolution.hostsKpiUniqueIps.errorSearchDescription": "Une erreur s'est produite lors de la recherche des IP uniques du KPI des hôtes", - "xpack.securitySolution.hostsKpiUniqueIps.failSearchDescription": "Impossible de lancer une recherche sur les IP uniques du KPI des hôtes", "xpack.securitySolution.hostsRiskTable.hostNameTitle": "Nom d'hôte", "xpack.securitySolution.hostsRiskTable.hostRiskScoreTitle": "Score de risque de l'hôte", "xpack.securitySolution.hostsRiskTable.hostRiskTitle": "Risque de l'hôte", @@ -36870,8 +36865,6 @@ "xpack.securitySolution.markdownEditor.plugins.timeline.noTimelineIdFoundErrorMsg": "Aucun ID de chronologie n'a été trouvé", "xpack.securitySolution.markdownEditor.plugins.timeline.noTimelineNameFoundErrorMsg": "Aucun nom de chronologie n'a été trouvé", "xpack.securitySolution.markdownEditor.plugins.timeline.timelineErrorTitle": "Erreur de chronologie", - "xpack.securitySolution.matrixHistogram.errorSearchDescription": "Une erreur s'est produite sur la recherche de l'histogramme de matrice", - "xpack.securitySolution.matrixHistogram.failSearchDescription": "Impossible de lancer une recherche sur l'histogramme de matrice", "xpack.securitySolution.ml.score.anomalousEntityTitle": "Entité anormale", "xpack.securitySolution.ml.score.anomalyJobTitle": "Tâche", "xpack.securitySolution.ml.score.detectedTitle": "Détecté", @@ -36983,16 +36976,6 @@ "xpack.securitySolution.networkHttpTable.column.requestsTitle": "Demandes", "xpack.securitySolution.networkHttpTable.column.statusTitle": "Statut", "xpack.securitySolution.networkHttpTable.title": "Requêtes HTTP", - "xpack.securitySolution.networkKpiDns.errorSearchDescription": "Une erreur s'est produite sur la recherche de DNS de KPI réseau", - "xpack.securitySolution.networkKpiDns.failSearchDescription": "Impossible de lancer la recherche sur le DNS de KPI réseau", - "xpack.securitySolution.networkKpiNetworkEvents.errorSearchDescription": "Une erreur s'est produite sur la recherche d'événements réseau de KPI réseau", - "xpack.securitySolution.networkKpiNetworkEvents.failSearchDescription": "Impossible de lancer la recherche sur les événements réseau de KPI réseau", - "xpack.securitySolution.networkKpiTlsHandshakes.errorSearchDescription": "Une erreur s'est produite sur la recherche d'établissements de liaison TLS avec le KPI réseau", - "xpack.securitySolution.networkKpiTlsHandshakes.failSearchDescription": "Impossible de lancer la recherche sur les établissements de liaison TLS avec le KPI réseau", - "xpack.securitySolution.networkKpiUniqueFlows.errorSearchDescription": "Une erreur s'est produite sur la recherche de flux uniques de KPI réseau", - "xpack.securitySolution.networkKpiUniqueFlows.failSearchDescription": "Impossible de lancer la recherche sur les flux uniques de KPI réseau", - "xpack.securitySolution.networkKpiUniquePrivateIps.errorSearchDescription": "Une erreur s'est produite sur la recherche d'IP privées uniques de KPI réseau", - "xpack.securitySolution.networkKpiUniquePrivateIps.failSearchDescription": "Impossible de lancer la recherche sur les IP privées uniques de KPI réseau", "xpack.securitySolution.networkTls.errorSearchDescription": "Une erreur s'est produite sur la recherche de TLS réseau", "xpack.securitySolution.networkTls.failSearchDescription": "Impossible de lancer la recherche sur le TLS réseau", "xpack.securitySolution.networkTopCountries.failSearchDescription": "Impossible de lancer la recherche sur les premiers pays du réseau", @@ -37998,8 +37981,6 @@ "xpack.securitySolution.users.navigation.riskTitle": "Risque de l'utilisateur", "xpack.securitySolution.users.navigation.userScoreOverTimeTitle": "Score de risque de l'utilisateur sur la durée", "xpack.securitySolution.users.pageTitle": "Utilisateurs", - "xpack.securitySolution.usersKpiAuthentications.errorSearchDescription": "Une erreur s'est produite lors de la recherche d'authentifications du KPI des utilisateurs", - "xpack.securitySolution.usersKpiAuthentications.failSearchDescription": "Impossible de lancer une recherche sur les authentifications du KPI des utilisateurs", "xpack.securitySolution.usersRiskTable.userNameTitle": "Nom d'utilisateur", "xpack.securitySolution.usersRiskTable.userRiskScoreTitle": "Score de risque de l'utilisateur", "xpack.securitySolution.usersTable.domainTitle": "Domaine", diff --git a/x-pack/plugins/translations/translations/ja-JP.json b/x-pack/plugins/translations/translations/ja-JP.json index 99f104ae06ff4..1458d03dc6a7a 100644 --- a/x-pack/plugins/translations/translations/ja-JP.json +++ b/x-pack/plugins/translations/translations/ja-JP.json @@ -33977,7 +33977,6 @@ "xpack.securitySolution.detectionEngine.alerts.createThresholdTimelineFailureTitle": "しきい値アラートタイムラインを作成できませんでした", "xpack.securitySolution.detectionEngine.alerts.documentTypeTitle": "アラート", "xpack.securitySolution.detectionEngine.alerts.fetchExceptionFilterFailure": "例外フィルターの取得エラー。", - "xpack.securitySolution.detectionEngine.alerts.histogram.allOthersGroupingLabel": "その他すべて", "xpack.securitySolution.detectionEngine.alerts.histogram.headerTitle": "傾向", "xpack.securitySolution.detectionEngine.alerts.histogram.notAvailableTooltip": "傾向ビューでは使用できません", "xpack.securitySolution.detectionEngine.alerts.histogram.stackByOptions.groupByLabel": "グループ分けの条件", @@ -36669,10 +36668,6 @@ "xpack.securitySolution.hosts.topRiskScoreContributors.ruleNameColumnTitle": "ルール名", "xpack.securitySolution.hosts.topRiskScoreContributors.title": "上位のリスクスコアの要因", "xpack.securitySolution.hosts.topRiskScoreContributorsTable.title": "上位のリスクスコアの要因", - "xpack.securitySolution.hostsKpiHosts.errorSearchDescription": "ホストKPIホスト検索でエラーが発生しました", - "xpack.securitySolution.hostsKpiHosts.failSearchDescription": "ホストKPIホストで検索を実行できませんでした", - "xpack.securitySolution.hostsKpiUniqueIps.errorSearchDescription": "ホストKPI一意のIP検索でエラーが発生しました", - "xpack.securitySolution.hostsKpiUniqueIps.failSearchDescription": "ホストKPI一意のIPで検索を実行できませんでした", "xpack.securitySolution.hostsRiskTable.hostNameTitle": "ホスト名", "xpack.securitySolution.hostsRiskTable.hostRiskScoreTitle": "ホストリスクスコア", "xpack.securitySolution.hostsRiskTable.hostRiskTitle": "ホストリスク", @@ -36839,8 +36834,6 @@ "xpack.securitySolution.markdownEditor.plugins.timeline.noTimelineIdFoundErrorMsg": "タイムラインIDが見つかりません", "xpack.securitySolution.markdownEditor.plugins.timeline.noTimelineNameFoundErrorMsg": "タイムライン名が見つかりません", "xpack.securitySolution.markdownEditor.plugins.timeline.timelineErrorTitle": "タイムラインエラー", - "xpack.securitySolution.matrixHistogram.errorSearchDescription": "行列ヒストグラム検索でエラーが発生しました", - "xpack.securitySolution.matrixHistogram.failSearchDescription": "行列ヒストグラムで検索を実行できませんでした", "xpack.securitySolution.ml.score.anomalousEntityTitle": "異常エンティティ", "xpack.securitySolution.ml.score.anomalyJobTitle": "ジョブ名", "xpack.securitySolution.ml.score.detectedTitle": "検出", @@ -36952,16 +36945,6 @@ "xpack.securitySolution.networkHttpTable.column.requestsTitle": "リクエスト", "xpack.securitySolution.networkHttpTable.column.statusTitle": "ステータス", "xpack.securitySolution.networkHttpTable.title": "HTTPリクエスト", - "xpack.securitySolution.networkKpiDns.errorSearchDescription": "ネットワークKPI DNS検索でエラーが発生しました", - "xpack.securitySolution.networkKpiDns.failSearchDescription": "ネットワークKPI DNSで検索を実行できませんでした", - "xpack.securitySolution.networkKpiNetworkEvents.errorSearchDescription": "ネットワークKPIネットワークイベント検索でエラーが発生しました", - "xpack.securitySolution.networkKpiNetworkEvents.failSearchDescription": "ネットワークKPIネットワークイベントで検索を実行できませんでした", - "xpack.securitySolution.networkKpiTlsHandshakes.errorSearchDescription": "ネットワークKPI TLSハンドシェイク検索でエラーが発生しました", - "xpack.securitySolution.networkKpiTlsHandshakes.failSearchDescription": "ネットワークKPI TLSハンドシェイクで検索を実行できませんでした", - "xpack.securitySolution.networkKpiUniqueFlows.errorSearchDescription": "ネットワークKPI一意のフロー検索でエラーが発生しました", - "xpack.securitySolution.networkKpiUniqueFlows.failSearchDescription": "ネットワークKPI一意のフローで検索を実行できませんでした", - "xpack.securitySolution.networkKpiUniquePrivateIps.errorSearchDescription": "ネットワークKPI一意のプライベートIP検索でエラーが発生しました", - "xpack.securitySolution.networkKpiUniquePrivateIps.failSearchDescription": "ネットワークKPI一意のプライベートIPで検索を実行できませんでした", "xpack.securitySolution.networkTls.errorSearchDescription": "ネットワークTLS検索でエラーが発生しました", "xpack.securitySolution.networkTls.failSearchDescription": "ネットワークTLSで検索を実行できませんでした", "xpack.securitySolution.networkTopCountries.failSearchDescription": "ネットワーク上位の国で検索を実行できませんでした", @@ -37967,8 +37950,6 @@ "xpack.securitySolution.users.navigation.riskTitle": "ユーザーリスク", "xpack.securitySolution.users.navigation.userScoreOverTimeTitle": "経時的なユーザーリスクスコア", "xpack.securitySolution.users.pageTitle": "ユーザー", - "xpack.securitySolution.usersKpiAuthentications.errorSearchDescription": "ユーザーKPI認証検索でエラーが発生しました", - "xpack.securitySolution.usersKpiAuthentications.failSearchDescription": "ユーザーKPI認証で検索を実行できませんでした", "xpack.securitySolution.usersRiskTable.userNameTitle": "ユーザー名", "xpack.securitySolution.usersRiskTable.userRiskScoreTitle": "ユーザーリスクスコア", "xpack.securitySolution.usersTable.domainTitle": "ドメイン", diff --git a/x-pack/plugins/translations/translations/zh-CN.json b/x-pack/plugins/translations/translations/zh-CN.json index c4df07aade234..300ba5c4121f2 100644 --- a/x-pack/plugins/translations/translations/zh-CN.json +++ b/x-pack/plugins/translations/translations/zh-CN.json @@ -34020,7 +34020,6 @@ "xpack.securitySolution.detectionEngine.alerts.createThresholdTimelineFailureTitle": "无法创建阈值告警时间线", "xpack.securitySolution.detectionEngine.alerts.documentTypeTitle": "告警", "xpack.securitySolution.detectionEngine.alerts.fetchExceptionFilterFailure": "提取例外筛选时出错。", - "xpack.securitySolution.detectionEngine.alerts.histogram.allOthersGroupingLabel": "所有其他", "xpack.securitySolution.detectionEngine.alerts.histogram.headerTitle": "趋势", "xpack.securitySolution.detectionEngine.alerts.histogram.notAvailableTooltip": "不适用于趋势视图", "xpack.securitySolution.detectionEngine.alerts.histogram.stackByOptions.groupByLabel": "分组依据", @@ -36712,10 +36711,6 @@ "xpack.securitySolution.hosts.topRiskScoreContributors.ruleNameColumnTitle": "规则名称", "xpack.securitySolution.hosts.topRiskScoreContributors.title": "风险分数主要因素", "xpack.securitySolution.hosts.topRiskScoreContributorsTable.title": "风险分数主要因素", - "xpack.securitySolution.hostsKpiHosts.errorSearchDescription": "搜索主机 KPI 主机时发生错误", - "xpack.securitySolution.hostsKpiHosts.failSearchDescription": "无法对主机 KPI 主机执行搜索", - "xpack.securitySolution.hostsKpiUniqueIps.errorSearchDescription": "搜索主机 KPI 唯一 IP 时发生错误", - "xpack.securitySolution.hostsKpiUniqueIps.failSearchDescription": "无法对主机 KPI 唯一 IP 执行搜索", "xpack.securitySolution.hostsRiskTable.hostNameTitle": "主机名", "xpack.securitySolution.hostsRiskTable.hostRiskScoreTitle": "主机风险分数", "xpack.securitySolution.hostsRiskTable.hostRiskTitle": "主机风险", @@ -36882,8 +36877,6 @@ "xpack.securitySolution.markdownEditor.plugins.timeline.noTimelineIdFoundErrorMsg": "找不到时间线 ID", "xpack.securitySolution.markdownEditor.plugins.timeline.noTimelineNameFoundErrorMsg": "找不到时间线名称", "xpack.securitySolution.markdownEditor.plugins.timeline.timelineErrorTitle": "时间线错误", - "xpack.securitySolution.matrixHistogram.errorSearchDescription": "搜索矩阵直方图时发生错误", - "xpack.securitySolution.matrixHistogram.failSearchDescription": "无法对矩阵直方图执行搜索", "xpack.securitySolution.ml.score.anomalousEntityTitle": "异常实体", "xpack.securitySolution.ml.score.anomalyJobTitle": "作业", "xpack.securitySolution.ml.score.detectedTitle": "已检测到", @@ -36995,16 +36988,6 @@ "xpack.securitySolution.networkHttpTable.column.requestsTitle": "请求", "xpack.securitySolution.networkHttpTable.column.statusTitle": "状态", "xpack.securitySolution.networkHttpTable.title": "HTTP 请求", - "xpack.securitySolution.networkKpiDns.errorSearchDescription": "搜索网络 KPI DNS 时发生错误", - "xpack.securitySolution.networkKpiDns.failSearchDescription": "无法对网络 KPI DNS 执行搜索", - "xpack.securitySolution.networkKpiNetworkEvents.errorSearchDescription": "搜索网络 KPI 网络事件时发生错误", - "xpack.securitySolution.networkKpiNetworkEvents.failSearchDescription": "无法对网络 KPI 网络事件执行搜索", - "xpack.securitySolution.networkKpiTlsHandshakes.errorSearchDescription": "搜索网络 KPI TLS 握手时发生错误", - "xpack.securitySolution.networkKpiTlsHandshakes.failSearchDescription": "无法对网络 KPI TLS 握手执行搜索", - "xpack.securitySolution.networkKpiUniqueFlows.errorSearchDescription": "搜索网络 KPI 唯一流时发生错误", - "xpack.securitySolution.networkKpiUniqueFlows.failSearchDescription": "无法对网络 KPI 唯一流执行搜索", - "xpack.securitySolution.networkKpiUniquePrivateIps.errorSearchDescription": "搜索网络 KPI 唯一专用 IP 时发生错误", - "xpack.securitySolution.networkKpiUniquePrivateIps.failSearchDescription": "无法对网络 KPI 唯一专用 IP 执行搜索", "xpack.securitySolution.networkTls.errorSearchDescription": "搜索网络 TLS 时发生错误", "xpack.securitySolution.networkTls.failSearchDescription": "无法对网络 TLS 执行搜索", "xpack.securitySolution.networkTopCountries.failSearchDescription": "无法对网络热门国家/地区执行搜索", @@ -38010,8 +37993,6 @@ "xpack.securitySolution.users.navigation.riskTitle": "用户风险", "xpack.securitySolution.users.navigation.userScoreOverTimeTitle": "一段时间的用户风险分数", "xpack.securitySolution.users.pageTitle": "用户", - "xpack.securitySolution.usersKpiAuthentications.errorSearchDescription": "搜索用户 KPI 身份验证时发生错误", - "xpack.securitySolution.usersKpiAuthentications.failSearchDescription": "无法对用户 KPI 身份验证执行搜索", "xpack.securitySolution.usersRiskTable.userNameTitle": "用户名", "xpack.securitySolution.usersRiskTable.userRiskScoreTitle": "用户风险分数", "xpack.securitySolution.usersTable.domainTitle": "域", diff --git a/x-pack/test/api_integration/apis/security_solution/index.js b/x-pack/test/api_integration/apis/security_solution/index.js index ba35ac7240852..501e2de697ec9 100644 --- a/x-pack/test/api_integration/apis/security_solution/index.js +++ b/x-pack/test/api_integration/apis/security_solution/index.js @@ -11,9 +11,6 @@ export default function ({ loadTestFile }) { loadTestFile(require.resolve('./events')); loadTestFile(require.resolve('./hosts')); loadTestFile(require.resolve('./host_details')); - loadTestFile(require.resolve('./kpi_network')); - loadTestFile(require.resolve('./kpi_hosts')); - loadTestFile(require.resolve('./matrix_dns_histogram')); loadTestFile(require.resolve('./network_details')); loadTestFile(require.resolve('./network_dns')); loadTestFile(require.resolve('./network_top_n_flow')); diff --git a/x-pack/test/api_integration/apis/security_solution/kpi_hosts.ts b/x-pack/test/api_integration/apis/security_solution/kpi_hosts.ts deleted file mode 100644 index d1ae827c535a3..0000000000000 --- a/x-pack/test/api_integration/apis/security_solution/kpi_hosts.ts +++ /dev/null @@ -1,201 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import expect from '@kbn/expect'; -import { - HostsKpiHostsStrategyResponse, - HostsKpiQueries, - HostsKpiUniqueIpsStrategyResponse, -} from '@kbn/security-solution-plugin/common/search_strategy'; -import { FtrProviderContext } from '../../ftr_provider_context'; - -export default function ({ getService }: FtrProviderContext) { - const esArchiver = getService('esArchiver'); - const supertest = getService('supertest'); - const bsearch = getService('bsearch'); - - describe('Kpi Hosts', () => { - describe('With filebeat', () => { - before( - async () => await esArchiver.load('x-pack/test/functional/es_archives/filebeat/kpi_hosts') - ); - after( - async () => await esArchiver.unload('x-pack/test/functional/es_archives/filebeat/kpi_hosts') - ); - - const FROM = '2000-01-01T00:00:00.000Z'; - const TO = '3000-01-01T00:00:00.000Z'; - const expectedResult = { - hosts: 1, - hostsHistogram: [ - { - x: new Date('2019-02-09T16:45:06.000Z').valueOf(), - y: 1, - }, - ], - uniqueSourceIps: 1, - uniqueSourceIpsHistogram: [ - { - x: new Date('2019-02-09T16:45:06.000Z').valueOf(), - y: 1, - }, - ], - uniqueDestinationIps: 1, - uniqueDestinationIpsHistogram: [ - { - x: new Date('2019-02-09T16:45:06.000Z').valueOf(), - y: 1, - }, - ], - }; - - it('Make sure that we get KpiHosts data', async () => { - const kpiHosts = await bsearch.send({ - supertest, - options: { - factoryQueryType: HostsKpiQueries.kpiHosts, - timerange: { - interval: '12h', - to: TO, - from: FROM, - }, - defaultIndex: ['filebeat-*'], - inspect: false, - }, - strategy: 'securitySolutionSearchStrategy', - }); - expect(kpiHosts.hostsHistogram).to.eql(expectedResult.hostsHistogram); - expect(kpiHosts.hosts).to.eql(expectedResult.hosts); - }); - - it('Make sure that we get KpiUniqueIps data', async () => { - const body = await bsearch.send({ - supertest, - options: { - factoryQueryType: HostsKpiQueries.kpiUniqueIps, - timerange: { - interval: '12h', - to: TO, - from: FROM, - }, - defaultIndex: ['filebeat-*'], - inspect: false, - }, - strategy: 'securitySolutionSearchStrategy', - }); - expect(body.uniqueDestinationIps).to.eql(expectedResult.uniqueDestinationIps); - expect(body.uniqueDestinationIpsHistogram).to.eql( - expectedResult.uniqueDestinationIpsHistogram - ); - expect(body.uniqueSourceIps).to.eql(expectedResult.uniqueSourceIps); - expect(body.uniqueSourceIpsHistogram).to.eql(expectedResult.uniqueSourceIpsHistogram); - }); - }); - - describe('With auditbeat', () => { - before( - async () => await esArchiver.load('x-pack/test/functional/es_archives/auditbeat/kpi_hosts') - ); - after( - async () => - await esArchiver.unload('x-pack/test/functional/es_archives/auditbeat/kpi_hosts') - ); - - const FROM = '2000-01-01T00:00:00.000Z'; - const TO = '3000-01-01T00:00:00.000Z'; - const expectedResult = { - hosts: 3, - hostsHistogram: [ - { - x: new Date('2018-11-27T00:00:00.000Z').valueOf(), - y: 1, - }, - { - x: new Date('2018-11-27T00:30:00.000Z').valueOf(), - y: 0, - }, - { - x: new Date('2018-11-27T01:00:00.000Z').valueOf(), - y: 0, - }, - { - x: new Date('2018-11-27T01:30:00.000Z').valueOf(), - y: 0, - }, - { - x: new Date('2018-11-27T02:00:00.000Z').valueOf(), - y: 1, - }, - { - x: new Date('2018-11-27T02:30:00.000Z').valueOf(), - y: 1, - }, - ], - uniqueSourceIps: 3, - uniqueSourceIpsHistogram: [ - { x: 1543276800000, y: 1 }, - { x: 1543278600000, y: 0 }, - { x: 1543280400000, y: 0 }, - { x: 1543282200000, y: 0 }, - { x: 1543284000000, y: 1 }, - { x: 1543285800000, y: 1 }, - ], - uniqueDestinationIps: 0, - uniqueDestinationIpsHistogram: [ - { x: 1543276800000, y: 0 }, - { x: 1543278600000, y: 0 }, - { x: 1543280400000, y: 0 }, - { x: 1543282200000, y: 0 }, - { x: 1543284000000, y: 0 }, - { x: 1543285800000, y: 0 }, - ], - }; - - it('Make sure that we get KpiHosts data', async () => { - const kpiHosts = await bsearch.send({ - supertest, - options: { - factoryQueryType: HostsKpiQueries.kpiHosts, - timerange: { - interval: '12h', - to: TO, - from: FROM, - }, - defaultIndex: ['auditbeat-*'], - inspect: false, - }, - strategy: 'securitySolutionSearchStrategy', - }); - expect(kpiHosts.hostsHistogram).to.eql(expectedResult.hostsHistogram); - expect(kpiHosts.hosts).to.eql(expectedResult.hosts); - }); - - it('Make sure that we get KpiUniqueIps data', async () => { - const body = await bsearch.send({ - supertest, - options: { - factoryQueryType: HostsKpiQueries.kpiUniqueIps, - timerange: { - interval: '12h', - to: TO, - from: FROM, - }, - defaultIndex: ['auditbeat-*'], - inspect: false, - }, - strategy: 'securitySolutionSearchStrategy', - }); - expect(body.uniqueDestinationIps!).to.eql(expectedResult.uniqueDestinationIps); - expect(body.uniqueDestinationIpsHistogram!).to.eql( - expectedResult.uniqueDestinationIpsHistogram - ); - expect(body.uniqueSourceIps!).to.eql(expectedResult.uniqueSourceIps); - expect(body.uniqueSourceIpsHistogram!).to.eql(expectedResult.uniqueSourceIpsHistogram); - }); - }); - }); -} diff --git a/x-pack/test/api_integration/apis/security_solution/kpi_network.ts b/x-pack/test/api_integration/apis/security_solution/kpi_network.ts deleted file mode 100644 index 446797d993294..0000000000000 --- a/x-pack/test/api_integration/apis/security_solution/kpi_network.ts +++ /dev/null @@ -1,323 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import expect from '@kbn/expect'; -import { - NetworkKpiDnsStrategyResponse, - NetworkKpiNetworkEventsStrategyResponse, - NetworkKpiQueries, - NetworkKpiTlsHandshakesStrategyResponse, - NetworkKpiUniqueFlowsStrategyResponse, - NetworkKpiUniquePrivateIpsStrategyResponse, -} from '@kbn/security-solution-plugin/common/search_strategy'; -import { FtrProviderContext } from '../../ftr_provider_context'; - -export default function ({ getService }: FtrProviderContext) { - const esArchiver = getService('esArchiver'); - const supertest = getService('supertest'); - const bsearch = getService('bsearch'); - - describe('Kpi Network', () => { - describe('With filebeat', () => { - before( - async () => await esArchiver.load('x-pack/test/functional/es_archives/filebeat/default') - ); - after( - async () => await esArchiver.unload('x-pack/test/functional/es_archives/filebeat/default') - ); - - const FROM = '2000-01-01T00:00:00.000Z'; - const TO = '3000-01-01T00:00:00.000Z'; - const expectedResult = { - networkEvents: 6157, - uniqueFlowId: 712, - uniqueSourcePrivateIps: 8, - uniqueSourcePrivateIpsHistogram: [ - { - x: new Date('2019-02-09T16:00:00.000Z').valueOf(), - y: 8, - }, - { - x: new Date('2019-02-09T19:00:00.000Z').valueOf(), - y: 0, - }, - { - x: new Date('2019-02-09T22:00:00.000Z').valueOf(), - y: 8, - }, - { - x: new Date('2019-02-10T01:00:00.000Z').valueOf(), - y: 7, - }, - ], - uniqueDestinationPrivateIps: 9, - uniqueDestinationPrivateIpsHistogram: [ - { - x: new Date('2019-02-09T16:00:00.000Z').valueOf(), - y: 8, - }, - { - x: new Date('2019-02-09T19:00:00.000Z').valueOf(), - y: 0, - }, - { - x: new Date('2019-02-09T22:00:00.000Z').valueOf(), - y: 8, - }, - { - x: new Date('2019-02-10T01:00:00.000Z').valueOf(), - y: 8, - }, - ], - dnsQueries: 169, - tlsHandshakes: 62, - }; - - it('Make sure that we get KpiNetwork uniqueFlows data', async () => { - const kpiNetwork = await bsearch.send({ - supertest, - options: { - factoryQueryType: NetworkKpiQueries.uniqueFlows, - timerange: { - interval: '12h', - to: TO, - from: FROM, - }, - defaultIndex: ['filebeat-*'], - inspect: false, - }, - strategy: 'securitySolutionSearchStrategy', - }); - expect(kpiNetwork.uniqueFlowId).to.eql(expectedResult.uniqueFlowId); - }); - - it('Make sure that we get KpiNetwork networkEvents data', async () => { - const kpiNetwork = await bsearch.send({ - supertest, - options: { - factoryQueryType: NetworkKpiQueries.networkEvents, - timerange: { - interval: '12h', - to: TO, - from: FROM, - }, - defaultIndex: ['filebeat-*'], - inspect: false, - }, - strategy: 'securitySolutionSearchStrategy', - }); - expect(kpiNetwork.networkEvents).to.eql(expectedResult.networkEvents); - }); - - it('Make sure that we get KpiNetwork DNS data', async () => { - const kpiNetwork = await bsearch.send({ - supertest, - options: { - factoryQueryType: NetworkKpiQueries.dns, - timerange: { - interval: '12h', - to: TO, - from: FROM, - }, - defaultIndex: ['filebeat-*'], - inspect: false, - }, - strategy: 'securitySolutionSearchStrategy', - }); - expect(kpiNetwork.dnsQueries).to.eql(expectedResult.dnsQueries); - }); - - it('Make sure that we get KpiNetwork networkEvents data', async () => { - const kpiNetwork = await bsearch.send({ - supertest, - options: { - factoryQueryType: NetworkKpiQueries.networkEvents, - timerange: { - interval: '12h', - to: TO, - from: FROM, - }, - defaultIndex: ['filebeat-*'], - inspect: false, - }, - strategy: 'securitySolutionSearchStrategy', - }); - expect(kpiNetwork.networkEvents).to.eql(expectedResult.networkEvents); - }); - - it('Make sure that we get KpiNetwork tlsHandshakes data', async () => { - const kpiNetwork = await bsearch.send({ - supertest, - options: { - factoryQueryType: NetworkKpiQueries.tlsHandshakes, - timerange: { - interval: '12h', - to: TO, - from: FROM, - }, - defaultIndex: ['filebeat-*'], - inspect: false, - }, - strategy: 'securitySolutionSearchStrategy', - }); - - expect(kpiNetwork.tlsHandshakes).to.eql(expectedResult.tlsHandshakes); - }); - - it('Make sure that we get KpiNetwork uniquePrivateIps data', async () => { - const kpiNetwork = await bsearch.send({ - supertest, - options: { - factoryQueryType: NetworkKpiQueries.uniquePrivateIps, - timerange: { - interval: '12h', - to: TO, - from: FROM, - }, - defaultIndex: ['filebeat-*'], - inspect: false, - }, - strategy: 'securitySolutionSearchStrategy', - }); - - expect(kpiNetwork.uniqueDestinationPrivateIps).to.eql( - expectedResult.uniqueDestinationPrivateIps - ); - expect(kpiNetwork.uniqueDestinationPrivateIpsHistogram).to.eql( - expectedResult.uniqueDestinationPrivateIpsHistogram - ); - expect(kpiNetwork.uniqueSourcePrivateIps).to.eql(expectedResult.uniqueSourcePrivateIps); - expect(kpiNetwork.uniqueSourcePrivateIpsHistogram).to.eql( - expectedResult.uniqueSourcePrivateIpsHistogram - ); - }); - }); - - describe('With packetbeat', () => { - before( - async () => await esArchiver.load('x-pack/test/functional/es_archives/packetbeat/default') - ); - after( - async () => await esArchiver.unload('x-pack/test/functional/es_archives/packetbeat/default') - ); - - const FROM = '2000-01-01T00:00:00.000Z'; - const TO = '3000-01-01T00:00:00.000Z'; - const expectedResult = { - networkEvents: 665, - uniqueFlowId: 124, - uniqueSourcePrivateIps: 0, - uniqueSourcePrivateIpsHistogram: null, - uniqueDestinationPrivateIps: 0, - uniqueDestinationPrivateIpsHistogram: null, - dnsQueries: 0, - tlsHandshakes: 1, - }; - - it('Make sure that we get KpiNetwork uniqueFlows data', async () => { - const kpiNetwork = await bsearch.send({ - supertest, - options: { - factoryQueryType: NetworkKpiQueries.uniqueFlows, - timerange: { - interval: '12h', - to: TO, - from: FROM, - }, - defaultIndex: ['packetbeat-*'], - inspect: false, - }, - strategy: 'securitySolutionSearchStrategy', - }); - expect(kpiNetwork.uniqueFlowId).to.eql(expectedResult.uniqueFlowId); - }); - - it('Make sure that we get KpiNetwork DNS data', async () => { - const kpiNetwork = await bsearch.send({ - supertest, - options: { - factoryQueryType: NetworkKpiQueries.dns, - timerange: { - interval: '12h', - to: TO, - from: FROM, - }, - defaultIndex: ['packetbeat-*'], - inspect: false, - }, - strategy: 'securitySolutionSearchStrategy', - }); - expect(kpiNetwork.dnsQueries).to.eql(expectedResult.dnsQueries); - }); - - it('Make sure that we get KpiNetwork networkEvents data', async () => { - const kpiNetwork = await bsearch.send({ - supertest, - options: { - factoryQueryType: NetworkKpiQueries.networkEvents, - timerange: { - interval: '12h', - to: TO, - from: FROM, - }, - defaultIndex: ['packetbeat-*'], - inspect: false, - }, - strategy: 'securitySolutionSearchStrategy', - }); - - expect(kpiNetwork.networkEvents).to.eql(expectedResult.networkEvents); - }); - - it('Make sure that we get KpiNetwork tlsHandshakes data', async () => { - const kpiNetwork = await bsearch.send({ - supertest, - options: { - factoryQueryType: NetworkKpiQueries.tlsHandshakes, - timerange: { - interval: '12h', - to: TO, - from: FROM, - }, - defaultIndex: ['packetbeat-*'], - inspect: false, - }, - strategy: 'securitySolutionSearchStrategy', - }); - expect(kpiNetwork.tlsHandshakes).to.eql(expectedResult.tlsHandshakes); - }); - - it('Make sure that we get KpiNetwork uniquePrivateIps data', async () => { - const kpiNetwork = await bsearch.send({ - supertest, - options: { - factoryQueryType: NetworkKpiQueries.uniquePrivateIps, - timerange: { - interval: '12h', - to: TO, - from: FROM, - }, - defaultIndex: ['packetbeat-*'], - inspect: false, - }, - strategy: 'securitySolutionSearchStrategy', - }); - - expect(kpiNetwork.uniqueDestinationPrivateIps).to.eql( - expectedResult.uniqueDestinationPrivateIps - ); - expect(kpiNetwork.uniqueDestinationPrivateIpsHistogram).to.eql( - expectedResult.uniqueDestinationPrivateIpsHistogram - ); - expect(kpiNetwork.uniqueSourcePrivateIps).to.eql(expectedResult.uniqueSourcePrivateIps); - expect(kpiNetwork.uniqueSourcePrivateIpsHistogram).to.eql( - expectedResult.uniqueSourcePrivateIpsHistogram - ); - }); - }); - }); -} diff --git a/x-pack/test/api_integration/apis/security_solution/kpi_users.ts b/x-pack/test/api_integration/apis/security_solution/kpi_users.ts deleted file mode 100644 index 20861f8856c83..0000000000000 --- a/x-pack/test/api_integration/apis/security_solution/kpi_users.ts +++ /dev/null @@ -1,99 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import expect from '@kbn/expect'; -import { - UsersKpiAuthenticationsStrategyResponse, - UsersQueries, -} from '@kbn/security-solution-plugin/common/search_strategy'; -import { FtrProviderContext } from '../../ftr_provider_context'; - -export default function ({ getService }: FtrProviderContext) { - const esArchiver = getService('esArchiver'); - const supertest = getService('supertest'); - const bsearch = getService('bsearch'); - - describe('Kpi Users', () => { - describe('With filebeat', () => { - before( - async () => await esArchiver.load('x-pack/test/functional/es_archives/filebeat/default') - ); - after( - async () => await esArchiver.unload('x-pack/test/functional/es_archives/filebeat/default') - ); - - const FROM = '2000-01-01T00:00:00.000Z'; - const TO = '3000-01-01T00:00:00.000Z'; - const expectedResult = { - authSuccess: 0, - authSuccessHistogram: null, - authFailure: 0, - authFailureHistogram: null, - }; - - it('Make sure that we get KpiAuthentications data', async () => { - const body = await bsearch.send({ - supertest, - options: { - factoryQueryType: UsersQueries.kpiAuthentications, - timerange: { - interval: '12h', - to: TO, - from: FROM, - }, - defaultIndex: ['filebeat-*'], - inspect: false, - }, - strategy: 'securitySolutionSearchStrategy', - }); - expect(body.authenticationsSuccess).to.eql(expectedResult.authSuccess); - expect(body.authenticationsSuccessHistogram).to.eql(expectedResult.authSuccessHistogram); - expect(body.authenticationsFailure).to.eql(expectedResult.authFailure); - expect(body.authenticationsFailureHistogram).to.eql(expectedResult.authFailureHistogram); - }); - }); - - describe('With auditbeat', () => { - before( - async () => await esArchiver.load('x-pack/test/functional/es_archives/auditbeat/default') - ); - after( - async () => await esArchiver.unload('x-pack/test/functional/es_archives/auditbeat/default') - ); - - const FROM = '2000-01-01T00:00:00.000Z'; - const TO = '3000-01-01T00:00:00.000Z'; - const expectedResult = { - authSuccess: 0, - authSuccessHistogram: null, - authFailure: 0, - authFailureHistogram: null, - }; - - it('Make sure that we get KpiAuthentications data', async () => { - const body = await bsearch.send({ - supertest, - options: { - factoryQueryType: UsersQueries.kpiAuthentications, - timerange: { - interval: '12h', - to: TO, - from: FROM, - }, - defaultIndex: ['auditbeat-*'], - inspect: false, - }, - strategy: 'securitySolutionSearchStrategy', - }); - expect(body.authenticationsSuccess).to.eql(expectedResult.authSuccess); - expect(body.authenticationsSuccessHistogram).to.eql(expectedResult.authSuccessHistogram); - expect(body.authenticationsFailure).to.eql(expectedResult.authFailure); - expect(body.authenticationsFailureHistogram).to.eql(expectedResult.authFailureHistogram); - }); - }); - }); -} diff --git a/x-pack/test/api_integration/apis/security_solution/matrix_dns_histogram.ts b/x-pack/test/api_integration/apis/security_solution/matrix_dns_histogram.ts deleted file mode 100644 index f418536d5d744..0000000000000 --- a/x-pack/test/api_integration/apis/security_solution/matrix_dns_histogram.ts +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import expect from '@kbn/expect'; - -import { - MatrixHistogramQuery, - MatrixHistogramType, - NetworkDnsStrategyResponse, -} from '@kbn/security-solution-plugin/common/search_strategy'; - -import { FtrProviderContext } from '../../ftr_provider_context'; - -export default function ({ getService }: FtrProviderContext) { - const esArchiver = getService('esArchiver'); - const supertest = getService('supertest'); - const bsearch = getService('bsearch'); - - describe('Matrix DNS Histogram', () => { - describe('Large data set', () => { - before( - async () => - await esArchiver.load( - 'x-pack/test/functional/es_archives/security_solution/matrix_dns_histogram/large_dns_query' - ) - ); - - after( - async () => - await esArchiver.unload( - 'x-pack/test/functional/es_archives/security_solution/matrix_dns_histogram/large_dns_query' - ) - ); - - const FROM = '2000-01-01T00:00:00.000Z'; - const TO = '3000-01-01T00:00:00.000Z'; - - it('Make sure that we get dns data without getting bucket errors when querying large volume of data', async () => { - const networkDns = await bsearch.send({ - supertest, - options: { - defaultIndex: ['large_volume_dns_data'], - factoryQueryType: MatrixHistogramQuery, - histogramType: MatrixHistogramType.dns, - filterQuery: - '{"bool":{"must":[],"filter":[{"match_all":{}}],"should":[],"must_not":[]}}', - isPtrIncluded: false, - timerange: { - interval: '12', - to: TO, - from: FROM, - }, - }, - strategy: 'securitySolutionSearchStrategy', - }); - // This can have a odd unknown flake if we do anything more strict than this. - const dnsCount = networkDns.rawResponse.aggregations?.dns_count as unknown as { - value: number; - }; - expect(dnsCount.value).to.be.above(0); - }); - }); - }); -} diff --git a/x-pack/test/security_solution_cypress/config.ts b/x-pack/test/security_solution_cypress/config.ts index 364327bf83b06..c3897eb24546a 100644 --- a/x-pack/test/security_solution_cypress/config.ts +++ b/x-pack/test/security_solution_cypress/config.ts @@ -46,7 +46,6 @@ export default async function ({ readConfigFile }: FtrConfigProviderContext) { '--xpack.ruleRegistry.unsafe.legacyMultiTenancy.enabled=true', `--xpack.securitySolution.enableExperimental=${JSON.stringify([ 'alertSuppressionForNewTermsRuleEnabled', - 'chartEmbeddablesEnabled', ])}`, // mock cloud to enable the guided onboarding tour in e2e tests '--xpack.cloud.id=test', diff --git a/x-pack/test/security_solution_cypress/cypress/screens/sourcerer.ts b/x-pack/test/security_solution_cypress/cypress/screens/sourcerer.ts index 450d1aa484b5d..0968be32ca005 100644 --- a/x-pack/test/security_solution_cypress/cypress/screens/sourcerer.ts +++ b/x-pack/test/security_solution_cypress/cypress/screens/sourcerer.ts @@ -30,4 +30,4 @@ export const SOURCERER = { }; export const HOSTS_STAT = - '[data-test-subj="stat-hosts"] [data-test-subj="stat-title"] [data-test-subj="metric_value"]'; + '[data-test-embeddable-id="hostsKpiHostsQuery-hosts-metric-embeddable"] [data-test-subj="metric_value"]'; From 3ab221324ae448ced66b42374e210363c5481133 Mon Sep 17 00:00:00 2001 From: Luke G <11671118+lgestc@users.noreply.github.com> Date: Mon, 15 Apr 2024 15:06:38 +0200 Subject: [PATCH 004/148] [Security Solution][Timeline] Fix 'is one of' filter dsl (#180455) ## Summary This PR fixes https://github.com/elastic/kibana/issues/175002 Follow steps defined in the linked issue during testing, but generally this is about adding custom filter in the timeline query tab. --- .../public/common/lib/kuery/index.test.ts | 29 ++++++++++++++++++- .../public/common/lib/kuery/index.ts | 2 +- 2 files changed, 29 insertions(+), 2 deletions(-) diff --git a/x-pack/plugins/security_solution/public/common/lib/kuery/index.test.ts b/x-pack/plugins/security_solution/public/common/lib/kuery/index.test.ts index 1a3cfe0eb9f08..095f49d2f1e0e 100644 --- a/x-pack/plugins/security_solution/public/common/lib/kuery/index.test.ts +++ b/x-pack/plugins/security_solution/public/common/lib/kuery/index.test.ts @@ -6,7 +6,8 @@ */ import expect from '@kbn/expect'; -import { convertToBuildEsQuery } from '.'; +import type { DataProvider } from '../../../../common/types/timeline'; +import { convertToBuildEsQuery, buildGlobalQuery } from '.'; import { mockIndexPattern } from '../../mock'; describe('convertToBuildEsQuery', () => { @@ -277,3 +278,29 @@ describe('convertToBuildEsQuery', () => { }); }); }); + +describe('buildGlobalQuery', () => { + it('should generate correct kql query when provided value is an array', () => { + const providers = [ + { + and: [], + enabled: true, + id: 'event-details-value-default-draggable-plain-column-renderer-formatted-field-value-timeline-1-Imhtx44Bu3sCtYk3xxsO-host_name-p1', + name: 'p1', + excluded: false, + kqlQuery: '', + queryMatch: { + field: 'host.name', + value: ['p1', 'p2'], + operator: 'includes', + displayField: 'host.name', + displayValue: '( p1 OR p2 )', + }, + } as DataProvider, + ]; + + const query = buildGlobalQuery(providers, {}); + + expect(query).to.equal('host.name : (p1 OR p2)'); + }); +}); diff --git a/x-pack/plugins/security_solution/public/common/lib/kuery/index.ts b/x-pack/plugins/security_solution/public/common/lib/kuery/index.ts index 80cf74a8f55b7..487917f381b9b 100644 --- a/x-pack/plugins/security_solution/public/common/lib/kuery/index.ts +++ b/x-pack/plugins/security_solution/public/common/lib/kuery/index.ts @@ -136,7 +136,7 @@ const buildQueryMatch = ( ? convertDateFieldToQuery(dataProvider.queryMatch.field, dataProvider.queryMatch.value) : `${dataProvider.queryMatch.field} : ${ Array.isArray(dataProvider.queryMatch.value) - ? dataProvider.queryMatch.value + ? `(${dataProvider.queryMatch.value.join(' OR ')})` : prepareKQLParam(dataProvider.queryMatch.value) }` : checkIfFieldTypeIsNested(dataProvider.queryMatch.field, browserFields) From bcd709352abb866f9a4a149f7bbd1ea1b191863a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Efe=20G=C3=BCrkan=20YALAMAN?= Date: Mon, 15 Apr 2024 15:14:57 +0200 Subject: [PATCH 005/148] [Search] Make connectors searchable from global search bar (#180365) ## Summary Add connectors search provider to globalSearch. We can now search the connectors available. Crawlers are searchable through their index as we don't have a path for them. Also fixed an issue with creating a new connector/crawler due to a recent path change. https://github.com/elastic/kibana/assets/1410658/972b1a8d-a620-4f7a-b458-81d121d8db48 ### Checklist Delete any items that are not applicable to this PR. - [x] Any text added follows [EUI's writing guidelines](https://elastic.github.io/eui/#/guidelines/writing), uses sentence case text and includes [i18n support](https://github.com/elastic/kibana/blob/main/packages/kbn-i18n/README.md) - [ ] [Documentation](https://www.elastic.co/guide/en/kibana/master/development-documentation.html) was added for features that require explanation or tutorials - [x] [Unit or functional tests](https://www.elastic.co/guide/en/kibana/master/development-tests.html) were updated or added to match the most common scenarios - [ ] [Flaky Test Runner](https://ci-stats.kibana.dev/trigger_flaky_test_runner/1) was used on any tests changed - [x] Any UI touched in this PR is usable by keyboard only (learn more about [keyboard accessibility](https://webaim.org/techniques/keyboard/)) - [x] Any UI touched in this PR does not create any new axe failures (run axe in browser: [FF](https://addons.mozilla.org/en-US/firefox/addon/axe-devtools/), [Chrome](https://chrome.google.com/webstore/detail/axe-web-accessibility-tes/lhdoppojpmngadmnindnejefpokejbdd?hl=en-US)) --------- Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- .../enterprise_search/server/plugin.ts | 2 + .../utils/calculate_search_score.test.ts | 52 +++++ .../server/utils/calculate_search_score.ts | 21 ++ .../connectors_search_result_provider.test.ts | 201 ++++++++++++++++++ .../connectors_search_result_provider.ts | 60 ++++++ .../utils/indices_search_result_provider.ts | 15 +- .../utils/search_result_provider.test.ts | 8 +- .../server/utils/search_result_provider.ts | 11 +- .../public/lib/result_to_option.test.ts | 9 + .../public/lib/result_to_option.tsx | 3 +- 10 files changed, 358 insertions(+), 24 deletions(-) create mode 100644 x-pack/plugins/enterprise_search/server/utils/calculate_search_score.test.ts create mode 100644 x-pack/plugins/enterprise_search/server/utils/calculate_search_score.ts create mode 100644 x-pack/plugins/enterprise_search/server/utils/connectors_search_result_provider.test.ts create mode 100644 x-pack/plugins/enterprise_search/server/utils/connectors_search_result_provider.ts diff --git a/x-pack/plugins/enterprise_search/server/plugin.ts b/x-pack/plugins/enterprise_search/server/plugin.ts index f445547858578..bd1498e0b0b61 100644 --- a/x-pack/plugins/enterprise_search/server/plugin.ts +++ b/x-pack/plugins/enterprise_search/server/plugin.ts @@ -81,6 +81,7 @@ import { workplaceSearchTelemetryType } from './saved_objects/workplace_search/t import { GlobalConfigService } from './services/global_config_service'; import { uiSettings as enterpriseSearchUISettings } from './ui_settings'; +import { getConnectorsSearchResultProvider } from './utils/connectors_search_result_provider'; import { getIndicesSearchResultProvider } from './utils/indices_search_result_provider'; import { getSearchResultProvider } from './utils/search_result_provider'; @@ -360,6 +361,7 @@ export class EnterpriseSearchPlugin implements Plugin { ) ); globalSearch.registerResultProvider(getIndicesSearchResultProvider(http.staticAssets)); + globalSearch.registerResultProvider(getConnectorsSearchResultProvider(http.staticAssets)); } } diff --git a/x-pack/plugins/enterprise_search/server/utils/calculate_search_score.test.ts b/x-pack/plugins/enterprise_search/server/utils/calculate_search_score.test.ts new file mode 100644 index 0000000000000..bb7756c0d600b --- /dev/null +++ b/x-pack/plugins/enterprise_search/server/utils/calculate_search_score.test.ts @@ -0,0 +1,52 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { calculateScore } from './calculate_search_score'; + +describe('calculateScore', () => { + it('should return 80 when the search term is undefined', () => { + const searchTerm = undefined; + const valueToTest = 'value to test'; + const score = calculateScore(searchTerm, valueToTest); + expect(score).toBe(80); + }); + + it('should return 80 when the search term is empty', () => { + const searchTerm = ''; + const valueToTest = 'valute to test'; + const score = calculateScore(searchTerm, valueToTest); + expect(score).toBe(80); + }); + + it('should return 100 when the search term matches the value', () => { + const searchTerm = 'connector'; + const valueToTest = 'connector'; + const score = calculateScore(searchTerm, valueToTest); + expect(score).toBe(100); + }); + + it('should return 90 when the search term starts with the value', () => { + const searchTerm = 'connector'; + const valueToTest = 'connector test'; + const score = calculateScore(searchTerm, valueToTest); + expect(score).toBe(90); + }); + + it('should return 75 when the search term includes the value', () => { + const searchTerm = 'connector'; + const valueToTest = 'test connector somewhere'; + const score = calculateScore(searchTerm, valueToTest); + expect(score).toBe(75); + }); + + it('should return 0 when the search term does not match the value', () => { + const searchTerm = 'connector'; + const valueToTest = 'index'; + const score = calculateScore(searchTerm, valueToTest); + expect(score).toBe(0); + }); +}); diff --git a/x-pack/plugins/enterprise_search/server/utils/calculate_search_score.ts b/x-pack/plugins/enterprise_search/server/utils/calculate_search_score.ts new file mode 100644 index 0000000000000..ba04697421e97 --- /dev/null +++ b/x-pack/plugins/enterprise_search/server/utils/calculate_search_score.ts @@ -0,0 +1,21 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +export const calculateScore = (searchTerm: string = '', valueToTest: string): number => { + const searchTermLower = searchTerm.toLowerCase(); + const valueToTestLower = valueToTest.toLowerCase(); + if (!searchTermLower) { + return 80; + } else if (valueToTestLower === searchTermLower) { + return 100; + } else if (valueToTestLower.startsWith(searchTermLower)) { + return 90; + } else if (valueToTestLower.includes(searchTermLower)) { + return 75; + } + return 0; +}; diff --git a/x-pack/plugins/enterprise_search/server/utils/connectors_search_result_provider.test.ts b/x-pack/plugins/enterprise_search/server/utils/connectors_search_result_provider.test.ts new file mode 100644 index 0000000000000..f865da1f0dcef --- /dev/null +++ b/x-pack/plugins/enterprise_search/server/utils/connectors_search_result_provider.test.ts @@ -0,0 +1,201 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { NEVER, lastValueFrom } from 'rxjs'; + +import { IScopedClusterClient } from '@kbn/core/server'; + +import { ENTERPRISE_SEARCH_CONTENT_PLUGIN } from '../../common/constants'; + +import { getConnectorsSearchResultProvider } from './connectors_search_result_provider'; + +describe('Enterprise Search - connectors search provider', () => { + const staticAssetsMock = { + getPluginAssetHref: (input: string) => `/kbn/${input}`, + } as any; + + const connectorsSearchResultProvider = getConnectorsSearchResultProvider(staticAssetsMock); + + const connectorNameMap = { + mssql: { + id: '101', + name: 'companyName mssql connector aug 12 2024 rev1.2', + }, + postgres: { id: '100', name: 'companyName-postgres-connector-all' }, + spaces: { id: '102', name: 'companyName with spaces etc companyName' }, + }; + + const mockConnectorResponse = { + results: [ + { id: connectorNameMap.postgres.id, name: connectorNameMap.postgres.name }, + { id: connectorNameMap.mssql.id, name: connectorNameMap.mssql.name }, + { id: connectorNameMap.spaces.id, name: connectorNameMap.spaces.name }, + ], + }; + + const getConnectorSearchData = (name: keyof typeof connectorNameMap) => ({ + id: connectorNameMap[name].name, + score: 90, + title: connectorNameMap[name].name, + type: 'Connector', + url: { + path: `${ENTERPRISE_SEARCH_CONTENT_PLUGIN.URL}/connectors/${connectorNameMap[name].id}`, + prependBasePath: true, + }, + icon: '/kbn/images/connector.svg', + }); + + const mockClient = { + asCurrentUser: { + transport: { + request: jest.fn(), + }, + }, + asInternalUser: {}, + }; + afterEach(() => { + jest.clearAllMocks(); + }); + const client = mockClient as unknown as IScopedClusterClient; + mockClient.asCurrentUser.transport.request.mockResolvedValue(mockConnectorResponse); + + describe('find', () => { + it('returns formatted results', async () => { + const results = await lastValueFrom( + connectorsSearchResultProvider.find( + { term: 'companyName-postgres-connector-all' }, + { + aborted$: NEVER, + maxResults: 100, + client, + preference: '', + }, + {} as any + ) + ); + expect(results).toEqual([{ ...getConnectorSearchData('postgres'), score: 100 }]); + }); + + it('returns all matched results', async () => { + const results = await lastValueFrom( + connectorsSearchResultProvider.find( + { term: 'companyName' }, + { + aborted$: NEVER, + client, + maxResults: 100, + preference: '', + }, + {} as any + ) + ); + expect(results).toEqual([ + { ...getConnectorSearchData('postgres'), score: 90 }, + { ...getConnectorSearchData('mssql'), score: 90 }, + { ...getConnectorSearchData('spaces'), score: 90 }, + ]); + }); + + it('returns all indices on empty string', async () => { + const results = await lastValueFrom( + connectorsSearchResultProvider.find( + { term: '' }, + { + aborted$: NEVER, + client, + maxResults: 100, + preference: '', + }, + {} as any + ) + ); + expect(results).toHaveLength(0); + }); + + it('respect maximum results', async () => { + const results = await lastValueFrom( + connectorsSearchResultProvider.find( + { term: 'companyName' }, + { + aborted$: NEVER, + client, + maxResults: 1, + preference: '', + }, + {} as any + ) + ); + expect(results).toEqual([{ ...getConnectorSearchData('postgres'), score: 90 }]); + }); + + describe('returns empty results', () => { + it('when term does not match with created indices', async () => { + const results = await lastValueFrom( + connectorsSearchResultProvider.find( + { term: 'sample' }, + { + aborted$: NEVER, + client, + maxResults: 100, + preference: '', + }, + {} as any + ) + ); + expect(results).toEqual([]); + }); + + it('if client is undefined', async () => { + const results = await lastValueFrom( + connectorsSearchResultProvider.find( + { term: 'sample' }, + { + aborted$: NEVER, + client: undefined, + maxResults: 100, + preference: '', + }, + {} as any + ) + ); + expect(results).toEqual([]); + }); + + it('if tag is specified', async () => { + const results = await lastValueFrom( + connectorsSearchResultProvider.find( + { term: 'search', tags: ['tag'] }, + { + aborted$: NEVER, + client, + maxResults: 100, + preference: '', + }, + {} as any + ) + ); + expect(results).toEqual([]); + }); + + it('if unknown type is specified', async () => { + const results = await lastValueFrom( + connectorsSearchResultProvider.find( + { term: 'search', types: ['tag'] }, + { + aborted$: NEVER, + client, + maxResults: 100, + preference: '', + }, + {} as any + ) + ); + expect(results).toEqual([]); + }); + }); + }); +}); diff --git a/x-pack/plugins/enterprise_search/server/utils/connectors_search_result_provider.ts b/x-pack/plugins/enterprise_search/server/utils/connectors_search_result_provider.ts new file mode 100644 index 0000000000000..3035a136f34de --- /dev/null +++ b/x-pack/plugins/enterprise_search/server/utils/connectors_search_result_provider.ts @@ -0,0 +1,60 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { from, takeUntil } from 'rxjs'; + +import { IStaticAssets } from '@kbn/core-http-browser'; + +import { + GlobalSearchProviderResult, + GlobalSearchResultProvider, +} from '@kbn/global-search-plugin/server'; +import { i18n } from '@kbn/i18n'; + +import { fetchConnectors } from '@kbn/search-connectors'; + +import { ENTERPRISE_SEARCH_CONTENT_PLUGIN } from '../../common/constants'; + +import { calculateScore } from './calculate_search_score'; + +export function getConnectorsSearchResultProvider( + staticAssets: IStaticAssets +): GlobalSearchResultProvider { + return { + find: ({ term, types, tags }, { aborted$, client, maxResults }) => { + if (!client || !term || tags || (types && !types.includes('connectors'))) { + return from([[]]); + } + const getConnectorData = async (): Promise => { + const connectorData = await fetchConnectors(client.asCurrentUser, undefined, false, term); + const searchResults: GlobalSearchProviderResult[] = connectorData + .map(({ name, id }) => { + const score = calculateScore(term, name); + return { + icon: staticAssets.getPluginAssetHref('images/connector.svg'), + id: name, + score, + title: name, + type: i18n.translate('xpack.enterpriseSearch.searchConnectorProvider.type.name', { + defaultMessage: 'Connector', + }), + url: { + path: `${ENTERPRISE_SEARCH_CONTENT_PLUGIN.URL}/connectors/${id}`, + prependBasePath: true, + }, + }; + }) + .filter((result) => result.score > 0) + .slice(0, maxResults); + return searchResults; + }; + return from(getConnectorData()).pipe(takeUntil(aborted$)); + }, + getSearchableTypes: () => ['connectors'], + id: 'enterpriseSearchConnectors', + }; +} diff --git a/x-pack/plugins/enterprise_search/server/utils/indices_search_result_provider.ts b/x-pack/plugins/enterprise_search/server/utils/indices_search_result_provider.ts index 478ee92d69f4e..295441e125aa4 100644 --- a/x-pack/plugins/enterprise_search/server/utils/indices_search_result_provider.ts +++ b/x-pack/plugins/enterprise_search/server/utils/indices_search_result_provider.ts @@ -18,6 +18,8 @@ import { ENTERPRISE_SEARCH_CONTENT_PLUGIN } from '../../common/constants'; import { getIndexData } from '../lib/indices/utils/get_index_data'; +import { calculateScore } from './calculate_search_score'; + export function getIndicesSearchResultProvider( staticAssets: IStaticAssets ): GlobalSearchResultProvider { @@ -31,18 +33,7 @@ export function getIndicesSearchResultProvider( const searchResults: GlobalSearchProviderResult[] = indexNames .map((indexName) => { - let score = 0; - const searchTerm = (term || '').toLowerCase(); - const searchName = indexName.toLowerCase(); - if (!searchTerm) { - score = 80; - } else if (searchName === searchTerm) { - score = 100; - } else if (searchName.startsWith(searchTerm)) { - score = 90; - } else if (searchName.includes(searchTerm)) { - score = 75; - } + const score = calculateScore(term, indexName); return { id: indexName, diff --git a/x-pack/plugins/enterprise_search/server/utils/search_result_provider.test.ts b/x-pack/plugins/enterprise_search/server/utils/search_result_provider.test.ts index 9f9966b5e5998..7175f6135e84c 100644 --- a/x-pack/plugins/enterprise_search/server/utils/search_result_provider.test.ts +++ b/x-pack/plugins/enterprise_search/server/utils/search_result_provider.test.ts @@ -55,7 +55,7 @@ describe('Enterprise Search search provider', () => { title: 'Elastic Web Crawler', type: 'Search', url: { - path: `${ENTERPRISE_SEARCH_CONTENT_PLUGIN.URL}/search_indices/new_index/crawler`, + path: `${ENTERPRISE_SEARCH_CONTENT_PLUGIN.URL}/crawlers/new_crawler`, prependBasePath: true, }, }; @@ -67,7 +67,7 @@ describe('Enterprise Search search provider', () => { title: 'MongoDB', type: 'Search', url: { - path: `${ENTERPRISE_SEARCH_CONTENT_PLUGIN.URL}/search_indices/new_index/connector?connector_type=connector_client&service_type=mongodb`, + path: `${ENTERPRISE_SEARCH_CONTENT_PLUGIN.URL}/connectors/new_connector?connector_type=connector_client&service_type=mongodb`, prependBasePath: true, }, }; @@ -79,7 +79,7 @@ describe('Enterprise Search search provider', () => { title: 'MongoDB', type: 'Search', url: { - path: `${ENTERPRISE_SEARCH_CONTENT_PLUGIN.URL}/search_indices/new_index/connector?connector_type=native&service_type=mongodb`, + path: `${ENTERPRISE_SEARCH_CONTENT_PLUGIN.URL}/connectors/new_connector?connector_type=native&service_type=mongodb`, prependBasePath: true, }, }; @@ -91,7 +91,7 @@ describe('Enterprise Search search provider', () => { title: 'Customized connector', type: 'Search', url: { - path: `${ENTERPRISE_SEARCH_CONTENT_PLUGIN.URL}/search_indices/new_index/connector?connector_type=connector_client&service_type=`, + path: `${ENTERPRISE_SEARCH_CONTENT_PLUGIN.URL}/connectors/new_connector?connector_type=connector_client&service_type=`, prependBasePath: true, }, }; diff --git a/x-pack/plugins/enterprise_search/server/utils/search_result_provider.ts b/x-pack/plugins/enterprise_search/server/utils/search_result_provider.ts index e7320f21768a5..d4791aa80fe45 100644 --- a/x-pack/plugins/enterprise_search/server/utils/search_result_provider.ts +++ b/x-pack/plugins/enterprise_search/server/utils/search_result_provider.ts @@ -54,6 +54,9 @@ export function toSearchResult({ ? 'native' : 'connector_client' : null; + const newUrl = isCrawler + ? `${ENTERPRISE_SEARCH_CONTENT_PLUGIN.URL}/crawlers/new_crawler` + : `${ENTERPRISE_SEARCH_CONTENT_PLUGIN.URL}/connectors/new_connector?connector_type=${connectorTypeParam}&service_type=${serviceType}`; return { icon: iconPath || 'logoEnterpriseSearch', @@ -64,13 +67,7 @@ export function toSearchResult({ defaultMessage: 'Search', }), url: { - path: - url ?? - `${ENTERPRISE_SEARCH_CONTENT_PLUGIN.URL}/search_indices/new_index/${ - isCrawler - ? 'crawler' - : `connector?connector_type=${connectorTypeParam}&service_type=${serviceType}` - }`, + path: url ?? newUrl, prependBasePath: true, }, }; diff --git a/x-pack/plugins/global_search_bar/public/lib/result_to_option.test.ts b/x-pack/plugins/global_search_bar/public/lib/result_to_option.test.ts index c0ac25ff0627d..e1fbd25b824ab 100644 --- a/x-pack/plugins/global_search_bar/public/lib/result_to_option.test.ts +++ b/x-pack/plugins/global_search_bar/public/lib/result_to_option.test.ts @@ -61,6 +61,15 @@ describe('resultToOption', () => { ); }); + it('uses icon for `connector` type', () => { + const input = createSearchResult({ type: 'connector', icon: 'connector-icon' }); + expect(resultToOption(input, [])).toEqual( + expect.objectContaining({ + icon: { type: 'connector-icon' }, + }) + ); + }); + it('does not use icon for other types', () => { const input = createSearchResult({ type: 'dashboard', icon: 'dash-icon' }); expect(resultToOption(input, [])).toEqual( diff --git a/x-pack/plugins/global_search_bar/public/lib/result_to_option.tsx b/x-pack/plugins/global_search_bar/public/lib/result_to_option.tsx index 555434a85404f..1e5de6bf3b788 100644 --- a/x-pack/plugins/global_search_bar/public/lib/result_to_option.tsx +++ b/x-pack/plugins/global_search_bar/public/lib/result_to_option.tsx @@ -26,7 +26,8 @@ export const resultToOption = ( type === 'integration' || type.toLowerCase() === 'enterprise search' || type.toLowerCase() === 'search' || - type.toLowerCase() === 'index'; + type.toLowerCase() === 'index' || + type.toLowerCase() === 'connector'; const option: EuiSelectableTemplateSitewideOption = { key: id, label: title, From 01e2379929f2fe8cfda3e8d95bb8f4e252f8ae9d Mon Sep 17 00:00:00 2001 From: Angela Chuang <6295984+angorayc@users.noreply.github.com> Date: Mon, 15 Apr 2024 14:15:48 +0100 Subject: [PATCH 006/148] [SecuritySolution] Display full name in greetings (#180670) ## Summary We could find the user's full name might not always be available from the 1st image below, but username should always exist. Previously, we displayed username straight away and it didn't look good. [bug](https://github.com/elastic/kibana/issues/177204) In this PR, we change the logic and display user's full name if it exists, otherwise fallback to the username. **No Full Name scenario - It displays username** Screenshot 2024-04-12 at 09 58 52 Screenshot 2024-04-12 at 09 59 18 **Full Name available scenario - It displays the full name** Screenshot 2024-04-12 at 10 07 28 Screenshot 2024-04-12 at 10 08 24 ### Checklist Delete any items that are not applicable to this PR. - [x] [Unit or functional tests](https://www.elastic.co/guide/en/kibana/master/development-tests.html) were updated or added to match the most common scenarios --------- Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- .../onboarding/onboarding.test.tsx | 7 +- .../onboarding/welcome_header/index.test.tsx | 86 +++++++++++++++++++ .../onboarding/welcome_header/index.tsx | 14 ++- 3 files changed, 103 insertions(+), 4 deletions(-) create mode 100644 x-pack/plugins/security_solution/public/common/components/landing_page/onboarding/welcome_header/index.test.tsx diff --git a/x-pack/plugins/security_solution/public/common/components/landing_page/onboarding/onboarding.test.tsx b/x-pack/plugins/security_solution/public/common/components/landing_page/onboarding/onboarding.test.tsx index cd8e83ea6f0f0..de37ea047335e 100644 --- a/x-pack/plugins/security_solution/public/common/components/landing_page/onboarding/onboarding.test.tsx +++ b/x-pack/plugins/security_solution/public/common/components/landing_page/onboarding/onboarding.test.tsx @@ -22,6 +22,7 @@ jest.mock('../../../lib/kibana', () => { const original = jest.requireActual('../../../lib/kibana'); return { ...original, + useCurrentUser: jest.fn().mockReturnValue({ fullName: 'UserFullName' }), useAppUrl: jest.fn().mockReturnValue({ getAppUrl: jest.fn().mockReturnValue('mock url') }), }; }); @@ -63,10 +64,14 @@ describe('OnboardingComponent', () => { ViewAlertsSteps.viewAlerts, ], }; + beforeEach(() => { + jest.clearAllMocks(); + }); + it('should render page title, subtitle, and description', () => { const { getByText } = render(); - const pageTitle = getByText('Hi Unknown!'); + const pageTitle = getByText('Hi UserFullName!'); const subtitle = getByText(`Get started with Security`); const description = getByText( `This area shows you everything you need to know. Feel free to explore all content. You can always come back here at any time.` diff --git a/x-pack/plugins/security_solution/public/common/components/landing_page/onboarding/welcome_header/index.test.tsx b/x-pack/plugins/security_solution/public/common/components/landing_page/onboarding/welcome_header/index.test.tsx new file mode 100644 index 0000000000000..0eaf44e9cc69c --- /dev/null +++ b/x-pack/plugins/security_solution/public/common/components/landing_page/onboarding/welcome_header/index.test.tsx @@ -0,0 +1,86 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ +import React from 'react'; +import { render } from '@testing-library/react'; +import { WelcomeHeader } from '.'; +import { useCurrentUser } from '../../../../lib/kibana'; +import { CurrentPlan } from './current_plan'; +import { ProductTier } from '../configs'; +import { useProjectFeaturesUrl } from '../hooks/use_project_features_url'; + +jest.mock('../../../../lib/kibana', () => ({ + useCurrentUser: jest.fn(), +})); + +jest.mock('../hooks/use_project_features_url', () => ({ + useProjectFeaturesUrl: jest.fn(), +})); + +jest.mock('./current_plan', () => ({ + CurrentPlan: jest.fn().mockReturnValue(
), +})); + +const mockUseCurrentUser = useCurrentUser as jest.Mock; +const mockCurrentPlan = CurrentPlan as unknown as jest.Mock; +const mockUseProjectFeaturesUrl = useProjectFeaturesUrl as jest.Mock; +const mockProjectFeaturesUrl = '/features'; + +describe('WelcomeHeaderComponent', () => { + beforeEach(() => { + jest.clearAllMocks(); + }); + + it('should render fullName when fullName is provided', () => { + const fullName = 'John Doe'; + mockUseCurrentUser.mockReturnValue({ fullName }); + const { getByText } = render(); + const titleElement = getByText(`Hi ${fullName}!`); + expect(titleElement).toBeInTheDocument(); + }); + + it('should render username when fullName is not provided', () => { + const username = 'jd'; + mockUseCurrentUser.mockReturnValue({ username }); + + const { getByText } = render(); + const titleElement = getByText(`Hi ${username}!`); + expect(titleElement).toBeInTheDocument(); + }); + + it('should not render the greeting message if both fullName and username are not available', () => { + mockUseCurrentUser.mockReturnValue({}); + + const { queryByTestId } = render(); + const greetings = queryByTestId(`welcome-header-greetings`); + expect(greetings).not.toBeInTheDocument(); + }); + + it('should render subtitle', () => { + const { getByText } = render(); + const subtitleElement = getByText('Get started with Security'); + expect(subtitleElement).toBeInTheDocument(); + }); + + it('should render description', () => { + const { getByText } = render(); + const descriptionElement = getByText( + 'This area shows you everything you need to know. Feel free to explore all content. You can always come back here at any time.' + ); + expect(descriptionElement).toBeInTheDocument(); + }); + + it('should render current plan', () => { + mockUseProjectFeaturesUrl.mockReturnValue(mockProjectFeaturesUrl); + const { getByTestId } = render(); + const currentPlanElement = getByTestId('current-plan'); + expect(currentPlanElement).toBeInTheDocument(); + expect(mockCurrentPlan.mock.calls[0][0]).toEqual({ + productTier: 'complete', + projectFeaturesUrl: mockProjectFeaturesUrl, + }); + }); +}); diff --git a/x-pack/plugins/security_solution/public/common/components/landing_page/onboarding/welcome_header/index.tsx b/x-pack/plugins/security_solution/public/common/components/landing_page/onboarding/welcome_header/index.tsx index b03829c29c8cc..c4d5fa13ec6f6 100644 --- a/x-pack/plugins/security_solution/public/common/components/landing_page/onboarding/welcome_header/index.tsx +++ b/x-pack/plugins/security_solution/public/common/components/landing_page/onboarding/welcome_header/index.tsx @@ -22,6 +22,10 @@ import { CurrentPlan } from './current_plan'; const WelcomeHeaderComponent: React.FC<{ productTier?: ProductTier }> = ({ productTier }) => { const userName = useCurrentUser(); + + // Full name could be null, user name should always exist + const name = userName?.fullName ?? userName?.username; + const projectFeaturesUrl = useProjectFeaturesUrl(); const { @@ -38,9 +42,13 @@ const WelcomeHeaderComponent: React.FC<{ productTier?: ProductTier }> = ({ produ return ( - {userName?.username && ( - - {GET_STARTED_PAGE_TITLE(userName.username)} + {name && ( + + {GET_STARTED_PAGE_TITLE(name)} )} From a73de7319c36fe1a31780feaee2f14328d150f73 Mon Sep 17 00:00:00 2001 From: Justin Kambic Date: Mon, 15 Apr 2024 09:20:53 -0400 Subject: [PATCH 007/148] [Observability Onboarding] Export package list from fleet (#179301) ## Summary Resolves https://github.com/elastic/kibana/issues/178945. Resolves #178947. Resolves https://github.com/elastic/kibana/issues/178952. ~Undergoing the work to export package list in a sharable way while minimally impacting the existing implementation used by the Fleet team.~ ### Update Updated to provide the flows for all three paths of the form. Synthetics and APM still link to their respective apps. Logs icons link to the embedded flows. #### Things to test - Check that the integration cards behave in a manner you'd expect. There's a lot of custom card creation happening and it's possible I have made a mistake in some linking. - Icons: there are a few icons that don't correspond to the design. I wasn't able to find the correct `src` for the colored-in APM logo, for example, and I'm not sure where the one logs icon lives. I've used the `logoFilebeat` icon in its place as it's quite similar and is heavily used in the integrations list. - For the searchable integrations list, I was unsure if I should re-hide it when the user changes their radio selection in the top-level question. Right now it'll just stay as-is with their original query. - The `Collections` feature, make sure collection buttons properly apply the search query. ~This now works with the exported package list grid from Fleet. I've introduced a real package list in place of the dummy grid that we had before. I also added a searchable grid below.~ ~Surely there are some things to iron out still. I also still consider the code rough, so if you should choose to review it you will likely find areas you want to see improved.~ ![20240405171834](https://github.com/elastic/kibana/assets/18429259/b3e4553a-1841-4c57-9713-81571fae1b44) --- **Note:** I will likely extract the Fleet-specific pieces of this to a separate patch that we can merge to Kibana `main` to make it easier for the Fleet team to review the changes. We can then merge those upstream and pull them into our feature branch. ^^ this is still true, before we merged this I'll likely pull out the Fleet-specific modifications we need and have the Fleet team review them separately. We can still merge this to the feature branch in the meantime and resolve it later. --------- Co-authored-by: Joe Reuter Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com> Co-authored-by: Thom Heymann <190132+thomheymann@users.noreply.github.com> --- .../experimental_onboarding_flow.tsx | 22 +- .../onboarding_flow_form.tsx | 98 ++++---- .../application/onboarding_flow_form/types.ts | 8 + .../use_custom_cards_for_category.ts | 212 ++++++++++++++++++ .../application/packages_list/index.tsx | 190 ++++++++++++++++ .../public/application/packages_list/lazy.tsx | 21 ++ .../public/application/packages_list/types.ts | 19 ++ .../use_integration_card_list.ts | 60 +++++ .../application/shared/use_custom_margin.ts | 13 ++ 9 files changed, 588 insertions(+), 55 deletions(-) create mode 100644 x-pack/plugins/observability_solution/observability_onboarding/public/application/onboarding_flow_form/types.ts create mode 100644 x-pack/plugins/observability_solution/observability_onboarding/public/application/onboarding_flow_form/use_custom_cards_for_category.ts create mode 100644 x-pack/plugins/observability_solution/observability_onboarding/public/application/packages_list/index.tsx create mode 100644 x-pack/plugins/observability_solution/observability_onboarding/public/application/packages_list/lazy.tsx create mode 100644 x-pack/plugins/observability_solution/observability_onboarding/public/application/packages_list/types.ts create mode 100644 x-pack/plugins/observability_solution/observability_onboarding/public/application/packages_list/use_integration_card_list.ts create mode 100644 x-pack/plugins/observability_solution/observability_onboarding/public/application/shared/use_custom_margin.ts diff --git a/x-pack/plugins/observability_solution/observability_onboarding/public/application/experimental_onboarding_flow.tsx b/x-pack/plugins/observability_solution/observability_onboarding/public/application/experimental_onboarding_flow.tsx index 13d0783c27fac..b27d27b538a04 100644 --- a/x-pack/plugins/observability_solution/observability_onboarding/public/application/experimental_onboarding_flow.tsx +++ b/x-pack/plugins/observability_solution/observability_onboarding/public/application/experimental_onboarding_flow.tsx @@ -6,21 +6,21 @@ */ import { i18n } from '@kbn/i18n'; - +import { QueryClient, QueryClientProvider } from '@tanstack/react-query'; import React from 'react'; +import { useHistory } from 'react-router-dom'; +import { Route, Routes } from '@kbn/shared-ux-router'; +import { reactRouterNavigate } from '@kbn/kibana-react-plugin/public'; +import { useNavigate, useLocation } from 'react-router-dom-v5-compat'; import { - EuiPageTemplate, - EuiSpacer, EuiButton, + EuiButtonEmpty, EuiFlexGroup, EuiFlexItem, - EuiButtonEmpty, + EuiPageTemplate, + EuiSpacer, } from '@elastic/eui'; import { css } from '@emotion/react'; -import { useHistory } from 'react-router-dom'; -import { Route, Routes } from '@kbn/shared-ux-router'; -import { reactRouterNavigate } from '@kbn/kibana-react-plugin/public'; -import { useNavigate, useLocation } from 'react-router-dom-v5-compat'; import backgroundImageUrl from './header/background.svg'; import { Footer } from './footer/footer'; import { OnboardingFlowForm } from './onboarding_flow_form/onboarding_flow_form'; @@ -28,12 +28,14 @@ import { Header } from './header/header'; import { SystemLogsPanel } from './quickstart_flows/system_logs'; import { CustomLogsPanel } from './quickstart_flows/custom_logs'; +const queryClient = new QueryClient(); + export function ExperimentalOnboardingFlow() { const history = useHistory(); const location = useLocation(); return ( - <> + {/* Test buttons to be removed once integrations selector has been implemented */} @@ -104,7 +106,7 @@ export function ExperimentalOnboardingFlow() {