diff --git a/.ci/end2end.groovy b/.ci/end2end.groovy index 0d9f5c9d92453..025836a90204c 100644 --- a/.ci/end2end.groovy +++ b/.ci/end2end.groovy @@ -41,7 +41,7 @@ pipeline { // Filter when to run based on the below reasons: // - On a PRs when: // - There are changes related to the APM UI project - // - only when the owners of those changes are members of the apm-ui team (new filter) + // - only when the owners of those changes are members of the given GitHub teams // - On merges to branches when: // - There are changes related to the APM UI project // - FORCE parameter is set to true. @@ -51,7 +51,7 @@ pipeline { apm_updated = isGitRegionMatch(patterns: [ "^x-pack/plugins/apm/.*" ]) } if (isPR()) { - def isMember = isMemberOf(user: env.CHANGE_AUTHOR, team: 'apm-ui') + def isMember = isMemberOf(user: env.CHANGE_AUTHOR, team: ['apm-ui', 'uptime']) setEnvVar('RUN_APM_E2E', params.FORCE || (apm_updated && isMember)) } else { setEnvVar('RUN_APM_E2E', params.FORCE || apm_updated) diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 03a4f9520c2ba..089e708e91f43 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -153,6 +153,7 @@ /x-pack/plugins/cloud/ @elastic/kibana-platform /x-pack/test/saved_objects_field_count/ @elastic/kibana-platform /packages/kbn-config-schema/ @elastic/kibana-platform +/packages/kbn-std/ @elastic/kibana-platform /src/legacy/server/config/ @elastic/kibana-platform /src/legacy/server/http/ @elastic/kibana-platform /src/legacy/server/logging/ @elastic/kibana-platform diff --git a/docs/developer/best-practices/images/state_inside_the_link.png b/docs/developer/best-practices/images/state_inside_the_link.png new file mode 100644 index 0000000000000..833478ccbda68 Binary files /dev/null and b/docs/developer/best-practices/images/state_inside_the_link.png differ diff --git a/docs/developer/best-practices/index.asciidoc b/docs/developer/best-practices/index.asciidoc index 42cee6ef0e58a..13ea010d0aa96 100644 --- a/docs/developer/best-practices/index.asciidoc +++ b/docs/developer/best-practices/index.asciidoc @@ -122,6 +122,14 @@ In addition, if users are relying on state stored in your app’s URL as part of your public contract, keep in mind that you may also need to provide backwards compatibility for bookmarked URLs. +[discrete] +=== Routing, Navigation and URL + +The {kib} platform provides a set of tools to help developers build consistent experience around routing and browser navigation. +Some of that tooling is inside `core`, some is available as part of various plugins. + +<> to get an idea of available tools and common approaches for handling routing and browser navigation. + [discrete] === Testing & stability @@ -131,6 +139,8 @@ Review: * <> * <> +include::navigation.asciidoc[leveloffset=+1] + include::stability.asciidoc[leveloffset=+1] include::security.asciidoc[leveloffset=+1] diff --git a/docs/developer/best-practices/navigation.asciidoc b/docs/developer/best-practices/navigation.asciidoc new file mode 100644 index 0000000000000..d01f2c2aa0f95 --- /dev/null +++ b/docs/developer/best-practices/navigation.asciidoc @@ -0,0 +1,226 @@ +[[kibana-navigation]] +== Routing, Navigation and URL + +The {kib} platform provides a set of tools to help developers build consistent experience around routing and browser navigation. +Some of that tooling is inside `core`, some is available as part of various plugins. + +The purpose of this guide is to give a high-level overview of available tools and to explain common approaches for handling routing and browser navigation. + +This guide covers following topics: + +* <> +* <> +* <> +* <> +* <> +* <> + +[[deep-linking]] +=== Deep-linking into {kib} apps + +Assuming you want to link from your app to *Discover*. When building such URL there are two things to consider: + +1. Prepending a proper `basePath`. +2. Specifying *Discover* state. + +==== Prepending a proper `basePath` + +To prepend {kib}'s `basePath` use {kib-repo}tree/{branch}/docs/development/core/public/kibana-plugin-core-public.ibasepath.prepend.md[core.http.basePath.prepend] helper: + +[source,typescript jsx] +---- +const discoverUrl = core.http.basePath.prepend(`/discover`); + +console.log(discoverUrl); // http://localhost:5601/bpr/s/space/app/discover +---- + +==== Specifying state + +**Consider a {kib} app URL a part of app's plugin contract:** + +. Avoid hardcoding other app's URL in your app's code. +. Avoid generating other app's state and serializing it into URL query params. + +[source,typescript jsx] +---- +// Avoid relying on other app's state structure in your app's code: +const discoverUrlWithSomeState = core.http.basePath.prepend(`/discover#/?_g=(filters:!(),refreshInterval:(pause:!t,value:0),time:(from:'2020-09-10T11:39:50.203Z',to:'2020-09-10T11:40:20.249Z'))&_a=(columns:!(_source),filters:!(),index:'90943e30-9a47-11e8-b64d-95841ca0b247',interval:auto,query:(language:kuery,query:''),sort:!())`); +---- + +Instead, each app should expose {kib-repo}tree/{branch}/src/plugins/share/public/url_generators/README.md[a URL generator]. +Other apps should use those URL generators for creating URLs. + +[source,typescript jsx] +---- +// Properly generated URL to *Discover* app. Generator code is owned by *Discover* app and available on *Discover*'s plugin contract. +const discoverUrl = discoverUrlGenerator.createUrl({filters, timeRange}); +---- + +To get a better idea, take a look at *Discover* URL generator {kib-repo}tree/{branch}/src/plugins/discover/public/url_generator.ts[implementation]. +It allows specifying various **Discover** app state pieces like: index pattern, filters, query, time range and more. + +There are two ways to access other's app URL generator in your code: + +1. From a plugin contract of a destination app *(preferred)*. +2. Using URL generator service instance on `share` plugin contract (in case an explicit plugin dependency is not possible). + +In case you want other apps to link to your app, then you should create a URL generator and expose it on your plugin's contract. + + +[[navigating-between-kibana-apps]] +=== Navigating between {kib} apps + +{kib} is a single page application and there is a set of simple rules developers should follow +to make sure there is no page reload when navigating from one place in {kib} to another. + +For example, navigation using native browser APIs would cause a full page reload. + +[source,js] +---- +const urlToADashboard = core.http.basePath.prepend(`/dashboard/my-dashboard`); + +// this would cause a full page reload: +window.location.href = urlToADashboard; +---- + +To navigate between different {kib} apps without a page reload there are APIs in `core`: + +* {kib-repo}tree/{branch}/docs/development/core/public/kibana-plugin-core-public.applicationstart.navigatetoapp.md[core.application.navigateToApp] +* {kib-repo}tree/{branch}/docs/development/core/public/kibana-plugin-core-public.applicationstart.navigatetourl.md[core.application.navigateToUrl] + +*Rendering a link to a different {kib} app on its own would also cause a full page reload:* + +[source,typescript jsx] +---- +const myLink = () => + Go to Dashboard; +---- + +A workaround could be to handle a click, prevent browser navigation and use `core.application.navigateToApp` API: + +[source,typescript jsx] +---- +const MySPALink = () => + { + e.preventDefault(); + core.application.navigateToApp('dashboard', { path: '/my-dashboard' }); + }} + > + Go to Dashboard + ; +---- + +As it would be too much boilerplate to do this for each {kib} link in your app, there is a handy wrapper that helps with it: +{kib-repo}tree/{branch}/src/plugins/kibana_react/public/app_links/redirect_app_link.tsx#L49[RedirectAppLinks]. + +[source,typescript jsx] +---- +const MyApp = () => + + {/*...*/} + {/* navigations using this link will happen in SPA friendly way */} + Go to Dashboard + {/*...*/} + +---- + +[[routing]] +=== Setting up internal app routing + +It is very common for {kib} apps to use React and React Router. +Common rules to follow in this scenario: + +* Set up `BrowserRouter` and not `HashRouter`. +* *Initialize your router with `history` instance provided by the `core`.* + +This is required to make sure `core` is aware of navigations triggered inside your app, so it could act accordingly when needed. + +* `Core`'s {kib-repo}tree/{branch}/docs/development/core/public/kibana-plugin-core-public.scopedhistory.md[ScopedHistory] instance. +* {kib-repo}tree/{branch}/docs/development/core/public/kibana-plugin-core-public.appmountparameters.history.md[Example usage] +* {kib-repo}tree/{branch}/test/plugin_functional/plugins/core_plugin_a/public/application.tsx#L120[Example plugin] + +Relative links will be resolved relative to your app's route (e.g.: `http://localhost5601/app/{your-app-id}`) +and setting up internal links in your app in SPA friendly way would look something like: + +[source,typescript jsx] +---- +import {Link} from 'react-router-dom'; + +const MyInternalLink = () => +---- + +[[history-and-location]] +=== Using history and browser location + +Try to avoid using `window.location` and `window.history` directly. + +Instead, consider using {kib-repo}tree/{branch}/docs/development/core/public/kibana-plugin-core-public.scopedhistory.md[ScopedHistory] +instance provided by `core`. + +* This way `core` will know about location changes triggered within your app, and it would act accordingly. +* Some plugins are listening to location changes. Triggering location change manually could lead to unpredictable and hard-to-catch bugs. + +Common use-case for using +`core`'s {kib-repo}tree/{branch}/docs/development/core/public/kibana-plugin-core-public.scopedhistory.md[ScopedHistory] directly: + +* Reading/writing query params or hash. +* Imperatively triggering internal navigations within your app. +* Listening to browser location changes. + + +[[state-sync]] +=== Syncing state with URL + +Historically {kib} apps store _a lot_ of application state in the URL. +The most common pattern that {kib} apps follow today is storing state in `_a` and `_g` query params in https://github.com/w33ble/rison-node#readme[rison] format. +[[query-params]] +Those query params follow the convention: + +* `_g` (*global*) - global UI state that should be shared and synced across multiple apps. common example from Analyze group apps: time range, refresh interval, *pinned* filters. +* `_a` (*application*) - UI state scoped to current app. + +NOTE: After migrating to KP platform we got navigations without page reloads. Since then there is no real need to follow `_g` and `_a` separation anymore. It's up you to decide if you want to follow this pattern or if you prefer a single query param or something else. The need for this separation earlier is explained in <>. + +There are utils to help you to implement such kind of state syncing. + +**When you should consider using state syncing utils:** + +* You want to sync your application state with URL in similar manner Analyze group applications do. +* You want to follow platform's <> out of the box. +* You want to support `state:storeInSessionStore` escape hatch for URL overflowing out of the box. +* You should also consider using them if you'd like to serialize state to different (not `rison`) format. Utils are composable, and you can implement your own `storage`. +* In case you want to sync part of your state with URL, but other part of it with browser storage. + +**When you shouldn't use state syncing utils:** + +* Adding a query param flag or simple key/value to the URL. + +Follow {kib-repo}tree/{branch}/src/plugins/kibana_utils/docs/state_sync#state-syncing-utilities[these] docs to learn more. + + +[[preserve-state]] +=== Preserving state between navigations + +Consider the scenario: + +1. You are in *Dashboard* app looking at a dashboard with some filters applied; +2. Navigate to *Discover* using in-app navigation; +3. Change the time filter' +4. Navigate to *Dashboard* using in-app navigation. + +You'd notice that you were navigated to *Dashboard* app with the *same state* that you left it with, +except that the time filter has changed to the one you applied on *Discover* app. + +Historically {kib} Analyze groups apps achieve that behavior relying on state in the URL. +If you'd have a closer look on a link in the navigation, +you'd notice that state is stored inside that link, and it also gets updated whenever relevant state changes happen: + +[role="screenshot"] +image:images/state_inside_the_link.png[State is stored inside the navigation link] + +This is where <> into `_a` and `_g` query params comes into play. What is considered a *global* state gets constantly updated in those navigation links. In the example above it was a time filter. +This is backed by {kib-repo}tree/{branch}/src/plugins/kibana_utils/public/state_management/url/kbn_url_tracker.ts#L57[KbnUrlTracker] util. You can use it to achieve similar behavior. + +NOTE: After migrating to KP navigation works without page reloads and all plugins are loaded simultaneously. +Hence, likely there are simpler ways to preserve state of your application, unless you want to do it through URL. diff --git a/docs/development/core/public/kibana-plugin-core-public.assertnever.md b/docs/development/core/public/kibana-plugin-core-public.assertnever.md deleted file mode 100644 index 8fefd4450d49b..0000000000000 --- a/docs/development/core/public/kibana-plugin-core-public.assertnever.md +++ /dev/null @@ -1,24 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-core-public](./kibana-plugin-core-public.md) > [assertNever](./kibana-plugin-core-public.assertnever.md) - -## assertNever() function - -Can be used in switch statements to ensure we perform exhaustive checks, see https://www.typescriptlang.org/docs/handbook/advanced-types.html\#exhaustiveness-checking - -Signature: - -```typescript -export declare function assertNever(x: never): never; -``` - -## Parameters - -| Parameter | Type | Description | -| --- | --- | --- | -| x | never | | - -Returns: - -`never` - diff --git a/docs/development/core/public/kibana-plugin-core-public.deepfreeze.md b/docs/development/core/public/kibana-plugin-core-public.deepfreeze.md deleted file mode 100644 index 7c879b659a852..0000000000000 --- a/docs/development/core/public/kibana-plugin-core-public.deepfreeze.md +++ /dev/null @@ -1,24 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-core-public](./kibana-plugin-core-public.md) > [deepFreeze](./kibana-plugin-core-public.deepfreeze.md) - -## deepFreeze() function - -Apply Object.freeze to a value recursively and convert the return type to Readonly variant recursively - -Signature: - -```typescript -export declare function deepFreeze(object: T): RecursiveReadonly; -``` - -## Parameters - -| Parameter | Type | Description | -| --- | --- | --- | -| object | T | | - -Returns: - -`RecursiveReadonly` - diff --git a/docs/development/core/public/kibana-plugin-core-public.freezable.md b/docs/development/core/public/kibana-plugin-core-public.freezable.md deleted file mode 100644 index fee87dde25c28..0000000000000 --- a/docs/development/core/public/kibana-plugin-core-public.freezable.md +++ /dev/null @@ -1,14 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-core-public](./kibana-plugin-core-public.md) > [Freezable](./kibana-plugin-core-public.freezable.md) - -## Freezable type - - -Signature: - -```typescript -export declare type Freezable = { - [k: string]: any; -} | any[]; -``` diff --git a/docs/development/core/public/kibana-plugin-core-public.getflattenedobject.md b/docs/development/core/public/kibana-plugin-core-public.getflattenedobject.md deleted file mode 100644 index 3ef9b6bf703eb..0000000000000 --- a/docs/development/core/public/kibana-plugin-core-public.getflattenedobject.md +++ /dev/null @@ -1,30 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-core-public](./kibana-plugin-core-public.md) > [getFlattenedObject](./kibana-plugin-core-public.getflattenedobject.md) - -## getFlattenedObject() function - -Flattens a deeply nested object to a map of dot-separated paths pointing to all primitive values \*\*and arrays\*\* from `rootValue`. - -example: getFlattenedObject({ a: { b: 1, c: \[2,3\] } }) // => { 'a.b': 1, 'a.c': \[2,3\] } - -Signature: - -```typescript -export declare function getFlattenedObject(rootValue: Record): { - [key: string]: any; -}; -``` - -## Parameters - -| Parameter | Type | Description | -| --- | --- | --- | -| rootValue | Record<string, any> | | - -Returns: - -`{ - [key: string]: any; -}` - diff --git a/docs/development/core/public/kibana-plugin-core-public.isrelativeurl.md b/docs/development/core/public/kibana-plugin-core-public.isrelativeurl.md deleted file mode 100644 index 3c2ffa6340a97..0000000000000 --- a/docs/development/core/public/kibana-plugin-core-public.isrelativeurl.md +++ /dev/null @@ -1,24 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-core-public](./kibana-plugin-core-public.md) > [isRelativeUrl](./kibana-plugin-core-public.isrelativeurl.md) - -## isRelativeUrl() function - -Determine if a url is relative. Any url including a protocol, hostname, or port is not considered relative. This means that absolute \*paths\* are considered to be relative \*urls\* - -Signature: - -```typescript -export declare function isRelativeUrl(candidatePath: string): boolean; -``` - -## Parameters - -| Parameter | Type | Description | -| --- | --- | --- | -| candidatePath | string | | - -Returns: - -`boolean` - diff --git a/docs/development/core/public/kibana-plugin-core-public.md b/docs/development/core/public/kibana-plugin-core-public.md index 08b12190ef638..f2bf72a597656 100644 --- a/docs/development/core/public/kibana-plugin-core-public.md +++ b/docs/development/core/public/kibana-plugin-core-public.md @@ -27,16 +27,6 @@ The plugin integrates with the core system via lifecycle events: `setup` | [AppNavLinkStatus](./kibana-plugin-core-public.appnavlinkstatus.md) | Status of the application's navLink. | | [AppStatus](./kibana-plugin-core-public.appstatus.md) | Accessibility status of an application. | -## Functions - -| Function | Description | -| --- | --- | -| [assertNever(x)](./kibana-plugin-core-public.assertnever.md) | Can be used in switch statements to ensure we perform exhaustive checks, see https://www.typescriptlang.org/docs/handbook/advanced-types.html\#exhaustiveness-checking | -| [deepFreeze(object)](./kibana-plugin-core-public.deepfreeze.md) | Apply Object.freeze to a value recursively and convert the return type to Readonly variant recursively | -| [getFlattenedObject(rootValue)](./kibana-plugin-core-public.getflattenedobject.md) | Flattens a deeply nested object to a map of dot-separated paths pointing to all primitive values \*\*and arrays\*\* from rootValue.example: getFlattenedObject({ a: { b: 1, c: \[2,3\] } }) // => { 'a.b': 1, 'a.c': \[2,3\] } | -| [isRelativeUrl(candidatePath)](./kibana-plugin-core-public.isrelativeurl.md) | Determine if a url is relative. Any url including a protocol, hostname, or port is not considered relative. This means that absolute \*paths\* are considered to be relative \*urls\* | -| [modifyUrl(url, urlModifier)](./kibana-plugin-core-public.modifyurl.md) | Takes a URL and a function that takes the meaningful parts of the URL as a key-value object, modifies some or all of the parts, and returns the modified parts formatted again as a url.Url Parts sent: - protocol - slashes (does the url have the //) - auth - hostname (just the name of the host, no port or auth information) - port - pathname (the path after the hostname, no query or hash, starts with a slash if there was a path) - query (always an object, even when no query on original url) - hashWhy? - The default url library in node produces several conflicting properties on the "parsed" output. Modifying any of these might lead to the modifications being ignored (depending on which property was modified) - It's not always clear whether to use path/pathname, host/hostname, so this tries to add helpful constraints | - ## Interfaces | Interface | Description | @@ -128,7 +118,6 @@ The plugin integrates with the core system via lifecycle events: `setup` | [ToastOptions](./kibana-plugin-core-public.toastoptions.md) | Options available for [IToasts](./kibana-plugin-core-public.itoasts.md) APIs. | | [UiSettingsParams](./kibana-plugin-core-public.uisettingsparams.md) | UiSettings parameters defined by the plugins. | | [UiSettingsState](./kibana-plugin-core-public.uisettingsstate.md) | | -| [URLMeaningfulParts](./kibana-plugin-core-public.urlmeaningfulparts.md) | We define our own typings because the current version of @types/node declares properties to be optional "hostname?: string". Although, parse call returns "hostname: null \| string". | | [UserProvidedValues](./kibana-plugin-core-public.userprovidedvalues.md) | Describes the values explicitly set by user. | ## Variables @@ -156,7 +145,6 @@ The plugin integrates with the core system via lifecycle events: `setup` | [ChromeHelpExtensionMenuLink](./kibana-plugin-core-public.chromehelpextensionmenulink.md) | | | [ChromeNavLinkUpdateableFields](./kibana-plugin-core-public.chromenavlinkupdateablefields.md) | | | [FatalErrorsStart](./kibana-plugin-core-public.fatalerrorsstart.md) | FatalErrors stop the Kibana Public Core and displays a fatal error screen with details about the Kibana build and the error. | -| [Freezable](./kibana-plugin-core-public.freezable.md) | | | [HandlerContextType](./kibana-plugin-core-public.handlercontexttype.md) | Extracts the type of the first argument of a [HandlerFunction](./kibana-plugin-core-public.handlerfunction.md) to represent the type of the context. | | [HandlerFunction](./kibana-plugin-core-public.handlerfunction.md) | A function that accepts a context object and an optional number of additional arguments. Used for the generic types in [IContextContainer](./kibana-plugin-core-public.icontextcontainer.md) | | [HandlerParameters](./kibana-plugin-core-public.handlerparameters.md) | Extracts the types of the additional arguments of a [HandlerFunction](./kibana-plugin-core-public.handlerfunction.md), excluding the [HandlerContextType](./kibana-plugin-core-public.handlercontexttype.md). | diff --git a/docs/development/core/public/kibana-plugin-core-public.modifyurl.md b/docs/development/core/public/kibana-plugin-core-public.modifyurl.md deleted file mode 100644 index b174f733a5c64..0000000000000 --- a/docs/development/core/public/kibana-plugin-core-public.modifyurl.md +++ /dev/null @@ -1,31 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-core-public](./kibana-plugin-core-public.md) > [modifyUrl](./kibana-plugin-core-public.modifyurl.md) - -## modifyUrl() function - -Takes a URL and a function that takes the meaningful parts of the URL as a key-value object, modifies some or all of the parts, and returns the modified parts formatted again as a url. - -Url Parts sent: - protocol - slashes (does the url have the //) - auth - hostname (just the name of the host, no port or auth information) - port - pathname (the path after the hostname, no query or hash, starts with a slash if there was a path) - query (always an object, even when no query on original url) - hash - -Why? - The default url library in node produces several conflicting properties on the "parsed" output. Modifying any of these might lead to the modifications being ignored (depending on which property was modified) - It's not always clear whether to use path/pathname, host/hostname, so this tries to add helpful constraints - -Signature: - -```typescript -export declare function modifyUrl(url: string, urlModifier: (urlParts: URLMeaningfulParts) => Partial | void): string; -``` - -## Parameters - -| Parameter | Type | Description | -| --- | --- | --- | -| url | string | | -| urlModifier | (urlParts: URLMeaningfulParts) => Partial<URLMeaningfulParts> | void | | - -Returns: - -`string` - -The modified and reformatted url - diff --git a/docs/development/core/public/kibana-plugin-core-public.urlmeaningfulparts.auth.md b/docs/development/core/public/kibana-plugin-core-public.urlmeaningfulparts.auth.md deleted file mode 100644 index 238dd66885896..0000000000000 --- a/docs/development/core/public/kibana-plugin-core-public.urlmeaningfulparts.auth.md +++ /dev/null @@ -1,11 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-core-public](./kibana-plugin-core-public.md) > [URLMeaningfulParts](./kibana-plugin-core-public.urlmeaningfulparts.md) > [auth](./kibana-plugin-core-public.urlmeaningfulparts.auth.md) - -## URLMeaningfulParts.auth property - -Signature: - -```typescript -auth?: string | null; -``` diff --git a/docs/development/core/public/kibana-plugin-core-public.urlmeaningfulparts.hash.md b/docs/development/core/public/kibana-plugin-core-public.urlmeaningfulparts.hash.md deleted file mode 100644 index 161e7dc7ebfae..0000000000000 --- a/docs/development/core/public/kibana-plugin-core-public.urlmeaningfulparts.hash.md +++ /dev/null @@ -1,11 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-core-public](./kibana-plugin-core-public.md) > [URLMeaningfulParts](./kibana-plugin-core-public.urlmeaningfulparts.md) > [hash](./kibana-plugin-core-public.urlmeaningfulparts.hash.md) - -## URLMeaningfulParts.hash property - -Signature: - -```typescript -hash?: string | null; -``` diff --git a/docs/development/core/public/kibana-plugin-core-public.urlmeaningfulparts.hostname.md b/docs/development/core/public/kibana-plugin-core-public.urlmeaningfulparts.hostname.md deleted file mode 100644 index f1884718337b5..0000000000000 --- a/docs/development/core/public/kibana-plugin-core-public.urlmeaningfulparts.hostname.md +++ /dev/null @@ -1,11 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-core-public](./kibana-plugin-core-public.md) > [URLMeaningfulParts](./kibana-plugin-core-public.urlmeaningfulparts.md) > [hostname](./kibana-plugin-core-public.urlmeaningfulparts.hostname.md) - -## URLMeaningfulParts.hostname property - -Signature: - -```typescript -hostname?: string | null; -``` diff --git a/docs/development/core/public/kibana-plugin-core-public.urlmeaningfulparts.md b/docs/development/core/public/kibana-plugin-core-public.urlmeaningfulparts.md deleted file mode 100644 index 2816d4c7df541..0000000000000 --- a/docs/development/core/public/kibana-plugin-core-public.urlmeaningfulparts.md +++ /dev/null @@ -1,27 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-core-public](./kibana-plugin-core-public.md) > [URLMeaningfulParts](./kibana-plugin-core-public.urlmeaningfulparts.md) - -## URLMeaningfulParts interface - -We define our own typings because the current version of @types/node declares properties to be optional "hostname?: string". Although, parse call returns "hostname: null \| string". - -Signature: - -```typescript -export interface URLMeaningfulParts -``` - -## Properties - -| Property | Type | Description | -| --- | --- | --- | -| [auth](./kibana-plugin-core-public.urlmeaningfulparts.auth.md) | string | null | | -| [hash](./kibana-plugin-core-public.urlmeaningfulparts.hash.md) | string | null | | -| [hostname](./kibana-plugin-core-public.urlmeaningfulparts.hostname.md) | string | null | | -| [pathname](./kibana-plugin-core-public.urlmeaningfulparts.pathname.md) | string | null | | -| [port](./kibana-plugin-core-public.urlmeaningfulparts.port.md) | string | null | | -| [protocol](./kibana-plugin-core-public.urlmeaningfulparts.protocol.md) | string | null | | -| [query](./kibana-plugin-core-public.urlmeaningfulparts.query.md) | ParsedQuery | | -| [slashes](./kibana-plugin-core-public.urlmeaningfulparts.slashes.md) | boolean | null | | - diff --git a/docs/development/core/public/kibana-plugin-core-public.urlmeaningfulparts.pathname.md b/docs/development/core/public/kibana-plugin-core-public.urlmeaningfulparts.pathname.md deleted file mode 100644 index 5ad21f004481c..0000000000000 --- a/docs/development/core/public/kibana-plugin-core-public.urlmeaningfulparts.pathname.md +++ /dev/null @@ -1,11 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-core-public](./kibana-plugin-core-public.md) > [URLMeaningfulParts](./kibana-plugin-core-public.urlmeaningfulparts.md) > [pathname](./kibana-plugin-core-public.urlmeaningfulparts.pathname.md) - -## URLMeaningfulParts.pathname property - -Signature: - -```typescript -pathname?: string | null; -``` diff --git a/docs/development/core/public/kibana-plugin-core-public.urlmeaningfulparts.port.md b/docs/development/core/public/kibana-plugin-core-public.urlmeaningfulparts.port.md deleted file mode 100644 index 2e70da2f17421..0000000000000 --- a/docs/development/core/public/kibana-plugin-core-public.urlmeaningfulparts.port.md +++ /dev/null @@ -1,11 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-core-public](./kibana-plugin-core-public.md) > [URLMeaningfulParts](./kibana-plugin-core-public.urlmeaningfulparts.md) > [port](./kibana-plugin-core-public.urlmeaningfulparts.port.md) - -## URLMeaningfulParts.port property - -Signature: - -```typescript -port?: string | null; -``` diff --git a/docs/development/core/public/kibana-plugin-core-public.urlmeaningfulparts.protocol.md b/docs/development/core/public/kibana-plugin-core-public.urlmeaningfulparts.protocol.md deleted file mode 100644 index cedc7f0b878e3..0000000000000 --- a/docs/development/core/public/kibana-plugin-core-public.urlmeaningfulparts.protocol.md +++ /dev/null @@ -1,11 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-core-public](./kibana-plugin-core-public.md) > [URLMeaningfulParts](./kibana-plugin-core-public.urlmeaningfulparts.md) > [protocol](./kibana-plugin-core-public.urlmeaningfulparts.protocol.md) - -## URLMeaningfulParts.protocol property - -Signature: - -```typescript -protocol?: string | null; -``` diff --git a/docs/development/core/public/kibana-plugin-core-public.urlmeaningfulparts.query.md b/docs/development/core/public/kibana-plugin-core-public.urlmeaningfulparts.query.md deleted file mode 100644 index a9541efe0882a..0000000000000 --- a/docs/development/core/public/kibana-plugin-core-public.urlmeaningfulparts.query.md +++ /dev/null @@ -1,11 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-core-public](./kibana-plugin-core-public.md) > [URLMeaningfulParts](./kibana-plugin-core-public.urlmeaningfulparts.md) > [query](./kibana-plugin-core-public.urlmeaningfulparts.query.md) - -## URLMeaningfulParts.query property - -Signature: - -```typescript -query: ParsedQuery; -``` diff --git a/docs/development/core/public/kibana-plugin-core-public.urlmeaningfulparts.slashes.md b/docs/development/core/public/kibana-plugin-core-public.urlmeaningfulparts.slashes.md deleted file mode 100644 index cb28a25f9e162..0000000000000 --- a/docs/development/core/public/kibana-plugin-core-public.urlmeaningfulparts.slashes.md +++ /dev/null @@ -1,11 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-core-public](./kibana-plugin-core-public.md) > [URLMeaningfulParts](./kibana-plugin-core-public.urlmeaningfulparts.md) > [slashes](./kibana-plugin-core-public.urlmeaningfulparts.slashes.md) - -## URLMeaningfulParts.slashes property - -Signature: - -```typescript -slashes?: boolean | null; -``` diff --git a/docs/development/core/server/kibana-plugin-core-server.assertnever.md b/docs/development/core/server/kibana-plugin-core-server.assertnever.md deleted file mode 100644 index c13c88df9b9bf..0000000000000 --- a/docs/development/core/server/kibana-plugin-core-server.assertnever.md +++ /dev/null @@ -1,24 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [assertNever](./kibana-plugin-core-server.assertnever.md) - -## assertNever() function - -Can be used in switch statements to ensure we perform exhaustive checks, see https://www.typescriptlang.org/docs/handbook/advanced-types.html\#exhaustiveness-checking - -Signature: - -```typescript -export declare function assertNever(x: never): never; -``` - -## Parameters - -| Parameter | Type | Description | -| --- | --- | --- | -| x | never | | - -Returns: - -`never` - diff --git a/docs/development/core/server/kibana-plugin-core-server.deepfreeze.md b/docs/development/core/server/kibana-plugin-core-server.deepfreeze.md deleted file mode 100644 index 946050bff0585..0000000000000 --- a/docs/development/core/server/kibana-plugin-core-server.deepfreeze.md +++ /dev/null @@ -1,24 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [deepFreeze](./kibana-plugin-core-server.deepfreeze.md) - -## deepFreeze() function - -Apply Object.freeze to a value recursively and convert the return type to Readonly variant recursively - -Signature: - -```typescript -export declare function deepFreeze(object: T): RecursiveReadonly; -``` - -## Parameters - -| Parameter | Type | Description | -| --- | --- | --- | -| object | T | | - -Returns: - -`RecursiveReadonly` - diff --git a/docs/development/core/server/kibana-plugin-core-server.freezable.md b/docs/development/core/server/kibana-plugin-core-server.freezable.md deleted file mode 100644 index 32ba89e8370c1..0000000000000 --- a/docs/development/core/server/kibana-plugin-core-server.freezable.md +++ /dev/null @@ -1,14 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [Freezable](./kibana-plugin-core-server.freezable.md) - -## Freezable type - - -Signature: - -```typescript -export declare type Freezable = { - [k: string]: any; -} | any[]; -``` diff --git a/docs/development/core/server/kibana-plugin-core-server.getflattenedobject.md b/docs/development/core/server/kibana-plugin-core-server.getflattenedobject.md deleted file mode 100644 index 2e7850ca579f6..0000000000000 --- a/docs/development/core/server/kibana-plugin-core-server.getflattenedobject.md +++ /dev/null @@ -1,30 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [getFlattenedObject](./kibana-plugin-core-server.getflattenedobject.md) - -## getFlattenedObject() function - -Flattens a deeply nested object to a map of dot-separated paths pointing to all primitive values \*\*and arrays\*\* from `rootValue`. - -example: getFlattenedObject({ a: { b: 1, c: \[2,3\] } }) // => { 'a.b': 1, 'a.c': \[2,3\] } - -Signature: - -```typescript -export declare function getFlattenedObject(rootValue: Record): { - [key: string]: any; -}; -``` - -## Parameters - -| Parameter | Type | Description | -| --- | --- | --- | -| rootValue | Record<string, any> | | - -Returns: - -`{ - [key: string]: any; -}` - diff --git a/docs/development/core/server/kibana-plugin-core-server.isrelativeurl.md b/docs/development/core/server/kibana-plugin-core-server.isrelativeurl.md deleted file mode 100644 index bff9eb05419be..0000000000000 --- a/docs/development/core/server/kibana-plugin-core-server.isrelativeurl.md +++ /dev/null @@ -1,24 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [isRelativeUrl](./kibana-plugin-core-server.isrelativeurl.md) - -## isRelativeUrl() function - -Determine if a url is relative. Any url including a protocol, hostname, or port is not considered relative. This means that absolute \*paths\* are considered to be relative \*urls\* - -Signature: - -```typescript -export declare function isRelativeUrl(candidatePath: string): boolean; -``` - -## Parameters - -| Parameter | Type | Description | -| --- | --- | --- | -| candidatePath | string | | - -Returns: - -`boolean` - diff --git a/docs/development/core/server/kibana-plugin-core-server.md b/docs/development/core/server/kibana-plugin-core-server.md index c16600d1d0492..30b98b9f0553e 100644 --- a/docs/development/core/server/kibana-plugin-core-server.md +++ b/docs/development/core/server/kibana-plugin-core-server.md @@ -42,13 +42,8 @@ The plugin integrates with the core system via lifecycle events: `setup` | Function | Description | | --- | --- | -| [assertNever(x)](./kibana-plugin-core-server.assertnever.md) | Can be used in switch statements to ensure we perform exhaustive checks, see https://www.typescriptlang.org/docs/handbook/advanced-types.html\#exhaustiveness-checking | -| [deepFreeze(object)](./kibana-plugin-core-server.deepfreeze.md) | Apply Object.freeze to a value recursively and convert the return type to Readonly variant recursively | | [exportSavedObjectsToStream({ types, objects, search, savedObjectsClient, exportSizeLimit, includeReferencesDeep, excludeExportDetails, namespace, })](./kibana-plugin-core-server.exportsavedobjectstostream.md) | Generates sorted saved object stream to be used for export. See the [options](./kibana-plugin-core-server.savedobjectsexportoptions.md) for more detailed information. | -| [getFlattenedObject(rootValue)](./kibana-plugin-core-server.getflattenedobject.md) | Flattens a deeply nested object to a map of dot-separated paths pointing to all primitive values \*\*and arrays\*\* from rootValue.example: getFlattenedObject({ a: { b: 1, c: \[2,3\] } }) // => { 'a.b': 1, 'a.c': \[2,3\] } | | [importSavedObjectsFromStream({ readStream, objectLimit, overwrite, createNewCopies, savedObjectsClient, typeRegistry, namespace, })](./kibana-plugin-core-server.importsavedobjectsfromstream.md) | Import saved objects from given stream. See the [options](./kibana-plugin-core-server.savedobjectsimportoptions.md) for more detailed information. | -| [isRelativeUrl(candidatePath)](./kibana-plugin-core-server.isrelativeurl.md) | Determine if a url is relative. Any url including a protocol, hostname, or port is not considered relative. This means that absolute \*paths\* are considered to be relative \*urls\* | -| [modifyUrl(url, urlModifier)](./kibana-plugin-core-server.modifyurl.md) | Takes a URL and a function that takes the meaningful parts of the URL as a key-value object, modifies some or all of the parts, and returns the modified parts formatted again as a url.Url Parts sent: - protocol - slashes (does the url have the //) - auth - hostname (just the name of the host, no port or auth information) - port - pathname (the path after the hostname, no query or hash, starts with a slash if there was a path) - query (always an object, even when no query on original url) - hashWhy? - The default url library in node produces several conflicting properties on the "parsed" output. Modifying any of these might lead to the modifications being ignored (depending on which property was modified) - It's not always clear whether to use path/pathname, host/hostname, so this tries to add helpful constraints | | [resolveSavedObjectsImportErrors({ readStream, objectLimit, retries, savedObjectsClient, typeRegistry, namespace, createNewCopies, })](./kibana-plugin-core-server.resolvesavedobjectsimporterrors.md) | Resolve and return saved object import errors. See the [options](./kibana-plugin-core-server.savedobjectsresolveimporterrorsoptions.md) for more detailed informations. | ## Interfaces @@ -217,7 +212,6 @@ The plugin integrates with the core system via lifecycle events: `setup` | [UiSettingsParams](./kibana-plugin-core-server.uisettingsparams.md) | UiSettings parameters defined by the plugins. | | [UiSettingsServiceSetup](./kibana-plugin-core-server.uisettingsservicesetup.md) | | | [UiSettingsServiceStart](./kibana-plugin-core-server.uisettingsservicestart.md) | | -| [URLMeaningfulParts](./kibana-plugin-core-server.urlmeaningfulparts.md) | We define our own typings because the current version of @types/node declares properties to be optional "hostname?: string". Although, parse call returns "hostname: null \| string". | | [UserProvidedValues](./kibana-plugin-core-server.userprovidedvalues.md) | Describes the values explicitly set by user. | ## Variables @@ -246,7 +240,6 @@ The plugin integrates with the core system via lifecycle events: `setup` | [DestructiveRouteMethod](./kibana-plugin-core-server.destructiveroutemethod.md) | Set of HTTP methods changing the state of the server. | | [ElasticsearchClient](./kibana-plugin-core-server.elasticsearchclient.md) | Client used to query the elasticsearch cluster. | | [ElasticsearchClientConfig](./kibana-plugin-core-server.elasticsearchclientconfig.md) | Configuration options to be used to create a [cluster client](./kibana-plugin-core-server.iclusterclient.md) using the [createClient API](./kibana-plugin-core-server.elasticsearchservicestart.createclient.md) | -| [Freezable](./kibana-plugin-core-server.freezable.md) | | | [GetAuthHeaders](./kibana-plugin-core-server.getauthheaders.md) | Get headers to authenticate a user against Elasticsearch. | | [GetAuthState](./kibana-plugin-core-server.getauthstate.md) | Gets authentication state for a request. Returned by auth interceptor. | | [HandlerContextType](./kibana-plugin-core-server.handlercontexttype.md) | Extracts the type of the first argument of a [HandlerFunction](./kibana-plugin-core-server.handlerfunction.md) to represent the type of the context. | diff --git a/docs/development/core/server/kibana-plugin-core-server.modifyurl.md b/docs/development/core/server/kibana-plugin-core-server.modifyurl.md deleted file mode 100644 index fc0bc354a3ca3..0000000000000 --- a/docs/development/core/server/kibana-plugin-core-server.modifyurl.md +++ /dev/null @@ -1,31 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [modifyUrl](./kibana-plugin-core-server.modifyurl.md) - -## modifyUrl() function - -Takes a URL and a function that takes the meaningful parts of the URL as a key-value object, modifies some or all of the parts, and returns the modified parts formatted again as a url. - -Url Parts sent: - protocol - slashes (does the url have the //) - auth - hostname (just the name of the host, no port or auth information) - port - pathname (the path after the hostname, no query or hash, starts with a slash if there was a path) - query (always an object, even when no query on original url) - hash - -Why? - The default url library in node produces several conflicting properties on the "parsed" output. Modifying any of these might lead to the modifications being ignored (depending on which property was modified) - It's not always clear whether to use path/pathname, host/hostname, so this tries to add helpful constraints - -Signature: - -```typescript -export declare function modifyUrl(url: string, urlModifier: (urlParts: URLMeaningfulParts) => Partial | void): string; -``` - -## Parameters - -| Parameter | Type | Description | -| --- | --- | --- | -| url | string | | -| urlModifier | (urlParts: URLMeaningfulParts) => Partial<URLMeaningfulParts> | void | | - -Returns: - -`string` - -The modified and reformatted url - diff --git a/docs/development/core/server/kibana-plugin-core-server.urlmeaningfulparts.auth.md b/docs/development/core/server/kibana-plugin-core-server.urlmeaningfulparts.auth.md deleted file mode 100644 index 0422738669a70..0000000000000 --- a/docs/development/core/server/kibana-plugin-core-server.urlmeaningfulparts.auth.md +++ /dev/null @@ -1,11 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [URLMeaningfulParts](./kibana-plugin-core-server.urlmeaningfulparts.md) > [auth](./kibana-plugin-core-server.urlmeaningfulparts.auth.md) - -## URLMeaningfulParts.auth property - -Signature: - -```typescript -auth?: string | null; -``` diff --git a/docs/development/core/server/kibana-plugin-core-server.urlmeaningfulparts.hash.md b/docs/development/core/server/kibana-plugin-core-server.urlmeaningfulparts.hash.md deleted file mode 100644 index 13a3f4a9c95c8..0000000000000 --- a/docs/development/core/server/kibana-plugin-core-server.urlmeaningfulparts.hash.md +++ /dev/null @@ -1,11 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [URLMeaningfulParts](./kibana-plugin-core-server.urlmeaningfulparts.md) > [hash](./kibana-plugin-core-server.urlmeaningfulparts.hash.md) - -## URLMeaningfulParts.hash property - -Signature: - -```typescript -hash?: string | null; -``` diff --git a/docs/development/core/server/kibana-plugin-core-server.urlmeaningfulparts.hostname.md b/docs/development/core/server/kibana-plugin-core-server.urlmeaningfulparts.hostname.md deleted file mode 100644 index 6631f6f6744c5..0000000000000 --- a/docs/development/core/server/kibana-plugin-core-server.urlmeaningfulparts.hostname.md +++ /dev/null @@ -1,11 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [URLMeaningfulParts](./kibana-plugin-core-server.urlmeaningfulparts.md) > [hostname](./kibana-plugin-core-server.urlmeaningfulparts.hostname.md) - -## URLMeaningfulParts.hostname property - -Signature: - -```typescript -hostname?: string | null; -``` diff --git a/docs/development/core/server/kibana-plugin-core-server.urlmeaningfulparts.md b/docs/development/core/server/kibana-plugin-core-server.urlmeaningfulparts.md deleted file mode 100644 index 257f7b4b634ab..0000000000000 --- a/docs/development/core/server/kibana-plugin-core-server.urlmeaningfulparts.md +++ /dev/null @@ -1,27 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [URLMeaningfulParts](./kibana-plugin-core-server.urlmeaningfulparts.md) - -## URLMeaningfulParts interface - -We define our own typings because the current version of @types/node declares properties to be optional "hostname?: string". Although, parse call returns "hostname: null \| string". - -Signature: - -```typescript -export interface URLMeaningfulParts -``` - -## Properties - -| Property | Type | Description | -| --- | --- | --- | -| [auth](./kibana-plugin-core-server.urlmeaningfulparts.auth.md) | string | null | | -| [hash](./kibana-plugin-core-server.urlmeaningfulparts.hash.md) | string | null | | -| [hostname](./kibana-plugin-core-server.urlmeaningfulparts.hostname.md) | string | null | | -| [pathname](./kibana-plugin-core-server.urlmeaningfulparts.pathname.md) | string | null | | -| [port](./kibana-plugin-core-server.urlmeaningfulparts.port.md) | string | null | | -| [protocol](./kibana-plugin-core-server.urlmeaningfulparts.protocol.md) | string | null | | -| [query](./kibana-plugin-core-server.urlmeaningfulparts.query.md) | ParsedQuery | | -| [slashes](./kibana-plugin-core-server.urlmeaningfulparts.slashes.md) | boolean | null | | - diff --git a/docs/development/core/server/kibana-plugin-core-server.urlmeaningfulparts.pathname.md b/docs/development/core/server/kibana-plugin-core-server.urlmeaningfulparts.pathname.md deleted file mode 100644 index 8fee8c8e146ca..0000000000000 --- a/docs/development/core/server/kibana-plugin-core-server.urlmeaningfulparts.pathname.md +++ /dev/null @@ -1,11 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [URLMeaningfulParts](./kibana-plugin-core-server.urlmeaningfulparts.md) > [pathname](./kibana-plugin-core-server.urlmeaningfulparts.pathname.md) - -## URLMeaningfulParts.pathname property - -Signature: - -```typescript -pathname?: string | null; -``` diff --git a/docs/development/core/server/kibana-plugin-core-server.urlmeaningfulparts.port.md b/docs/development/core/server/kibana-plugin-core-server.urlmeaningfulparts.port.md deleted file mode 100644 index dcf3517d92ba2..0000000000000 --- a/docs/development/core/server/kibana-plugin-core-server.urlmeaningfulparts.port.md +++ /dev/null @@ -1,11 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [URLMeaningfulParts](./kibana-plugin-core-server.urlmeaningfulparts.md) > [port](./kibana-plugin-core-server.urlmeaningfulparts.port.md) - -## URLMeaningfulParts.port property - -Signature: - -```typescript -port?: string | null; -``` diff --git a/docs/development/core/server/kibana-plugin-core-server.urlmeaningfulparts.protocol.md b/docs/development/core/server/kibana-plugin-core-server.urlmeaningfulparts.protocol.md deleted file mode 100644 index 914dcd4e8a8a5..0000000000000 --- a/docs/development/core/server/kibana-plugin-core-server.urlmeaningfulparts.protocol.md +++ /dev/null @@ -1,11 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [URLMeaningfulParts](./kibana-plugin-core-server.urlmeaningfulparts.md) > [protocol](./kibana-plugin-core-server.urlmeaningfulparts.protocol.md) - -## URLMeaningfulParts.protocol property - -Signature: - -```typescript -protocol?: string | null; -``` diff --git a/docs/development/core/server/kibana-plugin-core-server.urlmeaningfulparts.query.md b/docs/development/core/server/kibana-plugin-core-server.urlmeaningfulparts.query.md deleted file mode 100644 index 358adcfd3d180..0000000000000 --- a/docs/development/core/server/kibana-plugin-core-server.urlmeaningfulparts.query.md +++ /dev/null @@ -1,11 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [URLMeaningfulParts](./kibana-plugin-core-server.urlmeaningfulparts.md) > [query](./kibana-plugin-core-server.urlmeaningfulparts.query.md) - -## URLMeaningfulParts.query property - -Signature: - -```typescript -query: ParsedQuery; -``` diff --git a/docs/development/core/server/kibana-plugin-core-server.urlmeaningfulparts.slashes.md b/docs/development/core/server/kibana-plugin-core-server.urlmeaningfulparts.slashes.md deleted file mode 100644 index d5b598167f2f2..0000000000000 --- a/docs/development/core/server/kibana-plugin-core-server.urlmeaningfulparts.slashes.md +++ /dev/null @@ -1,11 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [URLMeaningfulParts](./kibana-plugin-core-server.urlmeaningfulparts.md) > [slashes](./kibana-plugin-core-server.urlmeaningfulparts.slashes.md) - -## URLMeaningfulParts.slashes property - -Signature: - -```typescript -slashes?: boolean | null; -``` diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.querystringinput.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.querystringinput.md index cf171d9ee9f37..e85747b8cc3d7 100644 --- a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.querystringinput.md +++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.querystringinput.md @@ -7,5 +7,5 @@ Signature: ```typescript -QueryStringInput: React.FC> +QueryStringInput: React.FC> ``` diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchsource.serialize.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchsource.serialize.md index 73ba8eb66040b..496e1ae9677d8 100644 --- a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchsource.serialize.md +++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchsource.serialize.md @@ -15,13 +15,13 @@ Using `createSearchSource`, the instance can be re-created. ```typescript serialize(): { searchSourceJSON: string; - references: import("../../../../../core/public").SavedObjectReference[]; + references: import("../../../../../core/types").SavedObjectReference[]; }; ``` Returns: `{ searchSourceJSON: string; - references: import("../../../../../core/public").SavedObjectReference[]; + references: import("../../../../../core/types").SavedObjectReference[]; }` diff --git a/examples/alerting_example/tsconfig.json b/examples/alerting_example/tsconfig.json index 09c130aca4642..214e4b78a9a70 100644 --- a/examples/alerting_example/tsconfig.json +++ b/examples/alerting_example/tsconfig.json @@ -11,5 +11,8 @@ "common/**/*.ts", "../../typings/**/*", ], - "exclude": [] + "exclude": [], + "references": [ + { "path": "../../src/core/tsconfig.json" } + ] } diff --git a/examples/bfetch_explorer/tsconfig.json b/examples/bfetch_explorer/tsconfig.json index 798a9c222c5ab..86b35c5e4943f 100644 --- a/examples/bfetch_explorer/tsconfig.json +++ b/examples/bfetch_explorer/tsconfig.json @@ -11,5 +11,8 @@ "server/**/*.ts", "../../typings/**/*", ], - "exclude": [] + "exclude": [], + "references": [ + { "path": "../../src/core/tsconfig.json" } + ] } diff --git a/examples/dashboard_embeddable_examples/tsconfig.json b/examples/dashboard_embeddable_examples/tsconfig.json index 798a9c222c5ab..86b35c5e4943f 100644 --- a/examples/dashboard_embeddable_examples/tsconfig.json +++ b/examples/dashboard_embeddable_examples/tsconfig.json @@ -11,5 +11,8 @@ "server/**/*.ts", "../../typings/**/*", ], - "exclude": [] + "exclude": [], + "references": [ + { "path": "../../src/core/tsconfig.json" } + ] } diff --git a/examples/developer_examples/tsconfig.json b/examples/developer_examples/tsconfig.json index 798a9c222c5ab..86b35c5e4943f 100644 --- a/examples/developer_examples/tsconfig.json +++ b/examples/developer_examples/tsconfig.json @@ -11,5 +11,8 @@ "server/**/*.ts", "../../typings/**/*", ], - "exclude": [] + "exclude": [], + "references": [ + { "path": "../../src/core/tsconfig.json" } + ] } diff --git a/examples/embeddable_examples/tsconfig.json b/examples/embeddable_examples/tsconfig.json index caeed2c1a434f..78098339c16f5 100644 --- a/examples/embeddable_examples/tsconfig.json +++ b/examples/embeddable_examples/tsconfig.json @@ -12,5 +12,8 @@ "server/**/*.ts", "../../typings/**/*" ], - "exclude": [] + "exclude": [], + "references": [ + { "path": "../../src/core/tsconfig.json" } + ] } diff --git a/examples/embeddable_explorer/tsconfig.json b/examples/embeddable_explorer/tsconfig.json index 798a9c222c5ab..86b35c5e4943f 100644 --- a/examples/embeddable_explorer/tsconfig.json +++ b/examples/embeddable_explorer/tsconfig.json @@ -11,5 +11,8 @@ "server/**/*.ts", "../../typings/**/*", ], - "exclude": [] + "exclude": [], + "references": [ + { "path": "../../src/core/tsconfig.json" } + ] } diff --git a/examples/routing_example/tsconfig.json b/examples/routing_example/tsconfig.json index 761a5c4da65ba..54ac800019f82 100644 --- a/examples/routing_example/tsconfig.json +++ b/examples/routing_example/tsconfig.json @@ -12,5 +12,8 @@ "common/**/*.ts", "../../typings/**/*", ], - "exclude": [] + "exclude": [], + "references": [ + { "path": "../../src/core/tsconfig.json" } + ] } diff --git a/examples/search_examples/tsconfig.json b/examples/search_examples/tsconfig.json index 8bec69ca40ccc..2b7d86d76a8a5 100644 --- a/examples/search_examples/tsconfig.json +++ b/examples/search_examples/tsconfig.json @@ -12,5 +12,8 @@ "server/**/*.ts", "../../typings/**/*", ], - "exclude": [] + "exclude": [], + "references": [ + { "path": "../../src/core/tsconfig.json" } + ] } diff --git a/examples/state_containers_examples/tsconfig.json b/examples/state_containers_examples/tsconfig.json index 007322e2d9525..6cfb9f9dc2321 100644 --- a/examples/state_containers_examples/tsconfig.json +++ b/examples/state_containers_examples/tsconfig.json @@ -12,5 +12,8 @@ "common/**/*.ts", "../../typings/**/*" ], - "exclude": [] + "exclude": [], + "references": [ + { "path": "../../src/core/tsconfig.json" } + ] } diff --git a/examples/ui_action_examples/tsconfig.json b/examples/ui_action_examples/tsconfig.json index 798a9c222c5ab..86b35c5e4943f 100644 --- a/examples/ui_action_examples/tsconfig.json +++ b/examples/ui_action_examples/tsconfig.json @@ -11,5 +11,8 @@ "server/**/*.ts", "../../typings/**/*", ], - "exclude": [] + "exclude": [], + "references": [ + { "path": "../../src/core/tsconfig.json" } + ] } diff --git a/examples/ui_actions_explorer/tsconfig.json b/examples/ui_actions_explorer/tsconfig.json index 119209114a7bb..782b9cd57fa7b 100644 --- a/examples/ui_actions_explorer/tsconfig.json +++ b/examples/ui_actions_explorer/tsconfig.json @@ -10,5 +10,8 @@ "public/**/*.tsx", "../../typings/**/*", ], - "exclude": [] + "exclude": [], + "references": [ + { "path": "../../src/core/tsconfig.json" } + ] } diff --git a/examples/url_generators_examples/tsconfig.json b/examples/url_generators_examples/tsconfig.json index 327b4642a8e7f..8aef3328b4222 100644 --- a/examples/url_generators_examples/tsconfig.json +++ b/examples/url_generators_examples/tsconfig.json @@ -11,5 +11,8 @@ "server/**/*.ts", "../../typings/**/*" ], - "exclude": [] + "exclude": [], + "references": [ + { "path": "../../src/core/tsconfig.json" } + ] } diff --git a/examples/url_generators_explorer/tsconfig.json b/examples/url_generators_explorer/tsconfig.json index 327b4642a8e7f..8aef3328b4222 100644 --- a/examples/url_generators_explorer/tsconfig.json +++ b/examples/url_generators_explorer/tsconfig.json @@ -11,5 +11,8 @@ "server/**/*.ts", "../../typings/**/*" ], - "exclude": [] + "exclude": [], + "references": [ + { "path": "../../src/core/tsconfig.json" } + ] } diff --git a/package.json b/package.json index 7468a49d56959..d4ebfefc87270 100644 --- a/package.json +++ b/package.json @@ -141,6 +141,7 @@ "@kbn/i18n": "1.0.0", "@kbn/interpreter": "1.0.0", "@kbn/pm": "1.0.0", + "@kbn/std": "1.0.0", "@kbn/telemetry-tools": "1.0.0", "@kbn/test-subj-selector": "0.2.1", "@kbn/ui-framework": "1.0.0", diff --git a/packages/kbn-std/README.md b/packages/kbn-std/README.md new file mode 100644 index 0000000000000..dfd98287ada4b --- /dev/null +++ b/packages/kbn-std/README.md @@ -0,0 +1,3 @@ +# `@kbn/std` — Kibana standard library + +This package is a set of utilities that can be used both on server-side and client-side. \ No newline at end of file diff --git a/packages/kbn-std/package.json b/packages/kbn-std/package.json new file mode 100644 index 0000000000000..4c67706b45d27 --- /dev/null +++ b/packages/kbn-std/package.json @@ -0,0 +1,21 @@ +{ + "name": "@kbn/std", + "main": "./target/index.js", + "types": "./target/index.d.ts", + "version": "1.0.0", + "license": "Apache-2.0", + "private": true, + "scripts": { + "build": "tsc", + "kbn:bootstrap": "yarn build" + }, + "devDependencies": { + "typescript": "4.0.2", + "tsd": "^0.13.1" + }, + "dependencies": { + "@kbn/utility-types": "1.0.0", + "lodash": "^4.17.15", + "query-string": "5.1.1" + } +} diff --git a/src/core/utils/__snapshots__/get.test.ts.snap b/packages/kbn-std/src/__snapshots__/get.test.ts.snap similarity index 100% rename from src/core/utils/__snapshots__/get.test.ts.snap rename to packages/kbn-std/src/__snapshots__/get.test.ts.snap diff --git a/src/core/utils/assert_never.ts b/packages/kbn-std/src/assert_never.ts similarity index 100% rename from src/core/utils/assert_never.ts rename to packages/kbn-std/src/assert_never.ts diff --git a/src/core/utils/deep_freeze.test.ts b/packages/kbn-std/src/deep_freeze.test.ts similarity index 100% rename from src/core/utils/deep_freeze.test.ts rename to packages/kbn-std/src/deep_freeze.test.ts diff --git a/src/core/utils/deep_freeze.ts b/packages/kbn-std/src/deep_freeze.ts similarity index 100% rename from src/core/utils/deep_freeze.ts rename to packages/kbn-std/src/deep_freeze.ts diff --git a/src/core/utils/get.test.ts b/packages/kbn-std/src/get.test.ts similarity index 100% rename from src/core/utils/get.test.ts rename to packages/kbn-std/src/get.test.ts diff --git a/src/core/utils/get.ts b/packages/kbn-std/src/get.ts similarity index 100% rename from src/core/utils/get.ts rename to packages/kbn-std/src/get.ts diff --git a/src/core/utils/get_flattened_object.test.ts b/packages/kbn-std/src/get_flattened_object.test.ts similarity index 100% rename from src/core/utils/get_flattened_object.test.ts rename to packages/kbn-std/src/get_flattened_object.test.ts diff --git a/src/core/utils/get_flattened_object.ts b/packages/kbn-std/src/get_flattened_object.ts similarity index 100% rename from src/core/utils/get_flattened_object.ts rename to packages/kbn-std/src/get_flattened_object.ts diff --git a/packages/kbn-std/src/index.ts b/packages/kbn-std/src/index.ts new file mode 100644 index 0000000000000..7cf70a0e28e2c --- /dev/null +++ b/packages/kbn-std/src/index.ts @@ -0,0 +1,29 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +export { assertNever } from './assert_never'; +export { deepFreeze, Freezable } from './deep_freeze'; +export { get } from './get'; +export { mapToObject } from './map_to_object'; +export { merge } from './merge'; +export { pick } from './pick'; +export { withTimeout } from './promise'; +export { isRelativeUrl, modifyUrl, URLMeaningfulParts } from './url'; +export { unset } from './unset'; +export { getFlattenedObject } from './get_flattened_object'; diff --git a/src/core/utils/map_to_object.ts b/packages/kbn-std/src/map_to_object.ts similarity index 100% rename from src/core/utils/map_to_object.ts rename to packages/kbn-std/src/map_to_object.ts diff --git a/src/core/utils/map_utils.test.ts b/packages/kbn-std/src/map_utils.test.ts similarity index 100% rename from src/core/utils/map_utils.test.ts rename to packages/kbn-std/src/map_utils.test.ts diff --git a/src/core/utils/map_utils.ts b/packages/kbn-std/src/map_utils.ts similarity index 100% rename from src/core/utils/map_utils.ts rename to packages/kbn-std/src/map_utils.ts diff --git a/src/core/utils/merge.test.ts b/packages/kbn-std/src/merge.test.ts similarity index 100% rename from src/core/utils/merge.test.ts rename to packages/kbn-std/src/merge.test.ts diff --git a/src/core/utils/merge.ts b/packages/kbn-std/src/merge.ts similarity index 98% rename from src/core/utils/merge.ts rename to packages/kbn-std/src/merge.ts index 43878c27b1e19..c0de50544a34e 100644 --- a/src/core/utils/merge.ts +++ b/packages/kbn-std/src/merge.ts @@ -16,7 +16,7 @@ * specific language governing permissions and limitations * under the License. */ -import { isPlainObject } from 'lodash'; +import isPlainObject from 'lodash/isPlainObject'; /** * Deeply merges two objects, omitting undefined values, and not deeply merging Arrays. * diff --git a/src/core/utils/pick.ts b/packages/kbn-std/src/pick.ts similarity index 100% rename from src/core/utils/pick.ts rename to packages/kbn-std/src/pick.ts diff --git a/src/core/utils/promise.test.ts b/packages/kbn-std/src/promise.test.ts similarity index 100% rename from src/core/utils/promise.test.ts rename to packages/kbn-std/src/promise.test.ts diff --git a/src/core/utils/promise.ts b/packages/kbn-std/src/promise.ts similarity index 100% rename from src/core/utils/promise.ts rename to packages/kbn-std/src/promise.ts diff --git a/src/core/utils/unset.test.ts b/packages/kbn-std/src/unset.test.ts similarity index 100% rename from src/core/utils/unset.test.ts rename to packages/kbn-std/src/unset.test.ts diff --git a/src/core/utils/unset.ts b/packages/kbn-std/src/unset.ts similarity index 100% rename from src/core/utils/unset.ts rename to packages/kbn-std/src/unset.ts diff --git a/src/core/utils/url.test.ts b/packages/kbn-std/src/url.test.ts similarity index 100% rename from src/core/utils/url.test.ts rename to packages/kbn-std/src/url.test.ts diff --git a/src/core/utils/url.ts b/packages/kbn-std/src/url.ts similarity index 100% rename from src/core/utils/url.ts rename to packages/kbn-std/src/url.ts diff --git a/packages/kbn-std/tsconfig.json b/packages/kbn-std/tsconfig.json new file mode 100644 index 0000000000000..5c86ad17a90e9 --- /dev/null +++ b/packages/kbn-std/tsconfig.json @@ -0,0 +1,16 @@ +{ + "extends": "../../tsconfig.base.json", + "compilerOptions": { + "declaration": true, + "declarationDir": "./target", + "outDir": "./target", + "stripInternal": true, + "declarationMap": true, + "types": ["jest", "node"] + }, + "include": [ + "./src/**/*.ts", + "../../typings/query_string.d.ts" + ], + "exclude": ["target"] +} diff --git a/packages/kbn-std/yarn.lock b/packages/kbn-std/yarn.lock new file mode 120000 index 0000000000000..3f82ebc9cdbae --- /dev/null +++ b/packages/kbn-std/yarn.lock @@ -0,0 +1 @@ +../../yarn.lock \ No newline at end of file diff --git a/packages/kbn-utility-types/index.ts b/packages/kbn-utility-types/index.ts index 6ccfeb8ab052c..d3fb5bdf36194 100644 --- a/packages/kbn-utility-types/index.ts +++ b/packages/kbn-utility-types/index.ts @@ -98,3 +98,15 @@ export type PublicKeys = keyof T; * Returns an object with public keys only. */ export type PublicContract = Pick>; + +/** + * Returns public method names + */ +export type MethodKeysOf = { + [K in keyof T]: T[K] extends (...args: any[]) => any ? K : never; +}[keyof T]; + +/** + * Returns an object with public methods only. + */ +export type PublicMethodsOf = Pick>; diff --git a/packages/kbn-utility-types/tsconfig.json b/packages/kbn-utility-types/tsconfig.json index 03cace5b9cb2c..79cf423fe78ac 100644 --- a/packages/kbn-utility-types/tsconfig.json +++ b/packages/kbn-utility-types/tsconfig.json @@ -7,7 +7,6 @@ "stripInternal": true, "declarationMap": true, "types": [ - "jest", "node" ] }, diff --git a/src/core/public/application/capabilities/capabilities_service.mock.ts b/src/core/public/application/capabilities/capabilities_service.mock.ts index 54aaa31e08859..ee37854762666 100644 --- a/src/core/public/application/capabilities/capabilities_service.mock.ts +++ b/src/core/public/application/capabilities/capabilities_service.mock.ts @@ -16,8 +16,10 @@ * specific language governing permissions and limitations * under the License. */ + +import { deepFreeze } from '@kbn/std'; +import type { PublicMethodsOf } from '@kbn/utility-types'; import { CapabilitiesService, CapabilitiesStart } from './capabilities_service'; -import { deepFreeze } from '../../../utils'; const createStartContractMock = (): jest.Mocked => ({ capabilities: deepFreeze({ diff --git a/src/core/public/application/capabilities/capabilities_service.tsx b/src/core/public/application/capabilities/capabilities_service.tsx index 7304a8e5a66bc..1164164aec4c5 100644 --- a/src/core/public/application/capabilities/capabilities_service.tsx +++ b/src/core/public/application/capabilities/capabilities_service.tsx @@ -17,9 +17,9 @@ * under the License. */ import { RecursiveReadonly } from '@kbn/utility-types'; +import { deepFreeze } from '@kbn/std'; import { Capabilities } from '../../../types/capabilities'; -import { deepFreeze } from '../../../utils'; import { HttpStart } from '../../http'; interface StartDeps { diff --git a/src/core/public/application/test_types.ts b/src/core/public/application/test_types.ts index 64012f0c0b6c1..6d29b77d92f36 100644 --- a/src/core/public/application/test_types.ts +++ b/src/core/public/application/test_types.ts @@ -16,7 +16,7 @@ * specific language governing permissions and limitations * under the License. */ - +import type { PublicMethodsOf } from '@kbn/utility-types'; import { AppUnmount, Mounter } from './types'; import { ApplicationService } from './application_service'; diff --git a/src/core/public/chrome/chrome_service.mock.ts b/src/core/public/chrome/chrome_service.mock.ts index 0ae8b132f1d86..9cd96763d2e79 100644 --- a/src/core/public/chrome/chrome_service.mock.ts +++ b/src/core/public/chrome/chrome_service.mock.ts @@ -17,6 +17,7 @@ * under the License. */ import { BehaviorSubject } from 'rxjs'; +import type { PublicMethodsOf } from '@kbn/utility-types'; import { ChromeBadge, ChromeBrand, ChromeBreadcrumb, ChromeService, InternalChromeStart } from './'; const createStartContractMock = () => { diff --git a/src/core/public/chrome/nav_links/nav_link.ts b/src/core/public/chrome/nav_links/nav_link.ts index 4b82e0ced4505..80f0265819c40 100644 --- a/src/core/public/chrome/nav_links/nav_link.ts +++ b/src/core/public/chrome/nav_links/nav_link.ts @@ -17,7 +17,7 @@ * under the License. */ -import { pick } from '../../../utils'; +import { pick } from '@kbn/std'; import { AppCategory } from '../../'; /** diff --git a/src/core/public/context/context_service.mock.ts b/src/core/public/context/context_service.mock.ts index eb55ced69dc04..3f9f647e1f7d0 100644 --- a/src/core/public/context/context_service.mock.ts +++ b/src/core/public/context/context_service.mock.ts @@ -16,7 +16,7 @@ * specific language governing permissions and limitations * under the License. */ - +import type { PublicMethodsOf } from '@kbn/utility-types'; import { ContextService, ContextSetup } from './context_service'; import { contextMock } from '../../utils/context.mock'; diff --git a/src/core/public/core_app/core_app.mock.ts b/src/core/public/core_app/core_app.mock.ts index b0e3871a40bf5..b2af81b3630a3 100644 --- a/src/core/public/core_app/core_app.mock.ts +++ b/src/core/public/core_app/core_app.mock.ts @@ -16,7 +16,7 @@ * specific language governing permissions and limitations * under the License. */ - +import type { PublicMethodsOf } from '@kbn/utility-types'; import { CoreApp } from './core_app'; type CoreAppContract = PublicMethodsOf; diff --git a/src/core/public/core_system.ts b/src/core/public/core_system.ts index 006d0036f7a12..a1d6f9c988b27 100644 --- a/src/core/public/core_system.ts +++ b/src/core/public/core_system.ts @@ -17,6 +17,7 @@ * under the License. */ +import { pick } from '@kbn/std'; import { CoreId } from '../server'; import { PackageInfo, EnvironmentMode } from '../server/types'; import { CoreSetup, CoreStart } from '.'; @@ -35,7 +36,6 @@ import { OverlayService } from './overlays'; import { PluginsService } from './plugins'; import { UiSettingsService } from './ui_settings'; import { ApplicationService } from './application'; -import { pick } from '../utils/'; import { DocLinksService } from './doc_links'; import { RenderingService } from './rendering'; import { SavedObjectsService } from './saved_objects'; diff --git a/src/core/public/doc_links/doc_links_service.mock.ts b/src/core/public/doc_links/doc_links_service.mock.ts index 105c13f96cef6..07e29edad8974 100644 --- a/src/core/public/doc_links/doc_links_service.mock.ts +++ b/src/core/public/doc_links/doc_links_service.mock.ts @@ -16,7 +16,7 @@ * specific language governing permissions and limitations * under the License. */ - +import type { PublicMethodsOf } from '@kbn/utility-types'; import { injectedMetadataServiceMock } from '../injected_metadata/injected_metadata_service.mock'; import { DocLinksService, DocLinksStart } from './doc_links_service'; diff --git a/src/core/public/doc_links/doc_links_service.ts b/src/core/public/doc_links/doc_links_service.ts index fae7a272c9635..47f58a3a9fcbf 100644 --- a/src/core/public/doc_links/doc_links_service.ts +++ b/src/core/public/doc_links/doc_links_service.ts @@ -17,8 +17,8 @@ * under the License. */ +import { deepFreeze } from '@kbn/std'; import { InjectedMetadataSetup } from '../injected_metadata'; -import { deepFreeze } from '../../utils'; interface StartDeps { injectedMetadata: InjectedMetadataSetup; diff --git a/src/core/public/fatal_errors/fatal_errors_service.mock.ts b/src/core/public/fatal_errors/fatal_errors_service.mock.ts index 6d9876f787fa9..326ce9a3923e9 100644 --- a/src/core/public/fatal_errors/fatal_errors_service.mock.ts +++ b/src/core/public/fatal_errors/fatal_errors_service.mock.ts @@ -16,6 +16,7 @@ * specific language governing permissions and limitations * under the License. */ +import type { PublicMethodsOf } from '@kbn/utility-types'; import { FatalErrorsService, FatalErrorsSetup } from './fatal_errors_service'; const createSetupContractMock = () => { diff --git a/src/core/public/http/base_path.ts b/src/core/public/http/base_path.ts index ac85d71c793fe..5d9eb51023b78 100644 --- a/src/core/public/http/base_path.ts +++ b/src/core/public/http/base_path.ts @@ -35,7 +35,7 @@ * under the License. */ -import { modifyUrl } from '../../utils'; +import { modifyUrl } from '@kbn/std'; export class BasePath { constructor( diff --git a/src/core/public/http/http_service.mock.ts b/src/core/public/http/http_service.mock.ts index 1111fd39ec78e..68533159765fb 100644 --- a/src/core/public/http/http_service.mock.ts +++ b/src/core/public/http/http_service.mock.ts @@ -16,7 +16,7 @@ * specific language governing permissions and limitations * under the License. */ - +import type { PublicMethodsOf } from '@kbn/utility-types'; import { HttpService } from './http_service'; import { HttpSetup } from './types'; import { BehaviorSubject } from 'rxjs'; diff --git a/src/core/public/http/loading_count_service.mock.ts b/src/core/public/http/loading_count_service.mock.ts index 79928aa4b160d..2ff635e815296 100644 --- a/src/core/public/http/loading_count_service.mock.ts +++ b/src/core/public/http/loading_count_service.mock.ts @@ -19,6 +19,7 @@ import { LoadingCountSetup, LoadingCountService } from './loading_count_service'; import { BehaviorSubject } from 'rxjs'; +import type { PublicMethodsOf } from '@kbn/utility-types'; const createSetupContractMock = () => { const setupContract: jest.Mocked = { diff --git a/src/core/public/i18n/i18n_service.mock.ts b/src/core/public/i18n/i18n_service.mock.ts index 1a9ca0869d7c1..a91710fbed780 100644 --- a/src/core/public/i18n/i18n_service.mock.ts +++ b/src/core/public/i18n/i18n_service.mock.ts @@ -18,6 +18,8 @@ */ import React from 'react'; +import type { PublicMethodsOf } from '@kbn/utility-types'; + import { I18nService, I18nStart } from './i18n_service'; const PassThroughComponent = ({ children }: { children: React.ReactNode }) => children; diff --git a/src/core/public/index.ts b/src/core/public/index.ts index a9774dafd2340..24d19e2d32074 100644 --- a/src/core/public/index.ts +++ b/src/core/public/index.ts @@ -68,7 +68,6 @@ import { UiSettingsState, IUiSettingsClient } from './ui_settings'; import { ApplicationSetup, Capabilities, ApplicationStart } from './application'; import { DocLinksStart } from './doc_links'; import { SavedObjectsStart } from './saved_objects'; -export { PackageInfo, EnvironmentMode } from '../server/types'; import { IContextContainer, IContextProvider, @@ -78,17 +77,9 @@ import { HandlerParameters, } from './context'; +export { PackageInfo, EnvironmentMode } from '../server/types'; export { CoreContext, CoreSystem } from './core_system'; -export { - DEFAULT_APP_CATEGORIES, - getFlattenedObject, - URLMeaningfulParts, - modifyUrl, - isRelativeUrl, - Freezable, - deepFreeze, - assertNever, -} from '../utils'; +export { DEFAULT_APP_CATEGORIES } from '../utils'; export { AppCategory, UiSettingsParams, diff --git a/src/core/public/injected_metadata/injected_metadata_service.mock.ts b/src/core/public/injected_metadata/injected_metadata_service.mock.ts index 3bb4358406246..33d04eedebb07 100644 --- a/src/core/public/injected_metadata/injected_metadata_service.mock.ts +++ b/src/core/public/injected_metadata/injected_metadata_service.mock.ts @@ -16,6 +16,7 @@ * specific language governing permissions and limitations * under the License. */ +import type { PublicMethodsOf } from '@kbn/utility-types'; import { InjectedMetadataService, InjectedMetadataSetup } from './injected_metadata_service'; const createSetupContractMock = () => { diff --git a/src/core/public/injected_metadata/injected_metadata_service.ts b/src/core/public/injected_metadata/injected_metadata_service.ts index 23630a5bcf228..5b51bc823d166 100644 --- a/src/core/public/injected_metadata/injected_metadata_service.ts +++ b/src/core/public/injected_metadata/injected_metadata_service.ts @@ -18,6 +18,7 @@ */ import { get } from 'lodash'; +import { deepFreeze } from '@kbn/std'; import { DiscoveredPlugin, PluginName } from '../../server'; import { EnvironmentMode, @@ -25,7 +26,6 @@ import { UiSettingsParams, UserProvidedValues, } from '../../server/types'; -import { deepFreeze } from '../../utils/'; import { AppCategory } from '../'; export interface InjectedPluginMetadata { diff --git a/src/core/public/integrations/integrations_service.mock.ts b/src/core/public/integrations/integrations_service.mock.ts index 4f6ca0fb68459..88458ebb747fe 100644 --- a/src/core/public/integrations/integrations_service.mock.ts +++ b/src/core/public/integrations/integrations_service.mock.ts @@ -16,7 +16,7 @@ * specific language governing permissions and limitations * under the License. */ - +import type { PublicMethodsOf } from '@kbn/utility-types'; import { IntegrationsService } from './integrations_service'; type IntegrationsServiceContract = PublicMethodsOf; diff --git a/src/core/public/notifications/notifications_service.mock.ts b/src/core/public/notifications/notifications_service.mock.ts index 464f47e20aa3b..990ab479d35c3 100644 --- a/src/core/public/notifications/notifications_service.mock.ts +++ b/src/core/public/notifications/notifications_service.mock.ts @@ -16,6 +16,7 @@ * specific language governing permissions and limitations * under the License. */ +import type { PublicMethodsOf } from '@kbn/utility-types'; import { NotificationsService, NotificationsSetup, diff --git a/src/core/public/overlays/banners/banners_service.mock.ts b/src/core/public/overlays/banners/banners_service.mock.ts index 14041b2720877..acd38af383d67 100644 --- a/src/core/public/overlays/banners/banners_service.mock.ts +++ b/src/core/public/overlays/banners/banners_service.mock.ts @@ -16,7 +16,7 @@ * specific language governing permissions and limitations * under the License. */ - +import type { PublicMethodsOf } from '@kbn/utility-types'; import { OverlayBannersStart, OverlayBannersService } from './banners_service'; const createStartContractMock = () => { diff --git a/src/core/public/overlays/flyout/flyout_service.mock.ts b/src/core/public/overlays/flyout/flyout_service.mock.ts index 91544500713d6..90dcb308de1b9 100644 --- a/src/core/public/overlays/flyout/flyout_service.mock.ts +++ b/src/core/public/overlays/flyout/flyout_service.mock.ts @@ -16,7 +16,7 @@ * specific language governing permissions and limitations * under the License. */ - +import type { PublicMethodsOf } from '@kbn/utility-types'; import { FlyoutService, OverlayFlyoutStart } from './flyout_service'; const createStartContractMock = () => { diff --git a/src/core/public/overlays/modal/modal_service.mock.ts b/src/core/public/overlays/modal/modal_service.mock.ts index 5ac49874dcf93..0af207d168fae 100644 --- a/src/core/public/overlays/modal/modal_service.mock.ts +++ b/src/core/public/overlays/modal/modal_service.mock.ts @@ -16,7 +16,7 @@ * specific language governing permissions and limitations * under the License. */ - +import type { PublicMethodsOf } from '@kbn/utility-types'; import { ModalService, OverlayModalStart } from './modal_service'; const createStartContractMock = () => { diff --git a/src/core/public/overlays/overlay_service.mock.ts b/src/core/public/overlays/overlay_service.mock.ts index e29247494034f..66ba36b20b45c 100644 --- a/src/core/public/overlays/overlay_service.mock.ts +++ b/src/core/public/overlays/overlay_service.mock.ts @@ -16,6 +16,7 @@ * specific language governing permissions and limitations * under the License. */ +import type { PublicMethodsOf } from '@kbn/utility-types'; import { OverlayService, OverlayStart } from './overlay_service'; import { overlayBannersServiceMock } from './banners/banners_service.mock'; import { overlayFlyoutServiceMock } from './flyout/flyout_service.mock'; diff --git a/src/core/public/plugins/plugins_service.mock.ts b/src/core/public/plugins/plugins_service.mock.ts index 900f20422b826..0625d2c3ec4b2 100644 --- a/src/core/public/plugins/plugins_service.mock.ts +++ b/src/core/public/plugins/plugins_service.mock.ts @@ -16,7 +16,7 @@ * specific language governing permissions and limitations * under the License. */ - +import type { PublicMethodsOf } from '@kbn/utility-types'; import { PluginsService, PluginsServiceSetup } from './plugins_service'; const createSetupContractMock = () => { diff --git a/src/core/public/plugins/plugins_service.ts b/src/core/public/plugins/plugins_service.ts index f9bc40ca52601..87219f4c0bdd3 100644 --- a/src/core/public/plugins/plugins_service.ts +++ b/src/core/public/plugins/plugins_service.ts @@ -17,6 +17,7 @@ * under the License. */ +import { withTimeout } from '@kbn/std'; import { PluginName, PluginOpaqueId } from '../../server'; import { CoreService } from '../../types'; import { CoreContext } from '../core_system'; @@ -28,7 +29,6 @@ import { } from './plugin_context'; import { InternalCoreSetup, InternalCoreStart } from '../core_system'; import { InjectedPluginMetadata } from '../injected_metadata'; -import { withTimeout } from '../../utils'; const Sec = 1000; /** @internal */ diff --git a/src/core/public/public.api.md b/src/core/public/public.api.md index a9bea7bcfdef1..d0b9e115bd524 100644 --- a/src/core/public/public.api.md +++ b/src/core/public/public.api.md @@ -7,7 +7,6 @@ import { Action } from 'history'; import { ApiResponse } from '@elastic/elasticsearch/lib/Transport'; import Boom from 'boom'; -import { ErrorToastOptions as ErrorToastOptions_2 } from 'src/core/public/notifications'; import { EuiBreadcrumb } from '@elastic/eui'; import { EuiButtonEmptyProps } from '@elastic/eui'; import { EuiConfirmModalProps } from '@elastic/eui'; @@ -22,15 +21,13 @@ import { Location } from 'history'; import { LocationDescriptorObject } from 'history'; import { MaybePromise } from '@kbn/utility-types'; import { Observable } from 'rxjs'; -import { ParsedQuery } from 'query-string'; import { Path } from 'history'; +import { PublicMethodsOf } from '@kbn/utility-types'; import { PublicUiSettingsParams as PublicUiSettingsParams_2 } from 'src/core/server/types'; import React from 'react'; import { RecursiveReadonly } from '@kbn/utility-types'; import * as Rx from 'rxjs'; -import { SavedObject as SavedObject_2 } from 'src/core/server'; import { ShallowPromise } from '@kbn/utility-types'; -import { ToastInputFields as ToastInputFields_2 } from 'src/core/public/notifications'; import { TransportRequestOptions } from '@elastic/elasticsearch/lib/Transport'; import { TransportRequestParams } from '@elastic/elasticsearch/lib/Transport'; import { TransportRequestPromise } from '@elastic/elasticsearch/lib/Transport'; @@ -187,9 +184,6 @@ export type AppUpdatableFields = Pick Partial | undefined; -// @public -export function assertNever(x: never): never; - // @public export interface Capabilities { [key: string]: Record>; @@ -446,9 +440,6 @@ export class CoreSystem { stop(): void; } -// @public -export function deepFreeze(object: T): RecursiveReadonly; - // @internal (undocumented) export const DEFAULT_APP_CATEGORIES: Readonly<{ kibana: { @@ -618,16 +609,6 @@ export interface FatalErrorsSetup { // @public export type FatalErrorsStart = FatalErrorsSetup; -// @public (undocumented) -export type Freezable = { - [k: string]: any; -} | any[]; - -// @public -export function getFlattenedObject(rootValue: Record): { - [key: string]: any; -}; - // @public export type HandlerContextType> = T extends HandlerFunction ? U : never; @@ -839,9 +820,6 @@ export interface ImageValidation { }; } -// @public -export function isRelativeUrl(candidatePath: string): boolean; - // @public export type IToasts = Pick; @@ -870,9 +848,6 @@ export interface IUiSettingsClient { set: (key: string, value: any) => Promise; } -// @public -export function modifyUrl(url: string, urlModifier: (urlParts: URLMeaningfulParts) => Partial | void): string; - // @public export type MountPoint = (element: T) => UnmountCallback; @@ -1449,26 +1424,6 @@ export type UnmountCallback = () => void; // @public export const URL_MAX_LENGTH: number; -// @public -export interface URLMeaningfulParts { - // (undocumented) - auth?: string | null; - // (undocumented) - hash?: string | null; - // (undocumented) - hostname?: string | null; - // (undocumented) - pathname?: string | null; - // (undocumented) - port?: string | null; - // (undocumented) - protocol?: string | null; - // (undocumented) - query: ParsedQuery; - // (undocumented) - slashes?: boolean | null; -} - // @public export interface UserProvidedValues { // (undocumented) diff --git a/src/core/public/rendering/rendering_service.mock.ts b/src/core/public/rendering/rendering_service.mock.ts index bb4723e69ab5e..803a7dae91a40 100644 --- a/src/core/public/rendering/rendering_service.mock.ts +++ b/src/core/public/rendering/rendering_service.mock.ts @@ -16,7 +16,7 @@ * specific language governing permissions and limitations * under the License. */ - +import type { PublicMethodsOf } from '@kbn/utility-types'; import { RenderingService } from './rendering_service'; type RenderingServiceContract = PublicMethodsOf; diff --git a/src/core/public/saved_objects/saved_objects_client.ts b/src/core/public/saved_objects/saved_objects_client.ts index 351020004b0e7..5a8949ca2f55f 100644 --- a/src/core/public/saved_objects/saved_objects_client.ts +++ b/src/core/public/saved_objects/saved_objects_client.ts @@ -19,6 +19,7 @@ import { cloneDeep, pick, throttle } from 'lodash'; import { resolve as resolveUrl } from 'url'; +import type { PublicMethodsOf } from '@kbn/utility-types'; import { SavedObject, diff --git a/src/core/public/ui_settings/ui_settings_service.mock.ts b/src/core/public/ui_settings/ui_settings_service.mock.ts index e1f7eeff93471..1921c26e57971 100644 --- a/src/core/public/ui_settings/ui_settings_service.mock.ts +++ b/src/core/public/ui_settings/ui_settings_service.mock.ts @@ -17,6 +17,7 @@ * under the License. */ import * as Rx from 'rxjs'; +import type { PublicMethodsOf } from '@kbn/utility-types'; import { UiSettingsService } from './'; import { IUiSettingsClient } from './types'; diff --git a/src/core/server/audit_trail/audit_trail_service.mock.ts b/src/core/server/audit_trail/audit_trail_service.mock.ts index d63b3539e5cdc..4c9c064840750 100644 --- a/src/core/server/audit_trail/audit_trail_service.mock.ts +++ b/src/core/server/audit_trail/audit_trail_service.mock.ts @@ -16,7 +16,7 @@ * specific language governing permissions and limitations * under the License. */ - +import type { PublicMethodsOf } from '@kbn/utility-types'; import { AuditTrailSetup, AuditTrailStart, Auditor } from './types'; import { AuditTrailService } from './audit_trail_service'; diff --git a/src/core/server/capabilities/capabilities_service.mock.ts b/src/core/server/capabilities/capabilities_service.mock.ts index 3f31eca8339d8..7d134f9592dc7 100644 --- a/src/core/server/capabilities/capabilities_service.mock.ts +++ b/src/core/server/capabilities/capabilities_service.mock.ts @@ -16,7 +16,7 @@ * specific language governing permissions and limitations * under the License. */ - +import type { PublicMethodsOf } from '@kbn/utility-types'; import { CapabilitiesService, CapabilitiesSetup, CapabilitiesStart } from './capabilities_service'; const createSetupContractMock = () => { diff --git a/src/core/server/config/config_service.ts b/src/core/server/config/config_service.ts index bceba420bb6ce..d77ee980b0491 100644 --- a/src/core/server/config/config_service.ts +++ b/src/core/server/config/config_service.ts @@ -16,7 +16,7 @@ * specific language governing permissions and limitations * under the License. */ - +import type { PublicMethodsOf } from '@kbn/utility-types'; import { Type } from '@kbn/config-schema'; import { isEqual } from 'lodash'; import { BehaviorSubject, combineLatest, Observable } from 'rxjs'; diff --git a/src/core/server/config/deprecation/deprecation_factory.ts b/src/core/server/config/deprecation/deprecation_factory.ts index cbc9984924c5d..0598347d2cffc 100644 --- a/src/core/server/config/deprecation/deprecation_factory.ts +++ b/src/core/server/config/deprecation/deprecation_factory.ts @@ -17,10 +17,10 @@ * under the License. */ -import { set } from '@elastic/safer-lodash-set'; import { get } from 'lodash'; +import { set } from '@elastic/safer-lodash-set'; +import { unset } from '@kbn/std'; import { ConfigDeprecation, ConfigDeprecationLogger, ConfigDeprecationFactory } from './types'; -import { unset } from '../../../utils'; const _rename = ( config: Record, diff --git a/src/core/server/config/object_to_config_adapter.ts b/src/core/server/config/object_to_config_adapter.ts index 50b31722dceeb..c4d6ac02ccf05 100644 --- a/src/core/server/config/object_to_config_adapter.ts +++ b/src/core/server/config/object_to_config_adapter.ts @@ -17,10 +17,10 @@ * under the License. */ -import { set } from '@elastic/safer-lodash-set'; import { cloneDeep, get, has } from 'lodash'; +import { set } from '@elastic/safer-lodash-set'; +import { getFlattenedObject } from '@kbn/std'; -import { getFlattenedObject } from '../../utils'; import { Config, ConfigPath } from './'; /** diff --git a/src/core/server/config/raw_config_service.mock.ts b/src/core/server/config/raw_config_service.mock.ts index fdcb17395aaad..73a3b5cc9e4d0 100644 --- a/src/core/server/config/raw_config_service.mock.ts +++ b/src/core/server/config/raw_config_service.mock.ts @@ -16,7 +16,7 @@ * specific language governing permissions and limitations * under the License. */ - +import type { PublicMethodsOf } from '@kbn/utility-types'; import { RawConfigService } from './raw_config_service'; import { Observable, of } from 'rxjs'; diff --git a/src/core/server/context/context_service.mock.ts b/src/core/server/context/context_service.mock.ts index eb55ced69dc04..a8d895acad624 100644 --- a/src/core/server/context/context_service.mock.ts +++ b/src/core/server/context/context_service.mock.ts @@ -16,6 +16,7 @@ * specific language governing permissions and limitations * under the License. */ +import type { PublicMethodsOf } from '@kbn/utility-types'; import { ContextService, ContextSetup } from './context_service'; import { contextMock } from '../../utils/context.mock'; diff --git a/src/core/server/core_context.mock.ts b/src/core/server/core_context.mock.ts index f870d30528df4..2b887358818e3 100644 --- a/src/core/server/core_context.mock.ts +++ b/src/core/server/core_context.mock.ts @@ -16,7 +16,6 @@ * specific language governing permissions and limitations * under the License. */ - import { CoreContext } from './core_context'; import { getEnvOptions } from './config/__mocks__/env'; import { Env, IConfigService } from './config'; diff --git a/src/core/server/elasticsearch/client/mocks.ts b/src/core/server/elasticsearch/client/mocks.ts index 2f2ca08fee6f2..6fb3dc090bfb4 100644 --- a/src/core/server/elasticsearch/client/mocks.ts +++ b/src/core/server/elasticsearch/client/mocks.ts @@ -16,7 +16,6 @@ * specific language governing permissions and limitations * under the License. */ - import { Client, ApiResponse } from '@elastic/elasticsearch'; import { TransportRequestPromise } from '@elastic/elasticsearch/lib/Transport'; import { ElasticsearchClient } from './types'; @@ -75,7 +74,7 @@ export type ElasticsearchClientMock = DeeplyMockedKeys; const createClientMock = (): ElasticsearchClientMock => (createInternalClientMock() as unknown) as ElasticsearchClientMock; -interface ScopedClusterClientMock { +export interface ScopedClusterClientMock { asInternalUser: ElasticsearchClientMock; asCurrentUser: ElasticsearchClientMock; } diff --git a/src/core/server/elasticsearch/elasticsearch_service.mock.ts b/src/core/server/elasticsearch/elasticsearch_service.mock.ts index 26186efc286bf..ad80928d2fe5e 100644 --- a/src/core/server/elasticsearch/elasticsearch_service.mock.ts +++ b/src/core/server/elasticsearch/elasticsearch_service.mock.ts @@ -18,6 +18,8 @@ */ import { BehaviorSubject } from 'rxjs'; +import type { PublicMethodsOf } from '@kbn/utility-types'; + import { ILegacyClusterClient, ILegacyCustomClusterClient } from './legacy'; import { elasticsearchClientMock, @@ -32,7 +34,7 @@ import { InternalElasticsearchServiceSetup, ElasticsearchStatusMeta } from './ty import { NodesVersionCompatibility } from './version_check/ensure_es_version'; import { ServiceStatus, ServiceStatusLevels } from '../status'; -interface MockedElasticSearchServiceSetup { +export interface MockedElasticSearchServiceSetup { legacy: { config$: BehaviorSubject; createClient: jest.Mock; diff --git a/src/core/server/elasticsearch/elasticsearch_service.ts b/src/core/server/elasticsearch/elasticsearch_service.ts index 2cc065aaaaeb1..5d07840e8bda7 100644 --- a/src/core/server/elasticsearch/elasticsearch_service.ts +++ b/src/core/server/elasticsearch/elasticsearch_service.ts @@ -19,9 +19,9 @@ import { Observable, Subject } from 'rxjs'; import { first, map, shareReplay, takeUntil } from 'rxjs/operators'; +import { merge } from '@kbn/std'; import { CoreService } from '../../types'; -import { merge } from '../../utils'; import { CoreContext } from '../core_context'; import { Logger } from '../logging'; import { diff --git a/src/core/server/elasticsearch/legacy/elasticsearch_client_config.ts b/src/core/server/elasticsearch/legacy/elasticsearch_client_config.ts index 3dbc1c2c647a9..6896c0a2e301f 100644 --- a/src/core/server/elasticsearch/legacy/elasticsearch_client_config.ts +++ b/src/core/server/elasticsearch/legacy/elasticsearch_client_config.ts @@ -22,7 +22,7 @@ import { cloneDeep } from 'lodash'; import { Duration } from 'moment'; import { checkServerIdentity } from 'tls'; import url from 'url'; -import { pick } from '../../../utils'; +import { pick } from '@kbn/std'; import { Logger } from '../../logging'; import { ElasticsearchConfig } from '../elasticsearch_config'; diff --git a/src/core/server/environment/environment_service.mock.ts b/src/core/server/environment/environment_service.mock.ts index 8bf726b4a6388..a956e369ba4a7 100644 --- a/src/core/server/environment/environment_service.mock.ts +++ b/src/core/server/environment/environment_service.mock.ts @@ -16,6 +16,7 @@ * specific language governing permissions and limitations * under the License. */ +import type { PublicMethodsOf } from '@kbn/utility-types'; import { EnvironmentService, InternalEnvironmentServiceSetup } from './environment_service'; diff --git a/src/core/server/environment/environment_service.test.ts b/src/core/server/environment/environment_service.test.ts index 06fd250ebe4f9..f6cffb5e26a9e 100644 --- a/src/core/server/environment/environment_service.test.ts +++ b/src/core/server/environment/environment_service.test.ts @@ -21,6 +21,7 @@ import { BehaviorSubject } from 'rxjs'; import { EnvironmentService } from './environment_service'; import { resolveInstanceUuid } from './resolve_uuid'; import { createDataFolder } from './create_data_folder'; +import { writePidFile } from './write_pid_file'; import { CoreContext } from '../core_context'; import { configServiceMock } from '../config/config_service.mock'; @@ -35,12 +36,20 @@ jest.mock('./create_data_folder', () => ({ createDataFolder: jest.fn(), })); +jest.mock('./write_pid_file', () => ({ + writePidFile: jest.fn(), +})); + const pathConfig = { data: 'data-folder', }; const serverConfig = { uuid: 'SOME_UUID', }; +const pidConfig = { + file: '/pid/file', + exclusive: 'false', +}; const getConfigService = () => { const configService = configServiceMock.create(); @@ -51,6 +60,9 @@ const getConfigService = () => { if (path === 'server') { return new BehaviorSubject(serverConfig); } + if (path === 'pid') { + return new BehaviorSubject(pidConfig); + } return new BehaviorSubject({}); }); return configService; @@ -76,7 +88,7 @@ describe('UuidService', () => { expect(resolveInstanceUuid).toHaveBeenCalledWith({ pathConfig, serverConfig, - logger: logger.get('uuid'), + logger: logger.get('environment'), }); }); @@ -86,7 +98,17 @@ describe('UuidService', () => { expect(createDataFolder).toHaveBeenCalledTimes(1); expect(createDataFolder).toHaveBeenCalledWith({ pathConfig, - logger: logger.get('uuid'), + logger: logger.get('environment'), + }); + }); + + it('calls writePidFile with correct parameters', async () => { + const service = new EnvironmentService(coreContext); + await service.setup(); + expect(writePidFile).toHaveBeenCalledTimes(1); + expect(writePidFile).toHaveBeenCalledWith({ + pidConfig, + logger: logger.get('environment'), }); }); diff --git a/src/core/server/environment/environment_service.ts b/src/core/server/environment/environment_service.ts index 6a0b1122c7053..caa4f34bcfaa7 100644 --- a/src/core/server/environment/environment_service.ts +++ b/src/core/server/environment/environment_service.ts @@ -23,8 +23,10 @@ import { Logger } from '../logging'; import { IConfigService } from '../config'; import { PathConfigType, config as pathConfigDef } from '../path'; import { HttpConfigType, config as httpConfigDef } from '../http'; +import { PidConfigType, config as pidConfigDef } from './pid_config'; import { resolveInstanceUuid } from './resolve_uuid'; import { createDataFolder } from './create_data_folder'; +import { writePidFile } from './write_pid_file'; /** * @internal @@ -43,17 +45,24 @@ export class EnvironmentService { private uuid: string = ''; constructor(core: CoreContext) { - this.log = core.logger.get('uuid'); + this.log = core.logger.get('environment'); this.configService = core.configService; } public async setup() { - const [pathConfig, serverConfig] = await Promise.all([ + const [pathConfig, serverConfig, pidConfig] = await Promise.all([ this.configService.atPath(pathConfigDef.path).pipe(take(1)).toPromise(), this.configService.atPath(httpConfigDef.path).pipe(take(1)).toPromise(), + this.configService.atPath(pidConfigDef.path).pipe(take(1)).toPromise(), ]); + // was present in the legacy `pid` file. + process.on('unhandledRejection', (reason) => { + this.log.warn(`Detected an unhandled Promise rejection.\n${reason}`); + }); + await createDataFolder({ pathConfig, logger: this.log }); + await writePidFile({ pidConfig, logger: this.log }); this.uuid = await resolveInstanceUuid({ pathConfig, diff --git a/src/core/server/environment/fs.ts b/src/core/server/environment/fs.ts index dc040ccb73615..b79c70dbee280 100644 --- a/src/core/server/environment/fs.ts +++ b/src/core/server/environment/fs.ts @@ -23,3 +23,4 @@ import { promisify } from 'util'; export const readFile = promisify(Fs.readFile); export const writeFile = promisify(Fs.writeFile); export const mkdir = promisify(Fs.mkdir); +export const exists = promisify(Fs.exists); diff --git a/src/core/server/environment/index.ts b/src/core/server/environment/index.ts index 57a26d5ea3c79..92b57c6af2fff 100644 --- a/src/core/server/environment/index.ts +++ b/src/core/server/environment/index.ts @@ -18,3 +18,4 @@ */ export { EnvironmentService, InternalEnvironmentServiceSetup } from './environment_service'; +export { config, PidConfigType } from './pid_config'; diff --git a/src/core/server/environment/pid_config.ts b/src/core/server/environment/pid_config.ts new file mode 100644 index 0000000000000..ee9963016717e --- /dev/null +++ b/src/core/server/environment/pid_config.ts @@ -0,0 +1,30 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { TypeOf, schema } from '@kbn/config-schema'; + +export const config = { + path: 'pid', + schema: schema.object({ + file: schema.maybe(schema.string()), + exclusive: schema.boolean({ defaultValue: false }), + }), +}; + +export type PidConfigType = TypeOf; diff --git a/src/core/server/environment/write_pid_file.test.ts b/src/core/server/environment/write_pid_file.test.ts new file mode 100644 index 0000000000000..f9eb78a486970 --- /dev/null +++ b/src/core/server/environment/write_pid_file.test.ts @@ -0,0 +1,144 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { writeFile, exists } from './fs'; +import { writePidFile } from './write_pid_file'; +import { loggingSystemMock } from '../logging/logging_system.mock'; + +jest.mock('./fs', () => ({ + writeFile: jest.fn(), + exists: jest.fn(), +})); + +const writeFileMock = writeFile as jest.MockedFunction; +const existsMock = exists as jest.MockedFunction; + +const pid = String(process.pid); + +describe('writePidFile', () => { + let logger: ReturnType; + + beforeEach(() => { + logger = loggingSystemMock.createLogger(); + jest.spyOn(process, 'once'); + + writeFileMock.mockImplementation(() => Promise.resolve()); + existsMock.mockImplementation(() => Promise.resolve(false)); + }); + + afterEach(() => { + jest.clearAllMocks(); + }); + + const allLogs = () => + Object.entries(loggingSystemMock.collect(logger)).reduce((messages, [key, value]) => { + return [...messages, ...(key === 'log' ? [] : (value as any[]).map(([msg]) => [key, msg]))]; + }, [] as any[]); + + it('does nothing if `pid.file` is not set', async () => { + await writePidFile({ + pidConfig: { + file: undefined, + exclusive: false, + }, + logger, + }); + expect(writeFile).not.toHaveBeenCalled(); + expect(process.once).not.toHaveBeenCalled(); + expect(allLogs()).toMatchInlineSnapshot(`Array []`); + }); + + it('writes the pid file to `pid.file`', async () => { + existsMock.mockResolvedValue(false); + + await writePidFile({ + pidConfig: { + file: '/pid-file', + exclusive: false, + }, + logger, + }); + + expect(writeFile).toHaveBeenCalledTimes(1); + expect(writeFile).toHaveBeenCalledWith('/pid-file', pid); + + expect(process.once).toHaveBeenCalledTimes(2); + expect(process.once).toHaveBeenCalledWith('exit', expect.any(Function)); + expect(process.once).toHaveBeenCalledWith('SIGINT', expect.any(Function)); + + expect(allLogs()).toMatchInlineSnapshot(` + Array [ + Array [ + "debug", + "wrote pid file to /pid-file", + ], + ] + `); + }); + + it('throws an error if the file exists and `pid.exclusive is true`', async () => { + existsMock.mockResolvedValue(true); + + await expect( + writePidFile({ + pidConfig: { + file: '/pid-file', + exclusive: true, + }, + logger, + }) + ).rejects.toThrowErrorMatchingInlineSnapshot(`"pid file already exists at /pid-file"`); + + expect(writeFile).not.toHaveBeenCalled(); + expect(process.once).not.toHaveBeenCalled(); + expect(allLogs()).toMatchInlineSnapshot(`Array []`); + }); + + it('logs a warning if the file exists and `pid.exclusive` is false', async () => { + existsMock.mockResolvedValue(true); + + await writePidFile({ + pidConfig: { + file: '/pid-file', + exclusive: false, + }, + logger, + }); + + expect(writeFile).toHaveBeenCalledTimes(1); + expect(writeFile).toHaveBeenCalledWith('/pid-file', pid); + + expect(process.once).toHaveBeenCalledTimes(2); + expect(process.once).toHaveBeenCalledWith('exit', expect.any(Function)); + expect(process.once).toHaveBeenCalledWith('SIGINT', expect.any(Function)); + + expect(allLogs()).toMatchInlineSnapshot(` + Array [ + Array [ + "debug", + "wrote pid file to /pid-file", + ], + Array [ + "warn", + "pid file already exists at /pid-file", + ], + ] + `); + }); +}); diff --git a/src/core/server/environment/write_pid_file.ts b/src/core/server/environment/write_pid_file.ts new file mode 100644 index 0000000000000..6ee20af02d7b0 --- /dev/null +++ b/src/core/server/environment/write_pid_file.ts @@ -0,0 +1,64 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { unlinkSync as unlink } from 'fs'; +import once from 'lodash/once'; +import { Logger } from '../logging'; +import { writeFile, exists } from './fs'; +import { PidConfigType } from './pid_config'; + +export const writePidFile = async ({ + pidConfig, + logger, +}: { + pidConfig: PidConfigType; + logger: Logger; +}) => { + const path = pidConfig.file; + if (!path) { + return; + } + + const pid = String(process.pid); + + if (await exists(path)) { + const message = `pid file already exists at ${path}`; + if (pidConfig.exclusive) { + throw new Error(message); + } else { + logger.warn(message, { path, pid }); + } + } + + await writeFile(path, pid); + + logger.debug(`wrote pid file to ${path}`, { path, pid }); + + const clean = once(() => { + unlink(path); + }); + + process.once('exit', clean); // for "natural" exits + process.once('SIGINT', () => { + // for Ctrl-C exits + clean(); + // resend SIGINT + process.kill(process.pid, 'SIGINT'); + }); +}; diff --git a/src/core/server/http/base_path_service.ts b/src/core/server/http/base_path_service.ts index 093d73b2da3bf..059eb36f42dd5 100644 --- a/src/core/server/http/base_path_service.ts +++ b/src/core/server/http/base_path_service.ts @@ -16,9 +16,9 @@ * specific language governing permissions and limitations * under the License. */ -import { ensureRawRequest, KibanaRequest, LegacyRequest } from './router'; +import { modifyUrl } from '@kbn/std'; -import { modifyUrl } from '../../utils'; +import { ensureRawRequest, KibanaRequest, LegacyRequest } from './router'; /** * Access or manipulate the Kibana base path diff --git a/src/core/server/http/http_service.mock.ts b/src/core/server/http/http_service.mock.ts index 676cee1954c59..3e38f6a6d384d 100644 --- a/src/core/server/http/http_service.mock.ts +++ b/src/core/server/http/http_service.mock.ts @@ -18,6 +18,8 @@ */ import { Server } from 'hapi'; +import type { PublicMethodsOf } from '@kbn/utility-types'; + import { CspConfig } from '../csp'; import { mockRouter, RouterMock } from './router/router.mock'; import { configMock } from '../config/config.mock'; diff --git a/src/core/server/http/http_service.ts b/src/core/server/http/http_service.ts index c2fd653918171..82b141c8e50dd 100644 --- a/src/core/server/http/http_service.ts +++ b/src/core/server/http/http_service.ts @@ -20,9 +20,9 @@ import { Observable, Subscription, combineLatest } from 'rxjs'; import { first, map } from 'rxjs/operators'; import { Server } from 'hapi'; +import { pick } from '@kbn/std'; import { CoreService } from '../../types'; -import { pick } from '../../utils'; import { Logger, LoggerFactory } from '../logging'; import { ContextSetup } from '../context'; import { Env } from '../config'; diff --git a/src/core/server/http/integration_tests/lifecycle_handlers.test.ts b/src/core/server/http/integration_tests/lifecycle_handlers.test.ts index a1401ba73813b..8d70b5c3ad119 100644 --- a/src/core/server/http/integration_tests/lifecycle_handlers.test.ts +++ b/src/core/server/http/integration_tests/lifecycle_handlers.test.ts @@ -20,7 +20,6 @@ import supertest from 'supertest'; import { BehaviorSubject } from 'rxjs'; import { ByteSizeValue } from '@kbn/config-schema'; -import pkg from '../../../../../package.json'; import { createHttpServer } from '../test_utils'; import { HttpService } from '../http_service'; @@ -30,6 +29,9 @@ import { IRouter, RouteRegistrar } from '../router'; import { configServiceMock } from '../../config/config_service.mock'; import { contextServiceMock } from '../../context/context_service.mock'; +// eslint-disable-next-line @typescript-eslint/no-var-requires +const pkg = require('../../../../../package.json'); + const actualVersion = pkg.version; const versionHeader = 'kbn-version'; const xsrfHeader = 'kbn-xsrf'; diff --git a/src/core/server/http/router/headers.ts b/src/core/server/http/router/headers.ts index f27f5e937b2c0..498dd153a43dd 100644 --- a/src/core/server/http/router/headers.ts +++ b/src/core/server/http/router/headers.ts @@ -17,8 +17,7 @@ * under the License. */ import { IncomingHttpHeaders } from 'http'; - -import { pick } from '../../../utils'; +import { pick } from '@kbn/std'; /** * Creates a Union type of all known keys of a given interface. diff --git a/src/core/server/http/router/request.ts b/src/core/server/http/router/request.ts index 76f8761a7e998..e04f8585981b5 100644 --- a/src/core/server/http/router/request.ts +++ b/src/core/server/http/router/request.ts @@ -23,8 +23,8 @@ import { Request, RouteOptionsApp, ApplicationState } from 'hapi'; import { Observable, fromEvent, merge } from 'rxjs'; import { shareReplay, first, takeUntil } from 'rxjs/operators'; import { RecursiveReadonly } from '@kbn/utility-types'; +import { deepFreeze } from '@kbn/std'; -import { deepFreeze } from '../../../utils'; import { Headers } from './headers'; import { RouteMethod, RouteConfigOptions, validBodyOutput, isSafeMethod } from './route'; import { KibanaSocket, IKibanaSocket } from './socket'; diff --git a/src/core/server/index.ts b/src/core/server/index.ts index d127471348d9f..01797d073ae2e 100644 --- a/src/core/server/index.ts +++ b/src/core/server/index.ts @@ -322,16 +322,7 @@ export { MetricsServiceSetup, } from './metrics'; -export { - DEFAULT_APP_CATEGORIES, - getFlattenedObject, - URLMeaningfulParts, - modifyUrl, - isRelativeUrl, - Freezable, - deepFreeze, - assertNever, -} from '../utils'; +export { DEFAULT_APP_CATEGORIES } from '../utils'; export { SavedObject, diff --git a/src/core/server/legacy/cli.js b/src/core/server/legacy/cli.js new file mode 100644 index 0000000000000..28e14d28eecd3 --- /dev/null +++ b/src/core/server/legacy/cli.js @@ -0,0 +1,20 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +export { startRepl } from '../../../cli/repl'; diff --git a/src/core/server/legacy/cluster_manager.js b/src/core/server/legacy/cluster_manager.js new file mode 100644 index 0000000000000..3c51fd6869a09 --- /dev/null +++ b/src/core/server/legacy/cluster_manager.js @@ -0,0 +1,20 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +export { ClusterManager } from '../../../cli/cluster/cluster_manager'; diff --git a/src/core/server/legacy/config/get_unused_config_keys.ts b/src/core/server/legacy/config/get_unused_config_keys.ts index d10c574f04974..c15c3b270df05 100644 --- a/src/core/server/legacy/config/get_unused_config_keys.ts +++ b/src/core/server/legacy/config/get_unused_config_keys.ts @@ -18,8 +18,8 @@ */ import { difference } from 'lodash'; +import { getFlattenedObject } from '@kbn/std'; import { unset } from '../../../../legacy/utils'; -import { getFlattenedObject } from '../../../utils'; import { hasConfigPathIntersection } from '../../config'; import { LegacyPluginSpec, LegacyConfig, LegacyVars } from '../types'; diff --git a/src/core/server/legacy/legacy_service.mock.ts b/src/core/server/legacy/legacy_service.mock.ts index c27f5be04d965..ab501bd6bb53b 100644 --- a/src/core/server/legacy/legacy_service.mock.ts +++ b/src/core/server/legacy/legacy_service.mock.ts @@ -16,7 +16,7 @@ * specific language governing permissions and limitations * under the License. */ - +import type { PublicMethodsOf } from '@kbn/utility-types'; import { LegacyService } from './legacy_service'; import { LegacyConfig, LegacyServiceDiscoverPlugins, LegacyServiceSetupDeps } from './types'; diff --git a/src/core/server/legacy/legacy_service.test.ts b/src/core/server/legacy/legacy_service.test.ts index d0492ea88c5e8..f3ce89f83a610 100644 --- a/src/core/server/legacy/legacy_service.test.ts +++ b/src/core/server/legacy/legacy_service.test.ts @@ -18,8 +18,7 @@ */ jest.mock('../../../legacy/server/kbn_server'); -jest.mock('../../../cli/cluster/cluster_manager'); - +jest.mock('./cluster_manager'); import { findLegacyPluginSpecsMock, logLegacyThirdPartyPluginDeprecationWarningMock, @@ -27,7 +26,8 @@ import { import { BehaviorSubject, throwError } from 'rxjs'; -import { ClusterManager as MockClusterManager } from '../../../cli/cluster/cluster_manager'; +// @ts-expect-error js file to remove TS dependency on cli +import { ClusterManager as MockClusterManager } from './cluster_manager'; import KbnServer from '../../../legacy/server/kbn_server'; import { Config, Env, ObjectToConfigAdapter } from '../config'; import { getEnvOptions } from '../config/__mocks__/env'; diff --git a/src/core/server/legacy/legacy_service.ts b/src/core/server/legacy/legacy_service.ts index 6e6d5cfc24340..d07c81b8b5ebe 100644 --- a/src/core/server/legacy/legacy_service.ts +++ b/src/core/server/legacy/legacy_service.ts @@ -16,7 +16,7 @@ * specific language governing permissions and limitations * under the License. */ - +import type { PublicMethodsOf } from '@kbn/utility-types'; import { combineLatest, ConnectableObservable, EMPTY, Observable, Subscription } from 'rxjs'; import { first, map, publishReplay, tap } from 'rxjs/operators'; @@ -233,7 +233,7 @@ export class LegacyService implements CoreService { : EMPTY; // eslint-disable-next-line @typescript-eslint/no-var-requires - const { ClusterManager } = require('../../../cli/cluster/cluster_manager'); + const { ClusterManager } = require('./cluster_manager'); return new ClusterManager( this.coreContext.env.cliArgs, config, @@ -368,7 +368,7 @@ export class LegacyService implements CoreService { // We only want one REPL. if (this.coreContext.env.cliArgs.repl && process.env.kbnWorkerType === 'server') { // eslint-disable-next-line @typescript-eslint/no-var-requires - require('../../../cli/repl').startRepl(kbnServer); + require('./cli').startRepl(kbnServer); } const { autoListen } = await this.httpConfig$.pipe(first()).toPromise(); diff --git a/src/core/server/legacy/plugins/collect_ui_exports.js b/src/core/server/legacy/plugins/collect_ui_exports.js new file mode 100644 index 0000000000000..842ab554d79d1 --- /dev/null +++ b/src/core/server/legacy/plugins/collect_ui_exports.js @@ -0,0 +1,21 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +// eslint-disable-next-line @kbn/eslint/no-restricted-paths +export { collectUiExports } from '../../../../legacy/ui/ui_exports/collect_ui_exports'; diff --git a/src/core/server/legacy/plugins/find_legacy_plugin_specs.ts b/src/core/server/legacy/plugins/find_legacy_plugin_specs.ts index 82e04496ffc3e..cb4277b130a88 100644 --- a/src/core/server/legacy/plugins/find_legacy_plugin_specs.ts +++ b/src/core/server/legacy/plugins/find_legacy_plugin_specs.ts @@ -25,12 +25,12 @@ import { defaultConfig, // @ts-expect-error } from '../../../../legacy/plugin_discovery/find_plugin_specs.js'; -// eslint-disable-next-line @kbn/eslint/no-restricted-paths -import { collectUiExports as collectLegacyUiExports } from '../../../../legacy/ui/ui_exports/collect_ui_exports'; +// @ts-expect-error +import { collectUiExports as collectLegacyUiExports } from './collect_ui_exports'; import { LoggerFactory } from '../../logging'; import { PackageInfo } from '../../config'; -import { LegacyPluginSpec, LegacyPluginPack, LegacyConfig } from '../types'; +import { LegacyUiExports, LegacyPluginSpec, LegacyPluginPack, LegacyConfig } from '../types'; export async function findLegacyPluginSpecs( settings: unknown, @@ -123,7 +123,7 @@ export async function findLegacyPluginSpecs( spec$.pipe(toArray()), log$.pipe(toArray()) ).toPromise(); - const uiExports = collectLegacyUiExports(pluginSpecs); + const uiExports: LegacyUiExports = collectLegacyUiExports(pluginSpecs); return { disabledPluginSpecs, diff --git a/src/core/server/logging/appenders/appenders.ts b/src/core/server/logging/appenders/appenders.ts index edfce4988275a..9c19ee2bd8be5 100644 --- a/src/core/server/logging/appenders/appenders.ts +++ b/src/core/server/logging/appenders/appenders.ts @@ -18,8 +18,8 @@ */ import { schema } from '@kbn/config-schema'; +import { assertNever } from '@kbn/std'; -import { assertNever } from '../../../utils'; import { LegacyAppender, LegacyAppenderConfig, diff --git a/src/core/server/logging/layouts/layouts.ts b/src/core/server/logging/layouts/layouts.ts index 124c007bae104..03e8adbee6311 100644 --- a/src/core/server/logging/layouts/layouts.ts +++ b/src/core/server/logging/layouts/layouts.ts @@ -18,8 +18,8 @@ */ import { schema } from '@kbn/config-schema'; +import { assertNever } from '@kbn/std'; -import { assertNever } from '../../../utils'; import { LogRecord } from '../log_record'; import { JsonLayout, JsonLayoutConfigType } from './json_layout'; import { PatternLayout, PatternLayoutConfigType } from './pattern_layout'; diff --git a/src/core/server/logging/log_level.ts b/src/core/server/logging/log_level.ts index 577239ddae8e5..165e56e632d6d 100644 --- a/src/core/server/logging/log_level.ts +++ b/src/core/server/logging/log_level.ts @@ -17,7 +17,7 @@ * under the License. */ -import { assertNever } from '../../utils'; +import { assertNever } from '@kbn/std'; /** * Possible log level string values. diff --git a/src/core/server/logging/logging_service.mock.ts b/src/core/server/logging/logging_service.mock.ts index 21edbe670eaec..6a721e134feed 100644 --- a/src/core/server/logging/logging_service.mock.ts +++ b/src/core/server/logging/logging_service.mock.ts @@ -16,6 +16,7 @@ * specific language governing permissions and limitations * under the License. */ +import type { PublicMethodsOf } from '@kbn/utility-types'; import { LoggingService, diff --git a/src/core/server/logging/logging_system.ts b/src/core/server/logging/logging_system.ts index 8aadab83bf716..a3970b1720950 100644 --- a/src/core/server/logging/logging_system.ts +++ b/src/core/server/logging/logging_system.ts @@ -16,6 +16,7 @@ * specific language governing permissions and limitations * under the License. */ +import type { PublicMethodsOf } from '@kbn/utility-types'; import { Appenders, DisposableAppender } from './appenders/appenders'; import { BufferAppender } from './appenders/buffer/buffer_appender'; import { LogLevel } from './log_level'; diff --git a/src/core/server/metrics/metrics_service.mock.ts b/src/core/server/metrics/metrics_service.mock.ts index 2af653004a479..caa7acc001db3 100644 --- a/src/core/server/metrics/metrics_service.mock.ts +++ b/src/core/server/metrics/metrics_service.mock.ts @@ -17,6 +17,8 @@ * under the License. */ import { BehaviorSubject } from 'rxjs'; +import type { PublicMethodsOf } from '@kbn/utility-types'; + import { MetricsService } from './metrics_service'; import { InternalMetricsServiceSetup, diff --git a/src/core/server/plugins/plugin_context.ts b/src/core/server/plugins/plugin_context.ts index af0b0e19b3227..55e63941523ee 100644 --- a/src/core/server/plugins/plugin_context.ts +++ b/src/core/server/plugins/plugin_context.ts @@ -19,6 +19,8 @@ import { map, shareReplay } from 'rxjs/operators'; import { combineLatest } from 'rxjs'; +import { pick, deepFreeze } from '@kbn/std'; + import { CoreContext } from '../core_context'; import { PluginWrapper } from './plugin'; import { PluginsServiceSetupDeps, PluginsServiceStartDeps } from './plugins_service'; @@ -34,7 +36,6 @@ import { ElasticsearchConfigType, config as elasticsearchConfig, } from '../elasticsearch/elasticsearch_config'; -import { pick, deepFreeze } from '../../utils'; import { CoreSetup, CoreStart } from '..'; export interface InstanceInfo { diff --git a/src/core/server/plugins/plugins_service.mock.ts b/src/core/server/plugins/plugins_service.mock.ts index a40566767ddae..14d6de889dd42 100644 --- a/src/core/server/plugins/plugins_service.mock.ts +++ b/src/core/server/plugins/plugins_service.mock.ts @@ -16,7 +16,7 @@ * specific language governing permissions and limitations * under the License. */ - +import type { PublicMethodsOf } from '@kbn/utility-types'; import { PluginsService, PluginsServiceSetup } from './plugins_service'; type PluginsServiceMock = jest.Mocked>; diff --git a/src/core/server/plugins/plugins_service.ts b/src/core/server/plugins/plugins_service.ts index 30cd47c9d44e1..e8fe42ee491ca 100644 --- a/src/core/server/plugins/plugins_service.ts +++ b/src/core/server/plugins/plugins_service.ts @@ -20,9 +20,10 @@ import Path from 'path'; import { Observable } from 'rxjs'; import { filter, first, map, mergeMap, tap, toArray } from 'rxjs/operators'; +import { pick } from '@kbn/std'; + import { CoreService } from '../../types'; import { CoreContext } from '../core_context'; - import { Logger } from '../logging'; import { discover, PluginDiscoveryError, PluginDiscoveryErrorType } from './discovery'; import { PluginWrapper } from './plugin'; @@ -31,7 +32,6 @@ import { PluginsConfig, PluginsConfigType } from './plugins_config'; import { PluginsSystem } from './plugins_system'; import { InternalCoreSetup, InternalCoreStart } from '../internal_types'; import { IConfigService } from '../config'; -import { pick } from '../../utils'; import { InternalEnvironmentServiceSetup } from '../environment'; /** @internal */ diff --git a/src/core/server/plugins/plugins_system.ts b/src/core/server/plugins/plugins_system.ts index b2acd9a6fd04b..72d2cfe158b37 100644 --- a/src/core/server/plugins/plugins_system.ts +++ b/src/core/server/plugins/plugins_system.ts @@ -17,13 +17,13 @@ * under the License. */ +import { withTimeout } from '@kbn/std'; import { CoreContext } from '../core_context'; import { Logger } from '../logging'; import { PluginWrapper } from './plugin'; import { DiscoveredPlugin, PluginName } from './types'; import { createPluginSetupContext, createPluginStartContext } from './plugin_context'; import { PluginsServiceSetupDeps, PluginsServiceStartDeps } from './plugins_service'; -import { withTimeout } from '../../utils'; import { PluginDependencies } from '.'; const Sec = 1000; diff --git a/src/core/server/rendering/__mocks__/rendering_service.ts b/src/core/server/rendering/__mocks__/rendering_service.ts index 2e35568873c9a..179a09b8619b0 100644 --- a/src/core/server/rendering/__mocks__/rendering_service.ts +++ b/src/core/server/rendering/__mocks__/rendering_service.ts @@ -16,7 +16,7 @@ * specific language governing permissions and limitations * under the License. */ - +import type { PublicMethodsOf } from '@kbn/utility-types'; import { RenderingService as Service } from '../rendering_service'; import { InternalRenderingServiceSetup } from '../types'; import { mockRenderingServiceParams } from './params'; diff --git a/src/core/server/saved_objects/es_query.js b/src/core/server/saved_objects/es_query.js new file mode 100644 index 0000000000000..68d582e3cae09 --- /dev/null +++ b/src/core/server/saved_objects/es_query.js @@ -0,0 +1,21 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +// a temporary file to remove circular deps in TS code between platform & data plugin +// eslint-disable-next-line @kbn/eslint/no-restricted-paths +export { esKuery } from '../../../plugins/data/server'; diff --git a/src/core/server/saved_objects/migrations/kibana/kibana_migrator.mock.ts b/src/core/server/saved_objects/migrations/kibana/kibana_migrator.mock.ts index fae33bc050dee..23d8c4518d3ab 100644 --- a/src/core/server/saved_objects/migrations/kibana/kibana_migrator.mock.ts +++ b/src/core/server/saved_objects/migrations/kibana/kibana_migrator.mock.ts @@ -16,6 +16,7 @@ * specific language governing permissions and limitations * under the License. */ +import type { PublicMethodsOf } from '@kbn/utility-types'; import { KibanaMigrator, KibanaMigratorStatus } from './kibana_migrator'; import { buildActiveMappings } from '../core'; diff --git a/src/core/server/saved_objects/saved_objects_service.mock.ts b/src/core/server/saved_objects/saved_objects_service.mock.ts index e3d44c20dd190..bd76658c21731 100644 --- a/src/core/server/saved_objects/saved_objects_service.mock.ts +++ b/src/core/server/saved_objects/saved_objects_service.mock.ts @@ -18,6 +18,7 @@ */ import { BehaviorSubject } from 'rxjs'; +import type { PublicMethodsOf } from '@kbn/utility-types'; import { SavedObjectsService, diff --git a/src/core/server/saved_objects/saved_objects_type_registry.ts b/src/core/server/saved_objects/saved_objects_type_registry.ts index d0035294226ea..bb840e459bf22 100644 --- a/src/core/server/saved_objects/saved_objects_type_registry.ts +++ b/src/core/server/saved_objects/saved_objects_type_registry.ts @@ -17,7 +17,7 @@ * under the License. */ -import { deepFreeze } from '../../utils'; +import { deepFreeze } from '@kbn/std'; import { SavedObjectsType } from './types'; /** diff --git a/src/core/server/saved_objects/service/lib/filter_utils.test.ts b/src/core/server/saved_objects/service/lib/filter_utils.test.ts index 60e8aa0afdda4..0608035ce51a2 100644 --- a/src/core/server/saved_objects/service/lib/filter_utils.test.ts +++ b/src/core/server/saved_objects/service/lib/filter_utils.test.ts @@ -16,8 +16,8 @@ * specific language governing permissions and limitations * under the License. */ -// eslint-disable-next-line @kbn/eslint/no-restricted-paths -import { esKuery } from '../../../../../plugins/data/server'; +// @ts-expect-error no ts +import { esKuery } from '../../es_query'; import { validateFilterKueryNode, validateConvertFilterToKueryNode } from './filter_utils'; diff --git a/src/core/server/saved_objects/service/lib/filter_utils.ts b/src/core/server/saved_objects/service/lib/filter_utils.ts index d19f06d74e419..be36807f0d02b 100644 --- a/src/core/server/saved_objects/service/lib/filter_utils.ts +++ b/src/core/server/saved_objects/service/lib/filter_utils.ts @@ -21,8 +21,9 @@ import { set } from '@elastic/safer-lodash-set'; import { get } from 'lodash'; import { SavedObjectsErrorHelpers } from './errors'; import { IndexMapping } from '../../mappings'; -// eslint-disable-next-line @kbn/eslint/no-restricted-paths -import { esKuery, KueryNode } from '../../../../../plugins/data/server'; +// @ts-expect-error no ts +import { esKuery } from '../../es_query'; +type KueryNode = any; const astFunctionType = ['is', 'range', 'nested']; diff --git a/src/core/server/saved_objects/service/lib/repository.test.js b/src/core/server/saved_objects/service/lib/repository.test.js index 7d30875b90796..352ce4c1c16eb 100644 --- a/src/core/server/saved_objects/service/lib/repository.test.js +++ b/src/core/server/saved_objects/service/lib/repository.test.js @@ -25,8 +25,8 @@ import { encodeHitVersion } from '../../version'; import { SavedObjectTypeRegistry } from '../../saved_objects_type_registry'; import { DocumentMigrator } from '../../migrations/core/document_migrator'; import { elasticsearchClientMock } from '../../../elasticsearch/client/mocks'; -// eslint-disable-next-line @kbn/eslint/no-restricted-paths -import { nodeTypes } from '../../../../../plugins/data/common/es_query'; +import { esKuery } from '../../es_query'; +const { nodeTypes } = esKuery; jest.mock('./search_dsl/search_dsl', () => ({ getSearchDsl: jest.fn() })); diff --git a/src/core/server/saved_objects/service/lib/search_dsl/query_params.test.ts b/src/core/server/saved_objects/service/lib/search_dsl/query_params.test.ts index 85c47029e36d5..4adc92df31805 100644 --- a/src/core/server/saved_objects/service/lib/search_dsl/query_params.test.ts +++ b/src/core/server/saved_objects/service/lib/search_dsl/query_params.test.ts @@ -17,8 +17,9 @@ * under the License. */ -// eslint-disable-next-line @kbn/eslint/no-restricted-paths -import { esKuery, KueryNode } from '../../../../../../plugins/data/server'; +// @ts-expect-error no ts +import { esKuery } from '../../../es_query'; +type KueryNode = any; import { typeRegistryMock } from '../../../saved_objects_type_registry.mock'; import { getQueryParams } from './query_params'; diff --git a/src/core/server/saved_objects/service/lib/search_dsl/query_params.ts b/src/core/server/saved_objects/service/lib/search_dsl/query_params.ts index 3ff72a86c2f89..642d51c70766e 100644 --- a/src/core/server/saved_objects/service/lib/search_dsl/query_params.ts +++ b/src/core/server/saved_objects/service/lib/search_dsl/query_params.ts @@ -16,8 +16,9 @@ * specific language governing permissions and limitations * under the License. */ -// eslint-disable-next-line @kbn/eslint/no-restricted-paths -import { esKuery, KueryNode } from '../../../../../../plugins/data/server'; +// @ts-expect-error no ts +import { esKuery } from '../../../es_query'; +type KueryNode = any; import { getRootPropertiesObjects, IndexMapping } from '../../../mappings'; import { ISavedObjectTypeRegistry } from '../../../saved_objects_type_registry'; diff --git a/src/core/server/saved_objects/service/lib/search_dsl/search_dsl.ts b/src/core/server/saved_objects/service/lib/search_dsl/search_dsl.ts index ddf20606800c8..aa79a10b2a9be 100644 --- a/src/core/server/saved_objects/service/lib/search_dsl/search_dsl.ts +++ b/src/core/server/saved_objects/service/lib/search_dsl/search_dsl.ts @@ -22,10 +22,10 @@ import Boom from 'boom'; import { IndexMapping } from '../../../mappings'; import { getQueryParams } from './query_params'; import { getSortingParams } from './sorting_params'; -// eslint-disable-next-line @kbn/eslint/no-restricted-paths -import { KueryNode } from '../../../../../../plugins/data/server'; import { ISavedObjectTypeRegistry } from '../../../saved_objects_type_registry'; +type KueryNode = any; + interface GetSearchDslOptions { type: string | string[]; search?: string; diff --git a/src/core/server/saved_objects/types.ts b/src/core/server/saved_objects/types.ts index 50c118ca64ffb..1885f5ec50139 100644 --- a/src/core/server/saved_objects/types.ts +++ b/src/core/server/saved_objects/types.ts @@ -35,8 +35,7 @@ export { import { SavedObject } from '../../types'; -// eslint-disable-next-line @kbn/eslint/no-restricted-paths -import { KueryNode } from '../../../plugins/data/common'; +type KueryNode = any; export { SavedObjectAttributes, diff --git a/src/core/server/server.api.md b/src/core/server/server.api.md index ec457704e89c7..97276a1425d53 100644 --- a/src/core/server/server.api.md +++ b/src/core/server/server.api.md @@ -40,7 +40,6 @@ import { DeleteScriptParams } from 'elasticsearch'; import { DeleteTemplateParams } from 'elasticsearch'; import { DetailedPeerCertificate } from 'tls'; import { Duration } from 'moment'; -import { ErrorToastOptions } from 'src/core/public/notifications'; import { ExistsParams } from 'elasticsearch'; import { ExplainParams } from 'elasticsearch'; import { FieldStatsParams } from 'elasticsearch'; @@ -106,7 +105,6 @@ import { NodesInfoParams } from 'elasticsearch'; import { NodesStatsParams } from 'elasticsearch'; import { ObjectType } from '@kbn/config-schema'; import { Observable } from 'rxjs'; -import { ParsedQuery } from 'query-string'; import { PeerCertificate } from 'tls'; import { PingParams } from 'elasticsearch'; import { PutScriptParams } from 'elasticsearch'; @@ -119,7 +117,6 @@ import { RenderSearchTemplateParams } from 'elasticsearch'; import { Request } from 'hapi'; import { ResponseObject } from 'hapi'; import { ResponseToolkit } from 'hapi'; -import { SavedObject as SavedObject_2 } from 'src/core/server'; import { SchemaTypeError } from '@kbn/config-schema'; import { ScrollParams } from 'elasticsearch'; import { SearchParams } from 'elasticsearch'; @@ -143,7 +140,6 @@ import { TasksCancelParams } from 'elasticsearch'; import { TasksGetParams } from 'elasticsearch'; import { TasksListParams } from 'elasticsearch'; import { TermvectorsParams } from 'elasticsearch'; -import { ToastInputFields } from 'src/core/public/notifications'; import { TransportRequestOptions } from '@elastic/elasticsearch/lib/Transport'; import { TransportRequestParams } from '@elastic/elasticsearch/lib/Transport'; import { TransportRequestPromise } from '@elastic/elasticsearch/lib/Transport'; @@ -160,9 +156,6 @@ import { Url } from 'url'; // @public (undocumented) export type AppenderConfigType = ConsoleAppenderConfig | FileAppenderConfig | LegacyAppenderConfig; -// @public -export function assertNever(x: never): never; - // @public @deprecated (undocumented) export interface AssistanceAPIResponse { // (undocumented) @@ -504,9 +497,6 @@ export interface CustomHttpResponseOptions(object: T): RecursiveReadonly; - // @internal (undocumented) export const DEFAULT_APP_CATEGORIES: Readonly<{ kibana: { @@ -716,11 +706,6 @@ export interface FakeRequest { headers: Headers; } -// @public (undocumented) -export type Freezable = { - [k: string]: any; -} | any[]; - // @public export type GetAuthHeaders = (request: KibanaRequest | LegacyRequest) => AuthHeaders | undefined; @@ -730,11 +715,6 @@ export type GetAuthState = (request: KibanaRequest | LegacyRequest) state: T; }; -// @public -export function getFlattenedObject(rootValue: Record): { - [key: string]: any; -}; - // @public (undocumented) export interface GetResponse { // (undocumented) @@ -966,9 +946,6 @@ export interface IScopedClusterClient { readonly asInternalUser: ElasticsearchClient; } -// @public -export function isRelativeUrl(candidatePath: string): boolean; - // @public export interface IUiSettingsClient { get: (key: string) => Promise; @@ -1543,9 +1520,6 @@ export type MIGRATION_ASSISTANCE_INDEX_ACTION = 'upgrade' | 'reindex'; // @public @deprecated (undocumented) export type MIGRATION_DEPRECATION_LEVEL = 'none' | 'info' | 'warning' | 'critical'; -// @public -export function modifyUrl(url: string, urlModifier: (urlParts: URLMeaningfulParts) => Partial | void): string; - // @public export type MutatingOperationRefreshSetting = boolean | 'wait_for'; @@ -2848,26 +2822,6 @@ export interface UiSettingsServiceStart { // @public export type UiSettingsType = 'undefined' | 'json' | 'markdown' | 'number' | 'select' | 'boolean' | 'string' | 'array' | 'image'; -// @public -export interface URLMeaningfulParts { - // (undocumented) - auth?: string | null; - // (undocumented) - hash?: string | null; - // (undocumented) - hostname?: string | null; - // (undocumented) - pathname?: string | null; - // (undocumented) - port?: string | null; - // (undocumented) - protocol?: string | null; - // (undocumented) - query: ParsedQuery; - // (undocumented) - slashes?: boolean | null; -} - // @public export interface UserProvidedValues { // (undocumented) diff --git a/src/core/server/server.ts b/src/core/server/server.ts index a02b0f51b559f..8015b184f6130 100644 --- a/src/core/server/server.ts +++ b/src/core/server/server.ts @@ -17,6 +17,7 @@ * under the License. */ +import { mapToObject } from '@kbn/std'; import { ConfigService, Env, RawConfigurationProvider, coreDeprecationProvider } from './config'; import { CoreApp } from './core_app'; import { AuditTrailService } from './audit_trail'; @@ -31,7 +32,7 @@ import { PluginsService, config as pluginsConfig } from './plugins'; import { SavedObjectsService } from '../server/saved_objects'; import { MetricsService, opsConfig } from './metrics'; import { CapabilitiesService } from './capabilities'; -import { EnvironmentService } from './environment'; +import { EnvironmentService, config as pidConfig } from './environment'; import { StatusService } from './status/status_service'; import { config as cspConfig } from './csp'; @@ -44,7 +45,6 @@ import { config as kibanaConfig } from './kibana_config'; import { savedObjectsConfig, savedObjectsMigrationConfig } from './saved_objects'; import { config as uiSettingsConfig } from './ui_settings'; import { config as statusConfig } from './status'; -import { mapToObject } from '../utils'; import { ContextService } from './context'; import { RequestHandlerContext } from '.'; import { InternalCoreSetup, InternalCoreStart, ServiceConfigDescriptor } from './internal_types'; @@ -310,6 +310,7 @@ export class Server { uiSettingsConfig, opsConfig, statusConfig, + pidConfig, ]; this.configService.addDeprecationProvider(rootConfigPath, coreDeprecationProvider); diff --git a/src/core/server/status/status_service.mock.ts b/src/core/server/status/status_service.mock.ts index 42b3eecdca310..930ee2970cf55 100644 --- a/src/core/server/status/status_service.mock.ts +++ b/src/core/server/status/status_service.mock.ts @@ -16,7 +16,7 @@ * specific language governing permissions and limitations * under the License. */ - +import type { PublicMethodsOf } from '@kbn/utility-types'; import { StatusService } from './status_service'; import { InternalStatusServiceSetup, diff --git a/src/core/server/status/types.ts b/src/core/server/status/types.ts index f884b80316fa8..9fa33a8c6d40c 100644 --- a/src/core/server/status/types.ts +++ b/src/core/server/status/types.ts @@ -18,7 +18,7 @@ */ import { Observable } from 'rxjs'; -import { deepFreeze } from '../../utils'; +import { deepFreeze } from '@kbn/std'; import { PluginName } from '../plugins'; /** diff --git a/src/core/server/ui_settings/settings/navigation.ts b/src/core/server/ui_settings/settings/navigation.ts index 6483e86a1395a..ec825a2779f38 100644 --- a/src/core/server/ui_settings/settings/navigation.ts +++ b/src/core/server/ui_settings/settings/navigation.ts @@ -19,8 +19,8 @@ import { schema } from '@kbn/config-schema'; import { i18n } from '@kbn/i18n'; +import { isRelativeUrl } from '@kbn/std'; import { UiSettingsParams } from '../../../types'; -import { isRelativeUrl } from '../../../utils'; export const getNavigationSettings = (): Record => { return { diff --git a/src/core/server/ui_settings/ui_settings_service.mock.ts b/src/core/server/ui_settings/ui_settings_service.mock.ts index 83cea6d7ab3e2..b1ed0dd188cde 100644 --- a/src/core/server/ui_settings/ui_settings_service.mock.ts +++ b/src/core/server/ui_settings/ui_settings_service.mock.ts @@ -16,7 +16,7 @@ * specific language governing permissions and limitations * under the License. */ - +import type { PublicMethodsOf } from '@kbn/utility-types'; import { IUiSettingsClient, InternalUiSettingsServiceSetup, diff --git a/src/core/server/ui_settings/ui_settings_service.ts b/src/core/server/ui_settings/ui_settings_service.ts index 8598cf7a62287..25062490f5b6b 100644 --- a/src/core/server/ui_settings/ui_settings_service.ts +++ b/src/core/server/ui_settings/ui_settings_service.ts @@ -19,10 +19,11 @@ import { Observable } from 'rxjs'; import { first } from 'rxjs/operators'; +import { mapToObject } from '@kbn/std'; + import { CoreService } from '../../types'; import { CoreContext } from '../core_context'; import { Logger } from '../logging'; - import { SavedObjectsClientContract } from '../saved_objects/types'; import { InternalSavedObjectsServiceSetup } from '../saved_objects'; import { InternalHttpServiceSetup } from '../http'; @@ -33,7 +34,6 @@ import { InternalUiSettingsServiceStart, UiSettingsParams, } from './types'; -import { mapToObject } from '../../utils/'; import { uiSettingsType } from './saved_objects'; import { registerRoutes } from './routes'; import { getCoreSettings } from './settings'; diff --git a/src/core/tsconfig.json b/src/core/tsconfig.json new file mode 100644 index 0000000000000..b8780321e11dd --- /dev/null +++ b/src/core/tsconfig.json @@ -0,0 +1,22 @@ +{ + "extends": "../../tsconfig.base.json", + "compilerOptions": { + "composite": true, + "outDir": "./target", + "emitDeclarationOnly": true, + "declaration": true, + "declarationMap": true + }, + "include": [ + "public/**/*", + "server/**/*", + "types/**/*", + "test_helpers/**/*", + "utils/**/*", + "index.ts", + "typings.ts" + ], + "references": [ + { "path": "../test_utils/" } + ] +} diff --git a/src/core/typings.ts b/src/core/typings.ts new file mode 100644 index 0000000000000..a84e1c01d2bd2 --- /dev/null +++ b/src/core/typings.ts @@ -0,0 +1,55 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +declare module 'query-string' { + type ArrayFormat = 'bracket' | 'index' | 'none'; + + export interface ParseOptions { + arrayFormat?: ArrayFormat; + sort: ((itemLeft: string, itemRight: string) => number) | false; + } + + export interface ParsedQuery { + [key: string]: T | T[] | null | undefined; + } + + export function parse(str: string, options?: ParseOptions): ParsedQuery; + + export function parseUrl(str: string, options?: ParseOptions): { url: string; query: any }; + + export interface StringifyOptions { + strict?: boolean; + encode?: boolean; + arrayFormat?: ArrayFormat; + sort: ((itemLeft: string, itemRight: string) => number) | false; + } + + export function stringify(obj: object, options?: StringifyOptions): string; + + export function extract(str: string): string; +} + +type DeeplyMockedKeys = { + [P in keyof T]: T[P] extends (...args: any[]) => any + ? jest.MockInstance, Parameters> + : DeeplyMockedKeys; +} & + T; + +type MockedKeys = { [P in keyof T]: jest.Mocked }; diff --git a/src/core/utils/context.ts b/src/core/utils/context.ts index 941bbceb0cd92..f28d3330b8e36 100644 --- a/src/core/utils/context.ts +++ b/src/core/utils/context.ts @@ -19,8 +19,8 @@ import { flatten } from 'lodash'; import { ShallowPromise } from '@kbn/utility-types'; -import { pick } from '.'; -import { CoreId, PluginOpaqueId } from '../server'; +import { pick } from '@kbn/std'; +import type { CoreId, PluginOpaqueId } from '../server'; /** * Make all properties in T optional, except for the properties whose keys are in the union K diff --git a/src/core/utils/index.ts b/src/core/utils/index.ts index a6df0992f6cc6..c620e4e5ee155 100644 --- a/src/core/utils/index.ts +++ b/src/core/utils/index.ts @@ -17,15 +17,12 @@ * under the License. */ -export * from './assert_never'; -export * from './context'; -export * from './deep_freeze'; -export * from './get'; -export * from './map_to_object'; -export * from './merge'; -export * from './pick'; -export * from './promise'; -export * from './url'; -export * from './unset'; -export * from './get_flattened_object'; -export * from './default_app_categories'; +export { + ContextContainer, + HandlerContextType, + HandlerFunction, + HandlerParameters, + IContextContainer, + IContextProvider, +} from './context'; +export { DEFAULT_APP_CATEGORIES } from './default_app_categories'; diff --git a/src/dev/typescript/projects.ts b/src/dev/typescript/projects.ts index e18c82b5b9e96..6fa07190dc43e 100644 --- a/src/dev/typescript/projects.ts +++ b/src/dev/typescript/projects.ts @@ -25,6 +25,7 @@ import { Project } from './project'; export const PROJECTS = [ new Project(resolve(REPO_ROOT, 'tsconfig.json')), new Project(resolve(REPO_ROOT, 'src/test_utils/tsconfig.json')), + new Project(resolve(REPO_ROOT, 'src/core/tsconfig.json')), new Project(resolve(REPO_ROOT, 'test/tsconfig.json'), { name: 'kibana/test' }), new Project(resolve(REPO_ROOT, 'x-pack/tsconfig.json')), new Project(resolve(REPO_ROOT, 'x-pack/test/tsconfig.json'), { name: 'x-pack/test' }), diff --git a/src/dev/typescript/run_type_check_cli.ts b/src/dev/typescript/run_type_check_cli.ts index e1fca23274a5a..00968b7259a30 100644 --- a/src/dev/typescript/run_type_check_cli.ts +++ b/src/dev/typescript/run_type_check_cli.ts @@ -98,7 +98,7 @@ export async function runTypeCheckCli() { } execInProjects(log, projects, process.execPath, (project) => [ - '--max-old-space-size=4096', + '--max-old-space-size=5120', require.resolve('typescript/bin/tsc'), ...['--project', project.tsConfigPath], ...tscArgs, diff --git a/src/legacy/server/config/schema.js b/src/legacy/server/config/schema.js index ce7a500a00dc8..f8736fb30f90e 100644 --- a/src/legacy/server/config/schema.js +++ b/src/legacy/server/config/schema.js @@ -42,10 +42,7 @@ export default () => basePathProxyTarget: Joi.number().default(5603), }).default(), - pid: Joi.object({ - file: Joi.string(), - exclusive: Joi.boolean().default(false), - }).default(), + pid: HANDLED_IN_NEW_PLATFORM, csp: HANDLED_IN_NEW_PLATFORM, diff --git a/src/legacy/server/i18n/index.ts b/src/legacy/server/i18n/index.ts index e895f83fe6901..cb86c3220bec1 100644 --- a/src/legacy/server/i18n/index.ts +++ b/src/legacy/server/i18n/index.ts @@ -21,6 +21,7 @@ import { i18n, i18nLoader } from '@kbn/i18n'; import { basename } from 'path'; import { Server } from 'hapi'; import { fromRoot } from '../../../core/server/utils'; +import type { UsageCollectionSetup } from '../../../plugins/usage_collection/server'; import { getTranslationPaths } from './get_translations_path'; import { I18N_RC } from './constants'; import KbnServer, { KibanaConfig } from '../kbn_server'; @@ -64,7 +65,10 @@ export async function i18nMixin(kbnServer: KbnServer, server: Server, config: Ki server.decorate('server', 'getTranslationsFilePaths', getTranslationsFilePaths); if (kbnServer.newPlatform.setup.plugins.usageCollection) { - registerLocalizationUsageCollector(kbnServer.newPlatform.setup.plugins.usageCollection, { + const { usageCollection } = kbnServer.newPlatform.setup.plugins as { + usageCollection: UsageCollectionSetup; + }; + registerLocalizationUsageCollector(usageCollection, { getLocale: () => config.get('i18n.locale') as string, getTranslationsFilePaths, }); diff --git a/src/legacy/server/kbn_server.d.ts b/src/legacy/server/kbn_server.d.ts index 663542618375a..8827dc53c5275 100644 --- a/src/legacy/server/kbn_server.d.ts +++ b/src/legacy/server/kbn_server.d.ts @@ -19,7 +19,6 @@ import { Server } from 'hapi'; -import { TelemetryCollectionManagerPluginSetup } from 'src/plugins/telemetry_collection_manager/server'; import { CoreSetup, CoreStart, @@ -35,8 +34,6 @@ import { LegacyConfig, ILegacyInternals } from '../../core/server/legacy'; // eslint-disable-next-line @kbn/eslint/no-restricted-paths import { UiPlugins } from '../../core/server/plugins'; import { ElasticsearchPlugin } from '../core_plugins/elasticsearch'; -import { UsageCollectionSetup } from '../../plugins/usage_collection/server'; -import { HomeServerPluginSetup } from '../../plugins/home/server'; // lot of legacy code was assuming this type only had these two methods export type KibanaConfig = Pick; @@ -60,9 +57,6 @@ declare module 'hapi' { type KbnMixinFunc = (kbnServer: KbnServer, server: Server, config: any) => Promise | void; export interface PluginsSetup { - usageCollection: UsageCollectionSetup; - telemetryCollectionManager: TelemetryCollectionManagerPluginSetup; - home: HomeServerPluginSetup; [key: string]: object; } diff --git a/src/legacy/server/kbn_server.js b/src/legacy/server/kbn_server.js index a5eefd140c8fa..24d00abb99a05 100644 --- a/src/legacy/server/kbn_server.js +++ b/src/legacy/server/kbn_server.js @@ -29,7 +29,6 @@ import { coreMixin } from './core'; import { loggingMixin } from './logging'; import warningsMixin from './warnings'; import { statusMixin } from './status'; -import pidMixin from './pid'; import configCompleteMixin from './config/complete'; import { optimizeMixin } from '../../optimize'; import * as Plugins from './plugins'; @@ -93,9 +92,6 @@ export default class KbnServer { warningsMixin, statusMixin, - // writes pid file - pidMixin, - // scan translations dirs, register locale files and initialize i18n engine. i18nMixin, diff --git a/src/legacy/server/pid/index.js b/src/legacy/server/pid/index.js deleted file mode 100644 index d7b9da1292252..0000000000000 --- a/src/legacy/server/pid/index.js +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import _ from 'lodash'; -import Boom from 'boom'; -import Bluebird from 'bluebird'; -import { unlinkSync as unlink } from 'fs'; -const writeFile = Bluebird.promisify(require('fs').writeFile); - -export default Bluebird.method(function (kbnServer, server, config) { - const path = config.get('pid.file'); - if (!path) return; - - const pid = String(process.pid); - - return writeFile(path, pid, { flag: 'wx' }) - .catch(function (err) { - if (err.code !== 'EEXIST') throw err; - - const message = `pid file already exists at ${path}`; - const metadata = { - path: path, - pid: pid, - }; - - if (config.get('pid.exclusive')) { - throw Boom.internal(message, { message, ...metadata }); - } else { - server.log(['pid', 'warning'], message, metadata); - } - - return writeFile(path, pid); - }) - .then(function () { - server.logWithMetadata(['pid', 'debug'], `wrote pid file to ${path}`, { - path: path, - pid: pid, - }); - - const clean = _.once(function () { - unlink(path); - }); - - process.once('exit', clean); // for "natural" exits - process.once('SIGINT', function () { - // for Ctrl-C exits - clean(); - - // resend SIGINT - process.kill(process.pid, 'SIGINT'); - }); - - process.on('unhandledRejection', function (reason) { - server.log(['warning'], `Detected an unhandled Promise rejection.\n${reason}`); - }); - }); -}); diff --git a/src/plugins/apm_oss/server/tutorial/index_pattern.json b/src/plugins/apm_oss/server/tutorial/index_pattern.json index 1d061f9e11e61..bb42b223c85ed 100644 --- a/src/plugins/apm_oss/server/tutorial/index_pattern.json +++ b/src/plugins/apm_oss/server/tutorial/index_pattern.json @@ -1,11 +1,11 @@ { "attributes": { - "fieldFormatMap": "{\"client.bytes\":{\"id\":\"bytes\"},\"client.nat.port\":{\"id\":\"string\"},\"client.port\":{\"id\":\"string\"},\"destination.bytes\":{\"id\":\"bytes\"},\"destination.nat.port\":{\"id\":\"string\"},\"destination.port\":{\"id\":\"string\"},\"event.duration\":{\"id\":\"duration\",\"params\":{\"inputFormat\":\"nanoseconds\",\"outputFormat\":\"asMilliseconds\",\"outputPrecision\":1}},\"event.sequence\":{\"id\":\"string\"},\"event.severity\":{\"id\":\"string\"},\"http.request.body.bytes\":{\"id\":\"bytes\"},\"http.request.bytes\":{\"id\":\"bytes\"},\"http.response.body.bytes\":{\"id\":\"bytes\"},\"http.response.bytes\":{\"id\":\"bytes\"},\"http.response.status_code\":{\"id\":\"string\"},\"log.syslog.facility.code\":{\"id\":\"string\"},\"log.syslog.priority\":{\"id\":\"string\"},\"network.bytes\":{\"id\":\"bytes\"},\"package.size\":{\"id\":\"string\"},\"process.parent.pgid\":{\"id\":\"string\"},\"process.parent.pid\":{\"id\":\"string\"},\"process.parent.ppid\":{\"id\":\"string\"},\"process.parent.thread.id\":{\"id\":\"string\"},\"process.pgid\":{\"id\":\"string\"},\"process.pid\":{\"id\":\"string\"},\"process.ppid\":{\"id\":\"string\"},\"process.thread.id\":{\"id\":\"string\"},\"server.bytes\":{\"id\":\"bytes\"},\"server.nat.port\":{\"id\":\"string\"},\"server.port\":{\"id\":\"string\"},\"source.bytes\":{\"id\":\"bytes\"},\"source.nat.port\":{\"id\":\"string\"},\"source.port\":{\"id\":\"string\"},\"system.cpu.total.norm.pct\":{\"id\":\"percent\"},\"system.memory.actual.free\":{\"id\":\"bytes\"},\"system.memory.total\":{\"id\":\"bytes\"},\"system.process.cpu.total.norm.pct\":{\"id\":\"percent\"},\"system.process.memory.rss.bytes\":{\"id\":\"bytes\"},\"system.process.memory.size\":{\"id\":\"bytes\"},\"url.port\":{\"id\":\"string\"},\"view spans\":{\"id\":\"url\",\"params\":{\"labelTemplate\":\"View Spans\"}}}", - "fields": "[{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"@timestamp\",\"scripted\":false,\"searchable\":true,\"type\":\"date\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"labels\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"message\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tags\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"agent.ephemeral_id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"agent.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"agent.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"agent.type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"agent.version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"as.number\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"as.organization.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"as.organization.name.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.address\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.as.number\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.as.organization.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.as.organization.name.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.bytes\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.geo.city_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.geo.continent_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.geo.country_iso_code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.geo.country_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.geo.location\",\"scripted\":false,\"searchable\":true,\"type\":\"geo_point\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.geo.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.geo.region_iso_code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.geo.region_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.ip\",\"scripted\":false,\"searchable\":true,\"type\":\"ip\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.mac\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.nat.ip\",\"scripted\":false,\"searchable\":true,\"type\":\"ip\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.nat.port\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.packets\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.port\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.registered_domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.top_level_domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.user.domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.user.email\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.user.full_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.user.full_name.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.user.group.domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.user.group.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.user.group.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.user.hash\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.user.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.user.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.user.name.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"cloud.account.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"cloud.availability_zone\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"cloud.instance.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"cloud.instance.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"cloud.machine.type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"cloud.provider\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"cloud.region\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"code_signature.exists\",\"scripted\":false,\"searchable\":true,\"type\":\"boolean\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"code_signature.status\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"code_signature.subject_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"code_signature.trusted\",\"scripted\":false,\"searchable\":true,\"type\":\"boolean\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"code_signature.valid\",\"scripted\":false,\"searchable\":true,\"type\":\"boolean\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"container.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"container.image.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"container.image.tag\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"container.labels\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"container.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"container.runtime\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.address\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.as.number\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.as.organization.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.as.organization.name.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.bytes\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.geo.city_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.geo.continent_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.geo.country_iso_code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.geo.country_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.geo.location\",\"scripted\":false,\"searchable\":true,\"type\":\"geo_point\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.geo.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.geo.region_iso_code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.geo.region_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.ip\",\"scripted\":false,\"searchable\":true,\"type\":\"ip\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.mac\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.nat.ip\",\"scripted\":false,\"searchable\":true,\"type\":\"ip\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.nat.port\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.packets\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.port\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.registered_domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.top_level_domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.user.domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.user.email\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.user.full_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.user.full_name.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.user.group.domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.user.group.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.user.group.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.user.hash\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.user.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.user.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.user.name.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dll.code_signature.exists\",\"scripted\":false,\"searchable\":true,\"type\":\"boolean\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dll.code_signature.status\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dll.code_signature.subject_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dll.code_signature.trusted\",\"scripted\":false,\"searchable\":true,\"type\":\"boolean\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dll.code_signature.valid\",\"scripted\":false,\"searchable\":true,\"type\":\"boolean\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dll.hash.md5\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dll.hash.sha1\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dll.hash.sha256\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dll.hash.sha512\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dll.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dll.path\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dll.pe.company\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dll.pe.description\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dll.pe.file_version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dll.pe.original_file_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dll.pe.product\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dns.answers\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dns.answers.class\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dns.answers.data\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dns.answers.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dns.answers.ttl\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dns.answers.type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dns.header_flags\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dns.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dns.op_code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dns.question.class\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dns.question.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dns.question.registered_domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dns.question.subdomain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dns.question.top_level_domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dns.question.type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dns.resolved_ip\",\"scripted\":false,\"searchable\":true,\"type\":\"ip\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dns.response_code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dns.type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"ecs.version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"error.code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":4,\"doc_values\":true,\"indexed\":true,\"name\":\"error.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"error.message\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"error.stack_trace\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"error.stack_trace.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"error.type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.action\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.category\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.created\",\"scripted\":false,\"searchable\":true,\"type\":\"date\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.dataset\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.duration\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.end\",\"scripted\":false,\"searchable\":true,\"type\":\"date\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.hash\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.ingested\",\"scripted\":false,\"searchable\":true,\"type\":\"date\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.kind\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.module\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.original\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.outcome\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.provider\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.reference\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.risk_score\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.risk_score_norm\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.sequence\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.severity\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.start\",\"scripted\":false,\"searchable\":true,\"type\":\"date\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.timezone\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.url\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.accessed\",\"scripted\":false,\"searchable\":true,\"type\":\"date\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.attributes\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.code_signature.exists\",\"scripted\":false,\"searchable\":true,\"type\":\"boolean\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.code_signature.status\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.code_signature.subject_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.code_signature.trusted\",\"scripted\":false,\"searchable\":true,\"type\":\"boolean\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.code_signature.valid\",\"scripted\":false,\"searchable\":true,\"type\":\"boolean\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.created\",\"scripted\":false,\"searchable\":true,\"type\":\"date\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.ctime\",\"scripted\":false,\"searchable\":true,\"type\":\"date\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.device\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.directory\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.drive_letter\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.extension\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.gid\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.group\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.hash.md5\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.hash.sha1\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.hash.sha256\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.hash.sha512\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.inode\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.mime_type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.mode\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.mtime\",\"scripted\":false,\"searchable\":true,\"type\":\"date\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.owner\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.path\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.path.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.pe.company\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.pe.description\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.pe.file_version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.pe.original_file_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.pe.product\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.size\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.target_path\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.target_path.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.uid\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"geo.city_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"geo.continent_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"geo.country_iso_code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"geo.country_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"geo.location\",\"scripted\":false,\"searchable\":true,\"type\":\"geo_point\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"geo.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"geo.region_iso_code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"geo.region_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"group.domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"group.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"group.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"hash.md5\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"hash.sha1\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"hash.sha256\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"hash.sha512\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.architecture\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.geo.city_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.geo.continent_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.geo.country_iso_code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.geo.country_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.geo.location\",\"scripted\":false,\"searchable\":true,\"type\":\"geo_point\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.geo.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.geo.region_iso_code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.geo.region_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.hostname\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.ip\",\"scripted\":false,\"searchable\":true,\"type\":\"ip\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.mac\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.os.family\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.os.full\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.os.full.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.os.kernel\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.os.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.os.name.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.os.platform\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.os.version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.uptime\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.user.domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.user.email\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.user.full_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.user.full_name.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.user.group.domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.user.group.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.user.group.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.user.hash\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.user.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.user.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.user.name.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"http.request.body.bytes\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"http.request.body.content\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"http.request.body.content.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"http.request.bytes\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"http.request.method\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"http.request.referrer\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"http.response.body.bytes\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"http.response.body.content\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"http.response.body.content.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"http.response.bytes\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"http.response.status_code\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"http.version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"interface.alias\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"interface.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"interface.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"log.level\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"log.logger\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"log.origin.file.line\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"log.origin.file.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"log.origin.function\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"log.original\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"log.syslog\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"log.syslog.facility.code\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"log.syslog.facility.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"log.syslog.priority\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"log.syslog.severity.code\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"log.syslog.severity.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"network.application\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"network.bytes\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"network.community_id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"network.direction\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"network.forwarded_ip\",\"scripted\":false,\"searchable\":true,\"type\":\"ip\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"network.iana_number\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"network.inner\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"network.inner.vlan.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"network.inner.vlan.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"network.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"network.packets\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"network.protocol\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"network.transport\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"network.type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"network.vlan.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"network.vlan.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.egress\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.egress.interface.alias\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.egress.interface.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.egress.interface.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.egress.vlan.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.egress.vlan.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.egress.zone\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.geo.city_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.geo.continent_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.geo.country_iso_code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.geo.country_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.geo.location\",\"scripted\":false,\"searchable\":true,\"type\":\"geo_point\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.geo.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.geo.region_iso_code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.geo.region_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.hostname\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.ingress\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.ingress.interface.alias\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.ingress.interface.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.ingress.interface.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.ingress.vlan.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.ingress.vlan.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.ingress.zone\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.ip\",\"scripted\":false,\"searchable\":true,\"type\":\"ip\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.mac\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.os.family\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.os.full\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.os.full.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.os.kernel\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.os.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.os.name.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.os.platform\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.os.version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.product\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.serial_number\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.vendor\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"organization.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"organization.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"organization.name.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"os.family\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"os.full\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"os.full.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"os.kernel\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"os.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"os.name.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"os.platform\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"os.version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"package.architecture\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"package.build_version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"package.checksum\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"package.description\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"package.install_scope\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"package.installed\",\"scripted\":false,\"searchable\":true,\"type\":\"date\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"package.license\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"package.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"package.path\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"package.reference\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"package.size\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"package.type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"package.version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"pe.company\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"pe.description\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"pe.file_version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"pe.original_file_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"pe.product\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.args\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.args_count\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.code_signature.exists\",\"scripted\":false,\"searchable\":true,\"type\":\"boolean\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.code_signature.status\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.code_signature.subject_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.code_signature.trusted\",\"scripted\":false,\"searchable\":true,\"type\":\"boolean\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.code_signature.valid\",\"scripted\":false,\"searchable\":true,\"type\":\"boolean\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.command_line\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.command_line.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.entity_id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.executable\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.executable.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.exit_code\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.hash.md5\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.hash.sha1\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.hash.sha256\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.hash.sha512\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.name.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.args\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.args_count\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.code_signature.exists\",\"scripted\":false,\"searchable\":true,\"type\":\"boolean\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.code_signature.status\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.code_signature.subject_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.code_signature.trusted\",\"scripted\":false,\"searchable\":true,\"type\":\"boolean\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.code_signature.valid\",\"scripted\":false,\"searchable\":true,\"type\":\"boolean\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.command_line\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.command_line.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.entity_id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.executable\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.executable.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.exit_code\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.hash.md5\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.hash.sha1\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.hash.sha256\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.hash.sha512\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.name.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.pgid\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.pid\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.ppid\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.start\",\"scripted\":false,\"searchable\":true,\"type\":\"date\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.thread.id\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.thread.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.title\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.title.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.uptime\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.working_directory\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.working_directory.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.pe.company\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.pe.description\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.pe.file_version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.pe.original_file_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.pe.product\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.pgid\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.pid\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.ppid\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.start\",\"scripted\":false,\"searchable\":true,\"type\":\"date\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.thread.id\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.thread.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.title\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.title.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.uptime\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.working_directory\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.working_directory.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"registry.data.bytes\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"registry.data.strings\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"registry.data.type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"registry.hive\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"registry.key\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"registry.path\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"registry.value\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"related.hash\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"related.ip\",\"scripted\":false,\"searchable\":true,\"type\":\"ip\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"related.user\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"rule.author\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"rule.category\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"rule.description\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"rule.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"rule.license\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"rule.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"rule.reference\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"rule.ruleset\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"rule.uuid\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"rule.version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.address\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.as.number\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.as.organization.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.as.organization.name.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.bytes\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.geo.city_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.geo.continent_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.geo.country_iso_code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.geo.country_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.geo.location\",\"scripted\":false,\"searchable\":true,\"type\":\"geo_point\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.geo.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.geo.region_iso_code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.geo.region_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.ip\",\"scripted\":false,\"searchable\":true,\"type\":\"ip\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.mac\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.nat.ip\",\"scripted\":false,\"searchable\":true,\"type\":\"ip\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.nat.port\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.packets\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.port\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.registered_domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.top_level_domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.user.domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.user.email\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.user.full_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.user.full_name.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.user.group.domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.user.group.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.user.group.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.user.hash\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.user.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.user.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.user.name.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"service.ephemeral_id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"service.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"service.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"service.node.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"service.state\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"service.type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"service.version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.address\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.as.number\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.as.organization.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.as.organization.name.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.bytes\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.geo.city_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.geo.continent_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.geo.country_iso_code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.geo.country_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.geo.location\",\"scripted\":false,\"searchable\":true,\"type\":\"geo_point\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.geo.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.geo.region_iso_code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.geo.region_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.ip\",\"scripted\":false,\"searchable\":true,\"type\":\"ip\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.mac\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.nat.ip\",\"scripted\":false,\"searchable\":true,\"type\":\"ip\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.nat.port\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.packets\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.port\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.registered_domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.top_level_domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.user.domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.user.email\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.user.full_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.user.full_name.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.user.group.domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.user.group.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.user.group.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.user.hash\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.user.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.user.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.user.name.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"threat.framework\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"threat.tactic.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"threat.tactic.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"threat.tactic.reference\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"threat.technique.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"threat.technique.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"threat.technique.name.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"threat.technique.reference\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.cipher\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.client.certificate\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.client.certificate_chain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.client.hash.md5\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.client.hash.sha1\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.client.hash.sha256\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.client.issuer\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.client.ja3\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.client.not_after\",\"scripted\":false,\"searchable\":true,\"type\":\"date\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.client.not_before\",\"scripted\":false,\"searchable\":true,\"type\":\"date\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.client.server_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.client.subject\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.client.supported_ciphers\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.curve\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.established\",\"scripted\":false,\"searchable\":true,\"type\":\"boolean\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.next_protocol\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.resumed\",\"scripted\":false,\"searchable\":true,\"type\":\"boolean\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.server.certificate\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.server.certificate_chain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.server.hash.md5\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.server.hash.sha1\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.server.hash.sha256\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.server.issuer\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.server.ja3s\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.server.not_after\",\"scripted\":false,\"searchable\":true,\"type\":\"date\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.server.not_before\",\"scripted\":false,\"searchable\":true,\"type\":\"date\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.server.subject\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.version_protocol\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tracing.trace.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tracing.transaction.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"url.domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"url.extension\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"url.fragment\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"url.full\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"url.full.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"url.original\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"url.original.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"url.password\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"url.path\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"url.port\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"url.query\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"url.registered_domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"url.scheme\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"url.top_level_domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"url.username\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user.domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user.email\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user.full_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user.full_name.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user.group.domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user.group.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user.group.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user.hash\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user.name.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user_agent.device.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user_agent.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user_agent.original\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user_agent.original.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user_agent.os.family\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user_agent.os.full\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user_agent.os.full.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user_agent.os.kernel\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user_agent.os.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user_agent.os.name.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user_agent.os.platform\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user_agent.os.version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user_agent.version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"vlan.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"vlan.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"vulnerability.category\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"vulnerability.classification\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"vulnerability.description\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"vulnerability.description.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"vulnerability.enumeration\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"vulnerability.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"vulnerability.reference\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"vulnerability.report_id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"vulnerability.scanner.vendor\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"vulnerability.score.base\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"vulnerability.score.environmental\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"vulnerability.score.temporal\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"vulnerability.score.version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"vulnerability.severity\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"agent.hostname\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"fields\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"timeseries.instance\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"cloud.project.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"cloud.image.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"docker.container.labels\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.containerized\",\"scripted\":false,\"searchable\":true,\"type\":\"boolean\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.os.build\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.os.codename\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"kubernetes.pod.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"kubernetes.pod.uid\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"kubernetes.namespace\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"kubernetes.node.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"kubernetes.labels.*\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"kubernetes.annotations.*\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"kubernetes.replicaset.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"kubernetes.deployment.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"kubernetes.statefulset.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"kubernetes.container.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"kubernetes.container.image\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"processor.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"processor.event\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":1,\"doc_values\":true,\"indexed\":true,\"name\":\"timestamp.us\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":false,\"enabled\":false,\"indexed\":false,\"name\":\"http.request.headers\",\"scripted\":false,\"searchable\":false},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"http.response.finished\",\"scripted\":false,\"searchable\":true,\"type\":\"boolean\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":false,\"enabled\":false,\"indexed\":false,\"name\":\"http.response.headers\",\"scripted\":false,\"searchable\":false},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"service.environment\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"service.language.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"service.language.version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"service.runtime.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"service.runtime.version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"service.framework.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"service.framework.version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.sampled\",\"scripted\":false,\"searchable\":true,\"type\":\"boolean\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.name.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.duration.count\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.duration.sum.us\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.self_time.count\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.self_time.sum.us\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.breakdown.count\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":1,\"doc_values\":true,\"indexed\":true,\"name\":\"span.type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":1,\"doc_values\":true,\"indexed\":true,\"name\":\"span.subtype\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"span.self_time.count\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"span.self_time.sum.us\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"trace.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"parent.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.listening\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.version_major\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"experimental\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"cloud.account.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"cloud.project.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":2,\"doc_values\":true,\"indexed\":true,\"name\":\"error.culprit\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"error.grouping_key\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"error.exception.code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":2,\"doc_values\":true,\"indexed\":true,\"name\":\"error.exception.message\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"error.exception.module\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":4,\"doc_values\":true,\"indexed\":true,\"name\":\"error.exception.type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":2,\"doc_values\":true,\"indexed\":true,\"name\":\"error.exception.handled\",\"scripted\":false,\"searchable\":true,\"type\":\"boolean\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"error.log.level\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"error.log.logger_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":2,\"doc_values\":true,\"indexed\":true,\"name\":\"error.log.message\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"error.log.param_message\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"system.cpu.total.norm.pct\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"system.memory.total\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"system.memory.actual.free\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"system.process.cpu.total.norm.pct\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"system.process.memory.size\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"system.process.memory.rss.bytes\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.root\",\"scripted\":false,\"searchable\":true,\"type\":\"boolean\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":1,\"doc_values\":true,\"indexed\":true,\"name\":\"profile.cpu.ns\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":1,\"doc_values\":true,\"indexed\":true,\"name\":\"profile.samples.count\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":1,\"doc_values\":true,\"indexed\":true,\"name\":\"profile.alloc_objects.count\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":1,\"doc_values\":true,\"indexed\":true,\"name\":\"profile.alloc_space.bytes\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":1,\"doc_values\":true,\"indexed\":true,\"name\":\"profile.inuse_objects.count\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":1,\"doc_values\":true,\"indexed\":true,\"name\":\"profile.inuse_space.bytes\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":1,\"doc_values\":true,\"indexed\":true,\"name\":\"profile.duration\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"profile.top.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":1,\"doc_values\":true,\"indexed\":true,\"name\":\"profile.top.function\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":1,\"doc_values\":true,\"indexed\":true,\"name\":\"profile.top.filename\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":1,\"doc_values\":true,\"indexed\":true,\"name\":\"profile.top.line\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"profile.stack.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"profile.stack.function\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"profile.stack.filename\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"profile.stack.line\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"sourcemap.service.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"sourcemap.service.version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"sourcemap.bundle_filepath\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"view spans\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"child.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"span.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":1,\"doc_values\":true,\"indexed\":true,\"name\":\"span.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":1,\"doc_values\":true,\"indexed\":true,\"name\":\"span.action\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":1,\"doc_values\":true,\"indexed\":true,\"name\":\"span.start.us\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":1,\"doc_values\":true,\"indexed\":true,\"name\":\"span.duration.us\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"span.sync\",\"scripted\":false,\"searchable\":true,\"type\":\"boolean\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"span.db.link\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"span.db.rows_affected\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"span.destination.service.type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"span.destination.service.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"span.destination.service.resource\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"span.message.queue.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"span.message.age.ms\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.duration.us\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.result\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.marks\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.marks.*.*\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.span_count.dropped\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.message.queue.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.message.age.ms\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.duration.histogram\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":false,\"indexed\":false,\"name\":\"_id\",\"scripted\":false,\"searchable\":false,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":false,\"indexed\":false,\"name\":\"_type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":false,\"indexed\":false,\"name\":\"_index\",\"scripted\":false,\"searchable\":false,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":false,\"indexed\":false,\"name\":\"_score\",\"scripted\":false,\"searchable\":false,\"type\":\"number\"}]", + "fieldFormatMap": "{\"client.bytes\":{\"id\":\"bytes\"},\"client.nat.port\":{\"id\":\"string\"},\"client.port\":{\"id\":\"string\"},\"destination.bytes\":{\"id\":\"bytes\"},\"destination.nat.port\":{\"id\":\"string\"},\"destination.port\":{\"id\":\"string\"},\"event.duration\":{\"id\":\"duration\",\"params\":{\"inputFormat\":\"nanoseconds\",\"outputFormat\":\"asMilliseconds\",\"outputPrecision\":1}},\"event.sequence\":{\"id\":\"string\"},\"event.severity\":{\"id\":\"string\"},\"http.request.body.bytes\":{\"id\":\"bytes\"},\"http.request.bytes\":{\"id\":\"bytes\"},\"http.response.body.bytes\":{\"id\":\"bytes\"},\"http.response.bytes\":{\"id\":\"bytes\"},\"http.response.status_code\":{\"id\":\"string\"},\"log.syslog.facility.code\":{\"id\":\"string\"},\"log.syslog.priority\":{\"id\":\"string\"},\"network.bytes\":{\"id\":\"bytes\"},\"package.size\":{\"id\":\"string\"},\"process.parent.pgid\":{\"id\":\"string\"},\"process.parent.pid\":{\"id\":\"string\"},\"process.parent.ppid\":{\"id\":\"string\"},\"process.parent.thread.id\":{\"id\":\"string\"},\"process.pgid\":{\"id\":\"string\"},\"process.pid\":{\"id\":\"string\"},\"process.ppid\":{\"id\":\"string\"},\"process.thread.id\":{\"id\":\"string\"},\"server.bytes\":{\"id\":\"bytes\"},\"server.nat.port\":{\"id\":\"string\"},\"server.port\":{\"id\":\"string\"},\"source.bytes\":{\"id\":\"bytes\"},\"source.nat.port\":{\"id\":\"string\"},\"source.port\":{\"id\":\"string\"},\"system.cpu.total.norm.pct\":{\"id\":\"percent\"},\"system.memory.actual.free\":{\"id\":\"bytes\"},\"system.memory.total\":{\"id\":\"bytes\"},\"system.process.cgroup.memory.mem.limit.bytes\":{\"id\":\"bytes\"},\"system.process.cgroup.memory.mem.usage.bytes\":{\"id\":\"bytes\"},\"system.process.cgroup.memory.stats.inactive_file.bytes\":{\"id\":\"bytes\"},\"system.process.cpu.total.norm.pct\":{\"id\":\"percent\"},\"system.process.memory.rss.bytes\":{\"id\":\"bytes\"},\"system.process.memory.size\":{\"id\":\"bytes\"},\"url.port\":{\"id\":\"string\"},\"view spans\":{\"id\":\"url\",\"params\":{\"labelTemplate\":\"View Spans\"}}}", + "fields": "[{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"@timestamp\",\"scripted\":false,\"searchable\":true,\"type\":\"date\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"labels\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"message\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tags\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"agent.ephemeral_id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"agent.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"agent.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"agent.type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"agent.version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"as.number\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"as.organization.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"as.organization.name.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.address\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.as.number\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.as.organization.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.as.organization.name.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.bytes\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.geo.city_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.geo.continent_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.geo.country_iso_code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.geo.country_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.geo.location\",\"scripted\":false,\"searchable\":true,\"type\":\"geo_point\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.geo.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.geo.region_iso_code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.geo.region_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.ip\",\"scripted\":false,\"searchable\":true,\"type\":\"ip\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.mac\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.nat.ip\",\"scripted\":false,\"searchable\":true,\"type\":\"ip\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.nat.port\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.packets\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.port\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.registered_domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.top_level_domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.user.domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.user.email\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.user.full_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.user.full_name.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.user.group.domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.user.group.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.user.group.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.user.hash\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.user.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.user.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.user.name.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"cloud.account.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"cloud.availability_zone\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"cloud.instance.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"cloud.instance.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"cloud.machine.type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"cloud.provider\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"cloud.region\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"code_signature.exists\",\"scripted\":false,\"searchable\":true,\"type\":\"boolean\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"code_signature.status\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"code_signature.subject_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"code_signature.trusted\",\"scripted\":false,\"searchable\":true,\"type\":\"boolean\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"code_signature.valid\",\"scripted\":false,\"searchable\":true,\"type\":\"boolean\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"container.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"container.image.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"container.image.tag\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"container.labels\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"container.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"container.runtime\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.address\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.as.number\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.as.organization.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.as.organization.name.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.bytes\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.geo.city_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.geo.continent_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.geo.country_iso_code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.geo.country_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.geo.location\",\"scripted\":false,\"searchable\":true,\"type\":\"geo_point\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.geo.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.geo.region_iso_code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.geo.region_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.ip\",\"scripted\":false,\"searchable\":true,\"type\":\"ip\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.mac\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.nat.ip\",\"scripted\":false,\"searchable\":true,\"type\":\"ip\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.nat.port\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.packets\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.port\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.registered_domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.top_level_domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.user.domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.user.email\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.user.full_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.user.full_name.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.user.group.domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.user.group.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.user.group.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.user.hash\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.user.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.user.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.user.name.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dll.code_signature.exists\",\"scripted\":false,\"searchable\":true,\"type\":\"boolean\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dll.code_signature.status\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dll.code_signature.subject_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dll.code_signature.trusted\",\"scripted\":false,\"searchable\":true,\"type\":\"boolean\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dll.code_signature.valid\",\"scripted\":false,\"searchable\":true,\"type\":\"boolean\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dll.hash.md5\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dll.hash.sha1\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dll.hash.sha256\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dll.hash.sha512\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dll.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dll.path\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dll.pe.company\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dll.pe.description\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dll.pe.file_version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dll.pe.original_file_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dll.pe.product\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dns.answers\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dns.answers.class\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dns.answers.data\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dns.answers.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dns.answers.ttl\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dns.answers.type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dns.header_flags\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dns.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dns.op_code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dns.question.class\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dns.question.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dns.question.registered_domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dns.question.subdomain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dns.question.top_level_domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dns.question.type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dns.resolved_ip\",\"scripted\":false,\"searchable\":true,\"type\":\"ip\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dns.response_code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dns.type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"ecs.version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"error.code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":4,\"doc_values\":true,\"indexed\":true,\"name\":\"error.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"error.message\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"error.stack_trace\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"error.stack_trace.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"error.type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.action\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.category\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.created\",\"scripted\":false,\"searchable\":true,\"type\":\"date\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.dataset\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.duration\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.end\",\"scripted\":false,\"searchable\":true,\"type\":\"date\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.hash\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.ingested\",\"scripted\":false,\"searchable\":true,\"type\":\"date\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.kind\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.module\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.original\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.outcome\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.provider\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.reference\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.risk_score\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.risk_score_norm\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.sequence\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.severity\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.start\",\"scripted\":false,\"searchable\":true,\"type\":\"date\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.timezone\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.url\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.accessed\",\"scripted\":false,\"searchable\":true,\"type\":\"date\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.attributes\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.code_signature.exists\",\"scripted\":false,\"searchable\":true,\"type\":\"boolean\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.code_signature.status\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.code_signature.subject_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.code_signature.trusted\",\"scripted\":false,\"searchable\":true,\"type\":\"boolean\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.code_signature.valid\",\"scripted\":false,\"searchable\":true,\"type\":\"boolean\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.created\",\"scripted\":false,\"searchable\":true,\"type\":\"date\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.ctime\",\"scripted\":false,\"searchable\":true,\"type\":\"date\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.device\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.directory\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.drive_letter\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.extension\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.gid\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.group\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.hash.md5\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.hash.sha1\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.hash.sha256\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.hash.sha512\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.inode\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.mime_type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.mode\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.mtime\",\"scripted\":false,\"searchable\":true,\"type\":\"date\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.owner\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.path\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.path.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.pe.company\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.pe.description\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.pe.file_version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.pe.original_file_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.pe.product\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.size\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.target_path\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.target_path.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.uid\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"geo.city_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"geo.continent_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"geo.country_iso_code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"geo.country_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"geo.location\",\"scripted\":false,\"searchable\":true,\"type\":\"geo_point\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"geo.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"geo.region_iso_code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"geo.region_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"group.domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"group.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"group.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"hash.md5\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"hash.sha1\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"hash.sha256\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"hash.sha512\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.architecture\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.geo.city_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.geo.continent_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.geo.country_iso_code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.geo.country_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.geo.location\",\"scripted\":false,\"searchable\":true,\"type\":\"geo_point\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.geo.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.geo.region_iso_code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.geo.region_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.hostname\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.ip\",\"scripted\":false,\"searchable\":true,\"type\":\"ip\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.mac\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.os.family\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.os.full\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.os.full.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.os.kernel\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.os.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.os.name.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.os.platform\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.os.version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.uptime\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.user.domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.user.email\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.user.full_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.user.full_name.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.user.group.domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.user.group.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.user.group.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.user.hash\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.user.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.user.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.user.name.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"http.request.body.bytes\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"http.request.body.content\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"http.request.body.content.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"http.request.bytes\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"http.request.method\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"http.request.referrer\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"http.response.body.bytes\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"http.response.body.content\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"http.response.body.content.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"http.response.bytes\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"http.response.status_code\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"http.version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"interface.alias\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"interface.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"interface.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"log.level\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"log.logger\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"log.origin.file.line\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"log.origin.file.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"log.origin.function\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"log.original\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"log.syslog\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"log.syslog.facility.code\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"log.syslog.facility.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"log.syslog.priority\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"log.syslog.severity.code\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"log.syslog.severity.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"network.application\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"network.bytes\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"network.community_id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"network.direction\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"network.forwarded_ip\",\"scripted\":false,\"searchable\":true,\"type\":\"ip\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"network.iana_number\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"network.inner\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"network.inner.vlan.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"network.inner.vlan.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"network.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"network.packets\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"network.protocol\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"network.transport\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"network.type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"network.vlan.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"network.vlan.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.egress\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.egress.interface.alias\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.egress.interface.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.egress.interface.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.egress.vlan.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.egress.vlan.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.egress.zone\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.geo.city_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.geo.continent_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.geo.country_iso_code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.geo.country_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.geo.location\",\"scripted\":false,\"searchable\":true,\"type\":\"geo_point\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.geo.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.geo.region_iso_code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.geo.region_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.hostname\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.ingress\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.ingress.interface.alias\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.ingress.interface.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.ingress.interface.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.ingress.vlan.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.ingress.vlan.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.ingress.zone\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.ip\",\"scripted\":false,\"searchable\":true,\"type\":\"ip\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.mac\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.os.family\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.os.full\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.os.full.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.os.kernel\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.os.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.os.name.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.os.platform\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.os.version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.product\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.serial_number\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.vendor\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"organization.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"organization.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"organization.name.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"os.family\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"os.full\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"os.full.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"os.kernel\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"os.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"os.name.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"os.platform\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"os.version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"package.architecture\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"package.build_version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"package.checksum\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"package.description\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"package.install_scope\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"package.installed\",\"scripted\":false,\"searchable\":true,\"type\":\"date\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"package.license\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"package.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"package.path\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"package.reference\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"package.size\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"package.type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"package.version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"pe.company\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"pe.description\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"pe.file_version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"pe.original_file_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"pe.product\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.args\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.args_count\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.code_signature.exists\",\"scripted\":false,\"searchable\":true,\"type\":\"boolean\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.code_signature.status\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.code_signature.subject_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.code_signature.trusted\",\"scripted\":false,\"searchable\":true,\"type\":\"boolean\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.code_signature.valid\",\"scripted\":false,\"searchable\":true,\"type\":\"boolean\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.command_line\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.command_line.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.entity_id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.executable\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.executable.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.exit_code\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.hash.md5\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.hash.sha1\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.hash.sha256\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.hash.sha512\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.name.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.args\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.args_count\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.code_signature.exists\",\"scripted\":false,\"searchable\":true,\"type\":\"boolean\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.code_signature.status\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.code_signature.subject_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.code_signature.trusted\",\"scripted\":false,\"searchable\":true,\"type\":\"boolean\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.code_signature.valid\",\"scripted\":false,\"searchable\":true,\"type\":\"boolean\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.command_line\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.command_line.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.entity_id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.executable\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.executable.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.exit_code\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.hash.md5\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.hash.sha1\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.hash.sha256\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.hash.sha512\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.name.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.pgid\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.pid\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.ppid\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.start\",\"scripted\":false,\"searchable\":true,\"type\":\"date\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.thread.id\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.thread.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.title\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.title.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.uptime\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.working_directory\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.working_directory.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.pe.company\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.pe.description\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.pe.file_version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.pe.original_file_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.pe.product\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.pgid\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.pid\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.ppid\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.start\",\"scripted\":false,\"searchable\":true,\"type\":\"date\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.thread.id\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.thread.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.title\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.title.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.uptime\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.working_directory\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.working_directory.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"registry.data.bytes\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"registry.data.strings\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"registry.data.type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"registry.hive\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"registry.key\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"registry.path\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"registry.value\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"related.hash\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"related.ip\",\"scripted\":false,\"searchable\":true,\"type\":\"ip\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"related.user\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"rule.author\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"rule.category\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"rule.description\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"rule.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"rule.license\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"rule.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"rule.reference\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"rule.ruleset\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"rule.uuid\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"rule.version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.address\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.as.number\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.as.organization.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.as.organization.name.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.bytes\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.geo.city_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.geo.continent_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.geo.country_iso_code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.geo.country_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.geo.location\",\"scripted\":false,\"searchable\":true,\"type\":\"geo_point\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.geo.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.geo.region_iso_code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.geo.region_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.ip\",\"scripted\":false,\"searchable\":true,\"type\":\"ip\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.mac\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.nat.ip\",\"scripted\":false,\"searchable\":true,\"type\":\"ip\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.nat.port\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.packets\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.port\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.registered_domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.top_level_domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.user.domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.user.email\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.user.full_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.user.full_name.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.user.group.domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.user.group.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.user.group.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.user.hash\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.user.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.user.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.user.name.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"service.ephemeral_id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"service.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"service.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"service.node.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"service.state\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"service.type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"service.version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.address\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.as.number\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.as.organization.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.as.organization.name.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.bytes\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.geo.city_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.geo.continent_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.geo.country_iso_code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.geo.country_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.geo.location\",\"scripted\":false,\"searchable\":true,\"type\":\"geo_point\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.geo.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.geo.region_iso_code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.geo.region_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.ip\",\"scripted\":false,\"searchable\":true,\"type\":\"ip\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.mac\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.nat.ip\",\"scripted\":false,\"searchable\":true,\"type\":\"ip\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.nat.port\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.packets\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.port\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.registered_domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.top_level_domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.user.domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.user.email\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.user.full_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.user.full_name.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.user.group.domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.user.group.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.user.group.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.user.hash\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.user.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.user.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.user.name.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"threat.framework\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"threat.tactic.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"threat.tactic.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"threat.tactic.reference\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"threat.technique.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"threat.technique.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"threat.technique.name.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"threat.technique.reference\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.cipher\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.client.certificate\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.client.certificate_chain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.client.hash.md5\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.client.hash.sha1\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.client.hash.sha256\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.client.issuer\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.client.ja3\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.client.not_after\",\"scripted\":false,\"searchable\":true,\"type\":\"date\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.client.not_before\",\"scripted\":false,\"searchable\":true,\"type\":\"date\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.client.server_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.client.subject\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.client.supported_ciphers\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.curve\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.established\",\"scripted\":false,\"searchable\":true,\"type\":\"boolean\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.next_protocol\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.resumed\",\"scripted\":false,\"searchable\":true,\"type\":\"boolean\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.server.certificate\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.server.certificate_chain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.server.hash.md5\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.server.hash.sha1\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.server.hash.sha256\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.server.issuer\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.server.ja3s\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.server.not_after\",\"scripted\":false,\"searchable\":true,\"type\":\"date\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.server.not_before\",\"scripted\":false,\"searchable\":true,\"type\":\"date\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.server.subject\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.version_protocol\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tracing.trace.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tracing.transaction.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"url.domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"url.extension\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"url.fragment\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"url.full\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"url.full.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"url.original\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"url.original.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"url.password\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"url.path\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"url.port\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"url.query\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"url.registered_domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"url.scheme\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"url.top_level_domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"url.username\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user.domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user.email\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user.full_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user.full_name.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user.group.domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user.group.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user.group.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user.hash\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user.name.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user_agent.device.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user_agent.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user_agent.original\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user_agent.original.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user_agent.os.family\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user_agent.os.full\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user_agent.os.full.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user_agent.os.kernel\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user_agent.os.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user_agent.os.name.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user_agent.os.platform\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user_agent.os.version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user_agent.version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"vlan.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"vlan.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"vulnerability.category\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"vulnerability.classification\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"vulnerability.description\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"vulnerability.description.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"vulnerability.enumeration\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"vulnerability.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"vulnerability.reference\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"vulnerability.report_id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"vulnerability.scanner.vendor\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"vulnerability.score.base\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"vulnerability.score.environmental\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"vulnerability.score.temporal\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"vulnerability.score.version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"vulnerability.severity\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"agent.hostname\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"fields\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"timeseries.instance\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"cloud.project.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"cloud.image.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"docker.container.labels\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.containerized\",\"scripted\":false,\"searchable\":true,\"type\":\"boolean\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.os.build\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.os.codename\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"kubernetes.pod.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"kubernetes.pod.uid\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"kubernetes.namespace\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"kubernetes.node.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"kubernetes.labels.*\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"kubernetes.annotations.*\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"kubernetes.replicaset.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"kubernetes.deployment.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"kubernetes.statefulset.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"kubernetes.container.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"kubernetes.container.image\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"processor.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"processor.event\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":1,\"doc_values\":true,\"indexed\":true,\"name\":\"timestamp.us\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":false,\"enabled\":false,\"indexed\":false,\"name\":\"http.request.headers\",\"scripted\":false,\"searchable\":false},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"http.response.finished\",\"scripted\":false,\"searchable\":true,\"type\":\"boolean\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":false,\"enabled\":false,\"indexed\":false,\"name\":\"http.response.headers\",\"scripted\":false,\"searchable\":false},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"service.environment\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"service.language.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"service.language.version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"service.runtime.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"service.runtime.version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"service.framework.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"service.framework.version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.sampled\",\"scripted\":false,\"searchable\":true,\"type\":\"boolean\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.name.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.duration.count\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.duration.sum.us\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.self_time.count\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.self_time.sum.us\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.breakdown.count\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":1,\"doc_values\":true,\"indexed\":true,\"name\":\"span.type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":1,\"doc_values\":true,\"indexed\":true,\"name\":\"span.subtype\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"span.self_time.count\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"span.self_time.sum.us\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"trace.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"parent.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.listening\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.version_major\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"experimental\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"cloud.account.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"cloud.project.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":2,\"doc_values\":true,\"indexed\":true,\"name\":\"error.culprit\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"error.grouping_key\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"error.exception.code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":2,\"doc_values\":true,\"indexed\":true,\"name\":\"error.exception.message\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"error.exception.module\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":4,\"doc_values\":true,\"indexed\":true,\"name\":\"error.exception.type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":2,\"doc_values\":true,\"indexed\":true,\"name\":\"error.exception.handled\",\"scripted\":false,\"searchable\":true,\"type\":\"boolean\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"error.log.level\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"error.log.logger_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":2,\"doc_values\":true,\"indexed\":true,\"name\":\"error.log.message\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"error.log.param_message\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"system.cpu.total.norm.pct\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"system.memory.total\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"system.memory.actual.free\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"system.process.cpu.total.norm.pct\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"system.process.memory.size\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"system.process.memory.rss.bytes\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"system.process.cgroup.memory.mem.limit.bytes\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"system.process.cgroup.memory.mem.usage.bytes\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"system.process.cgroup.memory.stats.inactive_file.bytes\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.root\",\"scripted\":false,\"searchable\":true,\"type\":\"boolean\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":1,\"doc_values\":true,\"indexed\":true,\"name\":\"profile.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":1,\"doc_values\":true,\"indexed\":true,\"name\":\"profile.duration\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":1,\"doc_values\":true,\"indexed\":true,\"name\":\"profile.cpu.ns\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":1,\"doc_values\":true,\"indexed\":true,\"name\":\"profile.samples.count\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":1,\"doc_values\":true,\"indexed\":true,\"name\":\"profile.alloc_objects.count\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":1,\"doc_values\":true,\"indexed\":true,\"name\":\"profile.alloc_space.bytes\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":1,\"doc_values\":true,\"indexed\":true,\"name\":\"profile.inuse_objects.count\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":1,\"doc_values\":true,\"indexed\":true,\"name\":\"profile.inuse_space.bytes\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"profile.top.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":1,\"doc_values\":true,\"indexed\":true,\"name\":\"profile.top.function\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":1,\"doc_values\":true,\"indexed\":true,\"name\":\"profile.top.filename\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":1,\"doc_values\":true,\"indexed\":true,\"name\":\"profile.top.line\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"profile.stack.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"profile.stack.function\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"profile.stack.filename\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"profile.stack.line\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"sourcemap.service.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"sourcemap.service.version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"sourcemap.bundle_filepath\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"view spans\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"child.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"span.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":1,\"doc_values\":true,\"indexed\":true,\"name\":\"span.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":1,\"doc_values\":true,\"indexed\":true,\"name\":\"span.action\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":1,\"doc_values\":true,\"indexed\":true,\"name\":\"span.start.us\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":1,\"doc_values\":true,\"indexed\":true,\"name\":\"span.duration.us\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"span.sync\",\"scripted\":false,\"searchable\":true,\"type\":\"boolean\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"span.db.link\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"span.db.rows_affected\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"span.destination.service.type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"span.destination.service.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"span.destination.service.resource\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"span.message.queue.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"span.message.age.ms\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.duration.us\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.result\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.marks\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.marks.*.*\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.experience.cls\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.experience.fid\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.experience.tbt\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.span_count.dropped\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.message.queue.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.message.age.ms\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.duration.histogram\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"metricset.period\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"span.destination.service.response_time.count\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"span.destination.service.response_time.sum.us\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":false,\"indexed\":false,\"name\":\"_id\",\"scripted\":false,\"searchable\":false,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":false,\"indexed\":false,\"name\":\"_type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":false,\"indexed\":false,\"name\":\"_index\",\"scripted\":false,\"searchable\":false,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":false,\"indexed\":false,\"name\":\"_score\",\"scripted\":false,\"searchable\":false,\"type\":\"number\"}]", "sourceFilters": "[{\"value\":\"sourcemap.sourcemap\"}]", "timeFieldName": "@timestamp" }, "id": "apm-*", "type": "index-pattern", "version": "1" -} \ No newline at end of file +} diff --git a/src/plugins/dashboard/public/attribute_service/attribute_service.tsx b/src/plugins/dashboard/public/attribute_service/attribute_service.tsx index a36363d22d87d..84df05154fb63 100644 --- a/src/plugins/dashboard/public/attribute_service/attribute_service.tsx +++ b/src/plugins/dashboard/public/attribute_service/attribute_service.tsx @@ -57,7 +57,7 @@ export interface AttributeServiceOptions { type: string, attributes: A, savedObjectId?: string - ) => Promise<{ id: string }>; + ) => Promise<{ id?: string } | { error: Error }>; customUnwrapMethod?: (savedObject: SimpleSavedObject) => A; } @@ -124,7 +124,10 @@ export class AttributeService< newAttributes, savedObjectId ); - return { ...originalInput, savedObjectId: savedItem.id } as RefType; + if ('id' in savedItem) { + return { ...originalInput, savedObjectId: savedItem.id } as RefType; + } + return { ...originalInput } as RefType; } if (savedObjectId) { @@ -208,7 +211,6 @@ export class AttributeService< return { error }; } }; - if (saveOptions && (saveOptions as { showSaveModal: boolean }).showSaveModal) { this.showSaveModal( ; + +const createStartContract = (): DashboardStart => { + // @ts-ignore + const startContract: DashboardStart = { + getAttributeService: jest.fn(), + }; + + return startContract; +}; + +export const dashboardPluginMock = { + createStartContract, +}; diff --git a/src/plugins/data/common/es_query/kuery/node_types/types.ts b/src/plugins/data/common/es_query/kuery/node_types/types.ts index 6d3019e75d483..894bd1812f084 100644 --- a/src/plugins/data/common/es_query/kuery/node_types/types.ts +++ b/src/plugins/data/common/es_query/kuery/node_types/types.ts @@ -76,6 +76,7 @@ export interface NamedArgTypeBuildNode { } interface WildcardType { + wildcardSymbol: string; buildNode: (value: string) => WildcardTypeBuildNode | KueryNode; test: (node: any, string: string) => boolean; toElasticsearchQuery: (node: any) => string; diff --git a/src/plugins/data/public/public.api.md b/src/plugins/data/public/public.api.md index fa5d3cd85f430..a8fbbcb08d358 100644 --- a/src/plugins/data/public/public.api.md +++ b/src/plugins/data/public/public.api.md @@ -28,7 +28,6 @@ import { ExpressionAstFunction } from 'src/plugins/expressions/common'; import { ExpressionsSetup } from 'src/plugins/expressions/public'; import { History } from 'history'; import { Href } from 'history'; -import { HttpStart } from 'src/core/public'; import { IconType } from '@elastic/eui'; import { InjectedIntl } from '@kbn/i18n/react'; import { ISearchOptions as ISearchOptions_2 } from 'src/plugins/data/public'; @@ -49,6 +48,7 @@ import { Path } from 'history'; import { Plugin as Plugin_2 } from 'src/core/public'; import { PluginInitializerContext as PluginInitializerContext_2 } from 'src/core/public'; import { PopoverAnchorPosition } from '@elastic/eui'; +import { PublicMethodsOf } from '@kbn/utility-types'; import { PublicUiSettingsParams } from 'src/core/server/types'; import React from 'react'; import * as React_2 from 'react'; @@ -1685,7 +1685,7 @@ export interface QueryStateChange extends QueryStateChangePartial { // Warning: (ae-missing-release-tag) "QueryStringInput" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // // @public (undocumented) -export const QueryStringInput: React.FC>; +export const QueryStringInput: React.FC>; // @public (undocumented) export type QuerySuggestion = QuerySuggestionBasic | QuerySuggestionField; @@ -2017,7 +2017,7 @@ export class SearchSource { onRequestStart(handler: (searchSource: SearchSource, options?: ISearchOptions) => Promise): void; serialize(): { searchSourceJSON: string; - references: import("../../../../../core/public").SavedObjectReference[]; + references: import("../../../../../core/types").SavedObjectReference[]; }; setField(field: K, value: SearchSourceFields[K]): this; setFields(newFields: SearchSourceFields): this; diff --git a/src/plugins/data/public/search/fetch/types.ts b/src/plugins/data/public/search/fetch/types.ts index 224a597766909..cdf10d8f1a1b0 100644 --- a/src/plugins/data/public/search/fetch/types.ts +++ b/src/plugins/data/public/search/fetch/types.ts @@ -17,9 +17,9 @@ * under the License. */ -import { HttpStart } from 'src/core/public'; -import { BehaviorSubject } from 'rxjs'; +import { SearchResponse } from 'elasticsearch'; import { GetConfigFn } from '../../../common'; +import { LegacyFetchHandlers } from '../legacy/types'; /** * @internal @@ -31,9 +31,17 @@ import { GetConfigFn } from '../../../common'; export type SearchRequest = Record; export interface FetchHandlers { - config: { get: GetConfigFn }; - http: HttpStart; - loadingCount$: BehaviorSubject; + getConfig: GetConfigFn; + /** + * Callback which can be used to hook into responses, modify them, or perform + * side effects like displaying UI errors on the client. + */ + onResponse: (request: SearchRequest, response: SearchResponse) => SearchResponse; + /** + * These handlers are only used by the legacy defaultSearchStrategy and can be removed + * once that strategy has been deprecated. + */ + legacy: LegacyFetchHandlers; } export interface SearchError { diff --git a/src/plugins/data/public/search/legacy/call_client.test.ts b/src/plugins/data/public/search/legacy/call_client.test.ts index 943a02d22088d..0a7913b0a734f 100644 --- a/src/plugins/data/public/search/legacy/call_client.test.ts +++ b/src/plugins/data/public/search/legacy/call_client.test.ts @@ -17,18 +17,13 @@ * under the License. */ -import { coreMock } from '../../../../../core/public/mocks'; import { callClient } from './call_client'; import { SearchStrategySearchParams } from './types'; import { defaultSearchStrategy } from './default_search_strategy'; import { FetchHandlers } from '../fetch'; -import { handleResponse } from '../fetch/handle_response'; import { BehaviorSubject } from 'rxjs'; const mockAbortFn = jest.fn(); -jest.mock('../fetch/handle_response', () => ({ - handleResponse: jest.fn((request, response) => response), -})); jest.mock('./default_search_strategy', () => { return { @@ -50,32 +45,36 @@ jest.mock('./default_search_strategy', () => { }); describe('callClient', () => { + const handleResponse = jest.fn().mockImplementation((req, res) => res); + const handlers = { + getConfig: jest.fn(), + onResponse: handleResponse, + legacy: { + callMsearch: jest.fn(), + loadingCount$: new BehaviorSubject(0), + }, + } as FetchHandlers; + beforeEach(() => { - (handleResponse as jest.Mock).mockClear(); + handleResponse.mockClear(); }); test('Passes the additional arguments it is given to the search strategy', () => { const searchRequests = [{ _searchStrategyId: 0 }]; - const args = { - http: coreMock.createStart().http, - legacySearchService: {}, - config: { get: jest.fn() }, - loadingCount$: new BehaviorSubject(0), - } as FetchHandlers; - callClient(searchRequests, [], args); + callClient(searchRequests, [], handlers); expect(defaultSearchStrategy.search).toBeCalled(); expect((defaultSearchStrategy.search as any).mock.calls[0][0]).toEqual({ searchRequests, - ...args, + ...handlers, }); }); test('Returns the responses in the original order', async () => { const searchRequests = [{ _searchStrategyId: 1 }, { _searchStrategyId: 0 }]; - const responses = await Promise.all(callClient(searchRequests, [], {} as FetchHandlers)); + const responses = await Promise.all(callClient(searchRequests, [], handlers)); expect(responses[0]).toEqual({ id: searchRequests[0]._searchStrategyId }); expect(responses[1]).toEqual({ id: searchRequests[1]._searchStrategyId }); @@ -84,7 +83,7 @@ describe('callClient', () => { test('Calls handleResponse with each request and response', async () => { const searchRequests = [{ _searchStrategyId: 0 }, { _searchStrategyId: 1 }]; - const responses = callClient(searchRequests, [], {} as FetchHandlers); + const responses = callClient(searchRequests, [], handlers); await Promise.all(responses); expect(handleResponse).toBeCalledTimes(2); @@ -105,7 +104,7 @@ describe('callClient', () => { }, ]; - callClient(searchRequests, requestOptions, {} as FetchHandlers); + callClient(searchRequests, requestOptions, handlers); abortController.abort(); expect(mockAbortFn).toBeCalled(); diff --git a/src/plugins/data/public/search/legacy/call_client.ts b/src/plugins/data/public/search/legacy/call_client.ts index d66796b9427a1..b87affdd59c54 100644 --- a/src/plugins/data/public/search/legacy/call_client.ts +++ b/src/plugins/data/public/search/legacy/call_client.ts @@ -19,7 +19,7 @@ import { SearchResponse } from 'elasticsearch'; import { ISearchOptions } from 'src/plugins/data/common'; -import { FetchHandlers, handleResponse } from '../fetch'; +import { FetchHandlers } from '../fetch'; import { defaultSearchStrategy } from './default_search_strategy'; import { SearchRequest } from '../index'; @@ -42,7 +42,7 @@ export function callClient( }); searchRequests.forEach((request, i) => { - const response = searching.then((results) => handleResponse(request, results[i])); + const response = searching.then((results) => fetchHandlers.onResponse(request, results[i])); const { abortSignal = null } = requestOptionsMap.get(request) || {}; if (abortSignal) abortSignal.addEventListener('abort', abort); requestResponseMap.set(request, response); diff --git a/src/plugins/data/public/search/legacy/call_msearch.ts b/src/plugins/data/public/search/legacy/call_msearch.ts new file mode 100644 index 0000000000000..fd4f8a07919f8 --- /dev/null +++ b/src/plugins/data/public/search/legacy/call_msearch.ts @@ -0,0 +1,37 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { HttpStart } from 'src/core/public'; +import { LegacyFetchHandlers } from './types'; + +/** + * Wrapper for calling the internal msearch endpoint from the client. + * This is needed to abstract away differences in the http service + * between client & server. + * + * @internal + */ +export function getCallMsearch({ http }: { http: HttpStart }): LegacyFetchHandlers['callMsearch'] { + return async ({ body, signal }) => { + return http.post('/internal/_msearch', { + body: JSON.stringify(body), + signal, + }); + }; +} diff --git a/src/plugins/data/public/search/legacy/default_search_strategy.test.ts b/src/plugins/data/public/search/legacy/default_search_strategy.test.ts index e74ab49131430..ad59e5c6c9625 100644 --- a/src/plugins/data/public/search/legacy/default_search_strategy.test.ts +++ b/src/plugins/data/public/search/legacy/default_search_strategy.test.ts @@ -19,8 +19,9 @@ import { HttpStart } from 'src/core/public'; import { coreMock } from '../../../../../core/public/mocks'; +import { getCallMsearch } from './call_msearch'; import { defaultSearchStrategy } from './default_search_strategy'; -import { SearchStrategySearchParams } from './types'; +import { LegacyFetchHandlers, SearchStrategySearchParams } from './types'; import { BehaviorSubject } from 'rxjs'; const { search } = defaultSearchStrategy; @@ -44,11 +45,12 @@ describe('defaultSearchStrategy', function () { index: { title: 'foo' }, }, ], - http, - config: { - get: jest.fn(), - }, - loadingCount$: new BehaviorSubject(0) as any, + getConfig: jest.fn(), + onResponse: (req, res) => res, + legacy: { + callMsearch: getCallMsearch({ http }), + loadingCount$: new BehaviorSubject(0) as any, + } as jest.Mocked, }; }); diff --git a/src/plugins/data/public/search/legacy/default_search_strategy.ts b/src/plugins/data/public/search/legacy/default_search_strategy.ts index cbcd0da20207f..bed86cb75cca6 100644 --- a/src/plugins/data/public/search/legacy/default_search_strategy.ts +++ b/src/plugins/data/public/search/legacy/default_search_strategy.ts @@ -29,12 +29,14 @@ export const defaultSearchStrategy: SearchStrategyProvider = { }, }; -function msearch({ searchRequests, config, http, loadingCount$ }: SearchStrategySearchParams) { +function msearch({ searchRequests, getConfig, legacy }: SearchStrategySearchParams) { + const { callMsearch, loadingCount$ } = legacy; + const requests = searchRequests.map(({ index, body }) => { return { header: { index: index.title || index, - preference: getPreference(config.get), + preference: getPreference(getConfig), }, body, }; @@ -55,12 +57,11 @@ function msearch({ searchRequests, config, http, loadingCount$ }: SearchStrategy } }; - const searching = http - .post('/internal/_msearch', { - body: JSON.stringify({ searches: requests }), - signal: abortController.signal, - }) - .then(({ body }) => body?.responses) + const searching = callMsearch({ + body: { searches: requests }, + signal: abortController.signal, + }) + .then((res: any) => res?.body?.responses) .finally(() => cleanup()); return { diff --git a/src/plugins/data/public/search/legacy/fetch_soon.test.ts b/src/plugins/data/public/search/legacy/fetch_soon.test.ts index d38a41cf5ffbc..7243ab158009a 100644 --- a/src/plugins/data/public/search/legacy/fetch_soon.test.ts +++ b/src/plugins/data/public/search/legacy/fetch_soon.test.ts @@ -67,25 +67,21 @@ describe('fetchSoon', () => { }); test('should execute asap if config is set to not batch searches', () => { - const config = { - get: getConfigStub({ [UI_SETTINGS.COURIER_BATCH_SEARCHES]: false }), - }; + const getConfig = getConfigStub({ [UI_SETTINGS.COURIER_BATCH_SEARCHES]: false }); const request = {}; const options = {}; - fetchSoon(request, options, { config } as FetchHandlers); + fetchSoon(request, options, { getConfig } as FetchHandlers); expect(callClient).toBeCalled(); }); test('should delay by 50ms if config is set to batch searches', () => { - const config = { - get: getConfigStub({ [UI_SETTINGS.COURIER_BATCH_SEARCHES]: true }), - }; + const getConfig = getConfigStub({ [UI_SETTINGS.COURIER_BATCH_SEARCHES]: true }); const request = {}; const options = {}; - fetchSoon(request, options, { config } as FetchHandlers); + fetchSoon(request, options, { getConfig } as FetchHandlers); expect(callClient).not.toBeCalled(); jest.advanceTimersByTime(0); @@ -95,14 +91,12 @@ describe('fetchSoon', () => { }); test('should send a batch of requests to callClient', () => { - const config = { - get: getConfigStub({ [UI_SETTINGS.COURIER_BATCH_SEARCHES]: true }), - }; + const getConfig = getConfigStub({ [UI_SETTINGS.COURIER_BATCH_SEARCHES]: true }); const requests = [{ foo: 1 }, { foo: 2 }]; const options = [{ bar: 1 }, { bar: 2 }]; requests.forEach((request, i) => { - fetchSoon(request, options[i] as ISearchOptions, { config } as FetchHandlers); + fetchSoon(request, options[i] as ISearchOptions, { getConfig } as FetchHandlers); }); jest.advanceTimersByTime(50); @@ -112,13 +106,11 @@ describe('fetchSoon', () => { }); test('should return the response to the corresponding call for multiple batched requests', async () => { - const config = { - get: getConfigStub({ [UI_SETTINGS.COURIER_BATCH_SEARCHES]: true }), - }; + const getConfig = getConfigStub({ [UI_SETTINGS.COURIER_BATCH_SEARCHES]: true }); const requests = [{ _mockResponseId: 'foo' }, { _mockResponseId: 'bar' }]; const promises = requests.map((request) => { - return fetchSoon(request, {}, { config } as FetchHandlers); + return fetchSoon(request, {}, { getConfig } as FetchHandlers); }); jest.advanceTimersByTime(50); const results = await Promise.all(promises); @@ -127,18 +119,16 @@ describe('fetchSoon', () => { }); test('should wait for the previous batch to start before starting a new batch', () => { - const config = { - get: getConfigStub({ [UI_SETTINGS.COURIER_BATCH_SEARCHES]: true }), - }; + const getConfig = getConfigStub({ [UI_SETTINGS.COURIER_BATCH_SEARCHES]: true }); const firstBatch = [{ foo: 1 }, { foo: 2 }]; const secondBatch = [{ bar: 1 }, { bar: 2 }]; firstBatch.forEach((request) => { - fetchSoon(request, {}, { config } as FetchHandlers); + fetchSoon(request, {}, { getConfig } as FetchHandlers); }); jest.advanceTimersByTime(50); secondBatch.forEach((request) => { - fetchSoon(request, {}, { config } as FetchHandlers); + fetchSoon(request, {}, { getConfig } as FetchHandlers); }); expect(callClient).toBeCalledTimes(1); diff --git a/src/plugins/data/public/search/legacy/fetch_soon.ts b/src/plugins/data/public/search/legacy/fetch_soon.ts index 37c3827bb7bba..1c0573aa895d7 100644 --- a/src/plugins/data/public/search/legacy/fetch_soon.ts +++ b/src/plugins/data/public/search/legacy/fetch_soon.ts @@ -32,7 +32,7 @@ export async function fetchSoon( options: ISearchOptions, fetchHandlers: FetchHandlers ) { - const msToDelay = fetchHandlers.config.get(UI_SETTINGS.COURIER_BATCH_SEARCHES) ? 50 : 0; + const msToDelay = fetchHandlers.getConfig(UI_SETTINGS.COURIER_BATCH_SEARCHES) ? 50 : 0; return delayedFetch(request, options, fetchHandlers, msToDelay); } diff --git a/src/plugins/data/public/search/legacy/types.ts b/src/plugins/data/public/search/legacy/types.ts index ed17db464feff..740bc22a7485c 100644 --- a/src/plugins/data/public/search/legacy/types.ts +++ b/src/plugins/data/public/search/legacy/types.ts @@ -17,10 +17,20 @@ * under the License. */ +import { BehaviorSubject } from 'rxjs'; import { SearchResponse } from 'elasticsearch'; import { FetchHandlers } from '../fetch'; import { SearchRequest } from '..'; +// @internal +export interface LegacyFetchHandlers { + callMsearch: (params: { + body: SearchRequest; + signal: AbortSignal; + }) => Promise>>; + loadingCount$: BehaviorSubject; +} + export interface SearchStrategySearchParams extends FetchHandlers { searchRequests: SearchRequest[]; } diff --git a/src/plugins/data/public/search/search_service.ts b/src/plugins/data/public/search/search_service.ts index 6b73761c5a437..c41e1f78ee74e 100644 --- a/src/plugins/data/public/search/search_service.ts +++ b/src/plugins/data/public/search/search_service.ts @@ -21,6 +21,8 @@ import { Plugin, CoreSetup, CoreStart } from 'src/core/public'; import { BehaviorSubject } from 'rxjs'; import { ISearchSetup, ISearchStart, SearchEnhancements } from './types'; +import { handleResponse } from './fetch'; +import { getCallMsearch } from './legacy/call_msearch'; import { createSearchSource, SearchSource, SearchSourceDependencies } from './search_source'; import { AggsService, AggsStartDependencies } from './aggs'; import { IndexPatternsContract } from '../index_patterns/index_patterns'; @@ -49,7 +51,7 @@ export class SearchService implements Plugin { private usageCollector?: SearchUsageCollector; public setup( - { http, getStartServices, injectedMetadata, notifications, uiSettings }: CoreSetup, + { http, getStartServices, notifications, uiSettings }: CoreSetup, { expressions, usageCollection }: SearchServiceSetupDependencies ): ISearchSetup { this.usageCollector = createUsageCollector(getStartServices, usageCollection); @@ -82,7 +84,7 @@ export class SearchService implements Plugin { } public start( - { application, http, injectedMetadata, notifications, uiSettings }: CoreStart, + { application, http, notifications, uiSettings }: CoreStart, { fieldFormats, indexPatterns }: SearchServiceStartDependencies ): ISearchStart { const search = ((request, options) => { @@ -95,8 +97,11 @@ export class SearchService implements Plugin { const searchSourceDependencies: SearchSourceDependencies = { getConfig: uiSettings.get.bind(uiSettings), search, - http, - loadingCount$, + onResponse: handleResponse, + legacy: { + callMsearch: getCallMsearch({ http }), + loadingCount$, + }, }; return { diff --git a/src/plugins/data/public/search/search_source/create_search_source.test.ts b/src/plugins/data/public/search/search_source/create_search_source.test.ts index bc1c7c06c8806..6b6cfb0c9b1ca 100644 --- a/src/plugins/data/public/search/search_source/create_search_source.test.ts +++ b/src/plugins/data/public/search/search_source/create_search_source.test.ts @@ -22,7 +22,6 @@ import { SearchSourceDependencies } from './search_source'; import { IIndexPattern } from '../../../common/index_patterns'; import { IndexPatternsContract } from '../../index_patterns/index_patterns'; import { Filter } from '../../../common/es_query/filters'; -import { coreMock } from '../../../../../core/public/mocks'; import { BehaviorSubject } from 'rxjs'; describe('createSearchSource', () => { @@ -35,8 +34,11 @@ describe('createSearchSource', () => { dependencies = { getConfig: jest.fn(), search: jest.fn(), - http: coreMock.createStart().http, - loadingCount$: new BehaviorSubject(0), + onResponse: (req, res) => res, + legacy: { + callMsearch: jest.fn(), + loadingCount$: new BehaviorSubject(0), + }, }; indexPatternContractMock = ({ diff --git a/src/plugins/data/public/search/search_source/mocks.ts b/src/plugins/data/public/search/search_source/mocks.ts index adf53bee33fe1..f582861e37c15 100644 --- a/src/plugins/data/public/search/search_source/mocks.ts +++ b/src/plugins/data/public/search/search_source/mocks.ts @@ -18,7 +18,7 @@ */ import { BehaviorSubject } from 'rxjs'; -import { httpServiceMock, uiSettingsServiceMock } from '../../../../../core/public/mocks'; +import { uiSettingsServiceMock } from '../../../../../core/public/mocks'; import { ISearchSource, SearchSource } from './search_source'; import { SearchSourceFields } from './types'; @@ -54,6 +54,9 @@ export const createSearchSourceMock = (fields?: SearchSourceFields) => new SearchSource(fields, { getConfig: uiSettingsServiceMock.createStartContract().get, search: jest.fn(), - http: httpServiceMock.createStartContract(), - loadingCount$: new BehaviorSubject(0), + onResponse: jest.fn().mockImplementation((req, res) => res), + legacy: { + callMsearch: jest.fn(), + loadingCount$: new BehaviorSubject(0), + }, }); diff --git a/src/plugins/data/public/search/search_source/search_source.test.ts b/src/plugins/data/public/search/search_source/search_source.test.ts index 282a33e6d01f7..d9a9fb2f4fef3 100644 --- a/src/plugins/data/public/search/search_source/search_source.test.ts +++ b/src/plugins/data/public/search/search_source/search_source.test.ts @@ -22,7 +22,6 @@ import { GetConfigFn } from 'src/plugins/data/common'; import { SearchSource, SearchSourceDependencies } from './search_source'; import { IndexPattern, SortDirection } from '../..'; import { fetchSoon } from '../legacy'; -import { coreMock } from '../../../../../core/public/mocks'; jest.mock('../legacy', () => ({ fetchSoon: jest.fn().mockResolvedValue({}), @@ -68,8 +67,11 @@ describe('SearchSource', () => { searchSourceDependencies = { getConfig: jest.fn(), search: mockSearchMethod, - http: coreMock.createStart().http, - loadingCount$: new BehaviorSubject(0), + onResponse: (req, res) => res, + legacy: { + callMsearch: jest.fn(), + loadingCount$: new BehaviorSubject(0), + }, }; }); diff --git a/src/plugins/data/public/search/search_source/search_source.ts b/src/plugins/data/public/search/search_source/search_source.ts index a39898e6a9f52..4afee223454e4 100644 --- a/src/plugins/data/public/search/search_source/search_source.ts +++ b/src/plugins/data/public/search/search_source/search_source.ts @@ -72,19 +72,12 @@ import { setWith } from '@elastic/safer-lodash-set'; import { uniqueId, uniq, extend, pick, difference, omit, isObject, keys, isFunction } from 'lodash'; import { map } from 'rxjs/operators'; -import { HttpStart } from 'src/core/public'; -import { BehaviorSubject } from 'rxjs'; import { normalizeSortRequest } from './normalize_sort_request'; import { filterDocvalueFields } from './filter_docvalue_fields'; import { fieldWildcardFilter } from '../../../../kibana_utils/common'; import { IIndexPattern, ISearchGeneric } from '../..'; import { SearchSourceOptions, SearchSourceFields } from './types'; -import { - RequestFailure, - handleResponse, - getSearchParamsFromRequest, - SearchRequest, -} from '../fetch'; +import { FetchHandlers, RequestFailure, getSearchParamsFromRequest, SearchRequest } from '../fetch'; import { getEsQueryConfig, @@ -94,7 +87,6 @@ import { ISearchOptions, } from '../../../common'; import { getHighlightRequest } from '../../../common/field_formats'; -import { GetConfigFn } from '../../../common/types'; import { fetchSoon } from '../legacy'; import { extractReferences } from './extract_references'; @@ -114,11 +106,8 @@ export const searchSourceRequiredUiSettings = [ UI_SETTINGS.SORT_OPTIONS, ]; -export interface SearchSourceDependencies { - getConfig: GetConfigFn; +export interface SearchSourceDependencies extends FetchHandlers { search: ISearchGeneric; - http: HttpStart; - loadingCount$: BehaviorSubject; } /** @public **/ @@ -321,14 +310,14 @@ export class SearchSource { * @return {Observable>} */ private fetch$(searchRequest: SearchRequest, options: ISearchOptions) { - const { search, getConfig } = this.dependencies; + const { search, getConfig, onResponse } = this.dependencies; const params = getSearchParamsFromRequest(searchRequest, { getConfig, }); return search({ params, indexType: searchRequest.indexType }, options).pipe( - map(({ rawResponse }) => handleResponse(searchRequest, rawResponse)) + map(({ rawResponse }) => onResponse(searchRequest, rawResponse)) ); } @@ -337,7 +326,7 @@ export class SearchSource { * @return {Promise>} */ private async legacyFetch(searchRequest: SearchRequest, options: ISearchOptions) { - const { http, getConfig, loadingCount$ } = this.dependencies; + const { getConfig, legacy, onResponse } = this.dependencies; return await fetchSoon( searchRequest, @@ -346,9 +335,9 @@ export class SearchSource { ...options, }, { - http, - config: { get: getConfig }, - loadingCount$, + getConfig, + onResponse, + legacy, } ); } diff --git a/src/plugins/data/public/ui/shard_failure_modal/shard_failure_description.tsx b/src/plugins/data/public/ui/shard_failure_modal/shard_failure_description.tsx index 3606bfbaeb1f9..1f124291669ec 100644 --- a/src/plugins/data/public/ui/shard_failure_modal/shard_failure_description.tsx +++ b/src/plugins/data/public/ui/shard_failure_modal/shard_failure_description.tsx @@ -17,9 +17,9 @@ * under the License. */ import React from 'react'; +import { getFlattenedObject } from '@kbn/std'; import { EuiCodeBlock, EuiDescriptionList, EuiSpacer } from '@elastic/eui'; import { ShardFailure } from './shard_failure_types'; -import { getFlattenedObject } from '../../../../../core/public'; import { ShardFailureDescriptionHeader } from './shard_failure_description_header'; /** diff --git a/src/plugins/embeddable/public/lib/embeddables/default_embeddable_factory_provider.ts b/src/plugins/embeddable/public/lib/embeddables/default_embeddable_factory_provider.ts index 570a78fc41ea9..b22f16c94aff8 100644 --- a/src/plugins/embeddable/public/lib/embeddables/default_embeddable_factory_provider.ts +++ b/src/plugins/embeddable/public/lib/embeddables/default_embeddable_factory_provider.ts @@ -37,11 +37,11 @@ export const defaultEmbeddableFactoryProvider = < getExplicitInput: def.getExplicitInput ? def.getExplicitInput.bind(def) : () => Promise.resolve({}), - createFromSavedObject: - def.createFromSavedObject ?? - ((savedObjectId: string, input: Partial, parent?: IContainer) => { - throw new Error(`Creation from saved object not supported by type ${def.type}`); - }), + createFromSavedObject: def.createFromSavedObject + ? def.createFromSavedObject.bind(def) + : (savedObjectId: string, input: Partial, parent?: IContainer) => { + throw new Error(`Creation from saved object not supported by type ${def.type}`); + }, create: def.create.bind(def), type: def.type, isEditable: def.isEditable.bind(def), diff --git a/src/plugins/kibana_react/README.md b/src/plugins/kibana_react/README.md index 3389af9f1800b..adbdb628ea9dd 100644 --- a/src/plugins/kibana_react/README.md +++ b/src/plugins/kibana_react/README.md @@ -2,7 +2,6 @@ Tools for building React applications in Kibana. - ## Context You can create React context that holds Core or plugin services that your plugin depends on. @@ -51,7 +50,6 @@ import { KibanaContextProvider } from 'kibana-react'; ``` - ## Accessing context Using `useKibana` hook. @@ -61,11 +59,7 @@ import { useKibana } from 'kibana-react'; const Demo = () => { const kibana = useKibana(); - return ( -
- {kibana.services.uiSettings.get('theme:darkMode') ? 'dark' : 'light'} -
- ); + return
{kibana.services.uiSettings.get('theme:darkMode') ? 'dark' : 'light'}
; }; ``` @@ -75,11 +69,7 @@ Using `withKibana()` higher order component. import { withKibana } from 'kibana-react'; const Demo = ({ kibana }) => { - return ( -
- {kibana.services.uiSettings.get('theme:darkMode') ? 'dark' : 'light'} -
- ); + return
{kibana.services.uiSettings.get('theme:darkMode') ? 'dark' : 'light'}
; }; export default withKibana(Demo); @@ -92,21 +82,17 @@ import { UseKibana } from 'kibana-react'; const Demo = () => { return ( - {kibana => -
- {kibana.services.uiSettings.get('theme:darkMode') ? 'dark' : 'light'} -
- }
+ + {(kibana) =>
{kibana.services.uiSettings.get('theme:darkMode') ? 'dark' : 'light'}
} +
); }; ``` - ## `uiSettings` service Wrappers around Core's `uiSettings` service. - ### `useUiSetting` hook `useUiSetting` synchronously returns the latest setting from `CoreStart['uiSettings']` service. @@ -116,11 +102,7 @@ import { useUiSetting } from 'kibana-react'; const Demo = () => { const darkMode = useUiSetting('theme:darkMode'); - return ( -
- {darkMode ? 'dark' : 'light'} -
- ); + return
{darkMode ? 'dark' : 'light'}
; }; ``` @@ -130,7 +112,6 @@ const Demo = () => { useUiSetting(key: string, defaultValue: T): T; ``` - ### `useUiSetting$` hook `useUiSetting$` synchronously returns the latest setting from `CoreStart['uiSettings']` service and @@ -141,11 +122,7 @@ import { useUiSetting$ } from 'kibana-react'; const Demo = () => { const [darkMode] = useUiSetting$('theme:darkMode'); - return ( -
- {darkMode ? 'dark' : 'light'} -
- ); + return
{darkMode ? 'dark' : 'light'}
; }; ``` @@ -155,7 +132,6 @@ const Demo = () => { useUiSetting$(key: string, defaultValue: T): [T, (newValue: T) => void]; ``` - ## `overlays` service Wrapper around Core's `overlays` service, allows you to display React modals and flyouts @@ -166,13 +142,11 @@ import { createKibanaReactContext } from 'kibana-react'; class MyPlugin { start(core) { - const { value: { overlays } } = createKibanaReactContext(core); + const { + value: { overlays }, + } = createKibanaReactContext(core); - overlays.openModal( -
- Hello world! -
- ); + overlays.openModal(
Hello world!
); } } ``` @@ -186,16 +160,11 @@ You can access `overlays` service through React context. const Demo = () => { const { overlays } = useKibana(); useEffect(() => { - overlays.openModal( -
- Oooops! {errorMessage} -
- ); + overlays.openModal(
Oooops! {errorMessage}
); }, [errorMessage]); }; ``` - ## `notifications` service Wrapper around Core's `notifications` service, allows you to render React elements @@ -206,11 +175,13 @@ import { createKibanaReactContext } from 'kibana-react'; class MyPlugin { start(core) { - const { value: { notifications } } = createKibanaReactContext(core); + const { + value: { notifications }, + } = createKibanaReactContext(core); notifications.toasts.show({ title:
Hello
, - body:
world!
+ body:
world!
, }); } } @@ -234,3 +205,15 @@ const Demo = () => { }, [errorMessage]); }; ``` + +## RedirectAppLinks + +Utility component that will intercept click events on children anchor (`
`) elements to call +`application.navigateToUrl` with the link's href. This will trigger SPA friendly navigation +when the link points to a valid Kibana app. + +```tsx + + Go to another-app + +``` diff --git a/src/plugins/kibana_utils/common/state_containers/README.md b/src/plugins/kibana_utils/common/state_containers/README.md new file mode 100644 index 0000000000000..c623e8b306438 --- /dev/null +++ b/src/plugins/kibana_utils/common/state_containers/README.md @@ -0,0 +1,2 @@ +* [docs](../../docs/state_containers) +* [api reference](https://github.com/elastic/kibana/tree/master/src/plugins/kibana_utils/docs/state_containers) \ No newline at end of file diff --git a/src/plugins/kibana_utils/docs/state_sync/README.md b/src/plugins/kibana_utils/docs/state_sync/README.md index c84bf7f236330..6b4eb0cb1749b 100644 --- a/src/plugins/kibana_utils/docs/state_sync/README.md +++ b/src/plugins/kibana_utils/docs/state_sync/README.md @@ -3,6 +3,18 @@ State syncing utilities are a set of helpers for syncing your application state with URL or browser storage. +**When you should consider using state syncing utils:** + +- You want to sync your application state with URL in similar manner analyze applications do that. +- You want to follow platform's <> out of the box. +- You want to support `state:storeInSessionStore` escape hatch for URL overflowing out of the box. +- You should also consider using them if you'd like to serialize state to different (not `rison`) format. Utils are composable, and you can implement your own `storage`. +- In case you want to sync part of your state with URL, but other part of it with browser storage. + +**When you shouldn't look into using state syncing utils:** + +- Adding a query param flag or simple key/value to URL + They are designed to work together with [state containers](../state_containers). But state containers are not required. State syncing utilities include: @@ -42,9 +54,9 @@ stateContainer.set({ count: 2 }); stop(); ``` -## Demos Plugins +## Demo Plugins -See demos plugins [here](../../../../../examples/state_containers_examples). +See demo plugins [here](../../../../../examples/state_containers_examples). To run them, start kibana with `--run-examples` flag. diff --git a/src/plugins/kibana_utils/public/state_sync/README.md b/src/plugins/kibana_utils/public/state_sync/README.md new file mode 100644 index 0000000000000..eb5f6e60958fc --- /dev/null +++ b/src/plugins/kibana_utils/public/state_sync/README.md @@ -0,0 +1,3 @@ +- [docs](../../docs/state_sync) +- [demo plugins](../../../../../examples/state_containers_examples): run Kibana with `--run-examples` flag. +- [api reference](https://github.com/elastic/kibana/tree/master/src/plugins/kibana_utils/docs/state_sync) diff --git a/src/plugins/share/server/routes/goto.ts b/src/plugins/share/server/routes/goto.ts index 193f2acb87c95..0cd6d26adac26 100644 --- a/src/plugins/share/server/routes/goto.ts +++ b/src/plugins/share/server/routes/goto.ts @@ -19,11 +19,11 @@ import { CoreSetup, IRouter } from 'kibana/server'; import { schema } from '@kbn/config-schema'; +import { modifyUrl } from '@kbn/std'; import { shortUrlAssertValid } from './lib/short_url_assert_valid'; import { ShortUrlLookupService } from './lib/short_url_lookup'; import { getGotoPath } from '../../common/short_url_routes'; -import { modifyUrl } from '../../../../core/server'; export const createGotoRoute = ({ router, diff --git a/src/plugins/vis_type_timelion/server/plugin.ts b/src/plugins/vis_type_timelion/server/plugin.ts index 52c50b0646299..c518b73bb3cde 100644 --- a/src/plugins/vis_type_timelion/server/plugin.ts +++ b/src/plugins/vis_type_timelion/server/plugin.ts @@ -21,10 +21,10 @@ import { i18n } from '@kbn/i18n'; import { first } from 'rxjs/operators'; import { TypeOf, schema } from '@kbn/config-schema'; import { RecursiveReadonly } from '@kbn/utility-types'; +import { deepFreeze } from '@kbn/std'; import { PluginStart } from '../../../../src/plugins/data/server'; import { CoreSetup, PluginInitializerContext } from '../../../../src/core/server'; -import { deepFreeze } from '../../../../src/core/server'; import { configSchema } from '../config'; import loadFunctions from './lib/load_functions'; import { functionsRoute } from './routes/functions'; diff --git a/src/plugins/vis_type_timeseries/server/lib/vis_data/request_processors/table/filter_ratios.js b/src/plugins/vis_type_timeseries/server/lib/vis_data/request_processors/table/filter_ratios.js index 707ccd1e55bb0..13874166bc558 100644 --- a/src/plugins/vis_type_timeseries/server/lib/vis_data/request_processors/table/filter_ratios.js +++ b/src/plugins/vis_type_timeseries/server/lib/vis_data/request_processors/table/filter_ratios.js @@ -18,22 +18,27 @@ */ const filter = (metric) => metric.type === 'filter_ratio'; +import { esQuery } from '../../../../../../data/server'; import { bucketTransform } from '../../helpers/bucket_transform'; import { overwrite } from '../../helpers'; import { calculateAggRoot } from './calculate_agg_root'; -export function ratios(req, panel) { +export function ratios(req, panel, esQueryConfig, indexPatternObject) { return (next) => (doc) => { panel.series.forEach((column) => { const aggRoot = calculateAggRoot(doc, column); if (column.metrics.some(filter)) { column.metrics.filter(filter).forEach((metric) => { - overwrite(doc, `${aggRoot}.timeseries.aggs.${metric.id}-numerator.filter`, { - query_string: { query: metric.numerator || '*', analyze_wildcard: true }, - }); - overwrite(doc, `${aggRoot}.timeseries.aggs.${metric.id}-denominator.filter`, { - query_string: { query: metric.denominator || '*', analyze_wildcard: true }, - }); + overwrite( + doc, + `${aggRoot}.timeseries.aggs.${metric.id}-numerator.filter`, + esQuery.buildEsQuery(indexPatternObject, metric.numerator, [], esQueryConfig) + ); + overwrite( + doc, + `${aggRoot}.timeseries.aggs.${metric.id}-denominator.filter`, + esQuery.buildEsQuery(indexPatternObject, metric.denominator, [], esQueryConfig) + ); let numeratorPath = `${metric.id}-numerator>_count`; let denominatorPath = `${metric.id}-denominator>_count`; @@ -46,7 +51,7 @@ export function ratios(req, panel) { }), }; overwrite(doc, `${aggRoot}.timeseries.aggs.${metric.id}-numerator.aggs`, aggBody); - overwrite(doc, `${aggBody}.timeseries.aggs.${metric.id}-denominator.aggs`, aggBody); + overwrite(doc, `${aggRoot}.timeseries.aggs.${metric.id}-denominator.aggs`, aggBody); numeratorPath = `${metric.id}-numerator>metric`; denominatorPath = `${metric.id}-denominator>metric`; } diff --git a/src/plugins/visualizations/kibana.json b/src/plugins/visualizations/kibana.json index da3edfbdd3bf5..0bd5de1d9ee15 100644 --- a/src/plugins/visualizations/kibana.json +++ b/src/plugins/visualizations/kibana.json @@ -3,6 +3,6 @@ "version": "kibana", "server": true, "ui": true, - "requiredPlugins": ["data", "expressions", "uiActions", "embeddable", "usageCollection", "inspector"], + "requiredPlugins": ["data", "expressions", "uiActions", "embeddable", "usageCollection", "inspector", "dashboard"], "requiredBundles": ["kibanaUtils", "discover", "savedObjects"] } diff --git a/src/plugins/visualizations/public/embeddable/create_vis_embeddable_from_object.ts b/src/plugins/visualizations/public/embeddable/create_vis_embeddable_from_object.ts index 194deef82a5f0..b27d24d980e8d 100644 --- a/src/plugins/visualizations/public/embeddable/create_vis_embeddable_from_object.ts +++ b/src/plugins/visualizations/public/embeddable/create_vis_embeddable_from_object.ts @@ -18,7 +18,13 @@ */ import { Vis } from '../types'; -import { VisualizeInput, VisualizeEmbeddable } from './visualize_embeddable'; +import { + VisualizeInput, + VisualizeEmbeddable, + VisualizeByValueInput, + VisualizeByReferenceInput, + VisualizeSavedObjectAttributes, +} from './visualize_embeddable'; import { IContainer, ErrorEmbeddable } from '../../../../plugins/embeddable/public'; import { DisabledLabEmbeddable } from './disabled_lab_embeddable'; import { @@ -30,10 +36,18 @@ import { } from '../services'; import { VisualizeEmbeddableFactoryDeps } from './visualize_embeddable_factory'; import { VISUALIZE_ENABLE_LABS_SETTING } from '../../common/constants'; +import { SavedVisualizationsLoader } from '../saved_visualizations'; +import { AttributeService } from '../../../dashboard/public'; export const createVisEmbeddableFromObject = (deps: VisualizeEmbeddableFactoryDeps) => async ( vis: Vis, input: Partial & { id: string }, + savedVisualizationsLoader?: SavedVisualizationsLoader, + attributeService?: AttributeService< + VisualizeSavedObjectAttributes, + VisualizeByValueInput, + VisualizeByReferenceInput + >, parent?: IContainer ): Promise => { const savedVisualizations = getSavedVisualizationsLoader(); @@ -55,6 +69,7 @@ export const createVisEmbeddableFromObject = (deps: VisualizeEmbeddableFactoryDe const indexPattern = vis.data.indexPattern; const indexPatterns = indexPattern ? [indexPattern] : []; const editable = getCapabilities().visualize.save as boolean; + return new VisualizeEmbeddable( getTimeFilter(), { @@ -66,6 +81,8 @@ export const createVisEmbeddableFromObject = (deps: VisualizeEmbeddableFactoryDe deps, }, input, + attributeService, + savedVisualizationsLoader, parent ); } catch (e) { diff --git a/src/plugins/visualizations/public/embeddable/visualize_embeddable.ts b/src/plugins/visualizations/public/embeddable/visualize_embeddable.ts index cc278a6ee9b3d..18ae68ec40fe5 100644 --- a/src/plugins/visualizations/public/embeddable/visualize_embeddable.ts +++ b/src/plugins/visualizations/public/embeddable/visualize_embeddable.ts @@ -20,6 +20,7 @@ import _, { get } from 'lodash'; import { Subscription } from 'rxjs'; import * as Rx from 'rxjs'; +import { i18n } from '@kbn/i18n'; import { VISUALIZE_EMBEDDABLE_TYPE } from './constants'; import { IIndexPattern, @@ -35,6 +36,8 @@ import { Embeddable, IContainer, Adapters, + SavedObjectEmbeddableInput, + ReferenceOrValueEmbeddable, } from '../../../../plugins/embeddable/public'; import { IExpressionLoaderParams, @@ -47,6 +50,10 @@ import { getExpressions, getUiActions } from '../services'; import { VIS_EVENT_TO_TRIGGER } from './events'; import { VisualizeEmbeddableFactoryDeps } from './visualize_embeddable_factory'; import { TriggerId } from '../../../ui_actions/public'; +import { SavedObjectAttributes } from '../../../../core/types'; +import { AttributeService } from '../../../dashboard/public'; +import { SavedVisualizationsLoader } from '../saved_visualizations'; +import { VisSavedObject } from '../types'; const getKeys = (o: T): Array => Object.keys(o) as Array; @@ -75,9 +82,19 @@ export interface VisualizeOutput extends EmbeddableOutput { visTypeName: string; } +export type VisualizeSavedObjectAttributes = SavedObjectAttributes & { + title: string; + vis?: Vis; + savedVis?: VisSavedObject; +}; +export type VisualizeByValueInput = { attributes: VisualizeSavedObjectAttributes } & VisualizeInput; +export type VisualizeByReferenceInput = SavedObjectEmbeddableInput & VisualizeInput; + type ExpressionLoader = InstanceType; -export class VisualizeEmbeddable extends Embeddable { +export class VisualizeEmbeddable + extends Embeddable + implements ReferenceOrValueEmbeddable { private handler?: ExpressionLoader; private timefilter: TimefilterContract; private timeRange?: TimeRange; @@ -93,11 +110,23 @@ export class VisualizeEmbeddable extends Embeddable; + private savedVisualizationsLoader?: SavedVisualizationsLoader; constructor( timefilter: TimefilterContract, { vis, editPath, editUrl, indexPatterns, editable, deps }: VisualizeEmbeddableConfiguration, initialInput: VisualizeInput, + attributeService?: AttributeService< + VisualizeSavedObjectAttributes, + VisualizeByValueInput, + VisualizeByReferenceInput + >, + savedVisualizationsLoader?: SavedVisualizationsLoader, parent?: IContainer ) { super( @@ -118,6 +147,8 @@ export class VisualizeEmbeddable extends Embeddable { + if (!this.attributeService) { + throw new Error('AttributeService must be defined for getInputAsRefType'); + } + return this.attributeService.inputIsRefType(input as VisualizeByReferenceInput); + }; + + getInputAsValueType = async (): Promise => { + const input = { + savedVis: this.vis.serialize(), + }; + if (this.getTitle()) { + input.savedVis.title = this.getTitle(); + } + delete input.savedVis.id; + return new Promise((resolve) => { + resolve({ ...(input as VisualizeByValueInput) }); + }); + }; + + getInputAsRefType = async (): Promise => { + const savedVis = await this.savedVisualizationsLoader?.get({}); + if (!savedVis) { + throw new Error('Error creating a saved vis object'); + } + if (!this.attributeService) { + throw new Error('AttributeService must be defined for getInputAsRefType'); + } + const saveModalTitle = this.getTitle() + ? this.getTitle() + : i18n.translate('visualizations.embeddable.placeholderTitle', { + defaultMessage: 'Placeholder Title', + }); + // @ts-ignore + const attributes: VisualizeSavedObjectAttributes = { + savedVis, + vis: this.vis, + title: this.vis.title, + }; + return this.attributeService.getInputAsRefType( + { + id: this.id, + attributes, + }, + { showSaveModal: true, saveModalTitle } + ); + }; } diff --git a/src/plugins/visualizations/public/embeddable/visualize_embeddable_factory.tsx b/src/plugins/visualizations/public/embeddable/visualize_embeddable_factory.tsx index b81ff5c166183..75e53e8e92dbe 100644 --- a/src/plugins/visualizations/public/embeddable/visualize_embeddable_factory.tsx +++ b/src/plugins/visualizations/public/embeddable/visualize_embeddable_factory.tsx @@ -28,7 +28,14 @@ import { IContainer, } from '../../../embeddable/public'; import { DisabledLabEmbeddable } from './disabled_lab_embeddable'; -import { VisualizeEmbeddable, VisualizeInput, VisualizeOutput } from './visualize_embeddable'; +import { + VisualizeByReferenceInput, + VisualizeByValueInput, + VisualizeEmbeddable, + VisualizeInput, + VisualizeOutput, + VisualizeSavedObjectAttributes, +} from './visualize_embeddable'; import { VISUALIZE_EMBEDDABLE_TYPE } from './constants'; import { SerializedVis, Vis } from '../vis'; import { @@ -43,13 +50,16 @@ import { createVisEmbeddableFromObject } from './create_vis_embeddable_from_obje import { StartServicesGetter } from '../../../kibana_utils/public'; import { VisualizationsStartDeps } from '../plugin'; import { VISUALIZE_ENABLE_LABS_SETTING } from '../../common/constants'; +import { AttributeService } from '../../../dashboard/public'; interface VisualizationAttributes extends SavedObjectAttributes { visState: string; } export interface VisualizeEmbeddableFactoryDeps { - start: StartServicesGetter>; + start: StartServicesGetter< + Pick + >; } export class VisualizeEmbeddableFactory @@ -62,6 +72,12 @@ export class VisualizeEmbeddableFactory > { public readonly type = VISUALIZE_EMBEDDABLE_TYPE; + private attributeService?: AttributeService< + VisualizeSavedObjectAttributes, + VisualizeByValueInput, + VisualizeByReferenceInput + >; + public readonly savedObjectMetaData: SavedObjectMetaData = { name: i18n.translate('visualizations.savedObjectName', { defaultMessage: 'Visualization' }), includeFields: ['visState'], @@ -105,6 +121,19 @@ export class VisualizeEmbeddableFactory return await this.deps.start().core.application.currentAppId$.pipe(first()).toPromise(); } + private async getAttributeService() { + if (!this.attributeService) { + this.attributeService = await this.deps + .start() + .plugins.dashboard.getAttributeService< + VisualizeSavedObjectAttributes, + VisualizeByValueInput, + VisualizeByReferenceInput + >(this.type, { customSaveMethod: this.onSave }); + } + return this.attributeService!; + } + public async createFromSavedObject( savedObjectId: string, input: Partial & { id: string }, @@ -117,7 +146,13 @@ export class VisualizeEmbeddableFactory const visState = convertToSerializedVis(savedObject); const vis = new Vis(savedObject.visState.type, visState); await vis.setState(visState); - return createVisEmbeddableFromObject(this.deps)(vis, input, parent); + return createVisEmbeddableFromObject(this.deps)( + vis, + input, + savedVisualizations, + await this.getAttributeService(), + parent + ); } catch (e) { console.error(e); // eslint-disable-line no-console return new ErrorEmbeddable(e, input, parent); @@ -131,7 +166,14 @@ export class VisualizeEmbeddableFactory const visState = input.savedVis; const vis = new Vis(visState.type, visState); await vis.setState(visState); - return createVisEmbeddableFromObject(this.deps)(vis, input, parent); + const savedVisualizations = getSavedVisualizationsLoader(); + return createVisEmbeddableFromObject(this.deps)( + vis, + input, + savedVisualizations, + await this.getAttributeService(), + parent + ); } else { showNewVisModal({ originatingApp: await this.getCurrentAppId(), @@ -140,4 +182,47 @@ export class VisualizeEmbeddableFactory return undefined; } } + + private async onSave( + type: string, + attributes: VisualizeSavedObjectAttributes + ): Promise<{ id: string }> { + try { + const { title, savedVis } = attributes; + const visObj = attributes.vis; + if (!savedVis) { + throw new Error('No Saved Vis'); + } + const saveOptions = { + confirmOverwrite: false, + returnToOrigin: true, + }; + savedVis.title = title; + savedVis.copyOnSave = false; + savedVis.description = ''; + savedVis.searchSourceFields = visObj?.data.searchSource?.getSerializedFields(); + const serializedVis = ((visObj as unknown) as Vis).serialize(); + const { params, data } = serializedVis; + savedVis.visState = { + title, + type: serializedVis.type, + params, + aggs: data.aggs, + }; + if (visObj) { + savedVis.uiStateJSON = visObj?.uiState.toString(); + } + const id = await savedVis.save(saveOptions); + if (!id || id === '') { + throw new Error( + i18n.translate('visualizations.savingVisualizationFailed.errorMsg', { + defaultMessage: 'Saving a visualization failed', + }) + ); + } + return { id }; + } catch (error) { + throw error; + } + } } diff --git a/src/plugins/visualizations/public/mocks.ts b/src/plugins/visualizations/public/mocks.ts index e0ec4801b3caf..646acc49a6a83 100644 --- a/src/plugins/visualizations/public/mocks.ts +++ b/src/plugins/visualizations/public/mocks.ts @@ -27,6 +27,7 @@ import { dataPluginMock } from '../../../plugins/data/public/mocks'; import { usageCollectionPluginMock } from '../../../plugins/usage_collection/public/mocks'; import { uiActionsPluginMock } from '../../../plugins/ui_actions/public/mocks'; import { inspectorPluginMock } from '../../../plugins/inspector/public/mocks'; +import { dashboardPluginMock } from '../../../plugins/dashboard/public/mocks'; const createSetupContract = (): VisualizationsSetup => ({ createBaseVisualization: jest.fn(), @@ -69,6 +70,8 @@ const createInstance = async () => { uiActions: uiActionsPluginMock.createStartContract(), application: applicationServiceMock.createStartContract(), embeddable: embeddablePluginMock.createStartContract(), + dashboard: dashboardPluginMock.createStartContract(), + getAttributeService: jest.fn(), }); return { diff --git a/src/plugins/visualizations/public/plugin.ts b/src/plugins/visualizations/public/plugin.ts index 3546fa4056491..0ba80887b513f 100644 --- a/src/plugins/visualizations/public/plugin.ts +++ b/src/plugins/visualizations/public/plugin.ts @@ -76,6 +76,7 @@ import { convertToSerializedVis, } from './saved_visualizations/_saved_vis'; import { createSavedSearchesLoader } from '../../discover/public'; +import { DashboardStart } from '../../dashboard/public'; /** * Interface for this plugin's returned setup/start contracts. @@ -109,6 +110,8 @@ export interface VisualizationsStartDeps { inspector: InspectorStart; uiActions: UiActionsStart; application: ApplicationStart; + dashboard: DashboardStart; + getAttributeService: DashboardStart['getAttributeService']; } /** @@ -155,7 +158,7 @@ export class VisualizationsPlugin public start( core: CoreStart, - { data, expressions, uiActions, embeddable }: VisualizationsStartDeps + { data, expressions, uiActions, embeddable, dashboard }: VisualizationsStartDeps ): VisualizationsStart { const types = this.types.start(); setI18n(core.i18n); diff --git a/test/accessibility/apps/discover.ts b/test/accessibility/apps/discover.ts index 7e905fbe89fbd..44639af9da9f8 100644 --- a/test/accessibility/apps/discover.ts +++ b/test/accessibility/apps/discover.ts @@ -34,7 +34,8 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { ['geo.src', 'IN'], ]; - describe('Discover', () => { + // Failing: See https://github.com/elastic/kibana/issues/59975 + describe.skip('Discover', () => { before(async () => { await esArchiver.load('discover'); await esArchiver.loadIfNeeded('logstash_functional'); diff --git a/test/functional/page_objects/vega_chart_page.ts b/test/functional/page_objects/vega_chart_page.ts index 557c6bfada01e..044b6b61790ac 100644 --- a/test/functional/page_objects/vega_chart_page.ts +++ b/test/functional/page_objects/vega_chart_page.ts @@ -17,7 +17,6 @@ * under the License. */ -import { Key } from 'selenium-webdriver'; import expect from '@kbn/expect'; import { FtrProviderContext } from '../ftr_provider_context'; @@ -94,9 +93,9 @@ export function VegaChartPageProvider({ const aceGutter = await this.getAceGutterContainer(); await aceGutter.doubleClick(); - await browser.pressKeys(Key.RIGHT); - await browser.pressKeys(Key.LEFT); - await browser.pressKeys(Key.LEFT); + await browser.pressKeys(browser.keys.RIGHT); + await browser.pressKeys(browser.keys.LEFT); + await browser.pressKeys(browser.keys.LEFT); await browser.pressKeys(text); } @@ -105,7 +104,7 @@ export function VegaChartPageProvider({ await retry.try(async () => { await aceGutter.doubleClick(); - await browser.pressKeys(Key.BACK_SPACE); + await browser.pressKeys(browser.keys.BACK_SPACE); expect(await this.getSpec()).to.be(''); }); diff --git a/test/functional/page_objects/visual_builder_page.ts b/test/functional/page_objects/visual_builder_page.ts index a95d535281fa3..6e49fd3b03494 100644 --- a/test/functional/page_objects/visual_builder_page.ts +++ b/test/functional/page_objects/visual_builder_page.ts @@ -58,7 +58,10 @@ export function VisualBuilderPageProvider({ getService, getPageObjects }: FtrPro } public async checkTabIsLoaded(testSubj: string, name: string) { - const isPresent = await testSubjects.exists(testSubj, { timeout: 10000 }); + let isPresent = false; + await retry.try(async () => { + isPresent = await testSubjects.exists(testSubj, { timeout: 20000 }); + }); if (!isPresent) { throw new Error(`TSVB ${name} tab is not loaded`); } @@ -130,8 +133,8 @@ export function VisualBuilderPageProvider({ getService, getPageObjects }: FtrPro public async enterMarkdown(markdown: string) { const input = await find.byCssSelector('.tvbMarkdownEditor__editor textarea'); await this.clearMarkdown(); - await input.type(markdown, { charByChar: true }); - await PageObjects.visChart.waitForVisualizationRenderingStabilized(); + await input.type(markdown); + await PageObjects.common.sleep(3000); } public async clearMarkdown() { diff --git a/test/functional/services/common/browser.ts b/test/functional/services/common/browser.ts index e81845023a8fa..2f8e87c1d58d6 100644 --- a/test/functional/services/common/browser.ts +++ b/test/functional/services/common/browser.ts @@ -22,9 +22,9 @@ import { Key, Origin } from 'selenium-webdriver'; // @ts-ignore internal modules are not typed import { LegacyActionSequence } from 'selenium-webdriver/lib/actions'; import { ProvidedType } from '@kbn/test/types/ftr'; +import { modifyUrl } from '@kbn/std'; import Jimp from 'jimp'; -import { modifyUrl } from '../../../../src/core/utils'; import { WebElementWrapper } from '../lib/web_element_wrapper'; import { FtrProviderContext } from '../../ftr_provider_context'; import { Browsers } from '../remote/browsers'; diff --git a/test/interpreter_functional/plugins/kbn_tp_run_pipeline/tsconfig.json b/test/interpreter_functional/plugins/kbn_tp_run_pipeline/tsconfig.json index 4d979fbf7f15f..f77a5eaffc301 100644 --- a/test/interpreter_functional/plugins/kbn_tp_run_pipeline/tsconfig.json +++ b/test/interpreter_functional/plugins/kbn_tp_run_pipeline/tsconfig.json @@ -10,5 +10,8 @@ "public/**/*.tsx", "../../../../typings/**/*", ], - "exclude": [] + "exclude": [], + "references": [ + { "path": "../../../../src/core/tsconfig.json" } + ] } diff --git a/test/plugin_functional/plugins/app_link_test/tsconfig.json b/test/plugin_functional/plugins/app_link_test/tsconfig.json index 4d979fbf7f15f..f77a5eaffc301 100644 --- a/test/plugin_functional/plugins/app_link_test/tsconfig.json +++ b/test/plugin_functional/plugins/app_link_test/tsconfig.json @@ -10,5 +10,8 @@ "public/**/*.tsx", "../../../../typings/**/*", ], - "exclude": [] + "exclude": [], + "references": [ + { "path": "../../../../src/core/tsconfig.json" } + ] } diff --git a/test/plugin_functional/plugins/core_plugin_a/tsconfig.json b/test/plugin_functional/plugins/core_plugin_a/tsconfig.json index ccbffc34bce4a..3d9d8ca9451d4 100644 --- a/test/plugin_functional/plugins/core_plugin_a/tsconfig.json +++ b/test/plugin_functional/plugins/core_plugin_a/tsconfig.json @@ -11,5 +11,8 @@ "server/**/*.ts", "../../../../typings/**/*", ], - "exclude": [] + "exclude": [], + "references": [ + { "path": "../../../../src/core/tsconfig.json" } + ] } diff --git a/test/plugin_functional/plugins/core_plugin_appleave/tsconfig.json b/test/plugin_functional/plugins/core_plugin_appleave/tsconfig.json index 4d979fbf7f15f..f77a5eaffc301 100644 --- a/test/plugin_functional/plugins/core_plugin_appleave/tsconfig.json +++ b/test/plugin_functional/plugins/core_plugin_appleave/tsconfig.json @@ -10,5 +10,8 @@ "public/**/*.tsx", "../../../../typings/**/*", ], - "exclude": [] + "exclude": [], + "references": [ + { "path": "../../../../src/core/tsconfig.json" } + ] } diff --git a/test/plugin_functional/plugins/core_plugin_b/tsconfig.json b/test/plugin_functional/plugins/core_plugin_b/tsconfig.json index ccbffc34bce4a..3d9d8ca9451d4 100644 --- a/test/plugin_functional/plugins/core_plugin_b/tsconfig.json +++ b/test/plugin_functional/plugins/core_plugin_b/tsconfig.json @@ -11,5 +11,8 @@ "server/**/*.ts", "../../../../typings/**/*", ], - "exclude": [] + "exclude": [], + "references": [ + { "path": "../../../../src/core/tsconfig.json" } + ] } diff --git a/test/plugin_functional/plugins/core_plugin_chromeless/tsconfig.json b/test/plugin_functional/plugins/core_plugin_chromeless/tsconfig.json index 4d979fbf7f15f..f77a5eaffc301 100644 --- a/test/plugin_functional/plugins/core_plugin_chromeless/tsconfig.json +++ b/test/plugin_functional/plugins/core_plugin_chromeless/tsconfig.json @@ -10,5 +10,8 @@ "public/**/*.tsx", "../../../../typings/**/*", ], - "exclude": [] + "exclude": [], + "references": [ + { "path": "../../../../src/core/tsconfig.json" } + ] } diff --git a/test/plugin_functional/plugins/core_plugin_route_timeouts/tsconfig.json b/test/plugin_functional/plugins/core_plugin_route_timeouts/tsconfig.json index 0e27246a49980..72793a327d97e 100644 --- a/test/plugin_functional/plugins/core_plugin_route_timeouts/tsconfig.json +++ b/test/plugin_functional/plugins/core_plugin_route_timeouts/tsconfig.json @@ -8,5 +8,8 @@ "server/**/*.ts", "../../../../typings/**/*" ], - "exclude": [] + "exclude": [], + "references": [ + { "path": "../../../../src/core/tsconfig.json" } + ] } diff --git a/test/plugin_functional/plugins/core_plugin_static_assets/tsconfig.json b/test/plugin_functional/plugins/core_plugin_static_assets/tsconfig.json index 433b041b9af3f..f9b0443e0a8bf 100644 --- a/test/plugin_functional/plugins/core_plugin_static_assets/tsconfig.json +++ b/test/plugin_functional/plugins/core_plugin_static_assets/tsconfig.json @@ -10,5 +10,8 @@ "public/**/*.tsx", "../../../../typings/**/*" ], - "exclude": [] + "exclude": [], + "references": [ + { "path": "../../../../src/core/tsconfig.json" } + ] } diff --git a/test/plugin_functional/plugins/core_provider_plugin/tsconfig.json b/test/plugin_functional/plugins/core_provider_plugin/tsconfig.json index 0aac2eb570987..eacd2f5e9aee3 100644 --- a/test/plugin_functional/plugins/core_provider_plugin/tsconfig.json +++ b/test/plugin_functional/plugins/core_provider_plugin/tsconfig.json @@ -10,5 +10,8 @@ "public/**/*.ts", "../../../../typings/**/*" ], - "exclude": [] + "exclude": [], + "references": [ + { "path": "../../../../src/core/tsconfig.json" } + ] } diff --git a/test/plugin_functional/plugins/doc_views_plugin/tsconfig.json b/test/plugin_functional/plugins/doc_views_plugin/tsconfig.json index 433b041b9af3f..f9b0443e0a8bf 100644 --- a/test/plugin_functional/plugins/doc_views_plugin/tsconfig.json +++ b/test/plugin_functional/plugins/doc_views_plugin/tsconfig.json @@ -10,5 +10,8 @@ "public/**/*.tsx", "../../../../typings/**/*" ], - "exclude": [] + "exclude": [], + "references": [ + { "path": "../../../../src/core/tsconfig.json" } + ] } diff --git a/test/plugin_functional/plugins/elasticsearch_client_plugin/tsconfig.json b/test/plugin_functional/plugins/elasticsearch_client_plugin/tsconfig.json index 0e27246a49980..72793a327d97e 100644 --- a/test/plugin_functional/plugins/elasticsearch_client_plugin/tsconfig.json +++ b/test/plugin_functional/plugins/elasticsearch_client_plugin/tsconfig.json @@ -8,5 +8,8 @@ "server/**/*.ts", "../../../../typings/**/*" ], - "exclude": [] + "exclude": [], + "references": [ + { "path": "../../../../src/core/tsconfig.json" } + ] } diff --git a/test/plugin_functional/plugins/index_patterns/tsconfig.json b/test/plugin_functional/plugins/index_patterns/tsconfig.json index d5ccf7adddb2d..9d11a9850f151 100644 --- a/test/plugin_functional/plugins/index_patterns/tsconfig.json +++ b/test/plugin_functional/plugins/index_patterns/tsconfig.json @@ -10,5 +10,8 @@ "server/**/*.tsx", "../../../../typings/**/*", ], - "exclude": [] + "exclude": [], + "references": [ + { "path": "../../../../src/core/tsconfig.json" } + ] } diff --git a/test/plugin_functional/plugins/kbn_sample_panel_action/tsconfig.json b/test/plugin_functional/plugins/kbn_sample_panel_action/tsconfig.json index 4d979fbf7f15f..f77a5eaffc301 100644 --- a/test/plugin_functional/plugins/kbn_sample_panel_action/tsconfig.json +++ b/test/plugin_functional/plugins/kbn_sample_panel_action/tsconfig.json @@ -10,5 +10,8 @@ "public/**/*.tsx", "../../../../typings/**/*", ], - "exclude": [] + "exclude": [], + "references": [ + { "path": "../../../../src/core/tsconfig.json" } + ] } diff --git a/test/plugin_functional/plugins/kbn_top_nav/tsconfig.json b/test/plugin_functional/plugins/kbn_top_nav/tsconfig.json index ccbffc34bce4a..3d9d8ca9451d4 100644 --- a/test/plugin_functional/plugins/kbn_top_nav/tsconfig.json +++ b/test/plugin_functional/plugins/kbn_top_nav/tsconfig.json @@ -11,5 +11,8 @@ "server/**/*.ts", "../../../../typings/**/*", ], - "exclude": [] + "exclude": [], + "references": [ + { "path": "../../../../src/core/tsconfig.json" } + ] } diff --git a/test/plugin_functional/plugins/kbn_tp_custom_visualizations/tsconfig.json b/test/plugin_functional/plugins/kbn_tp_custom_visualizations/tsconfig.json index 7e2f7c97eb058..b704274a58aa4 100644 --- a/test/plugin_functional/plugins/kbn_tp_custom_visualizations/tsconfig.json +++ b/test/plugin_functional/plugins/kbn_tp_custom_visualizations/tsconfig.json @@ -15,5 +15,8 @@ "public/**/*.tsx", "../../../../typings/**/*" ], - "exclude": [] + "exclude": [], + "references": [ + { "path": "../../../../src/core/tsconfig.json" } + ] } diff --git a/test/plugin_functional/plugins/management_test_plugin/tsconfig.json b/test/plugin_functional/plugins/management_test_plugin/tsconfig.json index 4d979fbf7f15f..f77a5eaffc301 100644 --- a/test/plugin_functional/plugins/management_test_plugin/tsconfig.json +++ b/test/plugin_functional/plugins/management_test_plugin/tsconfig.json @@ -10,5 +10,8 @@ "public/**/*.tsx", "../../../../typings/**/*", ], - "exclude": [] + "exclude": [], + "references": [ + { "path": "../../../../src/core/tsconfig.json" } + ] } diff --git a/test/plugin_functional/plugins/rendering_plugin/tsconfig.json b/test/plugin_functional/plugins/rendering_plugin/tsconfig.json index ccbffc34bce4a..3d9d8ca9451d4 100644 --- a/test/plugin_functional/plugins/rendering_plugin/tsconfig.json +++ b/test/plugin_functional/plugins/rendering_plugin/tsconfig.json @@ -11,5 +11,8 @@ "server/**/*.ts", "../../../../typings/**/*", ], - "exclude": [] + "exclude": [], + "references": [ + { "path": "../../../../src/core/tsconfig.json" } + ] } diff --git a/test/plugin_functional/plugins/ui_settings_plugin/tsconfig.json b/test/plugin_functional/plugins/ui_settings_plugin/tsconfig.json index 33b2d6c0f64ad..05b1c2c11da03 100644 --- a/test/plugin_functional/plugins/ui_settings_plugin/tsconfig.json +++ b/test/plugin_functional/plugins/ui_settings_plugin/tsconfig.json @@ -8,5 +8,8 @@ "server/**/*.ts", "../../../../typings/**/*", ], - "exclude": [] + "exclude": [], + "references": [ + { "path": "../../../../src/core/tsconfig.json" } + ] } diff --git a/test/tsconfig.json b/test/tsconfig.json index 325db48978022..6e846690d54d9 100644 --- a/test/tsconfig.json +++ b/test/tsconfig.json @@ -16,5 +16,8 @@ "exclude": [ "plugin_functional/plugins/**/*", "interpreter_functional/plugins/**/*" + ], + "references": [ + { "path": "../src/core/tsconfig.json" } ] } diff --git a/tsconfig.json b/tsconfig.json index 21a817213c62f..11838627c5319 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,7 +1,7 @@ { "extends": "./tsconfig.base.json", "compilerOptions": { - "tsBuildInfoFile": "./build/tsbuildinfo/kibana", + "tsBuildInfoFile": "./build/tsbuildinfo/kibana" }, "include": [ "kibana.d.ts", @@ -11,7 +11,8 @@ ], "exclude": [ "src/**/__fixtures__/**/*", - "src/test_utils/**/*" + "src/test_utils/**/*", + "src/core/**/*" // In the build we actually exclude **/public/**/* from this config so that // we can run the TSC on both this and the .browser version of this config // file, but if we did it during development IDEs would not be able to find @@ -19,6 +20,7 @@ // "src/**/public/**/*" ], "references": [ - { "path": "./src/test_utils/tsconfig.json" } + { "path": "./src/test_utils/tsconfig.json" }, + { "path": "./src/core/tsconfig.json" } ] } diff --git a/tsconfig.refs.json b/tsconfig.refs.json index 0e4cc1bd32da3..66282687f633b 100644 --- a/tsconfig.refs.json +++ b/tsconfig.refs.json @@ -1,6 +1,7 @@ { "include": [], "references": [ - { "path": "./src/test_utils" } + { "path": "./src/test_utils" }, + { "path": "./src/core" }, ] } diff --git a/x-pack/examples/ui_actions_enhanced_examples/tsconfig.json b/x-pack/examples/ui_actions_enhanced_examples/tsconfig.json index cae75bb81c723..9f4f010c20fec 100644 --- a/x-pack/examples/ui_actions_enhanced_examples/tsconfig.json +++ b/x-pack/examples/ui_actions_enhanced_examples/tsconfig.json @@ -11,5 +11,8 @@ "server/**/*.ts", "../../typings/**/*" ], - "exclude": [] + "exclude": [], + "references": [ + { "path": "../../../src/core/tsconfig.json" } + ] } diff --git a/x-pack/package.json b/x-pack/package.json index 1e2fa4d7ee550..3e1e1173be2d7 100644 --- a/x-pack/package.json +++ b/x-pack/package.json @@ -95,7 +95,6 @@ "@types/jsdom": "^16.2.3", "@types/json-stable-stringify": "^1.0.32", "@types/jsonwebtoken": "^7.2.8", - "@types/lodash": "^4.14.159", "@types/mapbox-gl": "^1.9.1", "@types/memoize-one": "^4.1.0", "@types/mime": "^2.0.1", @@ -338,7 +337,7 @@ "js-yaml": "3.13.1", "json-stable-stringify": "^1.0.1", "jsonwebtoken": "^8.5.1", - "lodash": "^4.17.15", + "lodash": "^4.17.20", "markdown-it": "^10.0.0", "mime": "^2.4.4", "moment": "^2.24.0", diff --git a/x-pack/plugins/actions/server/lib/license_state.ts b/x-pack/plugins/actions/server/lib/license_state.ts index 914aada08bb2c..1686d0201e96c 100644 --- a/x-pack/plugins/actions/server/lib/license_state.ts +++ b/x-pack/plugins/actions/server/lib/license_state.ts @@ -6,7 +6,7 @@ import { i18n } from '@kbn/i18n'; import { Observable, Subscription } from 'rxjs'; -import { assertNever } from '../../../../../src/core/server'; +import { assertNever } from '@kbn/std'; import { ILicense } from '../../../licensing/common/types'; import { PLUGIN } from '../constants/plugin'; import { ActionType } from '../types'; diff --git a/x-pack/plugins/alerts/server/alerts_client.test.ts b/x-pack/plugins/alerts/server/alerts_client.test.ts index 801c2c8775361..b20e6c6be2ebf 100644 --- a/x-pack/plugins/alerts/server/alerts_client.test.ts +++ b/x-pack/plugins/alerts/server/alerts_client.test.ts @@ -7,6 +7,8 @@ import uuid from 'uuid'; import { schema } from '@kbn/config-schema'; import { AlertsClient, CreateOptions, ConstructorOptions } from './alerts_client'; import { savedObjectsClientMock, loggingSystemMock } from '../../../../src/core/server/mocks'; +import { nodeTypes } from '../../../../src/plugins/data/common'; +import { esKuery } from '../../../../src/plugins/data/server'; import { taskManagerMock } from '../../task_manager/server/task_manager.mock'; import { alertTypeRegistryMock } from './alert_type_registry.mock'; import { alertsAuthorizationMock } from './authorization/alerts_authorization.mock'; @@ -2722,6 +2724,7 @@ describe('find()', () => { Array [ Object { "fields": undefined, + "filter": undefined, "type": "alert", }, ] @@ -2730,9 +2733,11 @@ describe('find()', () => { describe('authorization', () => { test('ensures user is query filter types down to those the user is authorized to find', async () => { + const filter = esKuery.fromKueryExpression( + '((alert.attributes.alertTypeId:myType and alert.attributes.consumer:myApp) or (alert.attributes.alertTypeId:myOtherType and alert.attributes.consumer:myApp) or (alert.attributes.alertTypeId:myOtherType and alert.attributes.consumer:myOtherApp))' + ); authorization.getFindAuthorizationFilter.mockResolvedValue({ - filter: - '((alert.attributes.alertTypeId:myType and alert.attributes.consumer:myApp) or (alert.attributes.alertTypeId:myOtherType and alert.attributes.consumer:myApp) or (alert.attributes.alertTypeId:myOtherType and alert.attributes.consumer:myOtherApp))', + filter, ensureAlertTypeIsAuthorized() {}, logSuccessfulAuthorization() {}, }); @@ -2741,8 +2746,8 @@ describe('find()', () => { await alertsClient.find({ options: { filter: 'someTerm' } }); const [options] = unsecuredSavedObjectsClient.find.mock.calls[0]; - expect(options.filter).toMatchInlineSnapshot( - `"someTerm and ((alert.attributes.alertTypeId:myType and alert.attributes.consumer:myApp) or (alert.attributes.alertTypeId:myOtherType and alert.attributes.consumer:myApp) or (alert.attributes.alertTypeId:myOtherType and alert.attributes.consumer:myOtherApp))"` + expect(options.filter).toEqual( + nodeTypes.function.buildNode('and', [esKuery.fromKueryExpression('someTerm'), filter]) ); expect(authorization.getFindAuthorizationFilter).toHaveBeenCalledTimes(1); }); @@ -2759,7 +2764,6 @@ describe('find()', () => { const ensureAlertTypeIsAuthorized = jest.fn(); const logSuccessfulAuthorization = jest.fn(); authorization.getFindAuthorizationFilter.mockResolvedValue({ - filter: '', ensureAlertTypeIsAuthorized, logSuccessfulAuthorization, }); diff --git a/x-pack/plugins/alerts/server/alerts_client.ts b/x-pack/plugins/alerts/server/alerts_client.ts index 0703a1e13937c..f8da17f4bf089 100644 --- a/x-pack/plugins/alerts/server/alerts_client.ts +++ b/x-pack/plugins/alerts/server/alerts_client.ts @@ -13,6 +13,7 @@ import { SavedObjectReference, SavedObject, } from 'src/core/server'; +import { esKuery } from '../../../../src/plugins/data/server'; import { ActionsClient, ActionsAuthorization } from '../../actions/server'; import { Alert, @@ -37,11 +38,7 @@ import { TaskManagerStartContract } from '../../task_manager/server'; import { taskInstanceToAlertTaskInstance } from './task_runner/alert_task_instance'; import { deleteTaskIfItExists } from './lib/delete_task_if_it_exists'; import { RegistryAlertType } from './alert_type_registry'; -import { - AlertsAuthorization, - WriteOperations, - ReadOperations, -} from './authorization/alerts_authorization'; +import { AlertsAuthorization, WriteOperations, ReadOperations, and } from './authorization'; import { IEventLogClient } from '../../../plugins/event_log/server'; import { parseIsoOrRelativeDate } from './lib/iso_or_relative_date'; import { alertInstanceSummaryFromEventLog } from './lib/alert_instance_summary_from_event_log'; @@ -339,11 +336,6 @@ export class AlertsClient { logSuccessfulAuthorization, } = await this.authorization.getFindAuthorizationFilter(); - if (authorizationFilter) { - options.filter = options.filter - ? `${options.filter} and ${authorizationFilter}` - : authorizationFilter; - } const { page, per_page: perPage, @@ -351,6 +343,10 @@ export class AlertsClient { saved_objects: data, } = await this.unsecuredSavedObjectsClient.find({ ...options, + filter: + (authorizationFilter && options.filter + ? and([esKuery.fromKueryExpression(options.filter), authorizationFilter]) + : authorizationFilter) ?? options.filter, fields: fields ? this.includeFieldsRequiredForAuthentication(fields) : fields, type: 'alert', }); diff --git a/x-pack/plugins/alerts/server/authorization/alerts_authorization.test.ts b/x-pack/plugins/alerts/server/authorization/alerts_authorization.test.ts index c2506381b9df9..9515987af8dd9 100644 --- a/x-pack/plugins/alerts/server/authorization/alerts_authorization.test.ts +++ b/x-pack/plugins/alerts/server/authorization/alerts_authorization.test.ts @@ -6,17 +6,13 @@ import { KibanaRequest } from 'kibana/server'; import { alertTypeRegistryMock } from '../alert_type_registry.mock'; import { securityMock } from '../../../../plugins/security/server/mocks'; +import { esKuery } from '../../../../../src/plugins/data/server'; import { PluginStartContract as FeaturesStartContract, KibanaFeature, } from '../../../features/server'; import { featuresPluginMock } from '../../../features/server/mocks'; -import { - AlertsAuthorization, - ensureFieldIsSafeForQuery, - WriteOperations, - ReadOperations, -} from './alerts_authorization'; +import { AlertsAuthorization, WriteOperations, ReadOperations } from './alerts_authorization'; import { alertsAuthorizationAuditLoggerMock } from './audit_logger.mock'; import { AlertsAuthorizationAuditLogger, AuthorizationResult } from './audit_logger'; import uuid from 'uuid'; @@ -616,8 +612,10 @@ describe('AlertsAuthorization', () => { }); alertTypeRegistry.list.mockReturnValue(setOfAlertTypes); - expect((await alertAuthorization.getFindAuthorizationFilter()).filter).toMatchInlineSnapshot( - `"((alert.attributes.alertTypeId:myAppAlertType and alert.attributes.consumer:(alerts or myApp or myOtherApp or myAppWithSubFeature)) or (alert.attributes.alertTypeId:myOtherAppAlertType and alert.attributes.consumer:(alerts or myApp or myOtherApp or myAppWithSubFeature)) or (alert.attributes.alertTypeId:mySecondAppAlertType and alert.attributes.consumer:(alerts or myApp or myOtherApp or myAppWithSubFeature)))"` + expect((await alertAuthorization.getFindAuthorizationFilter()).filter).toEqual( + esKuery.fromKueryExpression( + `((alert.attributes.alertTypeId:myAppAlertType and alert.attributes.consumer:(alerts or myApp or myOtherApp or myAppWithSubFeature)) or (alert.attributes.alertTypeId:myOtherAppAlertType and alert.attributes.consumer:(alerts or myApp or myOtherApp or myAppWithSubFeature)) or (alert.attributes.alertTypeId:mySecondAppAlertType and alert.attributes.consumer:(alerts or myApp or myOtherApp or myAppWithSubFeature)))` + ) ); expect(auditLogger.alertsAuthorizationSuccess).not.toHaveBeenCalled(); @@ -1246,36 +1244,4 @@ describe('AlertsAuthorization', () => { `); }); }); - - describe('ensureFieldIsSafeForQuery', () => { - test('throws if field contains character that isnt safe in a KQL query', () => { - expect(() => ensureFieldIsSafeForQuery('id', 'alert-*')).toThrowError( - `expected id not to include invalid character: *` - ); - - expect(() => ensureFieldIsSafeForQuery('id', '<=""')).toThrowError( - `expected id not to include invalid character: <=` - ); - - expect(() => ensureFieldIsSafeForQuery('id', '>=""')).toThrowError( - `expected id not to include invalid character: >=` - ); - - expect(() => ensureFieldIsSafeForQuery('id', '1 or alertid:123')).toThrowError( - `expected id not to include whitespace and invalid character: :` - ); - - expect(() => ensureFieldIsSafeForQuery('id', ') or alertid:123')).toThrowError( - `expected id not to include whitespace and invalid characters: ), :` - ); - - expect(() => ensureFieldIsSafeForQuery('id', 'some space')).toThrowError( - `expected id not to include whitespace` - ); - }); - - test('doesnt throws if field is safe as part of a KQL query', () => { - expect(() => ensureFieldIsSafeForQuery('id', '123-0456-678')).not.toThrow(); - }); - }); }); diff --git a/x-pack/plugins/alerts/server/authorization/alerts_authorization.ts b/x-pack/plugins/alerts/server/authorization/alerts_authorization.ts index 9dda006c1eb8e..20b9fecd601e6 100644 --- a/x-pack/plugins/alerts/server/authorization/alerts_authorization.ts +++ b/x-pack/plugins/alerts/server/authorization/alerts_authorization.ts @@ -5,7 +5,7 @@ */ import Boom from 'boom'; -import { map, mapValues, remove, fromPairs, has } from 'lodash'; +import { map, mapValues, fromPairs, has } from 'lodash'; import { KibanaRequest } from 'src/core/server'; import { ALERTS_FEATURE_ID } from '../../common'; import { AlertTypeRegistry } from '../types'; @@ -14,6 +14,8 @@ import { RegistryAlertType } from '../alert_type_registry'; import { PluginStartContract as FeaturesPluginStart } from '../../../features/server'; import { AlertsAuthorizationAuditLogger, ScopeType } from './audit_logger'; import { Space } from '../../../spaces/server'; +import { asFiltersByAlertTypeAndConsumer } from './alerts_authorization_kuery'; +import { KueryNode } from '../../../../../src/plugins/data/server'; export enum ReadOperations { Get = 'get', @@ -215,7 +217,7 @@ export class AlertsAuthorization { } public async getFindAuthorizationFilter(): Promise<{ - filter?: string; + filter?: KueryNode; ensureAlertTypeIsAuthorized: (alertTypeId: string, consumer: string) => void; logSuccessfulAuthorization: () => void; }> { @@ -244,7 +246,7 @@ export class AlertsAuthorization { const authorizedEntries: Map> = new Map(); return { - filter: `(${this.asFiltersByAlertTypeAndConsumer(authorizedAlertTypes).join(' or ')})`, + filter: asFiltersByAlertTypeAndConsumer(authorizedAlertTypes), ensureAlertTypeIsAuthorized: (alertTypeId: string, consumer: string) => { if (!authorizedAlertTypeIdsToConsumers.has(`${alertTypeId}/${consumer}`)) { throw Boom.forbidden( @@ -400,39 +402,6 @@ export class AlertsAuthorization { })) ); } - - private asFiltersByAlertTypeAndConsumer(alertTypes: Set): string[] { - return Array.from(alertTypes).reduce((filters, { id, authorizedConsumers }) => { - ensureFieldIsSafeForQuery('alertTypeId', id); - filters.push( - `(alert.attributes.alertTypeId:${id} and alert.attributes.consumer:(${Object.keys( - authorizedConsumers - ) - .map((consumer) => { - ensureFieldIsSafeForQuery('alertTypeId', id); - return consumer; - }) - .join(' or ')}))` - ); - return filters; - }, []); - } -} - -export function ensureFieldIsSafeForQuery(field: string, value: string): boolean { - const invalid = value.match(/([>=<\*:()]+|\s+)/g); - if (invalid) { - const whitespace = remove(invalid, (chars) => chars.trim().length === 0); - const errors = []; - if (whitespace.length) { - errors.push(`whitespace`); - } - if (invalid.length) { - errors.push(`invalid character${invalid.length > 1 ? `s` : ``}: ${invalid?.join(`, `)}`); - } - throw new Error(`expected ${field} not to include ${errors.join(' and ')}`); - } - return true; } function mergeHasPrivileges(left: HasPrivileges, right?: HasPrivileges): HasPrivileges { diff --git a/x-pack/plugins/alerts/server/authorization/alerts_authorization_kuery.test.ts b/x-pack/plugins/alerts/server/authorization/alerts_authorization_kuery.test.ts new file mode 100644 index 0000000000000..e4b9f8c54c38d --- /dev/null +++ b/x-pack/plugins/alerts/server/authorization/alerts_authorization_kuery.test.ts @@ -0,0 +1,144 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ +import { esKuery } from '../../../../../src/plugins/data/server'; +import { + asFiltersByAlertTypeAndConsumer, + ensureFieldIsSafeForQuery, +} from './alerts_authorization_kuery'; + +describe('asFiltersByAlertTypeAndConsumer', () => { + test('constructs filter for single alert type with single authorized consumer', async () => { + expect( + asFiltersByAlertTypeAndConsumer( + new Set([ + { + actionGroups: [], + defaultActionGroupId: 'default', + id: 'myAppAlertType', + name: 'myAppAlertType', + producer: 'myApp', + authorizedConsumers: { + myApp: { read: true, all: true }, + }, + }, + ]) + ) + ).toEqual( + esKuery.fromKueryExpression( + `((alert.attributes.alertTypeId:myAppAlertType and alert.attributes.consumer:(myApp)))` + ) + ); + }); + + test('constructs filter for single alert type with multiple authorized consumer', async () => { + expect( + asFiltersByAlertTypeAndConsumer( + new Set([ + { + actionGroups: [], + defaultActionGroupId: 'default', + id: 'myAppAlertType', + name: 'myAppAlertType', + producer: 'myApp', + authorizedConsumers: { + alerts: { read: true, all: true }, + myApp: { read: true, all: true }, + myOtherApp: { read: true, all: true }, + }, + }, + ]) + ) + ).toEqual( + esKuery.fromKueryExpression( + `((alert.attributes.alertTypeId:myAppAlertType and alert.attributes.consumer:(alerts or myApp or myOtherApp)))` + ) + ); + }); + + test('constructs filter for multiple alert types across authorized consumer', async () => { + expect( + asFiltersByAlertTypeAndConsumer( + new Set([ + { + actionGroups: [], + defaultActionGroupId: 'default', + id: 'myAppAlertType', + name: 'myAppAlertType', + producer: 'myApp', + authorizedConsumers: { + alerts: { read: true, all: true }, + myApp: { read: true, all: true }, + myOtherApp: { read: true, all: true }, + myAppWithSubFeature: { read: true, all: true }, + }, + }, + { + actionGroups: [], + defaultActionGroupId: 'default', + id: 'myOtherAppAlertType', + name: 'myOtherAppAlertType', + producer: 'alerts', + authorizedConsumers: { + alerts: { read: true, all: true }, + myApp: { read: true, all: true }, + myOtherApp: { read: true, all: true }, + myAppWithSubFeature: { read: true, all: true }, + }, + }, + { + actionGroups: [], + defaultActionGroupId: 'default', + id: 'mySecondAppAlertType', + name: 'mySecondAppAlertType', + producer: 'myApp', + authorizedConsumers: { + alerts: { read: true, all: true }, + myApp: { read: true, all: true }, + myOtherApp: { read: true, all: true }, + myAppWithSubFeature: { read: true, all: true }, + }, + }, + ]) + ) + ).toEqual( + esKuery.fromKueryExpression( + `((alert.attributes.alertTypeId:myAppAlertType and alert.attributes.consumer:(alerts or myApp or myOtherApp or myAppWithSubFeature)) or (alert.attributes.alertTypeId:myOtherAppAlertType and alert.attributes.consumer:(alerts or myApp or myOtherApp or myAppWithSubFeature)) or (alert.attributes.alertTypeId:mySecondAppAlertType and alert.attributes.consumer:(alerts or myApp or myOtherApp or myAppWithSubFeature)))` + ) + ); + }); +}); + +describe('ensureFieldIsSafeForQuery', () => { + test('throws if field contains character that isnt safe in a KQL query', () => { + expect(() => ensureFieldIsSafeForQuery('id', 'alert-*')).toThrowError( + `expected id not to include invalid character: *` + ); + + expect(() => ensureFieldIsSafeForQuery('id', '<=""')).toThrowError( + `expected id not to include invalid character: <=` + ); + + expect(() => ensureFieldIsSafeForQuery('id', '>=""')).toThrowError( + `expected id not to include invalid character: >=` + ); + + expect(() => ensureFieldIsSafeForQuery('id', '1 or alertid:123')).toThrowError( + `expected id not to include whitespace and invalid character: :` + ); + + expect(() => ensureFieldIsSafeForQuery('id', ') or alertid:123')).toThrowError( + `expected id not to include whitespace and invalid characters: ), :` + ); + + expect(() => ensureFieldIsSafeForQuery('id', 'some space')).toThrowError( + `expected id not to include whitespace` + ); + }); + + test('doesnt throws if field is safe as part of a KQL query', () => { + expect(() => ensureFieldIsSafeForQuery('id', '123-0456-678')).not.toThrow(); + }); +}); diff --git a/x-pack/plugins/alerts/server/authorization/alerts_authorization_kuery.ts b/x-pack/plugins/alerts/server/authorization/alerts_authorization_kuery.ts new file mode 100644 index 0000000000000..f236ee7f3c258 --- /dev/null +++ b/x-pack/plugins/alerts/server/authorization/alerts_authorization_kuery.ts @@ -0,0 +1,61 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { remove } from 'lodash'; +import { nodeTypes } from '../../../../../src/plugins/data/common'; +import { KueryNode } from '../../../../../src/plugins/data/server'; +import { RegistryAlertTypeWithAuth } from './alerts_authorization'; + +export const is = (fieldName: string, value: string | KueryNode) => + nodeTypes.function.buildNodeWithArgumentNodes('is', [ + nodeTypes.literal.buildNode(fieldName), + typeof value === 'string' ? nodeTypes.literal.buildNode(value) : value, + nodeTypes.literal.buildNode(false), + ]); + +export const or = ([first, ...args]: KueryNode[]): KueryNode => + args.length ? nodeTypes.function.buildNode('or', [first, or(args)]) : first; + +export const and = ([first, ...args]: KueryNode[]): KueryNode => + args.length ? nodeTypes.function.buildNode('and', [first, and(args)]) : first; + +export function asFiltersByAlertTypeAndConsumer( + alertTypes: Set +): KueryNode { + return or( + Array.from(alertTypes).reduce((filters, { id, authorizedConsumers }) => { + ensureFieldIsSafeForQuery('alertTypeId', id); + filters.push( + and([ + is(`alert.attributes.alertTypeId`, id), + or( + Object.keys(authorizedConsumers).map((consumer) => { + ensureFieldIsSafeForQuery('consumer', consumer); + return is(`alert.attributes.consumer`, consumer); + }) + ), + ]) + ); + return filters; + }, []) + ); +} + +export function ensureFieldIsSafeForQuery(field: string, value: string): boolean { + const invalid = value.match(/([>=<\*:()]+|\s+)/g); + if (invalid) { + const whitespace = remove(invalid, (chars) => chars.trim().length === 0); + const errors = []; + if (whitespace.length) { + errors.push(`whitespace`); + } + if (invalid.length) { + errors.push(`invalid character${invalid.length > 1 ? `s` : ``}: ${invalid?.join(`, `)}`); + } + throw new Error(`expected ${field} not to include ${errors.join(' and ')}`); + } + return true; +} diff --git a/x-pack/plugins/alerts/server/authorization/index.ts b/x-pack/plugins/alerts/server/authorization/index.ts new file mode 100644 index 0000000000000..66c7f0afd0122 --- /dev/null +++ b/x-pack/plugins/alerts/server/authorization/index.ts @@ -0,0 +1,7 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ +export * from './alerts_authorization'; +export * from './alerts_authorization_kuery'; diff --git a/x-pack/plugins/alerts/server/lib/license_state.ts b/x-pack/plugins/alerts/server/lib/license_state.ts index ea0106f717b02..b3204d886960f 100644 --- a/x-pack/plugins/alerts/server/lib/license_state.ts +++ b/x-pack/plugins/alerts/server/lib/license_state.ts @@ -6,9 +6,9 @@ import Boom from 'boom'; import { i18n } from '@kbn/i18n'; +import { assertNever } from '@kbn/std'; import { Observable, Subscription } from 'rxjs'; import { ILicense } from '../../../licensing/common/types'; -import { assertNever } from '../../../../../src/core/server'; import { PLUGIN } from '../constants/plugin'; export interface AlertingLicenseInformation { diff --git a/x-pack/plugins/apm/e2e/cypress/integration/apm.feature b/x-pack/plugins/apm/e2e/cypress/integration/apm.feature index 82d896c5ba17e..285615108266b 100644 --- a/x-pack/plugins/apm/e2e/cypress/integration/apm.feature +++ b/x-pack/plugins/apm/e2e/cypress/integration/apm.feature @@ -1,4 +1,4 @@ -KibanaFeature: APM +Feature: APM Scenario: Transaction duration charts Given a user browses the APM UI application diff --git a/x-pack/plugins/apm/e2e/cypress/support/step_definitions/apm.ts b/x-pack/plugins/apm/e2e/cypress/support/step_definitions/apm.ts index 66d604a663fbf..ab2bf20b36ed4 100644 --- a/x-pack/plugins/apm/e2e/cypress/support/step_definitions/apm.ts +++ b/x-pack/plugins/apm/e2e/cypress/support/step_definitions/apm.ts @@ -12,7 +12,7 @@ export const DEFAULT_TIMEOUT = 60 * 1000; Given(`a user browses the APM UI application`, () => { // open service overview page - loginAndWaitForPage(`/app/apm#/services`, { + loginAndWaitForPage(`/app/apm/services`, { from: '2020-06-01T14:59:32.686Z', to: '2020-06-16T16:59:36.219Z', }); diff --git a/x-pack/plugins/apm/e2e/cypress/support/step_definitions/rum/rum_dashboard.ts b/x-pack/plugins/apm/e2e/cypress/support/step_definitions/rum/rum_dashboard.ts index 804974d8d437d..31aef30c4e23f 100644 --- a/x-pack/plugins/apm/e2e/cypress/support/step_definitions/rum/rum_dashboard.ts +++ b/x-pack/plugins/apm/e2e/cypress/support/step_definitions/rum/rum_dashboard.ts @@ -15,7 +15,7 @@ Given(`a user browses the APM UI application for RUM Data`, () => { // open service overview page const RANGE_FROM = 'now-24h'; const RANGE_TO = 'now'; - loginAndWaitForPage(`/app/apm#/rum-preview`, { + loginAndWaitForPage(`/app/apm/rum-preview`, { from: RANGE_FROM, to: RANGE_TO, }); diff --git a/x-pack/plugins/apm/public/application/application.test.tsx b/x-pack/plugins/apm/public/application/application.test.tsx index fc369b9cf672a..0566ff19017f4 100644 --- a/x-pack/plugins/apm/public/application/application.test.tsx +++ b/x-pack/plugins/apm/public/application/application.test.tsx @@ -14,6 +14,10 @@ import { createCallApmApi } from '../services/rest/createCallApmApi'; import { renderApp } from './'; import { disableConsoleWarning } from '../utils/testHelpers'; +jest.mock('../services/rest/index_pattern', () => ({ + createStaticIndexPattern: () => Promise.resolve(undefined), +})); + describe('renderApp', () => { let mockConsole: jest.SpyInstance; diff --git a/x-pack/plugins/apm/public/application/index.tsx b/x-pack/plugins/apm/public/application/index.tsx index 536d70b053f76..9843f73dafdbb 100644 --- a/x-pack/plugins/apm/public/application/index.tsx +++ b/x-pack/plugins/apm/public/application/index.tsx @@ -25,7 +25,6 @@ import { ScrollToTopOnPathChange } from '../components/app/Main/ScrollToTopOnPat import { ApmPluginContext } from '../context/ApmPluginContext'; import { LicenseProvider } from '../context/LicenseContext'; import { LoadingIndicatorProvider } from '../context/LoadingIndicatorContext'; -import { LocationProvider } from '../context/LocationContext'; import { UrlParamsProvider } from '../context/UrlParamsContext'; import { useBreadcrumbs } from '../hooks/use_breadcrumbs'; import { ApmPluginSetupDeps } from '../plugin'; @@ -99,15 +98,13 @@ export function ApmAppRoot({ - - - - - - - - - + + + + + + + diff --git a/x-pack/plugins/apm/public/components/app/ErrorGroupOverview/List/__test__/List.test.tsx b/x-pack/plugins/apm/public/components/app/ErrorGroupOverview/List/__test__/List.test.tsx index 1acfc5c49245d..84b72b62248b0 100644 --- a/x-pack/plugins/apm/public/components/app/ErrorGroupOverview/List/__test__/List.test.tsx +++ b/x-pack/plugins/apm/public/components/app/ErrorGroupOverview/List/__test__/List.test.tsx @@ -11,6 +11,7 @@ import { MockUrlParamsContextProvider } from '../../../../../context/UrlParamsCo import { mockMoment, toJson } from '../../../../../utils/testHelpers'; import { ErrorGroupList } from '../index'; import props from './props.json'; +import { MemoryRouter } from 'react-router-dom'; jest.mock('@elastic/eui/lib/services/accessibility/html_id_generator', () => { return { @@ -26,9 +27,11 @@ describe('ErrorGroupOverview -> List', () => { it('should render empty state', () => { const storeState = {}; const wrapper = mount( - - - , + + + + + , storeState ); @@ -37,11 +40,13 @@ describe('ErrorGroupOverview -> List', () => { it('should render with data', () => { const wrapper = mount( - - - - - + + + + + + + ); expect(toJson(wrapper)).toMatchSnapshot(); diff --git a/x-pack/plugins/apm/public/components/app/Main/route_config/index.tsx b/x-pack/plugins/apm/public/components/app/Main/route_config/index.tsx index 0cefcbdc54228..4aa2d841e8deb 100644 --- a/x-pack/plugins/apm/public/components/app/Main/route_config/index.tsx +++ b/x-pack/plugins/apm/public/components/app/Main/route_config/index.tsx @@ -113,33 +113,33 @@ function ServiceDetailsTransactions( return ; } -function SettingsAgentConfiguration() { +function SettingsAgentConfiguration(props: RouteComponentProps<{}>) { return ( - + ); } -function SettingsAnomalyDetection() { +function SettingsAnomalyDetection(props: RouteComponentProps<{}>) { return ( - + ); } -function SettingsApmIndices() { +function SettingsApmIndices(props: RouteComponentProps<{}>) { return ( - + ); } -function SettingsCustomizeUI() { +function SettingsCustomizeUI(props: RouteComponentProps<{}>) { return ( - + ); diff --git a/x-pack/plugins/apm/public/components/app/Main/route_config/route_handlers/agent_configuration.tsx b/x-pack/plugins/apm/public/components/app/Main/route_config/route_handlers/agent_configuration.tsx index cc07286457908..f2ae0c2ff99e8 100644 --- a/x-pack/plugins/apm/public/components/app/Main/route_config/route_handlers/agent_configuration.tsx +++ b/x-pack/plugins/apm/public/components/app/Main/route_config/route_handlers/agent_configuration.tsx @@ -13,10 +13,10 @@ import { AgentConfigurationCreateEdit } from '../../../Settings/AgentConfigurati type EditAgentConfigurationRouteHandler = RouteComponentProps<{}>; -export function EditAgentConfigurationRouteHandler({ - history, -}: EditAgentConfigurationRouteHandler) { - const { search } = history.location; +export function EditAgentConfigurationRouteHandler( + props: EditAgentConfigurationRouteHandler +) { + const { search } = props.history.location; // typescript complains because `pageStop` does not exist in `APMQueryParams` // Going forward we should move away from globally declared query params and this is a first step @@ -34,7 +34,7 @@ export function EditAgentConfigurationRouteHandler({ ); return ( - + ; -export function CreateAgentConfigurationRouteHandler({ - history, -}: CreateAgentConfigurationRouteHandlerProps) { - const { search } = history.location; +export function CreateAgentConfigurationRouteHandler( + props: CreateAgentConfigurationRouteHandlerProps +) { + const { search } = props.history.location; // Ignoring here because we specifically DO NOT want to add the query params to the global route handler // @ts-expect-error const { pageStep } = toQuery(search); return ( - + diff --git a/x-pack/plugins/apm/public/components/app/RumDashboard/CoreVitals/index.tsx b/x-pack/plugins/apm/public/components/app/RumDashboard/CoreVitals/index.tsx index e8305a6aef0d4..d0bd674ef5c79 100644 --- a/x-pack/plugins/apm/public/components/app/RumDashboard/CoreVitals/index.tsx +++ b/x-pack/plugins/apm/public/components/app/RumDashboard/CoreVitals/index.tsx @@ -20,10 +20,11 @@ const CoreVitalsThresholds = { export function CoreVitals() { const { urlParams, uiFilters } = useUrlParams(); - const { start, end, serviceName } = urlParams; + const { start, end } = urlParams; const { data, status } = useFetcher( (callApmApi) => { + const { serviceName } = uiFilters; if (start && end && serviceName) { return callApmApi({ pathname: '/api/apm/rum-client/web-core-vitals', @@ -34,7 +35,7 @@ export function CoreVitals() { } return Promise.resolve(null); }, - [start, end, serviceName, uiFilters] + [start, end, uiFilters] ); const { lcp, lcpRanks, fid, fidRanks, cls, clsRanks } = data || {}; diff --git a/x-pack/plugins/apm/public/components/app/ServiceMap/Popover/Buttons.tsx b/x-pack/plugins/apm/public/components/app/ServiceMap/Popover/Buttons.tsx index 55d068cba5935..8670cf623c253 100644 --- a/x-pack/plugins/apm/public/components/app/ServiceMap/Popover/Buttons.tsx +++ b/x-pack/plugins/apm/public/components/app/ServiceMap/Popover/Buttons.tsx @@ -25,11 +25,7 @@ export function Buttons({ }: ButtonsProps) { const { core } = useApmPluginContext(); const { basePath } = core.http; - // The params may contain the service name. We want to use the selected node's - // service name in the button URLs, so make a copy and set the - // `serviceName` property. - const urlParams = { ...useUrlParams().urlParams } as APMQueryParams; - urlParams.serviceName = selectedNodeServiceName; + const urlParams = useUrlParams().urlParams as APMQueryParams; const detailsUrl = getAPMHref({ basePath, diff --git a/x-pack/plugins/apm/public/components/app/ServiceOverview/__test__/ServiceOverview.test.tsx b/x-pack/plugins/apm/public/components/app/ServiceOverview/__test__/ServiceOverview.test.tsx index 8eeff018ad03f..e4ba1e36378d9 100644 --- a/x-pack/plugins/apm/public/components/app/ServiceOverview/__test__/ServiceOverview.test.tsx +++ b/x-pack/plugins/apm/public/components/app/ServiceOverview/__test__/ServiceOverview.test.tsx @@ -6,21 +6,22 @@ import { render, wait, waitForElement } from '@testing-library/react'; import { CoreStart } from 'kibana/public'; +import { merge } from 'lodash'; import React, { FunctionComponent, ReactChild } from 'react'; +import { MemoryRouter } from 'react-router-dom'; import { createKibanaReactContext } from 'src/plugins/kibana_react/public'; -import { merge } from 'lodash'; import { ServiceOverview } from '..'; +import { EuiThemeProvider } from '../../../../../../observability/public'; import { ApmPluginContextValue } from '../../../../context/ApmPluginContext'; import { mockApmPluginContextValue, MockApmPluginContextWrapper, } from '../../../../context/ApmPluginContext/MockApmPluginContext'; +import * as useAnomalyDetectionJobs from '../../../../hooks/useAnomalyDetectionJobs'; import { FETCH_STATUS } from '../../../../hooks/useFetcher'; import * as useLocalUIFilters from '../../../../hooks/useLocalUIFilters'; import * as urlParamsHooks from '../../../../hooks/useUrlParams'; -import * as useAnomalyDetectionJobs from '../../../../hooks/useAnomalyDetectionJobs'; import { SessionStorageMock } from '../../../../services/__test__/SessionStorageMock'; -import { EuiThemeProvider } from '../../../../../../../legacy/common/eui_styled_components'; const KibanaReactContext = createKibanaReactContext({ usageCollection: { reportUiStats: () => {} }, @@ -44,13 +45,15 @@ function wrapper({ children }: { children: ReactChild }) { }) as unknown) as ApmPluginContextValue; return ( - + - - {children} - + + + {children} + + - + ); } diff --git a/x-pack/plugins/apm/public/components/app/Settings/AgentConfigurations/List/index.tsx b/x-pack/plugins/apm/public/components/app/Settings/AgentConfigurations/List/index.tsx index 210b3c3da8d0b..a67df86b21b1e 100644 --- a/x-pack/plugins/apm/public/components/app/Settings/AgentConfigurations/List/index.tsx +++ b/x-pack/plugins/apm/public/components/app/Settings/AgentConfigurations/List/index.tsx @@ -15,12 +15,12 @@ import { import { i18n } from '@kbn/i18n'; import { isEmpty } from 'lodash'; import React, { useState } from 'react'; +import { useLocation } from 'react-router-dom'; import { getOptionLabel } from '../../../../../../common/agent_configuration/all_option'; // eslint-disable-next-line @kbn/eslint/no-restricted-paths import { AgentConfigurationListAPIResponse } from '../../../../../../server/lib/settings/agent_configuration/list_configurations'; import { useApmPluginContext } from '../../../../../hooks/useApmPluginContext'; import { FETCH_STATUS } from '../../../../../hooks/useFetcher'; -import { useLocation } from '../../../../../hooks/useLocation'; import { useTheme } from '../../../../../hooks/useTheme'; import { px, units } from '../../../../../style/variables'; import { diff --git a/x-pack/plugins/apm/public/components/app/Settings/AgentConfigurations/index.tsx b/x-pack/plugins/apm/public/components/app/Settings/AgentConfigurations/index.tsx index 06d3f883e211a..8e32c55da9161 100644 --- a/x-pack/plugins/apm/public/components/app/Settings/AgentConfigurations/index.tsx +++ b/x-pack/plugins/apm/public/components/app/Settings/AgentConfigurations/index.tsx @@ -15,10 +15,10 @@ import { import { i18n } from '@kbn/i18n'; import { isEmpty } from 'lodash'; import React from 'react'; +import { useLocation } from 'react-router-dom'; import { useTrackPageview } from '../../../../../../observability/public'; import { useApmPluginContext } from '../../../../hooks/useApmPluginContext'; import { useFetcher } from '../../../../hooks/useFetcher'; -import { useLocation } from '../../../../hooks/useLocation'; import { createAgentConfigurationHref } from '../../../shared/Links/apm/agentConfigurationLinks'; import { AgentConfigurationList } from './List'; diff --git a/x-pack/plugins/apm/public/components/app/Settings/Settings.test.tsx b/x-pack/plugins/apm/public/components/app/Settings/Settings.test.tsx index 0e0194cac848c..21da12477b024 100644 --- a/x-pack/plugins/apm/public/components/app/Settings/Settings.test.tsx +++ b/x-pack/plugins/apm/public/components/app/Settings/Settings.test.tsx @@ -8,23 +8,27 @@ import { render } from '@testing-library/react'; import { MockApmPluginContextWrapper } from '../../../context/ApmPluginContext/MockApmPluginContext'; import React, { ReactNode } from 'react'; import { Settings } from './'; -import { LocationContext } from '../../../context/LocationContext'; import { createMemoryHistory } from 'history'; +import { MemoryRouter, RouteComponentProps } from 'react-router-dom'; + +const { location } = createMemoryHistory(); function Wrapper({ children }: { children?: ReactNode }) { - const { location } = createMemoryHistory(); return ( - + {children} - + ); } describe('Settings', () => { it('renders', async () => { + const routerProps = ({ + location, + } as unknown) as RouteComponentProps<{}>; expect(() => render( - +
, { wrapper: Wrapper } diff --git a/x-pack/plugins/apm/public/components/app/Settings/index.tsx b/x-pack/plugins/apm/public/components/app/Settings/index.tsx index 9ed3a85fe68b5..aa71050802215 100644 --- a/x-pack/plugins/apm/public/components/app/Settings/index.tsx +++ b/x-pack/plugins/apm/public/components/app/Settings/index.tsx @@ -4,25 +4,29 @@ * you may not use this file except in compliance with the Elastic License. */ -import React, { ReactNode } from 'react'; -import { i18n } from '@kbn/i18n'; import { EuiButtonEmpty, EuiPage, - EuiSideNav, - EuiPageSideBar, EuiPageBody, + EuiPageSideBar, + EuiSideNav, } from '@elastic/eui'; -import { HomeLink } from '../../shared/Links/apm/HomeLink'; -import { useLocation } from '../../../hooks/useLocation'; -import { getAPMHref } from '../../shared/Links/apm/APMLink'; +import { i18n } from '@kbn/i18n'; +import React, { ReactNode } from 'react'; +import { RouteComponentProps } from 'react-router-dom'; import { useApmPluginContext } from '../../../hooks/useApmPluginContext'; +import { getAPMHref } from '../../shared/Links/apm/APMLink'; +import { HomeLink } from '../../shared/Links/apm/HomeLink'; + +interface SettingsProps extends RouteComponentProps<{}> { + children: ReactNode; +} -export function Settings(props: { children: ReactNode }) { +export function Settings({ children, location }: SettingsProps) { const { core } = useApmPluginContext(); const { basePath } = core.http; const canAccessML = !!core.application.capabilities.ml?.canAccessML; - const { search, pathname } = useLocation(); + const { search, pathname } = location; function getSettingsHref(path: string) { return getAPMHref({ basePath, path: `/settings${path}`, search }); @@ -94,7 +98,7 @@ export function Settings(props: { children: ReactNode }) { ]} /> - {props.children} + {children} ); diff --git a/x-pack/plugins/apm/public/components/app/TransactionDetails/index.tsx b/x-pack/plugins/apm/public/components/app/TransactionDetails/index.tsx index bab31c9a460d0..614089c0457ac 100644 --- a/x-pack/plugins/apm/public/components/app/TransactionDetails/index.tsx +++ b/x-pack/plugins/apm/public/components/app/TransactionDetails/index.tsx @@ -18,7 +18,6 @@ import { useTrackPageview } from '../../../../../observability/public'; import { Projection } from '../../../../common/projections'; import { ChartsSyncContextProvider } from '../../../context/ChartsSyncContext'; import { FETCH_STATUS } from '../../../hooks/useFetcher'; -import { useLocation } from '../../../hooks/useLocation'; import { useTransactionCharts } from '../../../hooks/useTransactionCharts'; import { useTransactionDistribution } from '../../../hooks/useTransactionDistribution'; import { useUrlParams } from '../../../hooks/useUrlParams'; @@ -32,9 +31,11 @@ import { WaterfallWithSummmary } from './WaterfallWithSummmary'; type TransactionDetailsProps = RouteComponentProps<{ serviceName: string }>; -export function TransactionDetails({ match }: TransactionDetailsProps) { +export function TransactionDetails({ + location, + match, +}: TransactionDetailsProps) { const { serviceName } = match.params; - const location = useLocation(); const { urlParams } = useUrlParams(); const { data: distributionData, diff --git a/x-pack/plugins/apm/public/components/app/TransactionOverview/index.tsx b/x-pack/plugins/apm/public/components/app/TransactionOverview/index.tsx index 544e2450fe5d9..3e32b0ec23b13 100644 --- a/x-pack/plugins/apm/public/components/app/TransactionOverview/index.tsx +++ b/x-pack/plugins/apm/public/components/app/TransactionOverview/index.tsx @@ -19,11 +19,11 @@ import { FormattedMessage } from '@kbn/i18n/react'; import { Location } from 'history'; import { first } from 'lodash'; import React, { useMemo } from 'react'; +import { useLocation } from 'react-router-dom'; import { useTrackPageview } from '../../../../../observability/public'; import { Projection } from '../../../../common/projections'; import { ChartsSyncContextProvider } from '../../../context/ChartsSyncContext'; import { IUrlParams } from '../../../context/UrlParamsContext/types'; -import { useLocation } from '../../../hooks/useLocation'; import { useServiceTransactionTypes } from '../../../hooks/useServiceTransactionTypes'; import { useTransactionCharts } from '../../../hooks/useTransactionCharts'; import { useTransactionList } from '../../../hooks/useTransactionList'; diff --git a/x-pack/plugins/apm/public/components/shared/DatePicker/__test__/DatePicker.test.tsx b/x-pack/plugins/apm/public/components/shared/DatePicker/__test__/DatePicker.test.tsx index 01b1628504b3b..9de70d50b25e1 100644 --- a/x-pack/plugins/apm/public/components/shared/DatePicker/__test__/DatePicker.test.tsx +++ b/x-pack/plugins/apm/public/components/shared/DatePicker/__test__/DatePicker.test.tsx @@ -11,7 +11,6 @@ import { createMemoryHistory } from 'history'; import React, { ReactNode } from 'react'; import { Router } from 'react-router-dom'; import { MockApmPluginContextWrapper } from '../../../../context/ApmPluginContext/MockApmPluginContext'; -import { LocationProvider } from '../../../../context/LocationContext'; import { UrlParamsContext, useUiFilters, @@ -46,11 +45,9 @@ function mountDatePicker(params?: IUrlParams) { return mount( - - - - - + + + ); diff --git a/x-pack/plugins/apm/public/components/shared/DatePicker/index.tsx b/x-pack/plugins/apm/public/components/shared/DatePicker/index.tsx index 549ee228b7afe..b4d716f89169e 100644 --- a/x-pack/plugins/apm/public/components/shared/DatePicker/index.tsx +++ b/x-pack/plugins/apm/public/components/shared/DatePicker/index.tsx @@ -7,10 +7,9 @@ import { EuiSuperDatePicker } from '@elastic/eui'; import { isEmpty, isEqual, pickBy } from 'lodash'; import React from 'react'; -import { useHistory } from 'react-router-dom'; +import { useHistory, useLocation } from 'react-router-dom'; import { UI_SETTINGS } from '../../../../../../../src/plugins/data/common'; import { useApmPluginContext } from '../../../hooks/useApmPluginContext'; -import { useLocation } from '../../../hooks/useLocation'; import { useUrlParams } from '../../../hooks/useUrlParams'; import { clearCache } from '../../../services/rest/callApi'; import { fromQuery, toQuery } from '../Links/url_helpers'; diff --git a/x-pack/plugins/apm/public/components/shared/EnvironmentFilter/index.tsx b/x-pack/plugins/apm/public/components/shared/EnvironmentFilter/index.tsx index 7e5c789507e07..c3ecaa1b053b6 100644 --- a/x-pack/plugins/apm/public/components/shared/EnvironmentFilter/index.tsx +++ b/x-pack/plugins/apm/public/components/shared/EnvironmentFilter/index.tsx @@ -8,13 +8,12 @@ import { EuiSelect } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import { History } from 'history'; import React from 'react'; -import { useHistory, useParams } from 'react-router-dom'; +import { useHistory, useLocation, useParams } from 'react-router-dom'; import { ENVIRONMENT_ALL, ENVIRONMENT_NOT_DEFINED, } from '../../../../common/environment_filter_values'; import { useEnvironments } from '../../../hooks/useEnvironments'; -import { useLocation } from '../../../hooks/useLocation'; import { useUrlParams } from '../../../hooks/useUrlParams'; import { fromQuery, toQuery } from '../Links/url_helpers'; diff --git a/x-pack/plugins/apm/public/components/shared/KueryBar/index.tsx b/x-pack/plugins/apm/public/components/shared/KueryBar/index.tsx index efd1446f21b21..157e014bee424 100644 --- a/x-pack/plugins/apm/public/components/shared/KueryBar/index.tsx +++ b/x-pack/plugins/apm/public/components/shared/KueryBar/index.tsx @@ -7,7 +7,7 @@ import { i18n } from '@kbn/i18n'; import { startsWith, uniqueId } from 'lodash'; import React, { useState } from 'react'; -import { useHistory, useParams } from 'react-router-dom'; +import { useHistory, useLocation, useParams } from 'react-router-dom'; import styled from 'styled-components'; import { esKuery, @@ -16,7 +16,6 @@ import { } from '../../../../../../../src/plugins/data/public'; import { useApmPluginContext } from '../../../hooks/useApmPluginContext'; import { useDynamicIndexPattern } from '../../../hooks/useDynamicIndexPattern'; -import { useLocation } from '../../../hooks/useLocation'; import { useUrlParams } from '../../../hooks/useUrlParams'; import { fromQuery, toQuery } from '../Links/url_helpers'; import { getBoolFilter } from './get_bool_filter'; diff --git a/x-pack/plugins/apm/public/components/shared/Links/DiscoverLinks/DiscoverLink.tsx b/x-pack/plugins/apm/public/components/shared/Links/DiscoverLinks/DiscoverLink.tsx index d4b20782a5527..93b5672aa54f9 100644 --- a/x-pack/plugins/apm/public/components/shared/Links/DiscoverLinks/DiscoverLink.tsx +++ b/x-pack/plugins/apm/public/components/shared/Links/DiscoverLinks/DiscoverLink.tsx @@ -8,11 +8,11 @@ import { EuiLink } from '@elastic/eui'; import { Location } from 'history'; import { IBasePath } from 'kibana/public'; import React from 'react'; +import { useLocation } from 'react-router-dom'; import rison, { RisonValue } from 'rison-node'; import url from 'url'; import { APM_STATIC_INDEX_PATTERN_ID } from '../../../../../../../../src/plugins/apm_oss/public'; import { useApmPluginContext } from '../../../../hooks/useApmPluginContext'; -import { useLocation } from '../../../../hooks/useLocation'; import { getTimepickerRisonData } from '../rison_helpers'; interface Props { diff --git a/x-pack/plugins/apm/public/components/shared/Links/MachineLearningLinks/MLLink.tsx b/x-pack/plugins/apm/public/components/shared/Links/MachineLearningLinks/MLLink.tsx index 5e2d728716704..d8ec212515c6f 100644 --- a/x-pack/plugins/apm/public/components/shared/Links/MachineLearningLinks/MLLink.tsx +++ b/x-pack/plugins/apm/public/components/shared/Links/MachineLearningLinks/MLLink.tsx @@ -6,11 +6,11 @@ import { EuiLink } from '@elastic/eui'; import React from 'react'; -import url from 'url'; +import { useLocation } from 'react-router-dom'; import rison, { RisonValue } from 'rison-node'; -import { useLocation } from '../../../../hooks/useLocation'; -import { getTimepickerRisonData, TimepickerRisonData } from '../rison_helpers'; +import url from 'url'; import { useApmPluginContext } from '../../../../hooks/useApmPluginContext'; +import { getTimepickerRisonData, TimepickerRisonData } from '../rison_helpers'; interface MlRisonData { ml?: { diff --git a/x-pack/plugins/apm/public/components/shared/Links/MachineLearningLinks/useTimeSeriesExplorerHref.test.ts b/x-pack/plugins/apm/public/components/shared/Links/MachineLearningLinks/useTimeSeriesExplorerHref.test.ts index 28daae7fd830e..66f3903ba849b 100644 --- a/x-pack/plugins/apm/public/components/shared/Links/MachineLearningLinks/useTimeSeriesExplorerHref.test.ts +++ b/x-pack/plugins/apm/public/components/shared/Links/MachineLearningLinks/useTimeSeriesExplorerHref.test.ts @@ -12,7 +12,7 @@ jest.mock('../../../../hooks/useApmPluginContext', () => ({ }), })); -jest.mock('../../../../hooks/useLocation', () => ({ +jest.mock('react-router-dom', () => ({ useLocation: () => ({ search: '?rangeFrom=2020-07-29T17:27:29.000Z&rangeTo=2020-07-29T18:45:00.000Z&refreshInterval=10000&refreshPaused=true', diff --git a/x-pack/plugins/apm/public/components/shared/Links/MachineLearningLinks/useTimeSeriesExplorerHref.ts b/x-pack/plugins/apm/public/components/shared/Links/MachineLearningLinks/useTimeSeriesExplorerHref.ts index 459ee8f0282ff..3b60962d797ed 100644 --- a/x-pack/plugins/apm/public/components/shared/Links/MachineLearningLinks/useTimeSeriesExplorerHref.ts +++ b/x-pack/plugins/apm/public/components/shared/Links/MachineLearningLinks/useTimeSeriesExplorerHref.ts @@ -4,10 +4,10 @@ * you may not use this file except in compliance with the Elastic License. */ -import url from 'url'; import querystring from 'querystring'; +import { useLocation } from 'react-router-dom'; import rison from 'rison-node'; -import { useLocation } from '../../../../hooks/useLocation'; +import url from 'url'; import { useApmPluginContext } from '../../../../hooks/useApmPluginContext'; import { getTimepickerRisonData } from '../rison_helpers'; diff --git a/x-pack/plugins/apm/public/components/shared/Links/apm/APMLink.tsx b/x-pack/plugins/apm/public/components/shared/Links/apm/APMLink.tsx index cde2471cc4ce3..bd43f2455c545 100644 --- a/x-pack/plugins/apm/public/components/shared/Links/apm/APMLink.tsx +++ b/x-pack/plugins/apm/public/components/shared/Links/apm/APMLink.tsx @@ -8,9 +8,9 @@ import { EuiLink, EuiLinkAnchorProps } from '@elastic/eui'; import { IBasePath } from 'kibana/public'; import { pick } from 'lodash'; import React from 'react'; +import { useLocation } from 'react-router-dom'; import url from 'url'; import { useApmPluginContext } from '../../../../hooks/useApmPluginContext'; -import { useLocation } from '../../../../hooks/useLocation'; import { APMQueryParams, fromQuery, toQuery } from '../url_helpers'; interface Props extends EuiLinkAnchorProps { diff --git a/x-pack/plugins/apm/public/components/shared/MetadataTable/ErrorMetadata/__test__/ErrorMetadata.test.tsx b/x-pack/plugins/apm/public/components/shared/MetadataTable/ErrorMetadata/__test__/ErrorMetadata.test.tsx index de77115ce90ee..e95122f54aff1 100644 --- a/x-pack/plugins/apm/public/components/shared/MetadataTable/ErrorMetadata/__test__/ErrorMetadata.test.tsx +++ b/x-pack/plugins/apm/public/components/shared/MetadataTable/ErrorMetadata/__test__/ErrorMetadata.test.tsx @@ -4,18 +4,27 @@ * you may not use this file except in compliance with the Elastic License. */ -import React from 'react'; -import { ErrorMetadata } from '..'; import { render } from '@testing-library/react'; +import React, { ReactNode } from 'react'; +import { MemoryRouter } from 'react-router-dom'; +import { ErrorMetadata } from '..'; import { APMError } from '../../../../../../typings/es_schemas/ui/apm_error'; +import { MockApmPluginContextWrapper } from '../../../../../context/ApmPluginContext/MockApmPluginContext'; import { expectTextsInDocument, expectTextsNotInDocument, } from '../../../../../utils/testHelpers'; -import { MockApmPluginContextWrapper } from '../../../../../context/ApmPluginContext/MockApmPluginContext'; + +function Wrapper({ children }: { children?: ReactNode }) { + return ( + + {children} + + ); +} const renderOptions = { - wrapper: MockApmPluginContextWrapper, + wrapper: Wrapper, }; function getError() { diff --git a/x-pack/plugins/apm/public/components/shared/MetadataTable/SpanMetadata/__test__/SpanMetadata.test.tsx b/x-pack/plugins/apm/public/components/shared/MetadataTable/SpanMetadata/__test__/SpanMetadata.test.tsx index f27a7ebb780e0..1f10d923e351e 100644 --- a/x-pack/plugins/apm/public/components/shared/MetadataTable/SpanMetadata/__test__/SpanMetadata.test.tsx +++ b/x-pack/plugins/apm/public/components/shared/MetadataTable/SpanMetadata/__test__/SpanMetadata.test.tsx @@ -4,18 +4,27 @@ * you may not use this file except in compliance with the Elastic License. */ -import React from 'react'; import { render } from '@testing-library/react'; +import React, { ReactNode } from 'react'; +import { MemoryRouter } from 'react-router-dom'; import { SpanMetadata } from '..'; import { Span } from '../../../../../../typings/es_schemas/ui/span'; +import { MockApmPluginContextWrapper } from '../../../../../context/ApmPluginContext/MockApmPluginContext'; import { expectTextsInDocument, expectTextsNotInDocument, } from '../../../../../utils/testHelpers'; -import { MockApmPluginContextWrapper } from '../../../../../context/ApmPluginContext/MockApmPluginContext'; + +function Wrapper({ children }: { children?: ReactNode }) { + return ( + + {children} + + ); +} const renderOptions = { - wrapper: MockApmPluginContextWrapper, + wrapper: Wrapper, }; describe('SpanMetadata', () => { diff --git a/x-pack/plugins/apm/public/components/shared/MetadataTable/TransactionMetadata/__test__/TransactionMetadata.test.tsx b/x-pack/plugins/apm/public/components/shared/MetadataTable/TransactionMetadata/__test__/TransactionMetadata.test.tsx index 0577dca852bcf..8359716fc6966 100644 --- a/x-pack/plugins/apm/public/components/shared/MetadataTable/TransactionMetadata/__test__/TransactionMetadata.test.tsx +++ b/x-pack/plugins/apm/public/components/shared/MetadataTable/TransactionMetadata/__test__/TransactionMetadata.test.tsx @@ -4,18 +4,27 @@ * you may not use this file except in compliance with the Elastic License. */ -import React from 'react'; -import { TransactionMetadata } from '..'; import { render } from '@testing-library/react'; +import React, { ReactNode } from 'react'; +import { MemoryRouter } from 'react-router-dom'; +import { TransactionMetadata } from '..'; import { Transaction } from '../../../../../../typings/es_schemas/ui/transaction'; +import { MockApmPluginContextWrapper } from '../../../../../context/ApmPluginContext/MockApmPluginContext'; import { expectTextsInDocument, expectTextsNotInDocument, } from '../../../../../utils/testHelpers'; -import { MockApmPluginContextWrapper } from '../../../../../context/ApmPluginContext/MockApmPluginContext'; + +function Wrapper({ children }: { children?: ReactNode }) { + return ( + + {children} + + ); +} const renderOptions = { - wrapper: MockApmPluginContextWrapper, + wrapper: Wrapper, }; function getTransaction() { diff --git a/x-pack/plugins/apm/public/components/shared/MetadataTable/__test__/MetadataTable.test.tsx b/x-pack/plugins/apm/public/components/shared/MetadataTable/__test__/MetadataTable.test.tsx index 0b40c2a727fa3..8e53aa4aa1089 100644 --- a/x-pack/plugins/apm/public/components/shared/MetadataTable/__test__/MetadataTable.test.tsx +++ b/x-pack/plugins/apm/public/components/shared/MetadataTable/__test__/MetadataTable.test.tsx @@ -4,15 +4,24 @@ * you may not use this file except in compliance with the Elastic License. */ -import React from 'react'; import { render } from '@testing-library/react'; +import React, { ReactNode } from 'react'; +import { MemoryRouter } from 'react-router-dom'; import { MetadataTable } from '..'; +import { MockApmPluginContextWrapper } from '../../../../context/ApmPluginContext/MockApmPluginContext'; import { expectTextsInDocument } from '../../../../utils/testHelpers'; import { SectionsWithRows } from '../helper'; -import { MockApmPluginContextWrapper } from '../../../../context/ApmPluginContext/MockApmPluginContext'; + +function Wrapper({ children }: { children?: ReactNode }) { + return ( + + {children} + + ); +} const renderOptions = { - wrapper: MockApmPluginContextWrapper, + wrapper: Wrapper, }; describe('MetadataTable', () => { diff --git a/x-pack/plugins/apm/public/components/shared/MetadataTable/index.tsx b/x-pack/plugins/apm/public/components/shared/MetadataTable/index.tsx index a8990e70150d1..1d2ac4d18a2a7 100644 --- a/x-pack/plugins/apm/public/components/shared/MetadataTable/index.tsx +++ b/x-pack/plugins/apm/public/components/shared/MetadataTable/index.tsx @@ -16,8 +16,7 @@ import { import { i18n } from '@kbn/i18n'; import { isEmpty } from 'lodash'; import React, { useCallback } from 'react'; -import { useHistory } from 'react-router-dom'; -import { useLocation } from '../../../hooks/useLocation'; +import { useHistory, useLocation } from 'react-router-dom'; import { useUrlParams } from '../../../hooks/useUrlParams'; import { ElasticDocsLink } from '../../shared/Links/ElasticDocsLink'; import { HeightRetainer } from '../HeightRetainer'; diff --git a/x-pack/plugins/apm/public/components/shared/TransactionActionMenu/CustomLink/CustomLinkPopover.test.tsx b/x-pack/plugins/apm/public/components/shared/TransactionActionMenu/CustomLink/CustomLinkPopover.test.tsx index 0f42d8f9beb46..62952d1fb501b 100644 --- a/x-pack/plugins/apm/public/components/shared/TransactionActionMenu/CustomLink/CustomLinkPopover.test.tsx +++ b/x-pack/plugins/apm/public/components/shared/TransactionActionMenu/CustomLink/CustomLinkPopover.test.tsx @@ -5,6 +5,7 @@ */ import { act, fireEvent, render } from '@testing-library/react'; import React, { ReactNode } from 'react'; +import { MemoryRouter } from 'react-router-dom'; import { CustomLink } from '../../../../../common/custom_link/custom_link_types'; import { Transaction } from '../../../../../typings/es_schemas/ui/transaction'; import { MockApmPluginContextWrapper } from '../../../../context/ApmPluginContext/MockApmPluginContext'; @@ -12,7 +13,11 @@ import { expectTextsInDocument } from '../../../../utils/testHelpers'; import { CustomLinkPopover } from './CustomLinkPopover'; function Wrapper({ children }: { children?: ReactNode }) { - return {children}; + return ( + + {children} + + ); } describe('CustomLinkPopover', () => { diff --git a/x-pack/plugins/apm/public/components/shared/TransactionActionMenu/CustomLink/ManageCustomLink.test.tsx b/x-pack/plugins/apm/public/components/shared/TransactionActionMenu/CustomLink/ManageCustomLink.test.tsx index a2a2a211a48b1..29e93a47629b3 100644 --- a/x-pack/plugins/apm/public/components/shared/TransactionActionMenu/CustomLink/ManageCustomLink.test.tsx +++ b/x-pack/plugins/apm/public/components/shared/TransactionActionMenu/CustomLink/ManageCustomLink.test.tsx @@ -4,17 +4,22 @@ * you may not use this file except in compliance with the Elastic License. */ +import { act, fireEvent, render } from '@testing-library/react'; import React, { ReactNode } from 'react'; -import { render, act, fireEvent } from '@testing-library/react'; -import { ManageCustomLink } from './ManageCustomLink'; +import { MemoryRouter } from 'react-router-dom'; +import { MockApmPluginContextWrapper } from '../../../../context/ApmPluginContext/MockApmPluginContext'; import { expectTextsInDocument, expectTextsNotInDocument, } from '../../../../utils/testHelpers'; -import { MockApmPluginContextWrapper } from '../../../../context/ApmPluginContext/MockApmPluginContext'; +import { ManageCustomLink } from './ManageCustomLink'; function Wrapper({ children }: { children?: ReactNode }) { - return {children}; + return ( + + {children} + + ); } describe('ManageCustomLink', () => { diff --git a/x-pack/plugins/apm/public/components/shared/TransactionActionMenu/CustomLink/index.test.tsx b/x-pack/plugins/apm/public/components/shared/TransactionActionMenu/CustomLink/index.test.tsx index 055fcc0955c68..5abeae265dfa6 100644 --- a/x-pack/plugins/apm/public/components/shared/TransactionActionMenu/CustomLink/index.test.tsx +++ b/x-pack/plugins/apm/public/components/shared/TransactionActionMenu/CustomLink/index.test.tsx @@ -6,6 +6,7 @@ import { act, fireEvent, render } from '@testing-library/react'; import React, { ReactNode } from 'react'; +import { MemoryRouter } from 'react-router-dom'; import { CustomLink } from '.'; import { CustomLink as CustomLinkType } from '../../../../../common/custom_link/custom_link_types'; import { Transaction } from '../../../../../typings/es_schemas/ui/transaction'; @@ -17,7 +18,11 @@ import { } from '../../../../utils/testHelpers'; function Wrapper({ children }: { children?: ReactNode }) { - return {children}; + return ( + + {children} + + ); } describe('Custom links', () => { diff --git a/x-pack/plugins/apm/public/components/shared/TransactionActionMenu/TransactionActionMenu.tsx b/x-pack/plugins/apm/public/components/shared/TransactionActionMenu/TransactionActionMenu.tsx index c7ce83053db5c..4a548b44cf361 100644 --- a/x-pack/plugins/apm/public/components/shared/TransactionActionMenu/TransactionActionMenu.tsx +++ b/x-pack/plugins/apm/public/components/shared/TransactionActionMenu/TransactionActionMenu.tsx @@ -7,6 +7,7 @@ import { EuiButtonEmpty } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import React, { useMemo, useState } from 'react'; +import { useLocation } from 'react-router-dom'; import { ActionMenu, ActionMenuDivider, @@ -21,7 +22,6 @@ import { Transaction } from '../../../../typings/es_schemas/ui/transaction'; import { useApmPluginContext } from '../../../hooks/useApmPluginContext'; import { useFetcher } from '../../../hooks/useFetcher'; import { useLicense } from '../../../hooks/useLicense'; -import { useLocation } from '../../../hooks/useLocation'; import { useUrlParams } from '../../../hooks/useUrlParams'; import { CustomLinkFlyout } from '../../app/Settings/CustomizeUI/CustomLink/CustomLinkFlyout'; import { convertFiltersToQuery } from '../../app/Settings/CustomizeUI/CustomLink/CustomLinkFlyout/helper'; diff --git a/x-pack/plugins/apm/public/components/shared/TransactionActionMenu/__test__/TransactionActionMenu.test.tsx b/x-pack/plugins/apm/public/components/shared/TransactionActionMenu/__test__/TransactionActionMenu.test.tsx index e45df2feff771..ec0b473c3ade8 100644 --- a/x-pack/plugins/apm/public/components/shared/TransactionActionMenu/__test__/TransactionActionMenu.test.tsx +++ b/x-pack/plugins/apm/public/components/shared/TransactionActionMenu/__test__/TransactionActionMenu.test.tsx @@ -6,6 +6,7 @@ import { act, fireEvent, render } from '@testing-library/react'; import React from 'react'; +import { MemoryRouter } from 'react-router-dom'; import { License } from '../../../../../../licensing/common/license'; import { Transaction } from '../../../../../typings/es_schemas/ui/transaction'; import { MockApmPluginContextWrapper } from '../../../../context/ApmPluginContext/MockApmPluginContext'; @@ -19,13 +20,19 @@ import { import { TransactionActionMenu } from '../TransactionActionMenu'; import * as Transactions from './mockData'; +function Wrapper({ children }: { children?: React.ReactNode }) { + return ( + + {children} + + ); +} + const renderTransaction = async (transaction: Record) => { const rendered = render( , { - wrapper: ({ children }: { children?: React.ReactNode }) => ( - {children} - ), + wrapper: Wrapper, } ); @@ -246,14 +253,11 @@ describe('TransactionActionMenu component', () => { function renderTransactionActionMenuWithLicense(license: License) { return render( - - - - + + , + { wrapper: Wrapper } ); } it('doesnt show custom links when license is not valid', () => { @@ -286,14 +290,11 @@ describe('TransactionActionMenu component', () => { }); const component = render( - - - - + + , + { wrapper: Wrapper } ); act(() => { fireEvent.click(component.getByText('Actions')); diff --git a/x-pack/plugins/apm/public/components/shared/charts/ErroneousTransactionsRateChart/index.tsx b/x-pack/plugins/apm/public/components/shared/charts/ErroneousTransactionsRateChart/index.tsx index 1a91e398cec76..85d975870d9bc 100644 --- a/x-pack/plugins/apm/public/components/shared/charts/ErroneousTransactionsRateChart/index.tsx +++ b/x-pack/plugins/apm/public/components/shared/charts/ErroneousTransactionsRateChart/index.tsx @@ -3,12 +3,11 @@ * or more contributor license agreements. Licensed under the Elastic License; * you may not use this file except in compliance with the Elastic License. */ -import { EuiTitle } from '@elastic/eui'; +import { EuiPanel, EuiSpacer, EuiTitle } from '@elastic/eui'; import theme from '@elastic/eui/dist/eui_theme_light.json'; import { i18n } from '@kbn/i18n'; import React, { useCallback } from 'react'; -import { EuiPanel } from '@elastic/eui'; -import { EuiSpacer } from '@elastic/eui'; +import { useParams } from 'react-router-dom'; import { asPercent } from '../../../../../common/utils/formatters'; import { useChartsSync } from '../../../../hooks/useChartsSync'; import { useFetcher } from '../../../../hooks/useFetcher'; @@ -22,16 +21,11 @@ const tickFormatY = (y?: number) => { }; export function ErroneousTransactionsRateChart() { + const { serviceName } = useParams<{ serviceName?: string }>(); const { urlParams, uiFilters } = useUrlParams(); const syncedChartsProps = useChartsSync(); - const { - serviceName, - start, - end, - transactionType, - transactionName, - } = urlParams; + const { start, end, transactionType, transactionName } = urlParams; const { data } = useFetcher(() => { if (serviceName && start && end) { diff --git a/x-pack/plugins/apm/public/components/shared/charts/Timeline/Marker/ErrorMarker.test.tsx b/x-pack/plugins/apm/public/components/shared/charts/Timeline/Marker/ErrorMarker.test.tsx index 6a5ab344d2ba0..abe81185635b5 100644 --- a/x-pack/plugins/apm/public/components/shared/charts/Timeline/Marker/ErrorMarker.test.tsx +++ b/x-pack/plugins/apm/public/components/shared/charts/Timeline/Marker/ErrorMarker.test.tsx @@ -7,6 +7,7 @@ import { fireEvent } from '@testing-library/react'; import { act } from '@testing-library/react-hooks'; import React, { ReactNode } from 'react'; +import { MemoryRouter } from 'react-router-dom'; import { MockApmPluginContextWrapper } from '../../../../../context/ApmPluginContext/MockApmPluginContext'; import { expectTextsInDocument, @@ -16,7 +17,11 @@ import { ErrorMark } from '../../../../app/TransactionDetails/WaterfallWithSummm import { ErrorMarker } from './ErrorMarker'; function Wrapper({ children }: { children?: ReactNode }) { - return {children}; + return ( + + {children} + + ); } describe('ErrorMarker', () => { diff --git a/x-pack/plugins/apm/public/context/LocationContext.tsx b/x-pack/plugins/apm/public/context/LocationContext.tsx deleted file mode 100644 index 1e9c20494b42e..0000000000000 --- a/x-pack/plugins/apm/public/context/LocationContext.tsx +++ /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; - * you may not use this file except in compliance with the Elastic License. - */ - -import { Location } from 'history'; -import React, { createContext } from 'react'; -import { withRouter } from 'react-router-dom'; - -const initialLocation = {} as Location; - -const LocationContext = createContext(initialLocation); -const LocationProvider = withRouter(({ location, children }) => { - return ; -}); - -export { LocationContext, LocationProvider }; diff --git a/x-pack/plugins/apm/public/hooks/useAvgDurationByBrowser.test.ts b/x-pack/plugins/apm/public/hooks/useAvgDurationByBrowser.test.tsx similarity index 82% rename from x-pack/plugins/apm/public/hooks/useAvgDurationByBrowser.test.ts rename to x-pack/plugins/apm/public/hooks/useAvgDurationByBrowser.test.tsx index b34cc95a26399..bb947e307437e 100644 --- a/x-pack/plugins/apm/public/hooks/useAvgDurationByBrowser.test.ts +++ b/x-pack/plugins/apm/public/hooks/useAvgDurationByBrowser.test.tsx @@ -8,6 +8,12 @@ import { renderHook } from '@testing-library/react-hooks'; import theme from '@elastic/eui/dist/eui_theme_light.json'; import * as useFetcherModule from './useFetcher'; import { useAvgDurationByBrowser } from './useAvgDurationByBrowser'; +import React, { ReactNode } from 'react'; +import { MemoryRouter } from 'react-router-dom'; + +function Wrapper({ children }: { children?: ReactNode }) { + return {children}; +} describe('useAvgDurationByBrowser', () => { it('returns data', () => { @@ -19,7 +25,9 @@ describe('useAvgDurationByBrowser', () => { refetch: () => {}, status: 'success' as useFetcherModule.FETCH_STATUS, }); - const { result } = renderHook(() => useAvgDurationByBrowser()); + const { result } = renderHook(() => useAvgDurationByBrowser(), { + wrapper: Wrapper, + }); expect(result.current.data).toEqual([ { diff --git a/x-pack/plugins/apm/public/hooks/useAvgDurationByBrowser.ts b/x-pack/plugins/apm/public/hooks/useAvgDurationByBrowser.ts index a8312dd0448e6..78dc4210711ef 100644 --- a/x-pack/plugins/apm/public/hooks/useAvgDurationByBrowser.ts +++ b/x-pack/plugins/apm/public/hooks/useAvgDurationByBrowser.ts @@ -5,12 +5,13 @@ */ import theme from '@elastic/eui/dist/eui_theme_light.json'; -import { useFetcher } from './useFetcher'; -import { useUrlParams } from './useUrlParams'; +import { useParams } from 'react-router-dom'; +import { getVizColorForIndex } from '../../common/viz_colors'; // eslint-disable-next-line @kbn/eslint/no-restricted-paths import { AvgDurationByBrowserAPIResponse } from '../../server/lib/transactions/avg_duration_by_browser'; import { TimeSeries } from '../../typings/timeseries'; -import { getVizColorForIndex } from '../../common/viz_colors'; +import { useFetcher } from './useFetcher'; +import { useUrlParams } from './useUrlParams'; function toTimeSeries(data?: AvgDurationByBrowserAPIResponse): TimeSeries[] { if (!data) { @@ -27,8 +28,9 @@ function toTimeSeries(data?: AvgDurationByBrowserAPIResponse): TimeSeries[] { } export function useAvgDurationByBrowser() { + const { serviceName } = useParams<{ serviceName?: string }>(); const { - urlParams: { serviceName, start, end, transactionName }, + urlParams: { start, end, transactionName }, uiFilters, } = useUrlParams(); diff --git a/x-pack/plugins/apm/public/hooks/useAvgDurationByCountry.ts b/x-pack/plugins/apm/public/hooks/useAvgDurationByCountry.ts index 818657226cb14..983f949b72961 100644 --- a/x-pack/plugins/apm/public/hooks/useAvgDurationByCountry.ts +++ b/x-pack/plugins/apm/public/hooks/useAvgDurationByCountry.ts @@ -3,13 +3,14 @@ * or more contributor license agreements. Licensed under the Elastic License; * you may not use this file except in compliance with the Elastic License. */ - +import { useParams } from 'react-router-dom'; import { useFetcher } from './useFetcher'; import { useUrlParams } from './useUrlParams'; export function useAvgDurationByCountry() { + const { serviceName } = useParams<{ serviceName?: string }>(); const { - urlParams: { serviceName, start, end, transactionName }, + urlParams: { start, end, transactionName }, uiFilters, } = useUrlParams(); diff --git a/x-pack/plugins/apm/public/hooks/useTransactionBreakdown.ts b/x-pack/plugins/apm/public/hooks/useTransactionBreakdown.ts index 9db78fde2d8c8..08d2300c3254a 100644 --- a/x-pack/plugins/apm/public/hooks/useTransactionBreakdown.ts +++ b/x-pack/plugins/apm/public/hooks/useTransactionBreakdown.ts @@ -4,12 +4,14 @@ * you may not use this file except in compliance with the Elastic License. */ +import { useParams } from 'react-router-dom'; import { useFetcher } from './useFetcher'; import { useUrlParams } from './useUrlParams'; export function useTransactionBreakdown() { + const { serviceName } = useParams<{ serviceName?: string }>(); const { - urlParams: { serviceName, start, end, transactionName, transactionType }, + urlParams: { start, end, transactionName, transactionType }, uiFilters, } = useUrlParams(); diff --git a/x-pack/plugins/apm/public/hooks/useTransactionCharts.ts b/x-pack/plugins/apm/public/hooks/useTransactionCharts.ts index 2ecd900386496..e66d70a53afa6 100644 --- a/x-pack/plugins/apm/public/hooks/useTransactionCharts.ts +++ b/x-pack/plugins/apm/public/hooks/useTransactionCharts.ts @@ -5,13 +5,15 @@ */ import { useMemo } from 'react'; +import { useParams } from 'react-router-dom'; import { getTransactionCharts } from '../selectors/chartSelectors'; import { useFetcher } from './useFetcher'; import { useUrlParams } from './useUrlParams'; export function useTransactionCharts() { + const { serviceName } = useParams<{ serviceName?: string }>(); const { - urlParams: { serviceName, transactionType, start, end, transactionName }, + urlParams: { transactionType, start, end, transactionName }, uiFilters, } = useUrlParams(); diff --git a/x-pack/plugins/apm/public/hooks/useTransactionDistribution.ts b/x-pack/plugins/apm/public/hooks/useTransactionDistribution.ts index 539918c432783..d93a27df1c861 100644 --- a/x-pack/plugins/apm/public/hooks/useTransactionDistribution.ts +++ b/x-pack/plugins/apm/public/hooks/useTransactionDistribution.ts @@ -4,11 +4,12 @@ * you may not use this file except in compliance with the Elastic License. */ -import { IUrlParams } from '../context/UrlParamsContext/types'; -import { useFetcher } from './useFetcher'; -import { useUiFilters } from '../context/UrlParamsContext'; +import { useParams } from 'react-router-dom'; // eslint-disable-next-line @kbn/eslint/no-restricted-paths import { TransactionDistributionAPIResponse } from '../../server/lib/transactions/distribution'; +import { useUiFilters } from '../context/UrlParamsContext'; +import { IUrlParams } from '../context/UrlParamsContext/types'; +import { useFetcher } from './useFetcher'; const INITIAL_DATA = { buckets: [] as TransactionDistributionAPIResponse['buckets'], @@ -17,8 +18,8 @@ const INITIAL_DATA = { }; export function useTransactionDistribution(urlParams: IUrlParams) { + const { serviceName } = useParams<{ serviceName?: string }>(); const { - serviceName, start, end, transactionType, diff --git a/x-pack/plugins/apm/public/services/rest/apm_overview_fetchers.test.ts b/x-pack/plugins/apm/public/services/rest/apm_overview_fetchers.test.ts index 8b3ed38e25319..4e306c93805d0 100644 --- a/x-pack/plugins/apm/public/services/rest/apm_overview_fetchers.test.ts +++ b/x-pack/plugins/apm/public/services/rest/apm_overview_fetchers.test.ts @@ -51,7 +51,7 @@ describe('Observability dashboard data', () => { ); const response = await fetchOverviewPageData(params); expect(response).toEqual({ - appLink: '/app/apm#/services?rangeFrom=now-15m&rangeTo=now', + appLink: '/app/apm/services?rangeFrom=now-15m&rangeTo=now', stats: { services: { type: 'number', @@ -82,7 +82,7 @@ describe('Observability dashboard data', () => { ); const response = await fetchOverviewPageData(params); expect(response).toEqual({ - appLink: '/app/apm#/services?rangeFrom=now-15m&rangeTo=now', + appLink: '/app/apm/services?rangeFrom=now-15m&rangeTo=now', stats: { services: { type: 'number', @@ -109,7 +109,7 @@ describe('Observability dashboard data', () => { ); const response = await fetchOverviewPageData(params); expect(response).toEqual({ - appLink: '/app/apm#/services?rangeFrom=now-15m&rangeTo=now', + appLink: '/app/apm/services?rangeFrom=now-15m&rangeTo=now', stats: { services: { type: 'number', diff --git a/x-pack/plugins/apm/public/services/rest/apm_overview_fetchers.ts b/x-pack/plugins/apm/public/services/rest/apm_overview_fetchers.ts index a20f89fac2d60..422c7b882e5dc 100644 --- a/x-pack/plugins/apm/public/services/rest/apm_overview_fetchers.ts +++ b/x-pack/plugins/apm/public/services/rest/apm_overview_fetchers.ts @@ -32,7 +32,7 @@ export const fetchOverviewPageData = async ({ const { serviceCount, transactionCoordinates } = data; return { - appLink: `/app/apm#/services?rangeFrom=${relativeTime.start}&rangeTo=${relativeTime.end}`, + appLink: `/app/apm/services?rangeFrom=${relativeTime.start}&rangeTo=${relativeTime.end}`, stats: { services: { type: 'number', diff --git a/x-pack/plugins/apm/public/utils/testHelpers.tsx b/x-pack/plugins/apm/public/utils/testHelpers.tsx index 037da01c74464..a69288f7bd4f9 100644 --- a/x-pack/plugins/apm/public/utils/testHelpers.tsx +++ b/x-pack/plugins/apm/public/utils/testHelpers.tsx @@ -16,7 +16,6 @@ import { render, waitForElement } from '@testing-library/react'; import { MemoryRouter } from 'react-router-dom'; // eslint-disable-next-line @kbn/eslint/no-restricted-paths import { APMConfig } from '../../server'; -import { LocationProvider } from '../context/LocationContext'; import { PromiseReturnType } from '../../typings/common'; import { EuiThemeProvider } from '../../../observability/public'; import { @@ -68,9 +67,7 @@ export async function getRenderedHref(Component: React.FC, location: Location) { const el = render( - - - + ); diff --git a/x-pack/plugins/enterprise_search/public/applications/shared/flash_messages/handle_api_errors.test.ts b/x-pack/plugins/enterprise_search/public/applications/shared/flash_messages/handle_api_errors.test.ts new file mode 100644 index 0000000000000..6f2aec757eb37 --- /dev/null +++ b/x-pack/plugins/enterprise_search/public/applications/shared/flash_messages/handle_api_errors.test.ts @@ -0,0 +1,65 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +jest.mock('./', () => ({ + FlashMessagesLogic: { + actions: { + setFlashMessages: jest.fn(), + setQueuedMessages: jest.fn(), + }, + }, +})); +import { FlashMessagesLogic } from './'; + +import { flashAPIErrors } from './handle_api_errors'; + +describe('flashAPIErrors', () => { + const mockHttpError = { + body: { + statusCode: 404, + error: 'Not Found', + message: 'Could not find X,Could not find Y,Something else bad happened', + attributes: { + errors: ['Could not find X', 'Could not find Y', 'Something else bad happened'], + }, + }, + } as any; + + beforeEach(() => { + jest.clearAllMocks(); + }); + + it('converts API errors into flash messages', () => { + flashAPIErrors(mockHttpError); + + expect(FlashMessagesLogic.actions.setFlashMessages).toHaveBeenCalledWith([ + { type: 'error', message: 'Could not find X' }, + { type: 'error', message: 'Could not find Y' }, + { type: 'error', message: 'Something else bad happened' }, + ]); + }); + + it('queues messages when isQueued is passed', () => { + flashAPIErrors(mockHttpError, { isQueued: true }); + + expect(FlashMessagesLogic.actions.setQueuedMessages).toHaveBeenCalledWith([ + { type: 'error', message: 'Could not find X' }, + { type: 'error', message: 'Could not find Y' }, + { type: 'error', message: 'Something else bad happened' }, + ]); + }); + + it('displays a generic error message and re-throws non-API errors', () => { + try { + flashAPIErrors(Error('whatever') as any); + } catch (e) { + expect(e.message).toEqual('whatever'); + expect(FlashMessagesLogic.actions.setFlashMessages).toHaveBeenCalledWith([ + { type: 'error', message: 'An unexpected error occurred' }, + ]); + } + }); +}); diff --git a/x-pack/plugins/enterprise_search/public/applications/shared/flash_messages/handle_api_errors.ts b/x-pack/plugins/enterprise_search/public/applications/shared/flash_messages/handle_api_errors.ts new file mode 100644 index 0000000000000..5e56c4fb0bd22 --- /dev/null +++ b/x-pack/plugins/enterprise_search/public/applications/shared/flash_messages/handle_api_errors.ts @@ -0,0 +1,56 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { HttpResponse } from 'src/core/public'; + +import { FlashMessagesLogic, IFlashMessage } from './'; + +/** + * The API errors we are handling can come from one of two ways: + * - When our http calls recieve a response containing an error code, such as a 404 or 500 + * - Our own JS while handling a successful response + * + * In the first case, if it is a purposeful error (like a 404) we will receive an + * `errors` property in the response's data, which will contain messages we can + * display to the user. + */ +interface IErrorResponse { + statusCode: number; + error: string; + message: string; + attributes: { + errors: string[]; + }; +} +interface IOptions { + isQueued?: boolean; +} + +/** + * Converts API/HTTP errors into user-facing Flash Messages + */ +export const flashAPIErrors = ( + error: HttpResponse, + { isQueued }: IOptions = {} +) => { + const defaultErrorMessage = 'An unexpected error occurred'; + + const errorFlashMessages: IFlashMessage[] = Array.isArray(error?.body?.attributes?.errors) + ? error.body!.attributes.errors.map((message) => ({ type: 'error', message })) + : [{ type: 'error', message: defaultErrorMessage }]; + + if (isQueued) { + FlashMessagesLogic.actions.setQueuedMessages(errorFlashMessages); + } else { + FlashMessagesLogic.actions.setFlashMessages(errorFlashMessages); + } + + // If this was a programming error or a failed request (such as a CORS) error, + // we rethrow the error so it shows up in the developer console + if (!error?.body?.message) { + throw error; + } +}; diff --git a/x-pack/plugins/enterprise_search/public/applications/shared/http/http_logic.test.ts b/x-pack/plugins/enterprise_search/public/applications/shared/http/http_logic.test.ts index a6957340d33d3..c032e3b04ebe6 100644 --- a/x-pack/plugins/enterprise_search/public/applications/shared/http/http_logic.test.ts +++ b/x-pack/plugins/enterprise_search/public/applications/shared/http/http_logic.test.ts @@ -74,21 +74,24 @@ describe('HttpLogic', () => { describe('errorConnectingInterceptor', () => { it('handles errors connecting to Enterprise Search', async () => { const { responseError } = mockHttp.intercept.mock.calls[0][0] as any; - await responseError({ response: { url: '/api/app_search/engines', status: 502 } }); + const httpResponse = { response: { url: '/api/app_search/engines', status: 502 } }; + await expect(responseError(httpResponse)).rejects.toEqual(httpResponse); expect(HttpLogic.actions.setErrorConnecting).toHaveBeenCalled(); }); it('does not handle non-502 Enterprise Search errors', async () => { const { responseError } = mockHttp.intercept.mock.calls[0][0] as any; - await responseError({ response: { url: '/api/workplace_search/overview', status: 404 } }); + const httpResponse = { response: { url: '/api/workplace_search/overview', status: 404 } }; + await expect(responseError(httpResponse)).rejects.toEqual(httpResponse); expect(HttpLogic.actions.setErrorConnecting).not.toHaveBeenCalled(); }); it('does not handle errors for unrelated calls', async () => { const { responseError } = mockHttp.intercept.mock.calls[0][0] as any; - await responseError({ response: { url: '/api/some_other_plugin/', status: 502 } }); + const httpResponse = { response: { url: '/api/some_other_plugin/', status: 502 } }; + await expect(responseError(httpResponse)).rejects.toEqual(httpResponse); expect(HttpLogic.actions.setErrorConnecting).not.toHaveBeenCalled(); }); diff --git a/x-pack/plugins/enterprise_search/public/applications/shared/http/http_logic.ts b/x-pack/plugins/enterprise_search/public/applications/shared/http/http_logic.ts index fb2d9b1061723..ec9db30ddef3b 100644 --- a/x-pack/plugins/enterprise_search/public/applications/shared/http/http_logic.ts +++ b/x-pack/plugins/enterprise_search/public/applications/shared/http/http_logic.ts @@ -6,7 +6,7 @@ import { kea, MakeLogicType } from 'kea'; -import { HttpSetup } from 'src/core/public'; +import { HttpSetup, HttpInterceptorResponseError } from 'src/core/public'; export interface IHttpValues { http: HttpSetup; @@ -68,7 +68,9 @@ export const HttpLogic = kea>({ if (isApiResponse && hasErrorConnecting) { actions.setErrorConnecting(true); } - return httpResponse; + + // Re-throw error so that downstream catches work as expected + return Promise.reject(httpResponse) as Promise; }, }); httpInterceptors.push(errorConnectingInterceptor); diff --git a/x-pack/plugins/enterprise_search/server/lib/enterprise_search_request_handler.test.ts b/x-pack/plugins/enterprise_search/server/lib/enterprise_search_request_handler.test.ts index 34f83ef3a3fd2..0c1e81e3aba46 100644 --- a/x-pack/plugins/enterprise_search/server/lib/enterprise_search_request_handler.test.ts +++ b/x-pack/plugins/enterprise_search/server/lib/enterprise_search_request_handler.test.ts @@ -30,109 +30,198 @@ describe('EnterpriseSearchRequestHandler', () => { fetchMock.mockReset(); }); - it('makes an API call and returns the response', async () => { - const responseBody = { - results: [{ name: 'engine1' }], - meta: { page: { total_results: 1 } }, - }; + describe('createRequest()', () => { + it('makes an API call and returns the response', async () => { + const responseBody = { + results: [{ name: 'engine1' }], + meta: { page: { total_results: 1 } }, + }; - EnterpriseSearchAPI.mockReturn(responseBody); + EnterpriseSearchAPI.mockReturn(responseBody); - const requestHandler = enterpriseSearchRequestHandler.createRequest({ - path: '/as/credentials/collection', - }); + const requestHandler = enterpriseSearchRequestHandler.createRequest({ + path: '/as/credentials/collection', + }); - await makeAPICall(requestHandler, { - query: { - type: 'indexed', - pageIndex: 1, - }, - }); + await makeAPICall(requestHandler, { + query: { + type: 'indexed', + pageIndex: 1, + }, + }); - EnterpriseSearchAPI.shouldHaveBeenCalledWith( - 'http://localhost:3002/as/credentials/collection?type=indexed&pageIndex=1', - { method: 'GET' } - ); + EnterpriseSearchAPI.shouldHaveBeenCalledWith( + 'http://localhost:3002/as/credentials/collection?type=indexed&pageIndex=1', + { method: 'GET' } + ); - expect(responseMock.custom).toHaveBeenCalledWith({ - body: responseBody, - statusCode: 200, + expect(responseMock.custom).toHaveBeenCalledWith({ + body: responseBody, + statusCode: 200, + }); }); - }); - describe('request passing', () => { - it('passes route method', async () => { - const requestHandler = enterpriseSearchRequestHandler.createRequest({ path: '/api/example' }); + describe('request passing', () => { + it('passes route method', async () => { + const requestHandler = enterpriseSearchRequestHandler.createRequest({ + path: '/api/example', + }); + + await makeAPICall(requestHandler, { route: { method: 'POST' } }); + EnterpriseSearchAPI.shouldHaveBeenCalledWith('http://localhost:3002/api/example', { + method: 'POST', + }); - await makeAPICall(requestHandler, { route: { method: 'POST' } }); - EnterpriseSearchAPI.shouldHaveBeenCalledWith('http://localhost:3002/api/example', { - method: 'POST', + await makeAPICall(requestHandler, { route: { method: 'DELETE' } }); + EnterpriseSearchAPI.shouldHaveBeenCalledWith('http://localhost:3002/api/example', { + method: 'DELETE', + }); }); - await makeAPICall(requestHandler, { route: { method: 'DELETE' } }); - EnterpriseSearchAPI.shouldHaveBeenCalledWith('http://localhost:3002/api/example', { - method: 'DELETE', + it('passes request body', async () => { + const requestHandler = enterpriseSearchRequestHandler.createRequest({ + path: '/api/example', + }); + await makeAPICall(requestHandler, { body: { bodacious: true } }); + + EnterpriseSearchAPI.shouldHaveBeenCalledWith('http://localhost:3002/api/example', { + body: '{"bodacious":true}', + }); }); - }); - it('passes request body', async () => { - const requestHandler = enterpriseSearchRequestHandler.createRequest({ path: '/api/example' }); - await makeAPICall(requestHandler, { body: { bodacious: true } }); + it('passes custom params set by the handler, which override request params', async () => { + const requestHandler = enterpriseSearchRequestHandler.createRequest({ + path: '/api/example', + params: { someQuery: true }, + }); + await makeAPICall(requestHandler, { query: { someQuery: false } }); - EnterpriseSearchAPI.shouldHaveBeenCalledWith('http://localhost:3002/api/example', { - body: '{"bodacious":true}', + EnterpriseSearchAPI.shouldHaveBeenCalledWith( + 'http://localhost:3002/api/example?someQuery=true' + ); }); }); - it('passes custom params set by the handler, which override request params', async () => { - const requestHandler = enterpriseSearchRequestHandler.createRequest({ - path: '/api/example', - params: { someQuery: true }, + describe('response passing', () => { + it('returns the response status code from Enterprise Search', async () => { + EnterpriseSearchAPI.mockReturn({}, { status: 201 }); + + const requestHandler = enterpriseSearchRequestHandler.createRequest({ + path: '/api/example', + }); + await makeAPICall(requestHandler); + + EnterpriseSearchAPI.shouldHaveBeenCalledWith('http://localhost:3002/api/example'); + expect(responseMock.custom).toHaveBeenCalledWith({ body: {}, statusCode: 201 }); }); - await makeAPICall(requestHandler, { query: { someQuery: false } }); - EnterpriseSearchAPI.shouldHaveBeenCalledWith( - 'http://localhost:3002/api/example?someQuery=true' - ); + // TODO: It's possible we may also pass back headers at some point + // from Enterprise Search, e.g. the x-read-only mode header }); }); - describe('response passing', () => { - it('returns the response status code from Enterprise Search', async () => { - EnterpriseSearchAPI.mockReturn({}, { status: 404 }); + describe('error responses', () => { + describe('handleClientError()', () => { + afterEach(() => { + EnterpriseSearchAPI.shouldHaveBeenCalledWith('http://localhost:3002/api/4xx'); + expect(mockLogger.error).not.toHaveBeenCalled(); + }); - const requestHandler = enterpriseSearchRequestHandler.createRequest({ path: '/api/example' }); - await makeAPICall(requestHandler); + it('passes back json.error', async () => { + const error = 'some error message'; + EnterpriseSearchAPI.mockReturn({ error }, { status: 404, headers: JSON_HEADER }); - EnterpriseSearchAPI.shouldHaveBeenCalledWith('http://localhost:3002/api/example'); - expect(responseMock.custom).toHaveBeenCalledWith({ body: {}, statusCode: 404 }); - }); + const requestHandler = enterpriseSearchRequestHandler.createRequest({ path: '/api/4xx' }); + await makeAPICall(requestHandler); - // TODO: It's possible we may also pass back headers at some point - // from Enterprise Search, e.g. the x-read-only mode header - }); + expect(responseMock.customError).toHaveBeenCalledWith({ + statusCode: 404, + body: { + message: 'some error message', + attributes: { errors: ['some error message'] }, + }, + }); + }); - describe('error handling', () => { - afterEach(() => { - expect(mockLogger.error).toHaveBeenCalledWith( - expect.stringContaining('Error connecting to Enterprise Search') - ); + it('passes back json.errors', async () => { + const errors = ['one', 'two', 'three']; + EnterpriseSearchAPI.mockReturn({ errors }, { status: 400, headers: JSON_HEADER }); + + const requestHandler = enterpriseSearchRequestHandler.createRequest({ path: '/api/4xx' }); + await makeAPICall(requestHandler); + + expect(responseMock.customError).toHaveBeenCalledWith({ + statusCode: 400, + body: { + message: 'one,two,three', + attributes: { errors: ['one', 'two', 'three'] }, + }, + }); + }); + + it('handles empty json', async () => { + EnterpriseSearchAPI.mockReturn({}, { status: 400, headers: JSON_HEADER }); + + const requestHandler = enterpriseSearchRequestHandler.createRequest({ path: '/api/4xx' }); + await makeAPICall(requestHandler); + + expect(responseMock.customError).toHaveBeenCalledWith({ + statusCode: 400, + body: { + message: 'Bad Request', + attributes: { errors: ['Bad Request'] }, + }, + }); + }); + + it('handles invalid json', async () => { + EnterpriseSearchAPI.mockReturn('invalid' as any, { status: 400, headers: JSON_HEADER }); + + const requestHandler = enterpriseSearchRequestHandler.createRequest({ path: '/api/4xx' }); + await makeAPICall(requestHandler); + + expect(responseMock.customError).toHaveBeenCalledWith({ + statusCode: 400, + body: { + message: 'Bad Request', + attributes: { errors: ['Bad Request'] }, + }, + }); + }); + + it('handles blank bodies', async () => { + EnterpriseSearchAPI.mockReturn(undefined as any, { status: 404 }); + + const requestHandler = enterpriseSearchRequestHandler.createRequest({ path: '/api/4xx' }); + await makeAPICall(requestHandler); + + expect(responseMock.customError).toHaveBeenCalledWith({ + statusCode: 404, + body: { + message: 'Not Found', + attributes: { errors: ['Not Found'] }, + }, + }); + }); }); - it('returns an error when an API request fails', async () => { - EnterpriseSearchAPI.mockReturnError(); - const requestHandler = enterpriseSearchRequestHandler.createRequest({ path: '/api/failed' }); + it('handleServerError()', async () => { + EnterpriseSearchAPI.mockReturn('something crashed!' as any, { status: 500 }); + const requestHandler = enterpriseSearchRequestHandler.createRequest({ path: '/api/5xx' }); await makeAPICall(requestHandler); - EnterpriseSearchAPI.shouldHaveBeenCalledWith('http://localhost:3002/api/failed'); + EnterpriseSearchAPI.shouldHaveBeenCalledWith('http://localhost:3002/api/5xx'); expect(responseMock.customError).toHaveBeenCalledWith({ - body: 'Error connecting to Enterprise Search: Failed', statusCode: 502, + body: expect.stringContaining('Enterprise Search encountered an internal server error'), }); + expect(mockLogger.error).toHaveBeenCalledWith( + 'Enterprise Search Server Error 500 at : "something crashed!"' + ); }); - it('returns an error when `hasValidData` fails', async () => { + it('handleInvalidDataError()', async () => { EnterpriseSearchAPI.mockReturn({ results: false }); const requestHandler = enterpriseSearchRequestHandler.createRequest({ path: '/api/invalid', @@ -143,15 +232,29 @@ describe('EnterpriseSearchRequestHandler', () => { EnterpriseSearchAPI.shouldHaveBeenCalledWith('http://localhost:3002/api/invalid'); expect(responseMock.customError).toHaveBeenCalledWith({ - body: 'Error connecting to Enterprise Search: Invalid data received', statusCode: 502, + body: 'Invalid data received from Enterprise Search', }); - expect(mockLogger.debug).toHaveBeenCalledWith( + expect(mockLogger.error).toHaveBeenCalledWith( 'Invalid data received from : {"results":false}' ); }); - describe('user authentication errors', () => { + it('handleConnectionError()', async () => { + EnterpriseSearchAPI.mockReturnError(); + const requestHandler = enterpriseSearchRequestHandler.createRequest({ path: '/api/failed' }); + + await makeAPICall(requestHandler); + EnterpriseSearchAPI.shouldHaveBeenCalledWith('http://localhost:3002/api/failed'); + + expect(responseMock.customError).toHaveBeenCalledWith({ + statusCode: 502, + body: 'Error connecting to Enterprise Search: Failed', + }); + expect(mockLogger.error).toHaveBeenCalled(); + }); + + describe('handleAuthenticationError()', () => { afterEach(async () => { const requestHandler = enterpriseSearchRequestHandler.createRequest({ path: '/api/unauthenticated', @@ -160,9 +263,10 @@ describe('EnterpriseSearchRequestHandler', () => { EnterpriseSearchAPI.shouldHaveBeenCalledWith('http://localhost:3002/api/unauthenticated'); expect(responseMock.customError).toHaveBeenCalledWith({ - body: 'Error connecting to Enterprise Search: Cannot authenticate Enterprise Search user', statusCode: 502, + body: 'Cannot authenticate Enterprise Search user', }); + expect(mockLogger.error).toHaveBeenCalled(); }); it('errors when redirected to /login', async () => { @@ -175,7 +279,7 @@ describe('EnterpriseSearchRequestHandler', () => { }); }); - it('has a helper for checking empty objects', async () => { + it('isEmptyObj', async () => { expect(enterpriseSearchRequestHandler.isEmptyObj({})).toEqual(true); expect(enterpriseSearchRequestHandler.isEmptyObj({ empty: false })).toEqual(false); }); diff --git a/x-pack/plugins/enterprise_search/server/lib/enterprise_search_request_handler.ts b/x-pack/plugins/enterprise_search/server/lib/enterprise_search_request_handler.ts index 18f10c590847c..00d5eaf5d6a83 100644 --- a/x-pack/plugins/enterprise_search/server/lib/enterprise_search_request_handler.ts +++ b/x-pack/plugins/enterprise_search/server/lib/enterprise_search_request_handler.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import fetch from 'node-fetch'; +import fetch, { Response } from 'node-fetch'; import querystring from 'querystring'; import { RequestHandler, @@ -25,6 +25,12 @@ interface IRequestParams { params?: object; hasValidData?: (body?: ResponseBody) => boolean; } +interface IErrorResponse { + message: string; + attributes: { + errors: string[]; + }; +} export interface IEnterpriseSearchRequestHandler { createRequest(requestParams?: object): RequestHandler; } @@ -71,34 +77,131 @@ export class EnterpriseSearchRequestHandler { ? JSON.stringify(request.body) : undefined; - // Call the Enterprise Search API and pass back response to the front-end + // Call the Enterprise Search API const apiResponse = await fetch(url, { method, headers, body }); + // Handle authentication redirects if (apiResponse.url.endsWith('/login') || apiResponse.url.endsWith('/ent/select')) { - throw new Error('Cannot authenticate Enterprise Search user'); + return this.handleAuthenticationError(response); } + // Handle 400-500+ responses from the Enterprise Search server const { status } = apiResponse; - const json = await apiResponse.json(); + if (status >= 500) { + return this.handleServerError(response, apiResponse, url); + } else if (status >= 400) { + return this.handleClientError(response, apiResponse); + } - if (hasValidData(json)) { - return response.custom({ statusCode: status, body: json }); - } else { - this.log.debug(`Invalid data received from <${url}>: ${JSON.stringify(json)}`); - throw new Error('Invalid data received'); + // Check returned data + const json = await apiResponse.json(); + if (!hasValidData(json)) { + return this.handleInvalidDataError(response, url, json); } + + // Pass successful responses back to the front-end + return response.custom({ statusCode: status, body: json }); } catch (e) { - const errorMessage = `Error connecting to Enterprise Search: ${e?.message || e.toString()}`; + // Catch connection/auth errors + return this.handleConnectionError(response, e); + } + }; + } - this.log.error(errorMessage); - if (e instanceof Error) this.log.debug(e.stack as string); + /** + * Attempt to grab a usable error body from Enterprise Search - this isn't + * always possible because some of our internal endpoints send back blank + * bodies, and sometimes the server sends back Ruby on Rails error pages + */ + async getErrorResponseBody(apiResponse: Response) { + const { statusText } = apiResponse; + const contentType = apiResponse.headers.get('content-type') || ''; - return response.customError({ statusCode: 502, body: errorMessage }); - } + // Default response + let body: IErrorResponse = { + message: statusText, + attributes: { errors: [statusText] }, }; + + try { + if (contentType.includes('application/json')) { + // Try parsing body as JSON + const json = await apiResponse.json(); + + // Some of our internal endpoints return either an `error` or `errors` key, + // which can both return either a string or array of strings ¯\_(ツ)_/¯ + const errors = json.error || json.errors || [statusText]; + body = { + message: errors.toString(), + attributes: { errors: Array.isArray(errors) ? errors : [errors] }, + }; + } else { + // Try parsing body as text/html + const text = await apiResponse.text(); + if (text) { + body = { + message: text, + attributes: { errors: [text] }, + }; + } + } + } catch { + // Fail silently + } + + return body; + } + + /** + * Error response helpers + */ + + async handleClientError(response: KibanaResponseFactory, apiResponse: Response) { + const { status } = apiResponse; + const body = await this.getErrorResponseBody(apiResponse); + + return response.customError({ statusCode: status, body }); + } + + async handleServerError(response: KibanaResponseFactory, apiResponse: Response, url: string) { + const { status } = apiResponse; + const { message } = await this.getErrorResponseBody(apiResponse); + + // Don't expose server errors to the front-end, as they may contain sensitive stack traces + const errorMessage = + 'Enterprise Search encountered an internal server error. Please contact your system administrator if the problem persists.'; + + this.log.error(`Enterprise Search Server Error ${status} at <${url}>: ${message}`); + return response.customError({ statusCode: 502, body: errorMessage }); + } + + handleInvalidDataError(response: KibanaResponseFactory, url: string, json: object) { + const errorMessage = 'Invalid data received from Enterprise Search'; + + this.log.error(`Invalid data received from <${url}>: ${JSON.stringify(json)}`); + return response.customError({ statusCode: 502, body: errorMessage }); } - // Small helper + handleConnectionError(response: KibanaResponseFactory, e: Error) { + const errorMessage = `Error connecting to Enterprise Search: ${e?.message || e.toString()}`; + + this.log.error(errorMessage); + if (e instanceof Error) this.log.debug(e.stack as string); + + return response.customError({ statusCode: 502, body: errorMessage }); + } + + handleAuthenticationError(response: KibanaResponseFactory) { + const errorMessage = 'Cannot authenticate Enterprise Search user'; + + this.log.error(errorMessage); + return response.customError({ statusCode: 502, body: errorMessage }); + } + + /** + * Misc helpers + */ + isEmptyObj(obj: object) { return Object.keys(obj).length === 0; } diff --git a/x-pack/plugins/features/server/plugin.ts b/x-pack/plugins/features/server/plugin.ts index 8a799887bba09..857bba4c606d4 100644 --- a/x-pack/plugins/features/server/plugin.ts +++ b/x-pack/plugins/features/server/plugin.ts @@ -4,6 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ import { RecursiveReadonly } from '@kbn/utility-types'; +import { deepFreeze } from '@kbn/std'; import { CoreSetup, CoreStart, @@ -12,7 +13,6 @@ import { PluginInitializerContext, } from '../../../../src/core/server'; import { Capabilities as UICapabilities } from '../../../../src/core/server'; -import { deepFreeze } from '../../../../src/core/server'; import { PluginSetupContract as TimelionSetupContract } from '../../../../src/plugins/vis_type_timelion/server'; import { FeatureRegistry } from './feature_registry'; import { uiCapabilitiesForFeatures } from './ui_capabilities_for_features'; diff --git a/x-pack/plugins/graph/public/state_management/url_templates.ts b/x-pack/plugins/graph/public/state_management/url_templates.ts index 19de52d444209..9149a27a4f986 100644 --- a/x-pack/plugins/graph/public/state_management/url_templates.ts +++ b/x-pack/plugins/graph/public/state_management/url_templates.ts @@ -7,6 +7,7 @@ import actionCreatorFactory from 'typescript-fsa'; import { reducerWithInitialState } from 'typescript-fsa-reducers/dist'; import { i18n } from '@kbn/i18n'; +import { modifyUrl } from '@kbn/std'; import rison from 'rison-node'; import { takeEvery, select } from 'redux-saga/effects'; import { format, parse } from 'url'; @@ -17,7 +18,6 @@ import { setDatasource, IndexpatternDatasource, requestDatasource } from './data import { outlinkEncoders } from '../helpers/outlink_encoders'; import { urlTemplatePlaceholder } from '../helpers/url_template'; import { matchesOne } from './helpers'; -import { modifyUrl } from '../../../../../src/core/public'; const actionCreator = actionCreatorFactory('x-pack/graph/urlTemplates'); diff --git a/x-pack/plugins/index_management/__jest__/client_integration/helpers/http_requests.ts b/x-pack/plugins/index_management/__jest__/client_integration/helpers/http_requests.ts index 12cf7ccac6c59..20b1e0878a730 100644 --- a/x-pack/plugins/index_management/__jest__/client_integration/helpers/http_requests.ts +++ b/x-pack/plugins/index_management/__jest__/client_integration/helpers/http_requests.ts @@ -103,6 +103,17 @@ const registerHttpRequestMockHelpers = (server: SinonFakeServer) => { ]); }; + const setLoadComponentTemplatesResponse = (response?: HttpResponse, error?: any) => { + const status = error ? error.status || 400 : 200; + const body = error ? error.body : response; + + server.respondWith('GET', `${API_BASE_PATH}/component_templates`, [ + status, + { 'Content-Type': 'application/json' }, + JSON.stringify(body), + ]); + }; + return { setLoadTemplatesResponse, setLoadIndicesResponse, @@ -114,6 +125,7 @@ const registerHttpRequestMockHelpers = (server: SinonFakeServer) => { setCreateTemplateResponse, setUpdateTemplateResponse, setSimulateTemplateResponse, + setLoadComponentTemplatesResponse, }; }; diff --git a/x-pack/plugins/index_management/__jest__/client_integration/helpers/setup_environment.tsx b/x-pack/plugins/index_management/__jest__/client_integration/helpers/setup_environment.tsx index 910d9be842da8..e221c3d421e02 100644 --- a/x-pack/plugins/index_management/__jest__/client_integration/helpers/setup_environment.tsx +++ b/x-pack/plugins/index_management/__jest__/client_integration/helpers/setup_environment.tsx @@ -24,7 +24,11 @@ import { ExtensionsService } from '../../../public/services'; import { UiMetricService } from '../../../public/application/services/ui_metric'; import { setUiMetricService } from '../../../public/application/services/api'; import { setExtensionsService } from '../../../public/application/store/selectors'; -import { MappingsEditorProvider } from '../../../public/application/components'; +import { + MappingsEditorProvider, + ComponentTemplatesProvider, +} from '../../../public/application/components'; +import { componentTemplatesMockDependencies } from '../../../public/application/components/component_templates/__jest__'; import { init as initHttpRequests } from './http_requests'; const mockHttpClient = axios.create({ adapter: axiosXhrAdapter }); @@ -34,9 +38,11 @@ export const services = { extensionsService: new ExtensionsService(), uiMetricService: new UiMetricService('index_management'), }; + services.uiMetricService.setup({ reportUiStats() {} } as any); setExtensionsService(services.extensionsService); setUiMetricService(services.uiMetricService); + const appDependencies = { services, core: { getUrlForApp: () => {} }, @@ -66,9 +72,11 @@ export const WithAppDependencies = (Comp: any, overridingDependencies: any = {}) return ( - - - + + + + + ); diff --git a/x-pack/plugins/index_management/__jest__/client_integration/index_template_wizard/constants.ts b/x-pack/plugins/index_management/__jest__/client_integration/index_template_wizard/constants.ts index 3f6e5d7d4dab2..ef5cffc05d8d7 100644 --- a/x-pack/plugins/index_management/__jest__/client_integration/index_template_wizard/constants.ts +++ b/x-pack/plugins/index_management/__jest__/client_integration/index_template_wizard/constants.ts @@ -26,7 +26,5 @@ export const ALIASES = { }; export const MAPPINGS = { - _source: {}, - _meta: {}, properties: {}, }; diff --git a/x-pack/plugins/index_management/__jest__/client_integration/index_template_wizard/template_clone.test.tsx b/x-pack/plugins/index_management/__jest__/client_integration/index_template_wizard/template_clone.test.tsx index ccb729db44f9b..8b74e9fb0cdf8 100644 --- a/x-pack/plugins/index_management/__jest__/client_integration/index_template_wizard/template_clone.test.tsx +++ b/x-pack/plugins/index_management/__jest__/client_integration/index_template_wizard/template_clone.test.tsx @@ -7,8 +7,8 @@ import React from 'react'; import { act } from 'react-dom/test-utils'; -import { getTemplate } from '../../../test/fixtures'; -import { setupEnvironment, nextTick } from '../helpers'; +import { getComposableTemplate } from '../../../test/fixtures'; +import { setupEnvironment } from '../helpers'; import { TEMPLATE_NAME, INDEX_PATTERNS as DEFAULT_INDEX_PATTERNS, MAPPINGS } from './constants'; import { setup } from './template_clone.helpers'; @@ -41,32 +41,35 @@ jest.mock('@elastic/eui', () => { }; }); -// FLAKY: https://github.com/elastic/kibana/issues/59849 -describe.skip('', () => { +const templateToClone = getComposableTemplate({ + name: TEMPLATE_NAME, + indexPatterns: ['indexPattern1'], + template: { + mappings: MAPPINGS, + }, +}); + +describe('', () => { let testBed: TemplateFormTestBed; const { server, httpRequestsMockHelpers } = setupEnvironment(); - afterAll(() => { - server.restore(); + beforeAll(() => { + jest.useFakeTimers(); + httpRequestsMockHelpers.setLoadComponentTemplatesResponse([]); + httpRequestsMockHelpers.setLoadTemplateResponse(templateToClone); }); - const templateToClone = getTemplate({ - name: TEMPLATE_NAME, - indexPatterns: ['indexPattern1'], - template: { - mappings: MAPPINGS, - }, - isLegacy: true, + afterAll(() => { + server.restore(); + jest.useRealTimers(); }); beforeEach(async () => { - httpRequestsMockHelpers.setLoadTemplateResponse(templateToClone); - await act(async () => { testBed = await setup(); - await testBed.waitFor('templateForm'); }); + testBed.component.update(); }); test('should set the correct page title', () => { @@ -80,30 +83,26 @@ describe.skip('', () => { beforeEach(async () => { const { actions } = testBed; - await act(async () => { - // Complete step 1 (logistics) - // Specify index patterns, but do not change name (keep default) - await actions.completeStepOne({ - indexPatterns: DEFAULT_INDEX_PATTERNS, - }); - - // Bypass step 2 (index settings) - await actions.completeStepTwo(); - - // Bypass step 3 (mappings) - await actions.completeStepThree(); - - // Bypass step 4 (aliases) - await actions.completeStepFour(); + // Logistics + // Specify index patterns, but do not change name (keep default) + await actions.completeStepOne({ + indexPatterns: DEFAULT_INDEX_PATTERNS, }); + // Component templates + await actions.completeStepTwo(); + // Index settings + await actions.completeStepThree(); + // Mappings + await actions.completeStepFour(); + // Aliases + await actions.completeStepFive(); }); it('should send the correct payload', async () => { const { actions } = testBed; await act(async () => { - actions.clickSubmitButton(); - await nextTick(); + actions.clickNextButton(); }); const latestRequest = server.requests[server.requests.length - 1]; @@ -113,6 +112,8 @@ describe.skip('', () => { name: `${templateToClone.name}-copy`, indexPatterns: DEFAULT_INDEX_PATTERNS, }; + // @ts-expect-error + delete expected.template; // As no settings, mappings or aliases have been defined, no "template" param is sent expect(JSON.parse(JSON.parse(latestRequest.requestBody).body)).toEqual(expected); }); diff --git a/x-pack/plugins/index_management/__jest__/client_integration/index_template_wizard/template_create.test.tsx b/x-pack/plugins/index_management/__jest__/client_integration/index_template_wizard/template_create.test.tsx index 76b6c34f999d5..b67e503f8d3e2 100644 --- a/x-pack/plugins/index_management/__jest__/client_integration/index_template_wizard/template_create.test.tsx +++ b/x-pack/plugins/index_management/__jest__/client_integration/index_template_wizard/template_create.test.tsx @@ -7,12 +7,11 @@ import React from 'react'; import { act } from 'react-dom/test-utils'; -import { setupEnvironment, nextTick } from '../helpers'; +import { setupEnvironment } from '../helpers'; import { TEMPLATE_NAME, SETTINGS, - MAPPINGS, ALIASES, INDEX_PATTERNS as DEFAULT_INDEX_PATTERNS, } from './constants'; @@ -61,21 +60,50 @@ const KEYWORD_MAPPING_FIELD = { type: 'keyword', }; -// FLAKY: https://github.com/elastic/kibana/issues/67833 -describe.skip('', () => { +const componentTemplate1 = { + name: 'test_component_template_1', + hasMappings: true, + hasAliases: false, + hasSettings: false, + usedBy: [], + isManaged: false, +}; + +const componentTemplate2 = { + name: 'test_component_template_2', + hasMappings: false, + hasAliases: false, + hasSettings: true, + usedBy: ['test_index_template_1'], + isManaged: false, +}; + +const componentTemplates = [componentTemplate1, componentTemplate2]; + +describe('', () => { let testBed: TemplateFormTestBed; const { server, httpRequestsMockHelpers } = setupEnvironment(); + beforeAll(() => { + jest.useFakeTimers(); + + httpRequestsMockHelpers.setLoadComponentTemplatesResponse(componentTemplates); + + // disable all react-beautiful-dnd development warnings + (window as any)['__react-beautiful-dnd-disable-dev-warnings'] = true; + }); + afterAll(() => { server.restore(); + jest.useRealTimers(); + (window as any)['__react-beautiful-dnd-disable-dev-warnings'] = false; }); describe('on component mount', () => { beforeEach(async () => { await act(async () => { testBed = await setup(); - await testBed.waitFor('templateForm'); }); }); @@ -93,9 +121,8 @@ describe.skip('', () => { await act(async () => { actions.clickNextButton(); - await nextTick(); - component.update(); }); + component.update(); expect(find('nextButton').props().disabled).toEqual(true); }); @@ -105,21 +132,131 @@ describe.skip('', () => { beforeEach(async () => { await act(async () => { testBed = await setup(); - await testBed.waitFor('templateForm'); }); + testBed.component.update(); }); - describe('index settings (step 2)', () => { + describe('component templates (step 2)', () => { beforeEach(async () => { const { actions } = testBed; + await actions.completeStepOne({ name: TEMPLATE_NAME, indexPatterns: ['index1'] }); + }); + + it('should set the correct page title', async () => { + const { exists, find } = testBed; + + expect(exists('stepComponents')).toBe(true); + expect(find('stepTitle').text()).toEqual('Component templates (optional)'); + }); + + it('should list the available component templates', () => { + const { + actions: { + componentTemplates: { getComponentTemplatesInList }, + }, + } = testBed; + const componentsFound = getComponentTemplatesInList(); + expect(componentsFound).toEqual(componentTemplates.map((c) => c.name)); + }); + + it('should allow to search for a component', async () => { + const { + component, + form: { setInputValue }, + actions: { + componentTemplates: { getComponentTemplatesInList }, + }, + } = testBed; await act(async () => { - // Complete step 1 (logistics) - await actions.completeStepOne({ name: TEMPLATE_NAME, indexPatterns: ['index1'] }); + setInputValue('componentTemplateSearchBox', 'template_2'); }); + component.update(); + + const componentsFound = getComponentTemplatesInList(); + expect(componentsFound).toEqual(['test_component_template_2']); }); - it('should set the correct page title', () => { + it('should allow to filter component by Index settings, mappings and aliases', async () => { + const { + find, + exists, + actions: { + componentTemplates: { showFilters, selectFilter, getComponentTemplatesInList }, + }, + } = testBed; + + showFilters(); + + expect(find('filterList.filterItem').map((wrapper) => wrapper.text())).toEqual([ + 'Index settings', + 'Mappings', + 'Aliases', + ]); + + await selectFilter('settings'); + expect(getComponentTemplatesInList()).toEqual(['test_component_template_2']); // only this one has settings + + await selectFilter('mappings'); + expect(exists('componentTemplatesList')).toBe(false); // no component has **both** settings and mappings + expect(exists('componentTemplates.emptySearchResult')).toBe(true); + expect(find('componentTemplates.emptySearchResult').text()).toContain( + 'No components match your search' + ); + + await selectFilter('settings'); // unselect settings + expect(getComponentTemplatesInList()).toEqual(['test_component_template_1']); // only this one has mappings + + await selectFilter('mappings'); // unselect mappings (back to start) + expect(getComponentTemplatesInList()).toEqual([ + 'test_component_template_1', + 'test_component_template_2', + ]); + + await selectFilter('aliases'); + expect(exists('componentTemplatesList')).toBe(false); // no component has aliases defined. + }); + + it('should allow to select and unselect a component template', async () => { + const { + find, + exists, + actions: { + componentTemplates: { + selectComponentAt, + unSelectComponentAt, + getComponentTemplatesSelected, + }, + }, + } = testBed; + + // Start with empty selection + expect(exists('componentTemplatesSelection.emptyPrompt')).toBe(true); + expect(find('componentTemplatesSelection.emptyPrompt').text()).toContain( + 'Add component template building blocks to this template.' + ); + + // Select first component in the list + await selectComponentAt(0); + expect(exists('componentTemplatesSelection.emptyPrompt')).toBe(false); + expect(getComponentTemplatesSelected()).toEqual(['test_component_template_1']); + + // Unselect the component + await unSelectComponentAt(0); + expect(exists('componentTemplatesSelection.emptyPrompt')).toBe(true); + }); + }); + + describe('index settings (step 3)', () => { + beforeEach(async () => { + const { actions } = testBed; + // Logistics + await actions.completeStepOne({ name: TEMPLATE_NAME, indexPatterns: ['index1'] }); + // Component templates + await actions.completeStepTwo(); + }); + + it('should set the correct page title', async () => { const { exists, find } = testBed; expect(exists('stepSettings')).toBe(true); @@ -130,24 +267,22 @@ describe.skip('', () => { const { form, actions } = testBed; await act(async () => { - actions.completeStepTwo('{ invalidJsonString '); + actions.completeStepThree('{ invalidJsonString '); }); expect(form.getErrorsMessages()).toContain('Invalid JSON format.'); }); }); - describe('mappings (step 3)', () => { + describe('mappings (step 4)', () => { beforeEach(async () => { const { actions } = testBed; - - await act(async () => { - // Complete step 1 (logistics) - await actions.completeStepOne({ name: TEMPLATE_NAME, indexPatterns: ['index1'] }); - - // Complete step 2 (index settings) - await actions.completeStepTwo('{}'); - }); + // Logistics + await actions.completeStepOne({ name: TEMPLATE_NAME, indexPatterns: ['index1'] }); + // Component templates + await actions.completeStepTwo(); + // Index settings + await actions.completeStepThree('{}'); }); it('should set the correct page title', () => { @@ -160,11 +295,9 @@ describe.skip('', () => { it('should allow the user to define document fields for a mapping', async () => { const { actions, find } = testBed; - await act(async () => { - await actions.addMappingField('field_1', 'text'); - await actions.addMappingField('field_2', 'text'); - await actions.addMappingField('field_3', 'text'); - }); + await actions.mappings.addField('field_1', 'text'); + await actions.mappings.addField('field_2', 'text'); + await actions.mappings.addField('field_3', 'text'); expect(find('fieldsListItem').length).toBe(3); }); @@ -172,10 +305,8 @@ describe.skip('', () => { it('should allow the user to remove a document field from a mapping', async () => { const { actions, find } = testBed; - await act(async () => { - await actions.addMappingField('field_1', 'text'); - await actions.addMappingField('field_2', 'text'); - }); + await actions.mappings.addField('field_1', 'text'); + await actions.mappings.addField('field_2', 'text'); expect(find('fieldsListItem').length).toBe(2); @@ -187,20 +318,17 @@ describe.skip('', () => { }); }); - describe('aliases (step 4)', () => { + describe('aliases (step 5)', () => { beforeEach(async () => { const { actions } = testBed; - - await act(async () => { - // Complete step 1 (logistics) - await actions.completeStepOne({ name: TEMPLATE_NAME, indexPatterns: ['index1'] }); - - // Complete step 2 (index settings) - await actions.completeStepTwo('{}'); - - // Complete step 3 (mappings) - await actions.completeStepThree(); - }); + // Logistics + await actions.completeStepOne({ name: TEMPLATE_NAME, indexPatterns: ['index1'] }); + // Component templates + await actions.completeStepTwo(); + // Index settings + await actions.completeStepThree('{}'); + // Mappings + await actions.completeStepFour(); }); it('should set the correct page title', () => { @@ -213,39 +341,35 @@ describe.skip('', () => { it('should not allow invalid json', async () => { const { actions, form } = testBed; - await act(async () => { - // Complete step 4 (aliases) with invalid json - await actions.completeStepFour('{ invalidJsonString ', false); - }); + // Complete step 5 (aliases) with invalid json + await actions.completeStepFive('{ invalidJsonString '); expect(form.getErrorsMessages()).toContain('Invalid JSON format.'); }); }); }); - describe('review (step 5)', () => { + describe('review (step 6)', () => { beforeEach(async () => { await act(async () => { testBed = await setup(); - await testBed.waitFor('templateForm'); - - const { actions } = testBed; - - // Complete step 1 (logistics) - await actions.completeStepOne({ - name: TEMPLATE_NAME, - indexPatterns: DEFAULT_INDEX_PATTERNS, - }); - - // Complete step 2 (index settings) - await actions.completeStepTwo(JSON.stringify(SETTINGS)); - - // Complete step 3 (mappings) - await actions.completeStepThree(); + }); + testBed.component.update(); - // Complete step 4 (aliases) - await actions.completeStepFour(JSON.stringify(ALIASES)); + const { actions } = testBed; + // Logistics + await actions.completeStepOne({ + name: TEMPLATE_NAME, + indexPatterns: DEFAULT_INDEX_PATTERNS, }); + // Component templates + await actions.completeStepTwo('test_component_template_1'); + // Index settings + await actions.completeStepThree(JSON.stringify(SETTINGS)); + // Mappings + await actions.completeStepFour(); + // Aliases + await actions.completeStepFive(JSON.stringify(ALIASES)); }); it('should set the correct step title', () => { @@ -255,26 +379,30 @@ describe.skip('', () => { }); describe('tabs', () => { - test('should have 2 tabs', () => { + test('should have 3 tabs', () => { const { find } = testBed; - expect(find('summaryTabContent').find('.euiTab').length).toBe(2); + expect(find('summaryTabContent').find('.euiTab').length).toBe(3); expect( find('summaryTabContent') .find('.euiTab') .map((t) => t.text()) - ).toEqual(['Summary', 'Request']); + ).toEqual(['Summary', 'Preview', 'Request']); }); - test('should navigate to the Request tab', async () => { + test('should navigate to the preview and request tab', async () => { const { exists, actions } = testBed; expect(exists('summaryTab')).toBe(true); expect(exists('requestTab')).toBe(false); + expect(exists('previewTab')).toBe(false); - actions.selectSummaryTab('request'); - + await actions.review.selectTab('preview'); expect(exists('summaryTab')).toBe(false); + expect(exists('previewTab')).toBe(true); + + await actions.review.selectTab('request'); + expect(exists('previewTab')).toBe(false); expect(exists('requestTab')).toBe(true); }); }); @@ -282,24 +410,23 @@ describe.skip('', () => { it('should render a warning message if a wildcard is used as an index pattern', async () => { await act(async () => { testBed = await setup(); - await testBed.waitFor('templateForm'); - - const { actions } = testBed; - // Complete step 1 (logistics) - await actions.completeStepOne({ - name: TEMPLATE_NAME, - indexPatterns: ['*'], // Set wildcard index pattern - }); - - // Complete step 2 (index settings) - await actions.completeStepTwo(JSON.stringify({})); - - // Complete step 3 (mappings) - await actions.completeStepThree(); + }); + testBed.component.update(); - // Complete step 4 (aliases) - await actions.completeStepFour(JSON.stringify({})); + const { actions } = testBed; + // Logistics + await actions.completeStepOne({ + name: TEMPLATE_NAME, + indexPatterns: ['*'], // Set wildcard index pattern }); + // Component templates + await actions.completeStepTwo(); + // Index settings + await actions.completeStepThree(JSON.stringify({})); + // Mappings + await actions.completeStepFour(); + // Aliases + await actions.completeStepFive(JSON.stringify({})); const { exists, find } = testBed; @@ -316,32 +443,32 @@ describe.skip('', () => { await act(async () => { testBed = await setup(); - await testBed.waitFor('templateForm'); - - const { actions } = testBed; - // Complete step 1 (logistics) - await actions.completeStepOne({ - name: TEMPLATE_NAME, - indexPatterns: DEFAULT_INDEX_PATTERNS, - }); - - // Complete step 2 (index settings) - await actions.completeStepTwo(JSON.stringify(SETTINGS)); - - // Complete step 3 (mappings) - await actions.completeStepThree(MAPPING_FIELDS); + }); + testBed.component.update(); - // Complete step 4 (aliases) - await actions.completeStepFour(JSON.stringify(ALIASES)); + const { actions } = testBed; + // Logistics + await actions.completeStepOne({ + name: TEMPLATE_NAME, + indexPatterns: DEFAULT_INDEX_PATTERNS, }); + // Component templates + await actions.completeStepTwo('test_component_template_1'); + // Index settings + await actions.completeStepThree(JSON.stringify(SETTINGS)); + // Mappings + await actions.completeStepFour(MAPPING_FIELDS); + // Aliases + await actions.completeStepFive(JSON.stringify(ALIASES)); }); it('should send the correct payload', async () => { - const { actions } = testBed; + const { actions, find } = testBed; + + expect(find('stepTitle').text()).toEqual(`Review details for '${TEMPLATE_NAME}'`); await act(async () => { - actions.clickSubmitButton(); - await nextTick(); + actions.clickNextButton(); }); const latestRequest = server.requests[server.requests.length - 1]; @@ -349,10 +476,10 @@ describe.skip('', () => { const expected = { name: TEMPLATE_NAME, indexPatterns: DEFAULT_INDEX_PATTERNS, + composedOf: ['test_component_template_1'], template: { settings: SETTINGS, mappings: { - ...MAPPINGS, properties: { [BOOLEAN_MAPPING_FIELD.name]: { type: BOOLEAN_MAPPING_FIELD.type, @@ -370,6 +497,7 @@ describe.skip('', () => { _kbnMeta: { type: 'default', isLegacy: false, + hasDatastream: false, }, }; @@ -388,10 +516,9 @@ describe.skip('', () => { httpRequestsMockHelpers.setCreateTemplateResponse(undefined, { body: error }); await act(async () => { - actions.clickSubmitButton(); - await nextTick(); - component.update(); + actions.clickNextButton(); }); + component.update(); expect(exists('saveTemplateError')).toBe(true); expect(find('saveTemplateError').text()).toContain(error.message); diff --git a/x-pack/plugins/index_management/__jest__/client_integration/index_template_wizard/template_edit.test.tsx b/x-pack/plugins/index_management/__jest__/client_integration/index_template_wizard/template_edit.test.tsx index de66013241236..37d489b6afe72 100644 --- a/x-pack/plugins/index_management/__jest__/client_integration/index_template_wizard/template_edit.test.tsx +++ b/x-pack/plugins/index_management/__jest__/client_integration/index_template_wizard/template_edit.test.tsx @@ -8,7 +8,7 @@ import React from 'react'; import { act } from 'react-dom/test-utils'; import * as fixtures from '../../../test/fixtures'; -import { setupEnvironment, nextTick } from '../helpers'; +import { setupEnvironment } from '../helpers'; import { TEMPLATE_NAME, SETTINGS, ALIASES, MAPPINGS as DEFAULT_MAPPING } from './constants'; import { setup } from './template_edit.helpers'; @@ -52,51 +52,51 @@ jest.mock('@elastic/eui', () => { }; }); -// FLAKY: https://github.com/elastic/kibana/issues/65567 -describe.skip('', () => { +describe('', () => { let testBed: TemplateFormTestBed; const { server, httpRequestsMockHelpers } = setupEnvironment(); + beforeAll(() => { + jest.useFakeTimers(); + httpRequestsMockHelpers.setLoadComponentTemplatesResponse([]); + }); + afterAll(() => { server.restore(); + jest.useRealTimers(); }); describe('without mappings', () => { const templateToEdit = fixtures.getTemplate({ name: 'index_template_without_mappings', indexPatterns: ['indexPattern1'], - isLegacy: true, }); - beforeEach(async () => { + beforeAll(() => { httpRequestsMockHelpers.setLoadTemplateResponse(templateToEdit); + }); - testBed = await setup(); - + beforeEach(async () => { await act(async () => { - await nextTick(); - testBed.component.update(); + testBed = await setup(); }); + + testBed.component.update(); }); it('allows you to add mappings', async () => { const { actions, find } = testBed; - - await act(async () => { - // Complete step 1 (logistics) - await actions.completeStepOne(); - - // Step 2 (index settings) - await actions.completeStepTwo(); - - // Step 3 (mappings) - await act(async () => { - await actions.addMappingField('field_1', 'text'); - }); - - expect(find('fieldsListItem').length).toBe(1); - }); + // Logistics + await actions.completeStepOne(); + // Component templates + await actions.completeStepTwo(); + // Index settings + await actions.completeStepThree(); + // Mappings + await actions.mappings.addField('field_1', 'text'); + + expect(find('fieldsListItem').length).toBe(1); }); }); @@ -107,16 +107,17 @@ describe.skip('', () => { template: { mappings: MAPPING, }, - isLegacy: true, }); - beforeEach(async () => { + beforeAll(() => { httpRequestsMockHelpers.setLoadTemplateResponse(templateToEdit); + }); + beforeEach(async () => { await act(async () => { testBed = await setup(); - await testBed.waitFor('templateForm'); }); + testBed.component.update(); }); test('should set the correct page title', () => { @@ -138,64 +139,64 @@ describe.skip('', () => { beforeEach(async () => { const { actions } = testBed; - await act(async () => { - // Complete step 1 (logistics) - await actions.completeStepOne({ - indexPatterns: UPDATED_INDEX_PATTERN, - }); - - // Step 2 (index settings) - await actions.completeStepTwo(JSON.stringify(SETTINGS)); + // Logistics + await actions.completeStepOne({ + indexPatterns: UPDATED_INDEX_PATTERN, + priority: 3, }); + // Component templates + await actions.completeStepTwo(); + // Index settings + await actions.completeStepThree(JSON.stringify(SETTINGS)); }); it('should send the correct payload with changed values', async () => { - const { actions, component, find, form } = testBed; + const { actions, component, exists, form } = testBed; + // Make some changes to the mappings await act(async () => { - // Make some changes to the mappings (step 3) - actions.clickEditButtonAtField(0); // Select the first field to edit - await nextTick(); - component.update(); }); + component.update(); - // verify edit field flyout - expect(find('mappingsEditorFieldEdit').length).toEqual(1); + // Verify that the edit field flyout is opened + expect(exists('mappingsEditorFieldEdit')).toBe(true); + // Change the field name await act(async () => { - // change the field name form.setInputValue('nameParameterInput', UPDATED_MAPPING_TEXT_FIELD_NAME); + }); - // Save changes + // Save changes on the field + await act(async () => { actions.clickEditFieldUpdateButton(); - await nextTick(); - component.update(); + }); + component.update(); - // Proceed to the next step + // Proceed to the next step + await act(async () => { actions.clickNextButton(); - await nextTick(50); - component.update(); + }); + component.update(); - // Step 4 (aliases) - await actions.completeStepFour(JSON.stringify(ALIASES)); + // Aliases + await actions.completeStepFive(JSON.stringify(ALIASES)); - // Submit the form - actions.clickSubmitButton(); - await nextTick(); + // Submit the form + await act(async () => { + actions.clickNextButton(); }); const latestRequest = server.requests[server.requests.length - 1]; - const { version, order } = templateToEdit; + const { version } = templateToEdit; const expected = { name: TEMPLATE_NAME, version, - order, + priority: 3, indexPatterns: UPDATED_INDEX_PATTERN, template: { mappings: { - ...MAPPING, properties: { [UPDATED_MAPPING_TEXT_FIELD_NAME]: { type: 'text', @@ -215,6 +216,7 @@ describe.skip('', () => { _kbnMeta: { type: 'default', isLegacy: templateToEdit._kbnMeta.isLegacy, + hasDatastream: false, }, }; diff --git a/x-pack/plugins/index_management/__jest__/client_integration/index_template_wizard/template_form.helpers.ts b/x-pack/plugins/index_management/__jest__/client_integration/index_template_wizard/template_form.helpers.ts index fdf837a914cf1..025410129a002 100644 --- a/x-pack/plugins/index_management/__jest__/client_integration/index_template_wizard/template_form.helpers.ts +++ b/x-pack/plugins/index_management/__jest__/client_integration/index_template_wizard/template_form.helpers.ts @@ -3,10 +3,10 @@ * or more contributor license agreements. Licensed under the Elastic License; * you may not use this file except in compliance with the Elastic License. */ +import { act } from 'react-dom/test-utils'; import { TestBed, SetupFunc, UnwrapPromise } from '../../../../../test_utils'; import { TemplateDeserialized } from '../../../common'; -import { nextTick } from '../helpers'; interface MappingField { name: string; @@ -30,10 +30,6 @@ export const formSetup = async (initTestBed: SetupFunc) => { testBed.find('backButton').simulate('click'); }; - const clickSubmitButton = () => { - testBed.find('submitButton').simulate('click'); - }; - const clickEditButtonAtField = (index: number) => { testBed.find('editFieldButton').at(index).simulate('click'); }; @@ -52,16 +48,100 @@ export const formSetup = async (initTestBed: SetupFunc) => { testBed.find('createFieldForm.cancelButton').simulate('click'); }; + // Step component templates actions + const componentTemplates = { + getComponentTemplatesInList() { + const { find } = testBed; + return find('componentTemplatesList.item.name').map((wrapper) => wrapper.text()); + }, + getComponentTemplatesSelected() { + const { find } = testBed; + return find('componentTemplatesSelection.item.name').map((wrapper) => wrapper.text()); + }, + showFilters() { + const { find, component } = testBed; + act(() => { + find('componentTemplates.filterButton').simulate('click'); + }); + component.update(); + }, + async selectFilter(filter: 'settings' | 'mappings' | 'aliases') { + const { find, component } = testBed; + const filters = ['settings', 'mappings', 'aliases']; + const index = filters.indexOf(filter); + + await act(async () => { + find('filterList.filterItem').at(index).simulate('click'); + }); + component.update(); + }, + async selectComponentAt(index: number) { + const { find, component } = testBed; + + await act(async () => { + find('componentTemplatesList.item.action-plusInCircle').at(index).simulate('click'); + }); + component.update(); + }, + async unSelectComponentAt(index: number) { + const { find, component } = testBed; + + await act(async () => { + find('componentTemplatesSelection.item.action-minusInCircle').at(index).simulate('click'); + }); + component.update(); + }, + }; + + // Step Mappings actions + const mappings = { + async addField(name: string, type: string) { + const { find, form, component } = testBed; + + await act(async () => { + form.setInputValue('nameParameterInput', name); + find('createFieldForm.mockComboBox').simulate('change', [ + { + label: type, + value: type, + }, + ]); + }); + + await act(async () => { + find('createFieldForm.addButton').simulate('click'); + }); + + component.update(); + }, + }; + + // Step Review actions + const review = { + async selectTab(tab: 'summary' | 'preview' | 'request') { + const tabs = ['summary', 'preview', 'request']; + + await act(async () => { + testBed.find('summaryTabContent').find('.euiTab').at(tabs.indexOf(tab)).simulate('click'); + }); + + testBed.component.update(); + }, + }; + const completeStepOne = async ({ name, indexPatterns, order, + priority, version, }: Partial = {}) => { - const { form, find, waitFor } = testBed; + const { component, form, find } = testBed; if (name) { - form.setInputValue('nameField.input', name); + act(() => { + form.setInputValue('nameField.input', name); + }); } if (indexPatterns) { @@ -70,94 +150,104 @@ export const formSetup = async (initTestBed: SetupFunc) => { value: pattern, })); - find('mockComboBox').simulate('change', indexPatternsFormatted); // Using mocked EuiComboBox - await nextTick(); + act(() => { + find('mockComboBox').simulate('change', indexPatternsFormatted); // Using mocked EuiComboBox + }); } - if (order) { - form.setInputValue('orderField.input', JSON.stringify(order)); - } + await act(async () => { + if (order) { + form.setInputValue('orderField.input', JSON.stringify(order)); + } - if (version) { - form.setInputValue('versionField.input', JSON.stringify(version)); - } + if (priority) { + form.setInputValue('priorityField.input', JSON.stringify(priority)); + } - clickNextButton(); - await waitFor('stepSettings'); + if (version) { + form.setInputValue('versionField.input', JSON.stringify(version)); + } + + clickNextButton(); + }); + + component.update(); }; - const completeStepTwo = async (settings?: string) => { - const { find, component, waitFor } = testBed; + const completeStepTwo = async (componentName?: string) => { + const { find, component } = testBed; + + if (componentName) { + // Find the index of the template in the list + const allComponents = find('componentTemplatesList.item.name').map((wrapper) => + wrapper.text() + ); + const index = allComponents.indexOf(componentName); + if (index < 0) { + throw new Error( + `Could not find component "${componentName}" in the list ${JSON.stringify(allComponents)}` + ); + } - if (settings) { - find('mockCodeEditor').simulate('change', { - jsonString: settings, - }); // Using mocked EuiCodeEditor - await nextTick(); - component.update(); + await componentTemplates.selectComponentAt(index); } - clickNextButton(); - await waitFor('stepMappings'); + await act(async () => { + clickNextButton(); + }); + + component.update(); + }; + + const completeStepThree = async (settings?: string) => { + const { find, component } = testBed; + + await act(async () => { + if (settings) { + find('mockCodeEditor').simulate('change', { + jsonString: settings, + }); // Using mocked EuiCodeEditor + } + + clickNextButton(); + }); + + component.update(); }; - const completeStepThree = async (mappingFields?: MappingField[]) => { - const { waitFor } = testBed; + const completeStepFour = async (mappingFields?: MappingField[]) => { + const { component } = testBed; if (mappingFields) { for (const field of mappingFields) { const { name, type } = field; - await addMappingField(name, type); + await mappings.addField(name, type); } } - clickNextButton(); - await waitFor('stepAliases'); + await act(async () => { + clickNextButton(); + }); + + component.update(); }; - const completeStepFour = async (aliases?: string, waitForNextStep = true) => { - const { find, component, waitFor } = testBed; + const completeStepFive = async (aliases?: string) => { + const { find, component } = testBed; if (aliases) { - find('mockCodeEditor').simulate('change', { - jsonString: aliases, - }); // Using mocked EuiCodeEditor - await nextTick(); + await act(async () => { + find('mockCodeEditor').simulate('change', { + jsonString: aliases, + }); // Using mocked EuiCodeEditor + }); component.update(); } - clickNextButton(); - - if (waitForNextStep) { - await waitFor('summaryTab'); - } else { - component.update(); - } - }; - - const selectSummaryTab = (tab: 'summary' | 'request') => { - const tabs = ['summary', 'request']; - - testBed.find('summaryTabContent').find('.euiTab').at(tabs.indexOf(tab)).simulate('click'); - }; - - const addMappingField = async (name: string, type: string) => { - const { find, form, component } = testBed; - - form.setInputValue('nameParameterInput', name); - find('createFieldForm.mockComboBox').simulate('change', [ - { - label: type, - value: type, - }, - ]); - - await nextTick(50); - component.update(); - - find('createFieldForm.addButton').simulate('click'); + await act(async () => { + clickNextButton(); + }); - await nextTick(); component.update(); }; @@ -166,7 +256,6 @@ export const formSetup = async (initTestBed: SetupFunc) => { actions: { clickNextButton, clickBackButton, - clickSubmitButton, clickEditButtonAtField, clickEditFieldUpdateButton, deleteMappingsFieldAt, @@ -175,8 +264,10 @@ export const formSetup = async (initTestBed: SetupFunc) => { completeStepTwo, completeStepThree, completeStepFour, - selectSummaryTab, - addMappingField, + completeStepFive, + componentTemplates, + mappings, + review, }, }; }; @@ -187,6 +278,17 @@ export type TestSubjects = | 'backButton' | 'codeEditorContainer' | 'confirmModalConfirmButton' + | 'componentTemplates.filterButton' + | 'componentTemplates.emptySearchResult' + | 'filterList.filterItem' + | 'componentTemplatesList' + | 'componentTemplatesList.item.name' + | 'componentTemplatesList.item.action-plusInCircle' + | 'componentTemplatesSelection' + | 'componentTemplatesSelection.item.name' + | 'componentTemplatesSelection.item.action-minusInCircle' + | 'componentTemplatesSelection.emptyPrompt' + | 'componentTemplateSearchBox' | 'createFieldForm.addPropertyButton' | 'createFieldForm.addButton' | 'createFieldForm.addFieldButton' @@ -209,12 +311,15 @@ export type TestSubjects = | 'nextButton' | 'orderField' | 'orderField.input' + | 'priorityField.input' | 'pageTitle' + | 'previewTab' | 'removeFieldButton' | 'requestTab' | 'saveTemplateError' | 'settingsEditor' | 'systemTemplateEditCallout' + | 'stepComponents' | 'stepAliases' | 'stepMappings' | 'stepSettings' diff --git a/x-pack/plugins/index_management/public/application/components/component_templates/__jest__/client_integration/helpers/index.ts b/x-pack/plugins/index_management/public/application/components/component_templates/__jest__/client_integration/helpers/index.ts index 93eb65aac0761..4b92235993e26 100644 --- a/x-pack/plugins/index_management/public/application/components/component_templates/__jest__/client_integration/helpers/index.ts +++ b/x-pack/plugins/index_management/public/application/components/component_templates/__jest__/client_integration/helpers/index.ts @@ -9,7 +9,7 @@ import { setup as componentTemplateDetailsSetup } from './component_template_det export { nextTick, getRandomString, findTestSubject } from '../../../../../../../../../test_utils'; -export { setupEnvironment } from './setup_environment'; +export { setupEnvironment, appDependencies } from './setup_environment'; export const pageHelpers = { componentTemplateList: { setup: componentTemplatesListSetup }, diff --git a/x-pack/plugins/index_management/public/application/components/component_templates/__jest__/client_integration/helpers/setup_environment.tsx b/x-pack/plugins/index_management/public/application/components/component_templates/__jest__/client_integration/helpers/setup_environment.tsx index 79e213229fc51..ac748e1b7dc2c 100644 --- a/x-pack/plugins/index_management/public/application/components/component_templates/__jest__/client_integration/helpers/setup_environment.tsx +++ b/x-pack/plugins/index_management/public/application/components/component_templates/__jest__/client_integration/helpers/setup_environment.tsx @@ -24,7 +24,7 @@ import { API_BASE_PATH } from './constants'; const mockHttpClient = axios.create({ adapter: axiosXhrAdapter }); const { GlobalFlyoutProvider } = GlobalFlyout; -const appDependencies = { +export const appDependencies = { httpClient: (mockHttpClient as unknown) as HttpSetup, apiBasePath: API_BASE_PATH, trackMetric: () => {}, diff --git a/x-pack/plugins/apm/public/hooks/useLocation.tsx b/x-pack/plugins/index_management/public/application/components/component_templates/__jest__/index.ts similarity index 58% rename from x-pack/plugins/apm/public/hooks/useLocation.tsx rename to x-pack/plugins/index_management/public/application/components/component_templates/__jest__/index.ts index e2b4e3e479629..ebd2cd9392568 100644 --- a/x-pack/plugins/apm/public/hooks/useLocation.tsx +++ b/x-pack/plugins/index_management/public/application/components/component_templates/__jest__/index.ts @@ -4,9 +4,4 @@ * you may not use this file except in compliance with the Elastic License. */ -import { useContext } from 'react'; -import { LocationContext } from '../context/LocationContext'; - -export function useLocation() { - return useContext(LocationContext); -} +export { appDependencies as componentTemplatesMockDependencies } from './client_integration/helpers'; diff --git a/x-pack/plugins/index_management/public/application/components/component_templates/component_template_selector/component_templates.tsx b/x-pack/plugins/index_management/public/application/components/component_templates/component_template_selector/component_templates.tsx index b07279c57d2be..3c10ef2cc7edc 100644 --- a/x-pack/plugins/index_management/public/application/components/component_templates/component_template_selector/component_templates.tsx +++ b/x-pack/plugins/index_management/public/application/components/component_templates/component_template_selector/component_templates.tsx @@ -145,12 +145,13 @@ export const ComponentTemplates = ({ isLoading, components, listItemProps }: Pro /> } + data-test-subj="emptySearchResult" /> ); }; return ( -
+
@@ -162,6 +163,7 @@ export const ComponentTemplates = ({ isLoading, components, listItemProps }: Pro }} aria-label={i18nTexts.searchBoxPlaceholder} className="componentTemplates__searchBox" + data-test-subj="componentTemplateSearchBox" /> diff --git a/x-pack/plugins/index_management/public/application/components/component_templates/component_template_selector/component_templates_list.tsx b/x-pack/plugins/index_management/public/application/components/component_templates/component_template_selector/component_templates_list.tsx index 0c64c38c8963f..519f2482c9323 100644 --- a/x-pack/plugins/index_management/public/application/components/component_templates/component_template_selector/component_templates_list.tsx +++ b/x-pack/plugins/index_management/public/application/components/component_templates/component_template_selector/component_templates_list.tsx @@ -19,10 +19,10 @@ interface Props { export const ComponentTemplatesList = ({ components, listItemProps }: Props) => { return ( - <> +
{components.map((component) => ( ))} - +
); }; diff --git a/x-pack/plugins/index_management/public/application/components/component_templates/component_template_selector/component_templates_list_item.tsx b/x-pack/plugins/index_management/public/application/components/component_templates/component_template_selector/component_templates_list_item.tsx index ad75c8dcbcc54..40bb062f5ddf3 100644 --- a/x-pack/plugins/index_management/public/application/components/component_templates/component_template_selector/component_templates_list_item.tsx +++ b/x-pack/plugins/index_management/public/application/components/component_templates/component_template_selector/component_templates_list_item.tsx @@ -48,6 +48,7 @@ export const ComponentTemplatesListItem = ({ className={classNames('componentTemplatesListItem', { 'componentTemplatesListItem--selected': isSelectedValue, })} + data-test-subj="item" > @@ -59,7 +60,7 @@ export const ComponentTemplatesListItem = ({
)} - + {/* {component.name} */} onViewDetail(component)}>{component.name} @@ -83,7 +84,7 @@ export const ComponentTemplatesListItem = ({ action.handler(component)} - data-test-subj="addPropertyButton" + data-test-subj={`action-${action.icon}`} aria-label={action.label} /> diff --git a/x-pack/plugins/index_management/public/application/components/component_templates/component_template_selector/component_templates_selector.tsx b/x-pack/plugins/index_management/public/application/components/component_templates/component_template_selector/component_templates_selector.tsx index ff871b8b79247..f2fd5048931de 100644 --- a/x-pack/plugins/index_management/public/application/components/component_templates/component_template_selector/component_templates_selector.tsx +++ b/x-pack/plugins/index_management/public/application/components/component_templates/component_template_selector/component_templates_selector.tsx @@ -160,6 +160,7 @@ export const ComponentTemplatesSelector = ({ // eslint-disable-next-line @typescript-eslint/naming-convention 'componentTemplatesSelector__selection--is-empty': !hasSelection, })} + data-test-subj="componentTemplatesSelection" > {hasSelection ? ( <> @@ -200,7 +201,7 @@ export const ComponentTemplatesSelector = ({
) : ( - +

0} numActiveFilters={activeFilters.length} - data-test-subj="viewButton" + data-test-subj="filterButton" > { - let testBed: MappingsEditorTestBed; - /** * Variable to store the mappings data forwarded to the consumer component */ let data: any; + let onChangeHandler: jest.Mock = jest.fn(); + let getMappingsEditorData = getMappingsEditorDataFactory(onChangeHandler); + let testBed: MappingsEditorTestBed; beforeAll(() => { jest.useFakeTimers(); @@ -34,6 +34,11 @@ describe('Mappings editor: shape datatype', () => { jest.useRealTimers(); }); + beforeEach(() => { + onChangeHandler = jest.fn(); + getMappingsEditorData = getMappingsEditorDataFactory(onChangeHandler); + }); + test('initial view and default parameters values', async () => { const defaultMappings = { properties: { @@ -45,7 +50,10 @@ describe('Mappings editor: shape datatype', () => { const updatedMappings = { ...defaultMappings }; - testBed = setup({ value: defaultMappings, onChange: onChangeHandler }); + await act(async () => { + testBed = setup({ value: defaultMappings, onChange: onChangeHandler }); + }); + testBed.component.update(); const { component, @@ -53,7 +61,7 @@ describe('Mappings editor: shape datatype', () => { } = testBed; // Open the flyout to edit the field - startEditField('myField'); + await startEditField('myField'); // Save the field and close the flyout await updateFieldAndCloseFlyout(); diff --git a/x-pack/plugins/index_management/public/application/components/mappings_editor/__jest__/client_integration/datatypes/text_datatype.test.tsx b/x-pack/plugins/index_management/public/application/components/mappings_editor/__jest__/client_integration/datatypes/text_datatype.test.tsx index 66989baa2dc67..1832bedee0143 100644 --- a/x-pack/plugins/index_management/public/application/components/mappings_editor/__jest__/client_integration/datatypes/text_datatype.test.tsx +++ b/x-pack/plugins/index_management/public/application/components/mappings_editor/__jest__/client_integration/datatypes/text_datatype.test.tsx @@ -9,8 +9,6 @@ import { componentHelpers, MappingsEditorTestBed } from '../helpers'; import { getFieldConfig } from '../../../lib'; const { setup, getMappingsEditorDataFactory } = componentHelpers.mappingsEditor; -const onChangeHandler = jest.fn(); -const getMappingsEditorData = getMappingsEditorDataFactory(onChangeHandler); // Parameters automatically added to the text datatype when saved (with the default values) export const defaultTextParameters = { @@ -24,14 +22,14 @@ export const defaultTextParameters = { store: false, }; -// FLAKY: https://github.com/elastic/kibana/issues/66669 -describe.skip('Mappings editor: text datatype', () => { - let testBed: MappingsEditorTestBed; - +describe('Mappings editor: text datatype', () => { /** * Variable to store the mappings data forwarded to the consumer component */ let data: any; + let onChangeHandler: jest.Mock = jest.fn(); + let getMappingsEditorData = getMappingsEditorDataFactory(onChangeHandler); + let testBed: MappingsEditorTestBed; beforeAll(() => { jest.useFakeTimers(); @@ -41,8 +39,9 @@ describe.skip('Mappings editor: text datatype', () => { jest.useRealTimers(); }); - afterEach(() => { - onChangeHandler.mockReset(); + beforeEach(() => { + onChangeHandler = jest.fn(); + getMappingsEditorData = getMappingsEditorDataFactory(onChangeHandler); }); test('initial view and default parameters values', async () => { @@ -56,7 +55,10 @@ describe.skip('Mappings editor: text datatype', () => { const updatedMappings = { ...defaultMappings }; - testBed = setup({ value: defaultMappings, onChange: onChangeHandler }); + await act(async () => { + testBed = setup({ value: defaultMappings, onChange: onChangeHandler }); + }); + testBed.component.update(); const { component, @@ -64,7 +66,7 @@ describe.skip('Mappings editor: text datatype', () => { } = testBed; // Open the flyout to edit the field - startEditField('myField'); + await startEditField('myField'); // It should have searchable ("index" param) active by default const indexFieldConfig = getFieldConfig('index'); @@ -80,7 +82,7 @@ describe.skip('Mappings editor: text datatype', () => { ({ data } = await getMappingsEditorData(component)); expect(data).toEqual(updatedMappings); - }, 10000); + }); test('analyzer parameter: default values', async () => { const defaultMappings = { @@ -96,7 +98,10 @@ describe.skip('Mappings editor: text datatype', () => { }, }; - testBed = setup({ value: defaultMappings, onChange: onChangeHandler }); + await act(async () => { + testBed = setup({ value: defaultMappings, onChange: onChangeHandler }); + }); + testBed.component.update(); const { component, @@ -113,8 +118,8 @@ describe.skip('Mappings editor: text datatype', () => { const fieldToEdit = 'myField'; // Start edit and immediately save to have all the default values - startEditField(fieldToEdit); - showAdvancedSettings(); + await startEditField(fieldToEdit); + await showAdvancedSettings(); await updateFieldAndCloseFlyout(); expect(exists('mappingsEditorFieldEdit')).toBe(false); @@ -133,8 +138,8 @@ describe.skip('Mappings editor: text datatype', () => { expect(data).toEqual(updatedMappings); // Re-open the edit panel - startEditField(fieldToEdit); - showAdvancedSettings(); + await startEditField(fieldToEdit); + await showAdvancedSettings(); // When no analyzer is defined, defaults to "Index default" let indexAnalyzerValue = find('indexAnalyzer.select').props().value; @@ -158,9 +163,8 @@ describe.skip('Mappings editor: text datatype', () => { expect(exists('searchAnalyzer')).toBe(false); // Uncheck the "Use same analyzer for search" checkbox and make sure the dedicated select appears - selectCheckBox('useSameAnalyzerForSearchCheckBox.input', false); - act(() => { - jest.advanceTimersByTime(1000); + await act(async () => { + selectCheckBox('useSameAnalyzerForSearchCheckBox.input', false); }); component.update(); @@ -169,7 +173,6 @@ describe.skip('Mappings editor: text datatype', () => { let searchAnalyzerValue = find('searchAnalyzer.select').props().value; expect(searchAnalyzerValue).toEqual('index_default'); - // Change the value of the 3 analyzers await act(async () => { // Change the value of the 3 analyzers setSelectValue('indexAnalyzer.select', 'standard', false); @@ -195,8 +198,8 @@ describe.skip('Mappings editor: text datatype', () => { expect(data).toEqual(updatedMappings); // Re-open the flyout and make sure the select have the correct updated value - startEditField('myField'); - showAdvancedSettings(); + await startEditField('myField'); + await showAdvancedSettings(); isUseSameAnalyzerForSearchChecked = getCheckboxValue('useSameAnalyzerForSearchCheckBox.input'); expect(isUseSameAnalyzerForSearchChecked).toBe(false); @@ -208,7 +211,7 @@ describe.skip('Mappings editor: text datatype', () => { expect(indexAnalyzerValue).toBe('standard'); expect(searchAnalyzerValue).toBe('simple'); expect(searchQuoteAnalyzerValue).toBe('whitespace'); - }, 50000); + }); test('analyzer parameter: custom analyzer (external plugin)', async () => { const defaultMappings = { @@ -234,7 +237,10 @@ describe.skip('Mappings editor: text datatype', () => { }, }; - testBed = setup({ value: defaultMappings, onChange: onChangeHandler }); + await act(async () => { + testBed = setup({ value: defaultMappings, onChange: onChangeHandler }); + }); + testBed.component.update(); const { find, @@ -245,8 +251,8 @@ describe.skip('Mappings editor: text datatype', () => { } = testBed; const fieldToEdit = 'myField'; - startEditField(fieldToEdit); - showAdvancedSettings(); + await startEditField(fieldToEdit); + await showAdvancedSettings(); expect(exists('indexAnalyzer-custom')).toBe(true); expect(exists('searchAnalyzer-custom')).toBe(true); @@ -301,7 +307,7 @@ describe.skip('Mappings editor: text datatype', () => { }; expect(data).toEqual(updatedMappings); - }, 100000); + }); test('analyzer parameter: custom analyzer (from index settings)', async () => { const indexSettings = { @@ -320,8 +326,6 @@ describe.skip('Mappings editor: text datatype', () => { const customAnalyzers = Object.keys(indexSettings.analysis.analyzer); const defaultMappings = { - _meta: {}, - _source: {}, properties: { myField: { type: 'text', @@ -340,11 +344,14 @@ describe.skip('Mappings editor: text datatype', () => { }, }; - testBed = setup({ - value: defaultMappings, - onChange: onChangeHandler, - indexSettings, + await act(async () => { + testBed = setup({ + value: defaultMappings, + onChange: onChangeHandler, + indexSettings, + }); }); + testBed.component.update(); const { component, @@ -354,8 +361,8 @@ describe.skip('Mappings editor: text datatype', () => { } = testBed; const fieldToEdit = 'myField'; - startEditField(fieldToEdit); - showAdvancedSettings(); + await startEditField(fieldToEdit); + await showAdvancedSettings(); // It should have 2 selects const indexAnalyzerSelects = find('indexAnalyzer.select'); @@ -395,5 +402,5 @@ describe.skip('Mappings editor: text datatype', () => { }; expect(data).toEqual(updatedMappings); - }, 50000); + }); }); diff --git a/x-pack/plugins/index_management/public/application/components/mappings_editor/__jest__/client_integration/edit_field.test.tsx b/x-pack/plugins/index_management/public/application/components/mappings_editor/__jest__/client_integration/edit_field.test.tsx index c146c7704911f..9634817835101 100644 --- a/x-pack/plugins/index_management/public/application/components/mappings_editor/__jest__/client_integration/edit_field.test.tsx +++ b/x-pack/plugins/index_management/public/application/components/mappings_editor/__jest__/client_integration/edit_field.test.tsx @@ -8,10 +8,14 @@ import { act } from 'react-dom/test-utils'; import { componentHelpers, MappingsEditorTestBed } from './helpers'; import { defaultTextParameters, defaultShapeParameters } from './datatypes'; const { setup, getMappingsEditorDataFactory } = componentHelpers.mappingsEditor; -const onChangeHandler = jest.fn(); -const getMappingsEditorData = getMappingsEditorDataFactory(onChangeHandler); describe('Mappings editor: edit field', () => { + /** + * Variable to store the mappings data forwarded to the consumer component + */ + let data: any; + let onChangeHandler: jest.Mock = jest.fn(); + let getMappingsEditorData = getMappingsEditorDataFactory(onChangeHandler); let testBed: MappingsEditorTestBed; beforeAll(() => { @@ -22,8 +26,9 @@ describe('Mappings editor: edit field', () => { jest.useRealTimers(); }); - afterEach(() => { - onChangeHandler.mockReset(); + beforeEach(() => { + onChangeHandler = jest.fn(); + getMappingsEditorData = getMappingsEditorDataFactory(onChangeHandler); }); test('should open a flyout with the correct field to edit', async () => { @@ -43,7 +48,11 @@ describe('Mappings editor: edit field', () => { }, }; - testBed = setup({ value: defaultMappings, onChange: onChangeHandler }); + await act(async () => { + testBed = setup({ value: defaultMappings, onChange: onChangeHandler }); + }); + testBed.component.update(); + await testBed.actions.expandAllFieldsAndReturnMetadata(); const { @@ -51,7 +60,7 @@ describe('Mappings editor: edit field', () => { actions: { startEditField }, } = testBed; // Open the flyout to edit the field - startEditField('user.address.street'); + await startEditField('user.address.street'); // It should have the correct title expect(find('mappingsEditorFieldEdit.flyoutTitle').text()).toEqual(`Edit field 'street'`); @@ -72,7 +81,10 @@ describe('Mappings editor: edit field', () => { }, }; - testBed = setup({ value: defaultMappings, onChange: onChangeHandler }); + await act(async () => { + testBed = setup({ value: defaultMappings, onChange: onChangeHandler }); + }); + testBed.component.update(); const { find, @@ -83,19 +95,18 @@ describe('Mappings editor: edit field', () => { expect(exists('userNameField' as any)).toBe(true); // Open the flyout, change the field type and save it - startEditField('userName'); + await startEditField('userName'); // Change the field type - find('mappingsEditorFieldEdit.fieldType').simulate('change', [ - { label: 'Shape', value: defaultShapeParameters.type }, - ]); - act(() => { - jest.advanceTimersByTime(1000); + await act(async () => { + find('mappingsEditorFieldEdit.fieldType').simulate('change', [ + { label: 'Shape', value: defaultShapeParameters.type }, + ]); }); await updateFieldAndCloseFlyout(); - const { data } = await getMappingsEditorData(component); + ({ data } = await getMappingsEditorData(component)); const updatedMappings = { ...defaultMappings, @@ -107,5 +118,5 @@ describe('Mappings editor: edit field', () => { }; expect(data).toEqual(updatedMappings); - }, 50000); + }); }); diff --git a/x-pack/plugins/index_management/public/application/components/mappings_editor/__jest__/client_integration/helpers/mappings_editor.helpers.tsx b/x-pack/plugins/index_management/public/application/components/mappings_editor/__jest__/client_integration/helpers/mappings_editor.helpers.tsx index a6558b28a1273..2a4af89c46559 100644 --- a/x-pack/plugins/index_management/public/application/components/mappings_editor/__jest__/client_integration/helpers/mappings_editor.helpers.tsx +++ b/x-pack/plugins/index_management/public/application/components/mappings_editor/__jest__/client_integration/helpers/mappings_editor.helpers.tsx @@ -149,22 +149,28 @@ const createActions = (testBed: TestBed) => { return { field: find(testSubject as TestSubjects), testSubject }; }; - const addField = (name: string, type: string) => { - form.setInputValue('nameParameterInput', name); - find('createFieldForm.fieldType').simulate('change', [ - { - label: type, - value: type, - }, - ]); - find('createFieldForm.addButton').simulate('click'); + const addField = async (name: string, type: string) => { + await act(async () => { + form.setInputValue('nameParameterInput', name); + find('createFieldForm.fieldType').simulate('change', [ + { + label: type, + value: type, + }, + ]); + }); + + await act(async () => { + find('createFieldForm.addButton').simulate('click'); + }); + + component.update(); }; - const startEditField = (path: string) => { + const startEditField = async (path: string) => { const { testSubject } = getFieldAt(path); - find(`${testSubject}.editFieldButton` as TestSubjects).simulate('click'); - act(() => { - jest.advanceTimersByTime(1000); + await act(async () => { + find(`${testSubject}.editFieldButton` as TestSubjects).simulate('click'); }); component.update(); }; @@ -174,34 +180,33 @@ const createActions = (testBed: TestBed) => { find('mappingsEditorFieldEdit.editFieldUpdateButton').simulate('click'); }); component.update(); - - act(() => { - jest.advanceTimersByTime(1000); - }); }; - const showAdvancedSettings = () => { + const showAdvancedSettings = async () => { if (find('mappingsEditorFieldEdit.advancedSettings').props().style.display === 'block') { // Already opened, nothing else to do return; } - find('mappingsEditorFieldEdit.toggleAdvancedSetting').simulate('click'); - - act(() => { - jest.advanceTimersByTime(1000); + await act(async () => { + find('mappingsEditorFieldEdit.toggleAdvancedSetting').simulate('click'); }); + component.update(); }; - const selectTab = (tab: 'fields' | 'templates' | 'advanced') => { + const selectTab = async (tab: 'fields' | 'templates' | 'advanced') => { const index = ['fields', 'templates', 'advanced'].indexOf(tab); const tabElement = find('formTab').at(index); if (tabElement.length === 0) { throw new Error(`Tab not found: "${tab}"`); } - tabElement.simulate('click'); + + await act(async () => { + tabElement.simulate('click'); + }); + component.update(); }; const updateJsonEditor = (testSubject: TestSubjects, value: object) => { diff --git a/x-pack/plugins/index_management/public/application/components/mappings_editor/__jest__/client_integration/mappings_editor.test.tsx b/x-pack/plugins/index_management/public/application/components/mappings_editor/__jest__/client_integration/mappings_editor.test.tsx index 0743211a2b7bf..68933ddc9a935 100644 --- a/x-pack/plugins/index_management/public/application/components/mappings_editor/__jest__/client_integration/mappings_editor.test.tsx +++ b/x-pack/plugins/index_management/public/application/components/mappings_editor/__jest__/client_integration/mappings_editor.test.tsx @@ -8,15 +8,15 @@ import { act } from 'react-dom/test-utils'; import { componentHelpers, MappingsEditorTestBed } from './helpers'; const { setup, getMappingsEditorDataFactory } = componentHelpers.mappingsEditor; -const onChangeHandler = jest.fn(); -const getMappingsEditorData = getMappingsEditorDataFactory(onChangeHandler); -// FLAKY: https://github.com/elastic/kibana/issues/66457 -describe.skip('Mappings editor: core', () => { +describe('Mappings editor: core', () => { /** * Variable to store the mappings data forwarded to the consumer component */ let data: any; + let onChangeHandler: jest.Mock = jest.fn(); + let getMappingsEditorData = getMappingsEditorDataFactory(onChangeHandler); + let testBed: MappingsEditorTestBed; beforeAll(() => { jest.useFakeTimers(); @@ -26,8 +26,9 @@ describe.skip('Mappings editor: core', () => { jest.useRealTimers(); }); - afterEach(() => { - onChangeHandler.mockReset(); + beforeEach(() => { + onChangeHandler = jest.fn(); + getMappingsEditorData = getMappingsEditorDataFactory(onChangeHandler); }); test('default behaviour', async () => { @@ -42,11 +43,14 @@ describe.skip('Mappings editor: core', () => { }, }; - const { component } = setup({ value: defaultMappings, onChange: onChangeHandler }); + await act(async () => { + testBed = setup({ value: defaultMappings, onChange: onChangeHandler }); + }); + + const { component } = testBed; + component.update(); const expectedMappings = { - _meta: {}, // Was not defined so an empty object is returned - _source: {}, // Was not defined so an empty object is returned ...defaultMappings, properties: { user: { @@ -78,8 +82,13 @@ describe.skip('Mappings editor: core', () => { }, }, }; - const testBed = setup({ onChange: onChangeHandler, value }); - const { exists } = testBed; + + await act(async () => { + testBed = setup({ onChange: onChangeHandler, value }); + }); + + const { component, exists } = testBed; + component.update(); expect(exists('mappingsEditor')).toBe(true); expect(exists('mappingTypesDetectedCallout')).toBe(true); @@ -94,8 +103,12 @@ describe.skip('Mappings editor: core', () => { }, }, }; - const testBed = setup({ onChange: onChangeHandler, value }); - const { exists } = testBed; + await act(async () => { + testBed = setup({ onChange: onChangeHandler, value }); + }); + + const { component, exists } = testBed; + component.update(); expect(exists('mappingsEditor')).toBe(true); expect(exists('mappingTypesDetectedCallout')).toBe(false); @@ -108,10 +121,12 @@ describe.skip('Mappings editor: core', () => { properties: {}, dynamic_templates: [{ before: 'foo' }], }; - let testBed: MappingsEditorTestBed; beforeEach(async () => { - testBed = setup({ value: defaultMappings, onChange: onChangeHandler }); + await act(async () => { + testBed = setup({ value: defaultMappings, onChange: onChangeHandler }); + }); + testBed.component.update(); }); test('should keep the changes when switching tabs', async () => { @@ -129,10 +144,7 @@ describe.skip('Mappings editor: core', () => { expect(find('fieldsListItem').length).toEqual(0); // Check that we start with an empty list const newField = { name: 'John', type: 'text' }; - await act(async () => { - addField(newField.name, newField.type); - }); - component.update(); + await addField(newField.name, newField.type); expect(find('fieldsListItem').length).toEqual(1); @@ -142,10 +154,7 @@ describe.skip('Mappings editor: core', () => { // ------------------------------------- // Navigate to dynamic templates tab // ------------------------------------- - await act(async () => { - selectTab('templates'); - }); - component.update(); + await selectTab('templates'); let templatesValue = getJsonEditorValue('dynamicTemplatesEditor'); expect(templatesValue).toEqual(defaultMappings.dynamic_templates); @@ -163,10 +172,7 @@ describe.skip('Mappings editor: core', () => { // ------------------------------------------------------ // Switch to advanced settings tab and make some changes // ------------------------------------------------------ - await act(async () => { - selectTab('advanced'); - }); - component.update(); + await selectTab('advanced'); let isDynamicMappingsEnabled = getToggleValue( 'advancedConfiguration.dynamicMappingsToggle.input' @@ -194,10 +200,7 @@ describe.skip('Mappings editor: core', () => { // ---------------------------------------------------------------------------- // Go back to dynamic templates tab and make sure our changes are still there // ---------------------------------------------------------------------------- - await act(async () => { - selectTab('templates'); - }); - component.update(); + await selectTab('templates'); templatesValue = getJsonEditorValue('dynamicTemplatesEditor'); expect(templatesValue).toEqual(updatedValueTemplates); @@ -205,18 +208,13 @@ describe.skip('Mappings editor: core', () => { // ----------------------------------------------------------- // Go back to fields and make sure our created field is there // ----------------------------------------------------------- - await act(async () => { - selectTab('fields'); - }); - component.update(); + await selectTab('fields'); + field = find('fieldsListItem').at(0); expect(find('fieldName', field).text()).toEqual(newField.name); // Go back to advanced settings tab make sure dynamic mappings is disabled - await act(async () => { - selectTab('advanced'); - }); - component.update(); + await selectTab('advanced'); isDynamicMappingsEnabled = getToggleValue( 'advancedConfiguration.dynamicMappingsToggle.input' @@ -231,46 +229,47 @@ describe.skip('Mappings editor: core', () => { /** * Note: the "indexSettings" prop will be tested along with the "analyzer" parameter on a text datatype field, * as it is the only place where it is consumed by the mappings editor. - * - * The test that covers it is text_datatype.test.tsx: "analyzer parameter: custom analyzer (from index settings)" + * The test that covers it is in the "text_datatype.test.tsx": "analyzer parameter: custom analyzer (from index settings)" */ - const defaultMappings: any = { - dynamic: true, - numeric_detection: false, - date_detection: true, - properties: { - title: { type: 'text' }, - address: { - type: 'object', - properties: { - street: { type: 'text' }, - city: { type: 'text' }, + let defaultMappings: any; + + beforeEach(async () => { + defaultMappings = { + dynamic: true, + numeric_detection: false, + date_detection: true, + properties: { + title: { type: 'text' }, + address: { + type: 'object', + properties: { + street: { type: 'text' }, + city: { type: 'text' }, + }, }, }, - }, - dynamic_templates: [{ initial: 'value' }], - _source: { - enabled: true, - includes: ['field1', 'field2'], - excludes: ['field3'], - }, - _meta: { - some: 'metaData', - }, - _routing: { - required: false, - }, - }; - - let testBed: MappingsEditorTestBed; + dynamic_templates: [{ initial: 'value' }], + _source: { + enabled: true, + includes: ['field1', 'field2'], + excludes: ['field3'], + }, + _meta: { + some: 'metaData', + }, + _routing: { + required: false, + }, + }; - beforeEach(async () => { - testBed = setup({ value: defaultMappings, onChange: onChangeHandler }); + await act(async () => { + testBed = setup({ value: defaultMappings, onChange: onChangeHandler }); + }); + testBed.component.update(); }); test('props.value => should prepopulate the editor data', async () => { const { - component, actions: { selectTab, getJsonEditorValue, getComboBoxValue, getToggleValue }, find, } = testBed; @@ -285,10 +284,7 @@ describe.skip('Mappings editor: core', () => { /** * Dynamic templates */ - await act(async () => { - selectTab('templates'); - }); - component.update(); + await selectTab('templates'); // Test that dynamic templates JSON is rendered in the templates editor const templatesValue = getJsonEditorValue('dynamicTemplatesEditor'); @@ -297,10 +293,7 @@ describe.skip('Mappings editor: core', () => { /** * Advanced settings */ - await act(async () => { - selectTab('advanced'); - }); - component.update(); + await selectTab('advanced'); const isDynamicMappingsEnabled = getToggleValue( 'advancedConfiguration.dynamicMappingsToggle.input' @@ -339,7 +332,14 @@ describe.skip('Mappings editor: core', () => { /** * Mapped fields */ + await act(async () => { + find('addFieldButton').simulate('click'); + }); + component.update(); + const newField = { name: 'someNewField', type: 'text' }; + await addField(newField.name, newField.type); + updatedMappings = { ...updatedMappings, properties: { @@ -348,26 +348,14 @@ describe.skip('Mappings editor: core', () => { }, }; - await act(async () => { - find('addFieldButton').simulate('click'); - }); - component.update(); - - await act(async () => { - addField(newField.name, newField.type); - }); - component.update(); - ({ data } = await getMappingsEditorData(component)); + expect(data).toEqual(updatedMappings); /** * Dynamic templates */ - await act(async () => { - await selectTab('templates'); - }); - component.update(); + await selectTab('templates'); const updatedTemplatesValue = [{ someTemplateProp: 'updated' }]; updatedMappings = { @@ -385,10 +373,7 @@ describe.skip('Mappings editor: core', () => { /** * Advanced settings */ - await act(async () => { - selectTab('advanced'); - }); - component.update(); + await selectTab('advanced'); // Disbable dynamic mappings await act(async () => { diff --git a/x-pack/plugins/index_management/public/application/components/mappings_editor/components/document_fields/field_parameters/analyzer_parameter.tsx b/x-pack/plugins/index_management/public/application/components/mappings_editor/components/document_fields/field_parameters/analyzer_parameter.tsx index dc52a362008c6..1457c4583aa0e 100644 --- a/x-pack/plugins/index_management/public/application/components/mappings_editor/components/document_fields/field_parameters/analyzer_parameter.tsx +++ b/x-pack/plugins/index_management/public/application/components/mappings_editor/components/document_fields/field_parameters/analyzer_parameter.tsx @@ -71,9 +71,8 @@ export const AnalyzerParameter = ({ allowsIndexDefaultOption = true, 'data-test-subj': dataTestSubj, }: Props) => { - const indexSettings = useIndexSettings(); + const { value: indexSettings } = useIndexSettings(); const customAnalyzers = getCustomAnalyzers(indexSettings); - const analyzerOptions = allowsIndexDefaultOption ? ANALYZER_OPTIONS : ANALYZER_OPTIONS_WITHOUT_DEFAULT; diff --git a/x-pack/plugins/index_management/public/application/components/mappings_editor/components/document_fields/field_parameters/analyzer_parameter_selects.tsx b/x-pack/plugins/index_management/public/application/components/mappings_editor/components/document_fields/field_parameters/analyzer_parameter_selects.tsx index 17d3ea0909bfb..c966df82fb507 100644 --- a/x-pack/plugins/index_management/public/application/components/mappings_editor/components/document_fields/field_parameters/analyzer_parameter_selects.tsx +++ b/x-pack/plugins/index_management/public/application/components/mappings_editor/components/document_fields/field_parameters/analyzer_parameter_selects.tsx @@ -49,16 +49,17 @@ export const AnalyzerParameterSelects = ({ 'data-test-subj': dataTestSubj, }: Props) => { const { form } = useForm({ defaultValue: { main: mainDefaultValue, sub: subDefaultValue } }); + const { subscribe } = form; useEffect(() => { - const subscription = form.subscribe((updateData) => { + const subscription = subscribe((updateData) => { const formData = updateData.data.raw; const value = formData.sub ? formData.sub : formData.main; onChange(value); }); return subscription.unsubscribe; - }, [form, onChange]); + }, [subscribe, onChange]); const getSubOptionsMeta = useCallback( (mainValue: string) => diff --git a/x-pack/plugins/index_management/public/application/components/mappings_editor/index_settings_context.tsx b/x-pack/plugins/index_management/public/application/components/mappings_editor/index_settings_context.tsx index 411193f10b24a..bd84c3a905ec8 100644 --- a/x-pack/plugins/index_management/public/application/components/mappings_editor/index_settings_context.tsx +++ b/x-pack/plugins/index_management/public/application/components/mappings_editor/index_settings_context.tsx @@ -3,23 +3,32 @@ * or more contributor license agreements. Licensed under the Elastic License; * you may not use this file except in compliance with the Elastic License. */ -import React, { createContext, useContext } from 'react'; +import React, { createContext, useContext, useState } from 'react'; import { IndexSettings } from './types'; -const IndexSettingsContext = createContext(undefined); +const IndexSettingsContext = createContext< + { value: IndexSettings; update: (value: IndexSettings) => void } | undefined +>(undefined); interface Props { - indexSettings: IndexSettings | undefined; children: React.ReactNode; } -export const IndexSettingsProvider = ({ indexSettings = {}, children }: Props) => ( - {children} -); +export const IndexSettingsProvider = ({ children }: Props) => { + const [state, setState] = useState({}); + + return ( + + {children} + + ); +}; export const useIndexSettings = () => { const ctx = useContext(IndexSettingsContext); - - return ctx === undefined ? {} : ctx; + if (ctx === undefined) { + throw new Error('useIndexSettings must be used within a '); + } + return ctx; }; diff --git a/x-pack/plugins/index_management/public/application/components/mappings_editor/mappings_editor.tsx b/x-pack/plugins/index_management/public/application/components/mappings_editor/mappings_editor.tsx index 39451639bfb86..39c4a2885efa5 100644 --- a/x-pack/plugins/index_management/public/application/components/mappings_editor/mappings_editor.tsx +++ b/x-pack/plugins/index_management/public/application/components/mappings_editor/mappings_editor.tsx @@ -25,7 +25,7 @@ import { import { extractMappingsDefinition } from './lib'; import { useMappingsState } from './mappings_state_context'; import { useMappingsStateListener } from './use_state_listener'; -import { IndexSettingsProvider } from './index_settings_context'; +import { useIndexSettings } from './index_settings_context'; type TabName = 'fields' | 'advanced' | 'templates'; @@ -94,6 +94,12 @@ export const MappingsEditor = React.memo(({ onChange, value, indexSettings }: Pr */ useMappingsStateListener({ onChange, value: parsedDefaultValue }); + // Update the Index settings context so it is available in the Global flyout + const { update: updateIndexSettings } = useIndexSettings(); + if (indexSettings !== undefined) { + updateIndexSettings(indexSettings); + } + const state = useMappingsState(); const [selectedTab, selectTab] = useState('fields'); @@ -141,43 +147,41 @@ export const MappingsEditor = React.memo(({ onChange, value, indexSettings }: Pr {multipleMappingsDeclared ? ( ) : ( - -

- - changeTab('fields')} - isSelected={selectedTab === 'fields'} - data-test-subj="formTab" - > - {i18n.translate('xpack.idxMgmt.mappingsEditor.fieldsTabLabel', { - defaultMessage: 'Mapped fields', - })} - - changeTab('templates')} - isSelected={selectedTab === 'templates'} - data-test-subj="formTab" - > - {i18n.translate('xpack.idxMgmt.mappingsEditor.templatesTabLabel', { - defaultMessage: 'Dynamic templates', - })} - - changeTab('advanced')} - isSelected={selectedTab === 'advanced'} - data-test-subj="formTab" - > - {i18n.translate('xpack.idxMgmt.mappingsEditor.advancedTabLabel', { - defaultMessage: 'Advanced options', - })} - - - - - - {tabToContentMap[selectedTab]} -
- +
+ + changeTab('fields')} + isSelected={selectedTab === 'fields'} + data-test-subj="formTab" + > + {i18n.translate('xpack.idxMgmt.mappingsEditor.fieldsTabLabel', { + defaultMessage: 'Mapped fields', + })} + + changeTab('templates')} + isSelected={selectedTab === 'templates'} + data-test-subj="formTab" + > + {i18n.translate('xpack.idxMgmt.mappingsEditor.templatesTabLabel', { + defaultMessage: 'Dynamic templates', + })} + + changeTab('advanced')} + isSelected={selectedTab === 'advanced'} + data-test-subj="formTab" + > + {i18n.translate('xpack.idxMgmt.mappingsEditor.advancedTabLabel', { + defaultMessage: 'Advanced options', + })} + + + + + + {tabToContentMap[selectedTab]} +
)}
); diff --git a/x-pack/plugins/index_management/public/application/components/mappings_editor/mappings_editor_context.tsx b/x-pack/plugins/index_management/public/application/components/mappings_editor/mappings_editor_context.tsx index 596b49cc89ee8..8e30d07c2262f 100644 --- a/x-pack/plugins/index_management/public/application/components/mappings_editor/mappings_editor_context.tsx +++ b/x-pack/plugins/index_management/public/application/components/mappings_editor/mappings_editor_context.tsx @@ -6,7 +6,12 @@ import React from 'react'; import { StateProvider } from './mappings_state_context'; +import { IndexSettingsProvider } from './index_settings_context'; export const MappingsEditorProvider: React.FC = ({ children }) => { - return {children}; + return ( + + {children} + + ); }; diff --git a/x-pack/plugins/index_management/public/application/components/mappings_editor/reducer.ts b/x-pack/plugins/index_management/public/application/components/mappings_editor/reducer.ts index 2a8368c666859..e7efd6f28343b 100644 --- a/x-pack/plugins/index_management/public/application/components/mappings_editor/reducer.ts +++ b/x-pack/plugins/index_management/public/application/components/mappings_editor/reducer.ts @@ -175,10 +175,18 @@ export const reducer = (state: State, action: Action): State => { fields: action.value.fields, configuration: { ...state.configuration, + data: { + raw: action.value.configuration, + format: () => action.value.configuration, + }, defaultValue: action.value.configuration, }, templates: { ...state.templates, + data: { + raw: action.value.templates, + format: () => action.value.templates, + }, defaultValue: action.value.templates, }, documentFields: { diff --git a/x-pack/plugins/index_management/test/fixtures/template.ts b/x-pack/plugins/index_management/test/fixtures/template.ts index 3b9de2b3409b6..ac6e8b7879a26 100644 --- a/x-pack/plugins/index_management/test/fixtures/template.ts +++ b/x-pack/plugins/index_management/test/fixtures/template.ts @@ -11,6 +11,42 @@ const objHasProperties = (obj?: Record): boolean => { return obj === undefined || Object.keys(obj).length === 0 ? false : true; }; +export const getComposableTemplate = ({ + name = getRandomString(), + version = getRandomNumber(), + priority = getRandomNumber(), + indexPatterns = [], + template: { settings, aliases, mappings } = {}, + hasDatastream = false, + isLegacy = false, + type = 'default', +}: Partial< + TemplateDeserialized & { + isLegacy?: boolean; + type?: TemplateType; + hasDatastream: boolean; + } +> = {}): TemplateDeserialized => { + const indexTemplate = { + name, + version, + priority, + indexPatterns, + template: { + aliases, + mappings, + settings, + }, + _kbnMeta: { + type, + hasDatastream, + isLegacy, + }, + }; + + return indexTemplate; +}; + export const getTemplate = ({ name = getRandomString(), version = getRandomNumber(), diff --git a/x-pack/plugins/ingest_manager/common/constants/routes.ts b/x-pack/plugins/ingest_manager/common/constants/routes.ts index 551a0f7d60164..3e065142ea101 100644 --- a/x-pack/plugins/ingest_manager/common/constants/routes.ts +++ b/x-pack/plugins/ingest_manager/common/constants/routes.ts @@ -21,7 +21,8 @@ export const EPM_API_ROUTES = { LIST_PATTERN: EPM_PACKAGES_MANY, LIMITED_LIST_PATTERN: `${EPM_PACKAGES_MANY}/limited`, INFO_PATTERN: EPM_PACKAGES_ONE, - INSTALL_PATTERN: EPM_PACKAGES_ONE, + INSTALL_FROM_REGISTRY_PATTERN: EPM_PACKAGES_ONE, + INSTALL_BY_UPLOAD_PATTERN: EPM_PACKAGES_MANY, DELETE_PATTERN: EPM_PACKAGES_ONE, FILEPATH_PATTERN: `${EPM_PACKAGES_FILE}/{filePath*}`, CATEGORIES_PATTERN: `${EPM_API_ROOT}/categories`, diff --git a/x-pack/plugins/ingest_manager/common/services/routes.ts b/x-pack/plugins/ingest_manager/common/services/routes.ts index 1d802739a1b86..b7521f95b4f83 100644 --- a/x-pack/plugins/ingest_manager/common/services/routes.ts +++ b/x-pack/plugins/ingest_manager/common/services/routes.ts @@ -40,7 +40,10 @@ export const epmRouteService = { }, getInstallPath: (pkgkey: string) => { - return EPM_API_ROUTES.INSTALL_PATTERN.replace('{pkgkey}', pkgkey).replace(/\/$/, ''); // trim trailing slash + return EPM_API_ROUTES.INSTALL_FROM_REGISTRY_PATTERN.replace('{pkgkey}', pkgkey).replace( + /\/$/, + '' + ); // trim trailing slash }, getRemovePath: (pkgkey: string) => { diff --git a/x-pack/plugins/ingest_manager/common/types/rest_spec/epm.ts b/x-pack/plugins/ingest_manager/common/types/rest_spec/epm.ts index 5fb718f91b876..54e767fee4b22 100644 --- a/x-pack/plugins/ingest_manager/common/types/rest_spec/epm.ts +++ b/x-pack/plugins/ingest_manager/common/types/rest_spec/epm.ts @@ -71,6 +71,10 @@ export interface InstallPackageResponse { response: AssetReference[]; } +export interface MessageResponse { + response: string; +} + export interface DeletePackageRequest { params: { pkgkey: string; diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/services/index.ts b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/services/index.ts index 56179b02c5ba2..2c9e8b84d4069 100644 --- a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/services/index.ts +++ b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/services/index.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -export { getFlattenedObject } from '../../../../../../../src/core/public'; +export { getFlattenedObject } from '@kbn/std'; export { AgentStatusKueryHelper, diff --git a/x-pack/plugins/ingest_manager/server/routes/epm/handlers.ts b/x-pack/plugins/ingest_manager/server/routes/epm/handlers.ts index 385e256933c12..c40e0e4ac5c0b 100644 --- a/x-pack/plugins/ingest_manager/server/routes/epm/handlers.ts +++ b/x-pack/plugins/ingest_manager/server/routes/epm/handlers.ts @@ -9,6 +9,7 @@ import { appContextService } from '../../services'; import { GetInfoResponse, InstallPackageResponse, + MessageResponse, DeletePackageResponse, GetCategoriesResponse, GetPackagesResponse, @@ -19,7 +20,8 @@ import { GetPackagesRequestSchema, GetFileRequestSchema, GetInfoRequestSchema, - InstallPackageRequestSchema, + InstallPackageFromRegistryRequestSchema, + InstallPackageByUploadRequestSchema, DeletePackageRequestSchema, } from '../../types'; import { @@ -129,10 +131,10 @@ export const getInfoHandler: RequestHandler, +export const installPackageFromRegistryHandler: RequestHandler< + TypeOf, undefined, - TypeOf + TypeOf > = async (context, request, response) => { const logger = appContextService.getLogger(); const savedObjectsClient = context.core.savedObjects.client; @@ -183,6 +185,17 @@ export const installPackageHandler: RequestHandler< } }; +export const installPackageByUploadHandler: RequestHandler< + undefined, + undefined, + TypeOf +> = async (context, request, response) => { + const body: MessageResponse = { + response: 'package upload was received ok, but not installed (not implemented yet)', + }; + return response.ok({ body }); +}; + export const deletePackageHandler: RequestHandler> = async (context, request, response) => { diff --git a/x-pack/plugins/ingest_manager/server/routes/epm/index.ts b/x-pack/plugins/ingest_manager/server/routes/epm/index.ts index b524a7b33923e..9048652f0e8a9 100644 --- a/x-pack/plugins/ingest_manager/server/routes/epm/index.ts +++ b/x-pack/plugins/ingest_manager/server/routes/epm/index.ts @@ -11,7 +11,8 @@ import { getLimitedListHandler, getFileHandler, getInfoHandler, - installPackageHandler, + installPackageFromRegistryHandler, + installPackageByUploadHandler, deletePackageHandler, } from './handlers'; import { @@ -19,10 +20,13 @@ import { GetPackagesRequestSchema, GetFileRequestSchema, GetInfoRequestSchema, - InstallPackageRequestSchema, + InstallPackageFromRegistryRequestSchema, + InstallPackageByUploadRequestSchema, DeletePackageRequestSchema, } from '../../types'; +const MAX_FILE_SIZE_BYTES = 104857600; // 100MB + export const registerRoutes = (router: IRouter) => { router.get( { @@ -71,11 +75,27 @@ export const registerRoutes = (router: IRouter) => { router.post( { - path: EPM_API_ROUTES.INSTALL_PATTERN, - validate: InstallPackageRequestSchema, + path: EPM_API_ROUTES.INSTALL_FROM_REGISTRY_PATTERN, + validate: InstallPackageFromRegistryRequestSchema, options: { tags: [`access:${PLUGIN_ID}-all`] }, }, - installPackageHandler + installPackageFromRegistryHandler + ); + + router.post( + { + path: EPM_API_ROUTES.INSTALL_BY_UPLOAD_PATTERN, + validate: InstallPackageByUploadRequestSchema, + options: { + tags: [`access:${PLUGIN_ID}-all`], + body: { + accepts: ['application/gzip', 'application/zip'], + parse: false, + maxBytes: MAX_FILE_SIZE_BYTES, + }, + }, + }, + installPackageByUploadHandler ); router.delete( diff --git a/x-pack/plugins/ingest_manager/server/services/agents/actions.ts b/x-pack/plugins/ingest_manager/server/services/agents/actions.ts index 8519714334986..254c2c8b21e32 100644 --- a/x-pack/plugins/ingest_manager/server/services/agents/actions.ts +++ b/x-pack/plugins/ingest_manager/server/services/agents/actions.ts @@ -74,18 +74,19 @@ export async function getAgentActionsForCheckin( const filter = nodeTypes.function.buildNode('and', [ nodeTypes.function.buildNode( 'not', - nodeTypes.function.buildNode( - 'is', - `${AGENT_ACTION_SAVED_OBJECT_TYPE}.attributes.sent_at`, - '*' - ) - ), - nodeTypes.function.buildNode( - 'is', - `${AGENT_ACTION_SAVED_OBJECT_TYPE}.attributes.agent_id`, - agentId + nodeTypes.function.buildNodeWithArgumentNodes('is', [ + nodeTypes.literal.buildNode(`${AGENT_ACTION_SAVED_OBJECT_TYPE}.attributes.sent_at`), + nodeTypes.wildcard.buildNode(nodeTypes.wildcard.wildcardSymbol), + nodeTypes.literal.buildNode(false), + ]) ), + nodeTypes.function.buildNodeWithArgumentNodes('is', [ + nodeTypes.literal.buildNode(`${AGENT_ACTION_SAVED_OBJECT_TYPE}.attributes.agent_id`), + nodeTypes.literal.buildNode(agentId), + nodeTypes.literal.buildNode(false), + ]), ]); + const res = await soClient.find({ type: AGENT_ACTION_SAVED_OBJECT_TYPE, filter, @@ -176,11 +177,11 @@ export async function getNewActionsSince(soClient: SavedObjectsClientContract, t const filter = nodeTypes.function.buildNode('and', [ nodeTypes.function.buildNode( 'not', - nodeTypes.function.buildNode( - 'is', - `${AGENT_ACTION_SAVED_OBJECT_TYPE}.attributes.sent_at`, - '*' - ) + nodeTypes.function.buildNodeWithArgumentNodes('is', [ + nodeTypes.literal.buildNode(`${AGENT_ACTION_SAVED_OBJECT_TYPE}.attributes.sent_at`), + nodeTypes.wildcard.buildNode(nodeTypes.wildcard.wildcardSymbol), + nodeTypes.literal.buildNode(false), + ]) ), nodeTypes.function.buildNode( 'range', diff --git a/x-pack/plugins/ingest_manager/server/types/rest_spec/epm.ts b/x-pack/plugins/ingest_manager/server/types/rest_spec/epm.ts index 191014606f220..d7a801feec34f 100644 --- a/x-pack/plugins/ingest_manager/server/types/rest_spec/epm.ts +++ b/x-pack/plugins/ingest_manager/server/types/rest_spec/epm.ts @@ -32,7 +32,7 @@ export const GetInfoRequestSchema = { }), }; -export const InstallPackageRequestSchema = { +export const InstallPackageFromRegistryRequestSchema = { params: schema.object({ pkgkey: schema.string(), }), @@ -43,6 +43,10 @@ export const InstallPackageRequestSchema = { ), }; +export const InstallPackageByUploadRequestSchema = { + body: schema.buffer(), +}; + export const DeletePackageRequestSchema = { params: schema.object({ pkgkey: schema.string(), diff --git a/x-pack/plugins/lens/public/app_plugin/_app.scss b/x-pack/plugins/lens/public/app_plugin/_app.scss index 4ad8dd360bac6..8416577a60421 100644 --- a/x-pack/plugins/lens/public/app_plugin/_app.scss +++ b/x-pack/plugins/lens/public/app_plugin/_app.scss @@ -26,3 +26,17 @@ flex-direction: column; flex-grow: 1; } + +.lensChartIcon__subdued { + fill: $euiTextSubduedColor; + + // Not great, but the easiest way to fix the gray fill when stuck in a button with a fill + // Like when selected in a button group + .euiButton--fill & { + fill: currentColor; + } +} + +.lensChartIcon__accent { + fill: $euiColorVis0; +} diff --git a/x-pack/plugins/lens/public/assets/chart_area.svg b/x-pack/plugins/lens/public/assets/chart_area.svg deleted file mode 100644 index d291a084028db..0000000000000 --- a/x-pack/plugins/lens/public/assets/chart_area.svg +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/x-pack/plugins/lens/public/assets/chart_area.tsx b/x-pack/plugins/lens/public/assets/chart_area.tsx new file mode 100644 index 0000000000000..ae817e9794dc5 --- /dev/null +++ b/x-pack/plugins/lens/public/assets/chart_area.tsx @@ -0,0 +1,30 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import React from 'react'; +import { EuiIconProps } from '@elastic/eui'; + +export const LensIconChartArea = ({ title, titleId, ...props }: Omit) => ( + + {title ? {title} : null} + + + +); diff --git a/x-pack/plugins/lens/public/assets/chart_area_percentage.tsx b/x-pack/plugins/lens/public/assets/chart_area_percentage.tsx new file mode 100644 index 0000000000000..45c208d5d634b --- /dev/null +++ b/x-pack/plugins/lens/public/assets/chart_area_percentage.tsx @@ -0,0 +1,34 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import React from 'react'; +import { EuiIconProps } from '@elastic/eui'; + +export const LensIconChartAreaPercentage = ({ + title, + titleId, + ...props +}: Omit) => ( + + {title ? {title} : null} + + + +); diff --git a/x-pack/plugins/lens/public/assets/chart_area_stacked.svg b/x-pack/plugins/lens/public/assets/chart_area_stacked.svg deleted file mode 100644 index 6ae48bf6a640b..0000000000000 --- a/x-pack/plugins/lens/public/assets/chart_area_stacked.svg +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/x-pack/plugins/lens/public/assets/chart_area_stacked.tsx b/x-pack/plugins/lens/public/assets/chart_area_stacked.tsx new file mode 100644 index 0000000000000..0320ad7e9afa5 --- /dev/null +++ b/x-pack/plugins/lens/public/assets/chart_area_stacked.tsx @@ -0,0 +1,34 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import React from 'react'; +import { EuiIconProps } from '@elastic/eui'; + +export const LensIconChartAreaStacked = ({ + title, + titleId, + ...props +}: Omit) => ( + + {title ? {title} : null} + + + +); diff --git a/x-pack/plugins/lens/public/assets/chart_bar.svg b/x-pack/plugins/lens/public/assets/chart_bar.svg deleted file mode 100644 index 44553960a5cce..0000000000000 --- a/x-pack/plugins/lens/public/assets/chart_bar.svg +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/x-pack/plugins/lens/public/assets/chart_bar.tsx b/x-pack/plugins/lens/public/assets/chart_bar.tsx new file mode 100644 index 0000000000000..9408f77bd4237 --- /dev/null +++ b/x-pack/plugins/lens/public/assets/chart_bar.tsx @@ -0,0 +1,30 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import React from 'react'; +import { EuiIconProps } from '@elastic/eui'; + +export const LensIconChartBar = ({ title, titleId, ...props }: Omit) => ( + + {title ? {title} : null} + + + +); diff --git a/x-pack/plugins/lens/public/assets/chart_bar_horizontal.svg b/x-pack/plugins/lens/public/assets/chart_bar_horizontal.svg deleted file mode 100644 index e0d9dc8385971..0000000000000 --- a/x-pack/plugins/lens/public/assets/chart_bar_horizontal.svg +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/x-pack/plugins/lens/public/assets/chart_bar_horizontal.tsx b/x-pack/plugins/lens/public/assets/chart_bar_horizontal.tsx new file mode 100644 index 0000000000000..7ec48b107e2fb --- /dev/null +++ b/x-pack/plugins/lens/public/assets/chart_bar_horizontal.tsx @@ -0,0 +1,34 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import React from 'react'; +import { EuiIconProps } from '@elastic/eui'; + +export const LensIconChartBarHorizontal = ({ + title, + titleId, + ...props +}: Omit) => ( + + {title ? {title} : null} + + + +); diff --git a/x-pack/plugins/lens/public/assets/chart_bar_horizontal_percentage.tsx b/x-pack/plugins/lens/public/assets/chart_bar_horizontal_percentage.tsx new file mode 100644 index 0000000000000..6ce09265d4894 --- /dev/null +++ b/x-pack/plugins/lens/public/assets/chart_bar_horizontal_percentage.tsx @@ -0,0 +1,34 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import React from 'react'; +import { EuiIconProps } from '@elastic/eui'; + +export const LensIconChartBarHorizontalPercentage = ({ + title, + titleId, + ...props +}: Omit) => ( + + {title ? {title} : null} + + + +); diff --git a/x-pack/plugins/lens/public/assets/chart_bar_horizontal_stacked.svg b/x-pack/plugins/lens/public/assets/chart_bar_horizontal_stacked.svg deleted file mode 100644 index 602a06e696ecd..0000000000000 --- a/x-pack/plugins/lens/public/assets/chart_bar_horizontal_stacked.svg +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/x-pack/plugins/lens/public/assets/chart_bar_horizontal_stacked.tsx b/x-pack/plugins/lens/public/assets/chart_bar_horizontal_stacked.tsx new file mode 100644 index 0000000000000..c862121fd04f2 --- /dev/null +++ b/x-pack/plugins/lens/public/assets/chart_bar_horizontal_stacked.tsx @@ -0,0 +1,34 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import React from 'react'; +import { EuiIconProps } from '@elastic/eui'; + +export const LensIconChartBarHorizontalStacked = ({ + title, + titleId, + ...props +}: Omit) => ( + + {title ? {title} : null} + + + +); diff --git a/x-pack/plugins/lens/public/assets/chart_bar_percentage.tsx b/x-pack/plugins/lens/public/assets/chart_bar_percentage.tsx new file mode 100644 index 0000000000000..b7d6a0ed604af --- /dev/null +++ b/x-pack/plugins/lens/public/assets/chart_bar_percentage.tsx @@ -0,0 +1,34 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import React from 'react'; +import { EuiIconProps } from '@elastic/eui'; + +export const LensIconChartBarPercentage = ({ + title, + titleId, + ...props +}: Omit) => ( + + {title ? {title} : null} + + + +); diff --git a/x-pack/plugins/lens/public/assets/chart_bar_stacked.svg b/x-pack/plugins/lens/public/assets/chart_bar_stacked.svg deleted file mode 100644 index a954cce83873d..0000000000000 --- a/x-pack/plugins/lens/public/assets/chart_bar_stacked.svg +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/x-pack/plugins/lens/public/assets/chart_bar_stacked.tsx b/x-pack/plugins/lens/public/assets/chart_bar_stacked.tsx new file mode 100644 index 0000000000000..edf8e675178f0 --- /dev/null +++ b/x-pack/plugins/lens/public/assets/chart_bar_stacked.tsx @@ -0,0 +1,34 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import React from 'react'; +import { EuiIconProps } from '@elastic/eui'; + +export const LensIconChartBarStacked = ({ + title, + titleId, + ...props +}: Omit) => ( + + {title ? {title} : null} + + + +); diff --git a/x-pack/plugins/lens/public/assets/chart_datatable.svg b/x-pack/plugins/lens/public/assets/chart_datatable.svg deleted file mode 100644 index aba1f104264cb..0000000000000 --- a/x-pack/plugins/lens/public/assets/chart_datatable.svg +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/x-pack/plugins/lens/public/assets/chart_datatable.tsx b/x-pack/plugins/lens/public/assets/chart_datatable.tsx new file mode 100644 index 0000000000000..48cc844ea2805 --- /dev/null +++ b/x-pack/plugins/lens/public/assets/chart_datatable.tsx @@ -0,0 +1,34 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import React from 'react'; +import { EuiIconProps } from '@elastic/eui'; + +export const LensIconChartDatatable = ({ + title, + titleId, + ...props +}: Omit) => ( + + {title ? {title} : null} + + + +); diff --git a/x-pack/plugins/lens/public/assets/chart_donut.svg b/x-pack/plugins/lens/public/assets/chart_donut.svg deleted file mode 100644 index 5e0d8b7ea83bf..0000000000000 --- a/x-pack/plugins/lens/public/assets/chart_donut.svg +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/x-pack/plugins/lens/public/assets/chart_donut.tsx b/x-pack/plugins/lens/public/assets/chart_donut.tsx new file mode 100644 index 0000000000000..9482161de9d9e --- /dev/null +++ b/x-pack/plugins/lens/public/assets/chart_donut.tsx @@ -0,0 +1,30 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import React from 'react'; +import { EuiIconProps } from '@elastic/eui'; + +export const LensIconChartDonut = ({ title, titleId, ...props }: Omit) => ( + + {title ? {title} : null} + + + +); diff --git a/x-pack/plugins/lens/public/assets/chart_line.svg b/x-pack/plugins/lens/public/assets/chart_line.svg deleted file mode 100644 index 412c9f88f652b..0000000000000 --- a/x-pack/plugins/lens/public/assets/chart_line.svg +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/x-pack/plugins/lens/public/assets/chart_line.tsx b/x-pack/plugins/lens/public/assets/chart_line.tsx new file mode 100644 index 0000000000000..5b57e1fe28c16 --- /dev/null +++ b/x-pack/plugins/lens/public/assets/chart_line.tsx @@ -0,0 +1,30 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import React from 'react'; +import { EuiIconProps } from '@elastic/eui'; + +export const LensIconChartLine = ({ title, titleId, ...props }: Omit) => ( + + {title ? {title} : null} + + + +); diff --git a/x-pack/plugins/lens/public/assets/chart_metric.svg b/x-pack/plugins/lens/public/assets/chart_metric.svg deleted file mode 100644 index 84f0dc181587b..0000000000000 --- a/x-pack/plugins/lens/public/assets/chart_metric.svg +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/x-pack/plugins/lens/public/assets/chart_metric.tsx b/x-pack/plugins/lens/public/assets/chart_metric.tsx new file mode 100644 index 0000000000000..9faa4d6584258 --- /dev/null +++ b/x-pack/plugins/lens/public/assets/chart_metric.tsx @@ -0,0 +1,30 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import React from 'react'; +import { EuiIconProps } from '@elastic/eui'; + +export const LensIconChartMetric = ({ title, titleId, ...props }: Omit) => ( + + {title ? {title} : null} + + + +); diff --git a/x-pack/plugins/lens/public/assets/chart_mixed_xy.svg b/x-pack/plugins/lens/public/assets/chart_mixed_xy.svg deleted file mode 100644 index 943d5a08bcc0b..0000000000000 --- a/x-pack/plugins/lens/public/assets/chart_mixed_xy.svg +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - diff --git a/x-pack/plugins/lens/public/assets/chart_mixed_xy.tsx b/x-pack/plugins/lens/public/assets/chart_mixed_xy.tsx new file mode 100644 index 0000000000000..08eac8eb1605d --- /dev/null +++ b/x-pack/plugins/lens/public/assets/chart_mixed_xy.tsx @@ -0,0 +1,34 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import React from 'react'; +import { EuiIconProps } from '@elastic/eui'; + +export const LensIconChartMixedXy = ({ title, titleId, ...props }: Omit) => ( + + {title ? {title} : null} + + + + +); diff --git a/x-pack/plugins/lens/public/assets/chart_pie.svg b/x-pack/plugins/lens/public/assets/chart_pie.svg deleted file mode 100644 index 22faaf5d97661..0000000000000 --- a/x-pack/plugins/lens/public/assets/chart_pie.svg +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/x-pack/plugins/lens/public/assets/chart_pie.tsx b/x-pack/plugins/lens/public/assets/chart_pie.tsx new file mode 100644 index 0000000000000..cc26df4419caf --- /dev/null +++ b/x-pack/plugins/lens/public/assets/chart_pie.tsx @@ -0,0 +1,30 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import React from 'react'; +import { EuiIconProps } from '@elastic/eui'; + +export const LensIconChartPie = ({ title, titleId, ...props }: Omit) => ( + + {title ? {title} : null} + + + +); diff --git a/x-pack/plugins/lens/public/assets/chart_treemap.svg b/x-pack/plugins/lens/public/assets/chart_treemap.svg deleted file mode 100644 index b0ee04d02b2a6..0000000000000 --- a/x-pack/plugins/lens/public/assets/chart_treemap.svg +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/x-pack/plugins/lens/public/assets/chart_treemap.tsx b/x-pack/plugins/lens/public/assets/chart_treemap.tsx new file mode 100644 index 0000000000000..57205e94137a8 --- /dev/null +++ b/x-pack/plugins/lens/public/assets/chart_treemap.tsx @@ -0,0 +1,34 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import React from 'react'; +import { EuiIconProps } from '@elastic/eui'; + +export const LensIconChartTreemap = ({ title, titleId, ...props }: Omit) => ( + + {title ? {title} : null} + + + + +); diff --git a/x-pack/plugins/lens/public/datatable_visualization/expression.test.tsx b/x-pack/plugins/lens/public/datatable_visualization/expression.test.tsx index b9bdea5522f32..eb00cf93ccd34 100644 --- a/x-pack/plugins/lens/public/datatable_visualization/expression.test.tsx +++ b/x-pack/plugins/lens/public/datatable_visualization/expression.test.tsx @@ -15,6 +15,7 @@ import { IFieldFormat } from '../../../../../src/plugins/data/public'; import { IAggType } from 'src/plugins/data/public'; const onClickValue = jest.fn(); import { EmptyPlaceholder } from '../shared_components'; +import { LensIconChartDatatable } from '../assets/chart_datatable'; function sampleArgs() { const data: LensMultiTable = { @@ -219,7 +220,7 @@ describe('datatable_expression', () => { )} /> ); - expect(component.find(EmptyPlaceholder).prop('icon')).toEqual('visTable'); + expect(component.find(EmptyPlaceholder).prop('icon')).toEqual(LensIconChartDatatable); }); }); }); diff --git a/x-pack/plugins/lens/public/datatable_visualization/expression.tsx b/x-pack/plugins/lens/public/datatable_visualization/expression.tsx index 87ac2d1710b19..dac3b23b98e3b 100644 --- a/x-pack/plugins/lens/public/datatable_visualization/expression.tsx +++ b/x-pack/plugins/lens/public/datatable_visualization/expression.tsx @@ -23,6 +23,8 @@ import { import { VisualizationContainer } from '../visualization_container'; import { EmptyPlaceholder } from '../shared_components'; import { desanitizeFilterContext } from '../utils'; +import { LensIconChartDatatable } from '../assets/chart_datatable'; + export interface DatatableColumns { columnIds: string[]; } @@ -199,7 +201,7 @@ export function DatatableComponent(props: DatatableRenderProps) { )); if (isEmpty) { - return ; + return ; } return ( diff --git a/x-pack/plugins/lens/public/datatable_visualization/visualization.tsx b/x-pack/plugins/lens/public/datatable_visualization/visualization.tsx index 836ffcb15cfa1..5b462f44b3dd5 100644 --- a/x-pack/plugins/lens/public/datatable_visualization/visualization.tsx +++ b/x-pack/plugins/lens/public/datatable_visualization/visualization.tsx @@ -7,7 +7,7 @@ import { Ast } from '@kbn/interpreter/common'; import { i18n } from '@kbn/i18n'; import { SuggestionRequest, Visualization, VisualizationSuggestion, Operation } from '../types'; -import chartTableSVG from '../assets/chart_datatable.svg'; +import { LensIconChartDatatable } from '../assets/chart_datatable'; export interface LayerState { layerId: string; @@ -31,8 +31,7 @@ export const datatableVisualization: Visualization visualizationTypes: [ { id: 'lnsDatatable', - icon: 'visTable', - largeIcon: chartTableSVG, + icon: LensIconChartDatatable, label: i18n.translate('xpack.lens.datatable.label', { defaultMessage: 'Data table', }), @@ -55,7 +54,7 @@ export const datatableVisualization: Visualization getDescription() { return { - icon: chartTableSVG, + icon: LensIconChartDatatable, label: i18n.translate('xpack.lens.datatable.label', { defaultMessage: 'Data table', }), @@ -121,7 +120,7 @@ export const datatableVisualization: Visualization }, ], }, - previewIcon: chartTableSVG, + previewIcon: LensIconChartDatatable, // tables are hidden from suggestion bar, but used for drag & drop and chart switching hide: true, }, diff --git a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/_frame_layout.scss b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/_frame_layout.scss index c2e8d4f6c0049..9367e59b11717 100644 --- a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/_frame_layout.scss +++ b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/_frame_layout.scss @@ -11,7 +11,7 @@ .lnsFrameLayout__pageContent { display: flex; - overflow: auto; + overflow: hidden; flex-grow: 1; } @@ -39,11 +39,16 @@ } .lnsFrameLayout__sidebar--right { - @include euiScrollBar; + flex-basis: 25%; background-color: lightOrDarkTheme($euiColorLightestShade, $euiColorInk); min-width: $lnsPanelMinWidth + $euiSizeXL; - overflow-x: hidden; - overflow-y: scroll; - padding: $euiSize 0 $euiSize $euiSize; + max-width: $euiFormMaxWidth + $euiSizeXXL; max-height: 100%; + + .lnsConfigPanel { + @include euiScrollBar; + padding: $euiSize 0 $euiSize $euiSize; + overflow-x: hidden; + overflow-y: scroll; + } } diff --git a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/_suggestion_panel.scss b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/_suggestion_panel.scss index 1d088e2ec86f9..9d018076dc320 100644 --- a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/_suggestion_panel.scss +++ b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/_suggestion_panel.scss @@ -42,9 +42,8 @@ justify-content: center; padding: $euiSizeS; - // Targeting img as this won't target normal EuiIcon's only the custom svgs's - > img { - @include size($euiSize * 4); + &:not(:only-child) { + height: calc(100% - #{$euiSizeL}); } } diff --git a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/_index.scss b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/_index.scss deleted file mode 100644 index 954fbfadf159b..0000000000000 --- a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/_index.scss +++ /dev/null @@ -1,2 +0,0 @@ -@import 'config_panel'; -@import 'layer_panel'; diff --git a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/_config_panel.scss b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/config_panel.scss similarity index 100% rename from x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/_config_panel.scss rename to x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/config_panel.scss diff --git a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/config_panel.tsx b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/config_panel.tsx index 446f5b44c2e50..ad16038f44911 100644 --- a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/config_panel.tsx +++ b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/config_panel.tsx @@ -3,6 +3,7 @@ * or more contributor license agreements. Licensed under the Elastic License; * you may not use this file except in compliance with the Elastic License. */ +import './config_panel.scss'; import React, { useMemo, memo } from 'react'; import { EuiFlexItem, EuiToolTip, EuiButton, EuiForm } from '@elastic/eui'; diff --git a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/dimension_container.scss b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/dimension_container.scss new file mode 100644 index 0000000000000..f200e25453a2a --- /dev/null +++ b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/dimension_container.scss @@ -0,0 +1,29 @@ +@import '@elastic/eui/src/components/flyout/variables'; +@import '@elastic/eui/src/components/flyout/mixins'; + +.lnsDimensionContainer { + // Use the EuiFlyout style + @include euiFlyout; + // But with custom positioning to keep it within the sidebar contents + position: absolute; + right: 0; + left: 0; + top: 0; + bottom: 0; + animation: euiFlyout $euiAnimSpeedNormal $euiAnimSlightResistance; +} + +.lnsDimensionContainer--noAnimation { + animation: none; +} + +.lnsDimensionContainer__footer, +.lnsDimensionContainer__header { + padding: $euiSizeS; +} + +.lnsDimensionContainer__trigger { + width: 100%; + display: block; + word-break: break-word; +} diff --git a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/dimension_container.tsx b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/dimension_container.tsx new file mode 100644 index 0000000000000..d6b395ac74cce --- /dev/null +++ b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/dimension_container.tsx @@ -0,0 +1,134 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ +import './dimension_container.scss'; + +import React, { useState, useEffect } from 'react'; +import { + EuiFlyoutHeader, + EuiFlyoutFooter, + EuiTitle, + EuiButtonEmpty, + EuiFlexItem, + EuiFocusTrap, +} from '@elastic/eui'; + +import classNames from 'classnames'; +import { i18n } from '@kbn/i18n'; +import { VisualizationDimensionGroupConfig } from '../../../types'; +import { DimensionContainerState } from './types'; + +export function DimensionContainer({ + dimensionContainerState, + setDimensionContainerState, + groups, + accessor, + groupId, + trigger, + panel, + panelTitle, +}: { + dimensionContainerState: DimensionContainerState; + setDimensionContainerState: (newState: DimensionContainerState) => void; + groups: VisualizationDimensionGroupConfig[]; + accessor: string; + groupId: string; + trigger: React.ReactElement; + panel: React.ReactElement; + panelTitle: React.ReactNode; +}) { + const [openByCreation, setIsOpenByCreation] = useState( + dimensionContainerState.openId === accessor + ); + const [focusTrapIsEnabled, setFocusTrapIsEnabled] = useState(false); + const [flyoutIsVisible, setFlyoutIsVisible] = useState(false); + + const noMatch = dimensionContainerState.isOpen + ? !groups.some((d) => d.accessors.includes(accessor)) + : false; + + const closeFlyout = () => { + setDimensionContainerState({ + isOpen: false, + openId: null, + addingToGroupId: null, + }); + setIsOpenByCreation(false); + setFocusTrapIsEnabled(false); + setFlyoutIsVisible(false); + }; + + const openFlyout = () => { + setFlyoutIsVisible(true); + setTimeout(() => { + setFocusTrapIsEnabled(true); + }, 255); + }; + + const flyoutShouldBeOpen = + dimensionContainerState.isOpen && + (dimensionContainerState.openId === accessor || + (noMatch && dimensionContainerState.addingToGroupId === groupId)); + + useEffect(() => { + if (flyoutShouldBeOpen) { + openFlyout(); + } + }); + + useEffect(() => { + if (!flyoutShouldBeOpen) { + if (flyoutIsVisible) { + setFlyoutIsVisible(false); + } + if (focusTrapIsEnabled) { + setFocusTrapIsEnabled(false); + } + } + }, [flyoutShouldBeOpen, flyoutIsVisible, focusTrapIsEnabled]); + + const flyout = flyoutIsVisible && ( + +
+ + + + {panelTitle} + + + + + {panel} + + + + {i18n.translate('xpack.lens.dimensionContainer.close', { + defaultMessage: 'Close', + })} + + +
+
+ ); + + return ( + <> +
{trigger}
+ {flyout} + + ); +} diff --git a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/dimension_popover.scss b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/dimension_popover.scss deleted file mode 100644 index 98036c7f31bd9..0000000000000 --- a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/dimension_popover.scss +++ /dev/null @@ -1,18 +0,0 @@ -.lnsDimensionPopover { - line-height: 0; - flex-grow: 1; - max-width: calc(100% - #{$euiSizeL}); -} - -.lnsDimensionPopover__trigger { - max-width: 100%; - display: block; - word-break: break-word; -} - -// todo: remove after closing https://github.com/elastic/eui/issues/3548 -.lnsDimensionPopover__fixTranslateDnd { - // sass-lint:disable-block no-important - transform: none !important; -} - diff --git a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/dimension_popover.tsx b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/dimension_popover.tsx deleted file mode 100644 index a90bd8122d18e..0000000000000 --- a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/dimension_popover.tsx +++ /dev/null @@ -1,50 +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; - * you may not use this file except in compliance with the Elastic License. - */ -import './dimension_popover.scss'; - -import React from 'react'; -import { EuiPopover } from '@elastic/eui'; -import { VisualizationDimensionGroupConfig } from '../../../types'; -import { DimensionPopoverState } from './types'; - -export function DimensionPopover({ - popoverState, - setPopoverState, - groups, - accessor, - groupId, - trigger, - panel, -}: { - popoverState: DimensionPopoverState; - setPopoverState: (newState: DimensionPopoverState) => void; - groups: VisualizationDimensionGroupConfig[]; - accessor: string; - groupId: string; - trigger: React.ReactElement; - panel: React.ReactElement; -}) { - const noMatch = popoverState.isOpen ? !groups.some((d) => d.accessors.includes(accessor)) : false; - return ( - { - setPopoverState({ isOpen: false, openId: null, addingToGroupId: null, tabId: null }); - }} - button={trigger} - anchorPosition="leftUp" - panelPaddingSize="none" - > - {panel} - - ); -} diff --git a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/_layer_panel.scss b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/layer_panel.scss similarity index 82% rename from x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/_layer_panel.scss rename to x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/layer_panel.scss index ab53ff983ca26..b85c3e843613d 100644 --- a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/_layer_panel.scss +++ b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/layer_panel.scss @@ -6,6 +6,14 @@ max-width: calc(100% - #{$euiSize * 3.625}); } +.lnsLayerPanel__settingsFlexItem:empty + .lnsLayerPanel__sourceFlexItem { + max-width: calc(100% - #{$euiSizeS}); +} + +.lnsLayerPanel__settingsFlexItem:empty { + margin: 0; +} + .lnsLayerPanel__row { background: $euiColorLightestShade; padding: $euiSizeS; @@ -52,6 +60,5 @@ } .lnsLayerPanel__styleEditor { - width: $euiSize * 30; - padding: $euiSizeS; + padding: 0 $euiSizeS $euiSizeS; } diff --git a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/layer_panel.test.tsx b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/layer_panel.test.tsx index 85dbee6de524f..a9e2d6dc696ab 100644 --- a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/layer_panel.test.tsx +++ b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/layer_panel.test.tsx @@ -13,7 +13,7 @@ import { DatasourceMock, } from '../../mocks'; import { ChildDragDropProvider } from '../../../drag_drop'; -import { EuiFormRow, EuiPopover } from '@elastic/eui'; +import { EuiFormRow } from '@elastic/eui'; import { mount } from 'enzyme'; import { mountWithIntl } from 'test_utils/enzyme_helpers'; import { Visualization } from '../../../types'; @@ -203,7 +203,7 @@ describe('LayerPanel', () => { expect(group).toHaveLength(1); }); - it('should render the datasource and visualization panels inside the dimension popover', () => { + it('should render the datasource and visualization panels inside the dimension container', () => { mockVisualization.getConfiguration.mockReturnValueOnce({ groups: [ { @@ -221,16 +221,16 @@ describe('LayerPanel', () => { const component = mountWithIntl(); - const group = component.find('DimensionPopover'); + const group = component.find('DimensionContainer'); const panel = mount(group.prop('panel')); - expect(panel.find('EuiTabbedContent').prop('tabs')).toHaveLength(2); + expect(panel.children()).toHaveLength(2); }); - it('should keep the popover open when configuring a new dimension', () => { + it('should keep the DimensionContainer open when configuring a new dimension', () => { /** * The ID generation system for new dimensions has been messy before, so - * this tests that the ID used in the first render is used to keep the popover + * this tests that the ID used in the first render is used to keep the container * open in future renders */ (generateId as jest.Mock).mockReturnValueOnce(`newid`); @@ -264,20 +264,20 @@ describe('LayerPanel', () => { const component = mountWithIntl(); - const group = component.find('DimensionPopover'); + const group = component.find('DimensionContainer'); const triggerButton = mountWithIntl(group.prop('trigger')); act(() => { triggerButton.find('[data-test-subj="lns-empty-dimension"]').first().simulate('click'); }); component.update(); - expect(component.find(EuiPopover).prop('isOpen')).toBe(true); + expect(component.find('EuiFlyoutHeader').exists()).toBe(true); }); - it('should close the popover when the active visualization changes', () => { + it('should close the DimensionContainer when the active visualization changes', () => { /** * The ID generation system for new dimensions has been messy before, so - * this tests that the ID used in the first render is used to keep the popover + * this tests that the ID used in the first render is used to keep the container * open in future renders */ @@ -312,18 +312,18 @@ describe('LayerPanel', () => { const component = mountWithIntl(); - const group = component.find('DimensionPopover'); + const group = component.find('DimensionContainer'); const triggerButton = mountWithIntl(group.prop('trigger')); act(() => { triggerButton.find('[data-test-subj="lns-empty-dimension"]').first().simulate('click'); }); component.update(); - expect(component.find(EuiPopover).prop('isOpen')).toBe(true); + expect(component.find('EuiFlyoutHeader').exists()).toBe(true); act(() => { component.setProps({ activeVisualizationId: 'vis2' }); }); component.update(); - expect(component.find(EuiPopover).prop('isOpen')).toBe(false); + expect(component.find('EuiFlyoutHeader').exists()).toBe(false); }); }); diff --git a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/layer_panel.tsx b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/layer_panel.tsx index b45dd13bfa4fd..46cd0292f2459 100644 --- a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/layer_panel.tsx +++ b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/layer_panel.tsx @@ -3,6 +3,7 @@ * or more contributor license agreements. Licensed under the Elastic License; * you may not use this file except in compliance with the Elastic License. */ +import './layer_panel.scss'; import React, { useContext, useState, useEffect } from 'react'; import { @@ -13,7 +14,6 @@ import { EuiFlexItem, EuiButtonEmpty, EuiFormRow, - EuiTabbedContent, } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n/react'; @@ -24,14 +24,13 @@ import { DragContext, DragDrop, ChildDragDropProvider } from '../../../drag_drop import { LayerSettings } from './layer_settings'; import { trackUiEvent } from '../../../lens_ui_telemetry'; import { generateId } from '../../../id_generator'; -import { ConfigPanelWrapperProps, DimensionPopoverState } from './types'; -import { DimensionPopover } from './dimension_popover'; +import { ConfigPanelWrapperProps, DimensionContainerState } from './types'; +import { DimensionContainer } from './dimension_container'; -const initialPopoverState = { +const initialDimensionContainerState = { isOpen: false, openId: null, addingToGroupId: null, - tabId: null, }; export function LayerPanel( @@ -50,13 +49,15 @@ export function LayerPanel( } ) { const dragDropContext = useContext(DragContext); - const [popoverState, setPopoverState] = useState(initialPopoverState); + const [dimensionContainerState, setDimensionContainerState] = useState( + initialDimensionContainerState + ); const { framePublicAPI, layerId, isOnlyLayer, onRemoveLayer, dataTestSubj } = props; const datasourcePublicAPI = framePublicAPI.datasourceLayers[layerId]; useEffect(() => { - setPopoverState(initialPopoverState); + setDimensionContainerState(initialDimensionContainerState); }, [props.activeVisualizationId]); if ( @@ -100,7 +101,7 @@ export function LayerPanel( - + <> {group.accessors.map((accessor) => { - const tabs = [ - { - id: 'datasource', - name: i18n.translate('xpack.lens.editorFrame.quickFunctionsLabel', { - defaultMessage: 'Quick functions', - }), - content: ( + const datasourceDimensionEditor = ( + + ); + const visDimensionEditor = + activeVisualization.renderDimensionEditor && group.enableDimensionEditor ? ( +
- ), - }, - ]; - - if (activeVisualization.renderDimensionEditor && group.enableDimensionEditor) { - tabs.push({ - id: 'visualization', - name: i18n.translate('xpack.lens.editorFrame.formatStyleLabel', { - defaultMessage: 'Format & style', - }), - content: ( -
- -
- ), - }); - } - +
+ ) : null; return ( - { - if (popoverState.isOpen) { - setPopoverState(initialPopoverState); + onClick: () => { + if (dimensionContainerState.isOpen) { + setDimensionContainerState(initialDimensionContainerState); } else { - setPopoverState({ + setDimensionContainerState({ isOpen: true, openId: accessor, addingToGroupId: null, // not set for existing dimension - tabId: 'datasource', }); } }, @@ -298,22 +283,21 @@ export function LayerPanel( /> } panel={ - t.id === popoverState.tabId) || tabs[0]} - size="s" - onTabClick={(tab) => { - setPopoverState({ - ...popoverState, - tabId: tab.id as typeof popoverState['tabId'], - }); - }} - /> + <> + {datasourceDimensionEditor} + {visDimensionEditor} + } + panelTitle={i18n.translate('xpack.lens.configure.configurePanelTitle', { + defaultMessage: '{groupLabel} configuration', + values: { + groupLabel: group.groupLabel, + }, + })} /> - { - if (popoverState.isOpen) { - setPopoverState(initialPopoverState); + if (dimensionContainerState.isOpen) { + setDimensionContainerState(initialDimensionContainerState); } else { - setPopoverState({ + setDimensionContainerState({ isOpen: true, openId: newId, addingToGroupId: group.groupId, - tabId: 'datasource', }); } }} @@ -428,6 +411,12 @@ export function LayerPanel(
} + panelTitle={i18n.translate('xpack.lens.configure.configurePanelTitle', { + defaultMessage: '{groupLabel} configuration', + values: { + groupLabel: group.groupLabel, + }, + })} panel={ { getSuggestionsMock.mockReturnValue([ { datasourceState: {}, - previewIcon: chartTableSVG, + previewIcon: LensIconChartDatatable, score: 0.5, visualizationState: suggestion1State, visualizationId: 'vis', @@ -288,6 +288,6 @@ describe('suggestion_panel', () => { const wrapper = mount(); expect(wrapper.find(EuiIcon)).toHaveLength(1); - expect(wrapper.find(EuiIcon).prop('type')).toEqual(chartTableSVG); + expect(wrapper.find(EuiIcon).prop('type')).toEqual(LensIconChartDatatable); }); }); diff --git a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/workspace_panel/chart_switch.scss b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/workspace_panel/chart_switch.scss index 8a44d59ff1c0d..f84191e1bfb1a 100644 --- a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/workspace_panel/chart_switch.scss +++ b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/workspace_panel/chart_switch.scss @@ -8,6 +8,7 @@ .lnsChartSwitch__summaryIcon { margin-right: $euiSizeS; transform: translateY(-1px); + color: $euiTextSubduedColor; } // Targeting img as this won't target normal EuiIcon's only the custom svgs's diff --git a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/workspace_panel/chart_switch.tsx b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/workspace_panel/chart_switch.tsx index 5640c52ac4325..82983862e7c03 100644 --- a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/workspace_panel/chart_switch.tsx +++ b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/workspace_panel/chart_switch.tsx @@ -66,7 +66,7 @@ function VisualizationSummary(props: Props) { return ( <> {description.icon && ( - + )} {description.label} @@ -181,7 +181,7 @@ export function ChartSwitch(props: Props) { v.visualizationTypes.map((t) => ({ visualizationId: v.id, ...t, - icon: t.largeIcon || t.icon, + icon: t.icon, })) ) ).map((visualizationType) => ({ diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/_field_item.scss b/x-pack/plugins/lens/public/indexpattern_datasource/_field_item.scss index d194c694abdf8..d74c332dd42e5 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/_field_item.scss +++ b/x-pack/plugins/lens/public/indexpattern_datasource/_field_item.scss @@ -37,12 +37,12 @@ } } -.lnsFieldItem__fieldPopoverPanel { +.lnsFieldItem__fieldPanel { min-width: 260px; max-width: 300px; } -.lnsFieldItem__popoverButtonGroup { - // Enforce lowercase for buttons or else some browsers inherit all caps from popover title +.lnsFieldItem__buttonGroup { + // Enforce lowercase for buttons or else some browsers inherit all caps from flyout title text-transform: none; } diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/bucket_nesting_editor.tsx b/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/bucket_nesting_editor.tsx index 10ae1936291c4..281c72915e46e 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/bucket_nesting_editor.tsx +++ b/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/bucket_nesting_editor.tsx @@ -99,6 +99,7 @@ export function BucketNestingEditor({ label={i18n.translate('xpack.lens.indexPattern.groupingControlLabel', { defaultMessage: 'Grouping', })} + labelType="legend" > <> button { + padding-top: 0; + padding-bottom: 0; +} diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/popover_editor.tsx b/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/dimension_editor.tsx similarity index 64% rename from x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/popover_editor.tsx rename to x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/dimension_editor.tsx index d5f0110f071f1..98e9389a85819 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/popover_editor.tsx +++ b/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/dimension_editor.tsx @@ -4,21 +4,18 @@ * you may not use this file except in compliance with the Elastic License. */ -import './popover_editor.scss'; +import './dimension_editor.scss'; import _ from 'lodash'; import React, { useState, useMemo, useEffect } from 'react'; import { i18n } from '@kbn/i18n'; import { - EuiFlexItem, - EuiFlexGroup, EuiListGroup, - EuiCallOut, EuiFormRow, EuiFieldText, EuiSpacer, EuiListGroupItemProps, } from '@elastic/eui'; -import classNames from 'classnames'; +import { EuiFormLabel } from '@elastic/eui'; import { IndexPatternColumn, OperationType } from '../indexpattern'; import { IndexPatternDimensionEditorProps, OperationFieldSupportMatrix } from './dimension_panel'; import { @@ -37,7 +34,7 @@ import { FormatSelector } from './format_selector'; const operationPanels = getOperationDisplay(); -export interface PopoverEditorProps extends IndexPatternDimensionEditorProps { +export interface DimensionEditorProps extends IndexPatternDimensionEditorProps { selectedColumn?: IndexPatternColumn; operationFieldSupportMatrix: OperationFieldSupportMatrix; currentIndexPattern: IndexPattern; @@ -72,16 +69,25 @@ const LabelInput = ({ value, onChange }: { value: string; onChange: (value: stri }; return ( - + + + ); }; -export function PopoverEditor(props: PopoverEditorProps) { +export function DimensionEditor(props: DimensionEditorProps) { const { selectedColumn, operationFieldSupportMatrix, @@ -128,8 +134,8 @@ export function PopoverEditor(props: PopoverEditorProps) { ); } - function getSideNavItems(): EuiListGroupItemProps[] { - return getOperationTypes().map(({ operationType, compatibleWithCurrentField }) => { + const sideNavItems: EuiListGroupItemProps[] = getOperationTypes().map( + ({ operationType, compatibleWithCurrentField }) => { const isActive = Boolean( incompatibleSelectedOperationType === operationType || (!incompatibleSelectedOperationType && @@ -220,13 +226,42 @@ export function PopoverEditor(props: PopoverEditorProps) { ); }, }; - }); - } + } + ); return ( -
- - +
+
+ + {i18n.translate('xpack.lens.indexPattern.functionsLabel', { + defaultMessage: 'Choose a function', + })} + + + 3 ? 'lnsIndexPatternDimensionEditor__columns' : ''} + gutterSize="none" + listItems={sideNavItems} + maxWidth={false} + /> +
+ +
+ - - - - - - - - {incompatibleSelectedOperationType && selectedColumn && ( - <> - - - - )} - {incompatibleSelectedOperationType && !selectedColumn && ( - <> - - - - )} - {!incompatibleSelectedOperationType && ParamEditor && ( - <> - - - - )} - {!incompatibleSelectedOperationType && selectedColumn && ( - - { - setState({ - ...state, - layers: { - ...state.layers, - [layerId]: { - ...state.layers[layerId], - columns: { - ...state.layers[layerId].columns, - [columnId]: { - ...selectedColumn, - label: value, - customLabel: true, - }, - }, - }, - }, - }); - }} - /> - - )} + - {!hideGrouping && ( - { - setState({ - ...state, - layers: { - ...state.layers, - [props.layerId]: { - ...state.layers[props.layerId], - columnOrder, - }, + {!incompatibleSelectedOperationType && ParamEditor && ( + <> + + + + )} +
+ + + +
+ {!incompatibleSelectedOperationType && selectedColumn && ( + { + setState({ + ...state, + layers: { + ...state.layers, + [layerId]: { + ...state.layers[layerId], + columns: { + ...state.layers[layerId].columns, + [columnId]: { + ...selectedColumn, + label: value, + customLabel: true, }, - }); - }} - /> - )} + }, + }, + }, + }); + }} + /> + )} - {selectedColumn && selectedColumn.dataType === 'number' ? ( - { - setState( - updateColumnParam({ - state, - layerId, - currentColumn: selectedColumn, - paramName: 'format', - value: newFormat, - }) - ); - }} - /> - ) : null} - - - - + {!hideGrouping && ( + { + setState({ + ...state, + layers: { + ...state.layers, + [props.layerId]: { + ...state.layers[props.layerId], + columnOrder, + }, + }, + }); + }} + /> + )} + + {selectedColumn && selectedColumn.dataType === 'number' ? ( + { + setState( + updateColumnParam({ + state, + layerId, + currentColumn: selectedColumn, + paramName: 'format', + value: newFormat, + }) + ); + }} + /> + ) : null} +
); } diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/dimension_panel.test.tsx b/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/dimension_panel.test.tsx index f184d5628ab1c..dd7611ca7f41f 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/dimension_panel.test.tsx +++ b/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/dimension_panel.test.tsx @@ -7,7 +7,7 @@ import { ReactWrapper, ShallowWrapper } from 'enzyme'; import React from 'react'; import { act } from 'react-dom/test-utils'; -import { EuiComboBox, EuiListGroupItemProps, EuiListGroup, EuiFieldNumber } from '@elastic/eui'; +import { EuiComboBox, EuiListGroupItemProps, EuiListGroup, EuiRange } from '@elastic/eui'; import { DataPublicPluginStart } from '../../../../../../src/plugins/data/public'; import { changeColumn } from '../state_helpers'; import { @@ -619,9 +619,9 @@ describe('IndexPatternDimensionEditorPanel', () => { .find('button[data-test-subj="lns-indexPatternDimension-terms incompatible"]') .simulate('click'); - expect(wrapper.find('[data-test-subj="indexPattern-invalid-operation"]')).not.toHaveLength( - 0 - ); + expect( + wrapper.find('[data-test-subj="indexPattern-field-selection-row"]').first().prop('error') + ).toBeDefined(); expect(setState).not.toHaveBeenCalled(); }); @@ -1188,7 +1188,7 @@ describe('IndexPatternDimensionEditorPanel', () => { expect( wrapper - .find(EuiFieldNumber) + .find(EuiRange) .filter('[data-test-subj="indexPattern-dimension-formatDecimals"]') .prop('value') ).toEqual(0); @@ -1224,9 +1224,9 @@ describe('IndexPatternDimensionEditorPanel', () => { act(() => { wrapper - .find(EuiFieldNumber) + .find(EuiRange) .filter('[data-test-subj="indexPattern-dimension-formatDecimals"]') - .prop('onChange')!({ target: { value: '0' } }); + .prop('onChange')!({ currentTarget: { value: '0' } }); }); expect(setState).toHaveBeenCalledWith({ diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/dimension_panel.tsx b/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/dimension_panel.tsx index 1fbbefd8f1117..923f7145d1c64 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/dimension_panel.tsx +++ b/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/dimension_panel.tsx @@ -20,7 +20,7 @@ import { import { DataPublicPluginStart } from '../../../../../../src/plugins/data/public'; import { IndexPatternColumn, OperationType } from '../indexpattern'; import { getAvailableOperationsByMetadata, buildColumn, changeField } from '../operations'; -import { PopoverEditor } from './popover_editor'; +import { DimensionEditor } from './dimension_editor'; import { changeColumn } from '../state_helpers'; import { isDraggedField, hasField } from '../utils'; import { IndexPatternPrivateState, IndexPatternField } from '../types'; @@ -239,9 +239,7 @@ export const IndexPatternDimensionTriggerComponent = function IndexPatternDimens { - props.togglePopover(); - }} + onClick={props.onClick} data-test-subj="lns-dimensionTrigger" aria-label={i18n.translate('xpack.lens.configure.editConfig', { defaultMessage: 'Edit configuration', @@ -267,7 +265,7 @@ export const IndexPatternDimensionEditorComponent = function IndexPatternDimensi props.state.layers[layerId].columns[props.columnId] || null; return ( - { currentIndexPattern: IndexPattern; fieldMap: Record; incompatibleSelectedOperationType: OperationType | null; @@ -47,6 +53,7 @@ export function FieldSelect({ onChoose, onDeleteColumn, existingFields, + ...rest }: FieldSelectProps) { const { operationByField } = operationFieldSupportMatrix; const memoizedFieldOptions = useMemo(() => { @@ -155,7 +162,7 @@ export function FieldSelect({ defaultMessage: 'Field', })} options={(memoizedFieldOptions as unknown) as EuiComboBoxOptionOption[]} - isInvalid={Boolean(incompatibleSelectedOperationType && selectedColumnOperationType)} + isInvalid={Boolean(incompatibleSelectedOperationType)} selectedOptions={ ((selectedColumnOperationType ? selectedColumnSourceField @@ -194,6 +201,7 @@ export function FieldSelect({
); }} + {...rest} /> ); } diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/format_selector.tsx b/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/format_selector.tsx index b3b0190b9c400..8d9a91397cf2f 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/format_selector.tsx +++ b/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/format_selector.tsx @@ -6,7 +6,7 @@ import React, { useState } from 'react'; import { i18n } from '@kbn/i18n'; -import { EuiFormRow, EuiFieldNumber, EuiComboBox } from '@elastic/eui'; +import { EuiFormRow, EuiComboBox, EuiSpacer, EuiRange } from '@elastic/eui'; import { IndexPatternColumn } from '../indexpattern'; const supportedFormats: Record = { @@ -57,80 +57,84 @@ export function FormatSelector(props: FormatSelectorProps) { }), }; + const label = i18n.translate('xpack.lens.indexPattern.columnFormatLabel', { + defaultMessage: 'Value format', + }); + + const decimalsLabel = i18n.translate('xpack.lens.indexPattern.decimalPlacesLabel', { + defaultMessage: 'Decimals', + }); + return ( <> - - ({ - value: id, - label: format.title ?? id, - })), - ]} - selectedOptions={ - currentFormat - ? [ - { - value: currentFormat.id, - label: selectedFormat?.title ?? currentFormat.id, - }, - ] - : [defaultOption] - } - onChange={(choices) => { - if (choices.length === 0) { - return; - } - - if (!choices[0].value) { - onChange(); - return; + +
+ ({ + value: id, + label: format.title ?? id, + })), + ]} + selectedOptions={ + currentFormat + ? [ + { + value: currentFormat.id, + label: selectedFormat?.title ?? currentFormat.id, + }, + ] + : [defaultOption] } - onChange({ - id: choices[0].value, - params: { decimals: state.decimalPlaces }, - }); - }} - /> - + onChange={(choices) => { + if (choices.length === 0) { + return; + } - {currentFormat ? ( - - { - setState({ decimalPlaces: Number(e.target.value) }); + if (!choices[0].value) { + onChange(); + return; + } onChange({ - id: (selectedColumn.params as { format: { id: string } }).format.id, - params: { - decimals: Number(e.target.value), - }, + id: choices[0].value, + params: { decimals: state.decimalPlaces }, }); }} - compressed - fullWidth /> - - ) : null} + {currentFormat ? ( + <> + + { + setState({ decimalPlaces: Number(e.currentTarget.value) }); + onChange({ + id: (selectedColumn.params as { format: { id: string } }).format.id, + params: { + decimals: Number(e.currentTarget.value), + }, + }); + }} + data-test-subj="indexPattern-dimension-formatDecimals" + compressed + fullWidth + prepend={decimalsLabel} + aria-label={decimalsLabel} + /> + + ) : null} +
+
); } diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/popover_editor.scss b/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/popover_editor.scss deleted file mode 100644 index 3f75b5ad86669..0000000000000 --- a/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/popover_editor.scss +++ /dev/null @@ -1,20 +0,0 @@ -.lnsIndexPatternDimensionEditor { - width: $euiSize * 30; - padding: $euiSizeS; - max-width: 100%; -} - -.lnsIndexPatternDimensionEditor__left, -.lnsIndexPatternDimensionEditor__right { - padding: $euiSizeS; -} - -.lnsIndexPatternDimensionEditor__left { - background-color: $euiPageBackgroundColor; - width: $euiSize * 8; -} - -.lnsIndexPatternDimensionEditor__operation > button { - padding-top: 0; - padding-bottom: 0; -} diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/field_item.tsx b/x-pack/plugins/lens/public/indexpattern_datasource/field_item.tsx index cf15c29844053..1f6d7911b3a33 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/field_item.tsx +++ b/x-pack/plugins/lens/public/indexpattern_datasource/field_item.tsx @@ -231,7 +231,7 @@ export const InnerFieldItem = function InnerFieldItem(props: FieldItemProps) { isOpen={infoIsOpen} closePopover={() => setOpen(false)} anchorPosition="rightUp" - panelClassName="lnsFieldItem__fieldPopoverPanel" + panelClassName="lnsFieldItem__fieldPanel" > @@ -316,7 +316,7 @@ function FieldItemPopoverContents(props: State & FieldItemProps) { if (histogram && histogram.buckets.length && topValues && topValues.buckets.length) { title = ( {!intervalIsRestricted && ( - + )} @@ -197,6 +198,8 @@ export const dateHistogramOperation: OperationDefinition {intervalIsRestricted ? ( ) : ( <> - + { diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/terms.test.tsx b/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/terms.test.tsx index 2972ed2d0231b..6f67cb7531e1c 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/terms.test.tsx +++ b/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/terms.test.tsx @@ -345,7 +345,7 @@ describe('terms', () => { }); }); - describe('popover param editor', () => { + describe('param editor', () => { it('should render current order by value and options', () => { const setStateSpy = jest.fn(); const instance = shallow( diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/terms.tsx b/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/terms.tsx index c1b19fd5549e7..20c421008a746 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/terms.tsx +++ b/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/terms.tsx @@ -177,6 +177,7 @@ export const termsOperation: OperationDefinition = { defaultMessage: 'Number of values', })} display="columnCompressed" + fullWidth > = { defaultMessage: 'Order by', })} display="columnCompressed" + fullWidth > = { defaultMessage: 'Order direction', })} display="columnCompressed" + fullWidth > { expect(rest).toHaveLength(0); expect(suggestion).toMatchInlineSnapshot(` Object { - "previewIcon": "test-file-stub", + "previewIcon": [Function], "score": 0.1, "state": Object { "accessor": "bytes", diff --git a/x-pack/plugins/lens/public/metric_visualization/metric_suggestions.ts b/x-pack/plugins/lens/public/metric_visualization/metric_suggestions.ts index 0caac7dd0d092..c95467ab04e11 100644 --- a/x-pack/plugins/lens/public/metric_visualization/metric_suggestions.ts +++ b/x-pack/plugins/lens/public/metric_visualization/metric_suggestions.ts @@ -6,7 +6,7 @@ import { SuggestionRequest, VisualizationSuggestion, TableSuggestion } from '../types'; import { State } from './types'; -import chartMetricSVG from '../assets/chart_metric.svg'; +import { LensIconChartMetric } from '../assets/chart_metric'; /** * Generate suggestions for the metric chart. @@ -44,7 +44,7 @@ function getSuggestion(table: TableSuggestion): VisualizationSuggestion { return { title, score: 0.1, - previewIcon: chartMetricSVG, + previewIcon: LensIconChartMetric, state: { layerId: table.layerId, accessor: col.columnId, diff --git a/x-pack/plugins/lens/public/metric_visualization/metric_visualization.tsx b/x-pack/plugins/lens/public/metric_visualization/metric_visualization.tsx index 5f1ce5334dd36..72c07bed1acb2 100644 --- a/x-pack/plugins/lens/public/metric_visualization/metric_visualization.tsx +++ b/x-pack/plugins/lens/public/metric_visualization/metric_visualization.tsx @@ -7,9 +7,9 @@ import { i18n } from '@kbn/i18n'; import { Ast } from '@kbn/interpreter/target/common'; import { getSuggestions } from './metric_suggestions'; +import { LensIconChartMetric } from '../assets/chart_metric'; import { Visualization, OperationMetadata, DatasourcePublicAPI } from '../types'; import { State } from './types'; -import chartMetricSVG from '../assets/chart_metric.svg'; const toExpression = ( state: State, @@ -45,8 +45,7 @@ export const metricVisualization: Visualization = { visualizationTypes: [ { id: 'lnsMetric', - icon: 'visMetric', - largeIcon: chartMetricSVG, + icon: LensIconChartMetric, label: i18n.translate('xpack.lens.metric.label', { defaultMessage: 'Metric', }), @@ -70,7 +69,7 @@ export const metricVisualization: Visualization = { getDescription() { return { - icon: chartMetricSVG, + icon: LensIconChartMetric, label: i18n.translate('xpack.lens.metric.label', { defaultMessage: 'Metric', }), diff --git a/x-pack/plugins/lens/public/pie_visualization/constants.ts b/x-pack/plugins/lens/public/pie_visualization/constants.ts index 10672f91a81c7..ab5e64ea84029 100644 --- a/x-pack/plugins/lens/public/pie_visualization/constants.ts +++ b/x-pack/plugins/lens/public/pie_visualization/constants.ts @@ -5,25 +5,25 @@ */ import { i18n } from '@kbn/i18n'; -import chartDonutSVG from '../assets/chart_donut.svg'; -import chartPieSVG from '../assets/chart_pie.svg'; -import chartTreemapSVG from '../assets/chart_treemap.svg'; +import { LensIconChartDonut } from '../assets/chart_donut'; +import { LensIconChartPie } from '../assets/chart_pie'; +import { LensIconChartTreemap } from '../assets/chart_treemap'; export const CHART_NAMES = { donut: { - icon: chartDonutSVG, + icon: LensIconChartDonut, label: i18n.translate('xpack.lens.pie.donutLabel', { defaultMessage: 'Donut', }), }, pie: { - icon: chartPieSVG, + icon: LensIconChartPie, label: i18n.translate('xpack.lens.pie.pielabel', { defaultMessage: 'Pie', }), }, treemap: { - icon: chartTreemapSVG, + icon: LensIconChartTreemap, label: i18n.translate('xpack.lens.pie.treemaplabel', { defaultMessage: 'Treemap', }), @@ -33,4 +33,4 @@ export const CHART_NAMES = { export const MAX_PIE_BUCKETS = 3; export const MAX_TREEMAP_BUCKETS = 2; -export const DEFAULT_PERCENT_DECIMALS = 3; +export const DEFAULT_PERCENT_DECIMALS = 2; diff --git a/x-pack/plugins/lens/public/pie_visualization/pie_visualization.tsx b/x-pack/plugins/lens/public/pie_visualization/pie_visualization.tsx index 855bacd4f794c..dd1b36e00ebb9 100644 --- a/x-pack/plugins/lens/public/pie_visualization/pie_visualization.tsx +++ b/x-pack/plugins/lens/public/pie_visualization/pie_visualization.tsx @@ -37,17 +37,17 @@ export const pieVisualization: Visualization = { visualizationTypes: [ { id: 'donut', - largeIcon: CHART_NAMES.donut.icon, + icon: CHART_NAMES.donut.icon, label: CHART_NAMES.donut.label, }, { id: 'pie', - largeIcon: CHART_NAMES.pie.icon, + icon: CHART_NAMES.pie.icon, label: CHART_NAMES.pie.label, }, { id: 'treemap', - largeIcon: CHART_NAMES.treemap.icon, + icon: CHART_NAMES.treemap.icon, label: CHART_NAMES.treemap.label, }, ], diff --git a/x-pack/plugins/lens/public/pie_visualization/render_function.test.tsx b/x-pack/plugins/lens/public/pie_visualization/render_function.test.tsx index 38ef44a2fef18..ac952e307758b 100644 --- a/x-pack/plugins/lens/public/pie_visualization/render_function.test.tsx +++ b/x-pack/plugins/lens/public/pie_visualization/render_function.test.tsx @@ -12,6 +12,7 @@ import { PieComponent } from './render_function'; import { PieExpressionArgs } from './types'; import { EmptyPlaceholder } from '../shared_components'; import { chartPluginMock } from '../../../../../src/plugins/charts/public/mocks'; +import { LensIconChartDonut } from '../assets/chart_donut'; const chartsThemeService = chartPluginMock.createSetupContract().theme; @@ -189,7 +190,7 @@ describe('PieVisualization component', () => { const component = shallow( ); - expect(component.find(EmptyPlaceholder).prop('icon')).toEqual('visPie'); + expect(component.find(EmptyPlaceholder).prop('icon')).toEqual(LensIconChartDonut); }); }); }); diff --git a/x-pack/plugins/lens/public/pie_visualization/render_function.tsx b/x-pack/plugins/lens/public/pie_visualization/render_function.tsx index 4e813494d7d32..d97ab146e000d 100644 --- a/x-pack/plugins/lens/public/pie_visualization/render_function.tsx +++ b/x-pack/plugins/lens/public/pie_visualization/render_function.tsx @@ -33,6 +33,7 @@ import { EmptyPlaceholder } from '../shared_components'; import './visualization.scss'; import { desanitizeFilterContext } from '../utils'; import { ChartsPluginSetup } from '../../../../../src/plugins/charts/public'; +import { LensIconChartDonut } from '../assets/chart_donut'; const EMPTY_SLICE = Symbol('empty_slice'); @@ -186,7 +187,7 @@ export function PieComponent( const percentFormatter = props.formatFactory({ id: 'percent', params: { - pattern: `0,0.${'0'.repeat(percentDecimals ?? DEFAULT_PERCENT_DECIMALS)}%`, + pattern: `0,0.[${'0'.repeat(percentDecimals ?? DEFAULT_PERCENT_DECIMALS)}]%`, }, }); @@ -210,7 +211,7 @@ export function PieComponent( ); if (isEmpty) { - return ; + return ; } if (hasNegative) { diff --git a/x-pack/plugins/lens/public/pie_visualization/toolbar.tsx b/x-pack/plugins/lens/public/pie_visualization/toolbar.tsx index 501a2de24d9ad..9ee37fdf53a92 100644 --- a/x-pack/plugins/lens/public/pie_visualization/toolbar.tsx +++ b/x-pack/plugins/lens/public/pie_visualization/toolbar.tsx @@ -188,10 +188,10 @@ export function PieToolbar(props: VisualizationToolbarProps = DatasourceDimensionPro export type DatasourceDimensionTriggerProps = DatasourceDimensionProps & { dragDropContext: DragContextState; - togglePopover: () => void; + onClick: () => void; }; export interface DatasourceLayerPanelProps { @@ -417,8 +417,7 @@ export interface FramePublicAPI { export interface VisualizationType { id: string; - icon?: IconType; - largeIcon?: IconType; + icon: IconType; label: string; } diff --git a/x-pack/plugins/lens/public/xy_visualization/__snapshots__/xy_expression.test.tsx.snap b/x-pack/plugins/lens/public/xy_visualization/__snapshots__/xy_expression.test.tsx.snap index 79d3528eef4c4..ca6ca9b2722fd 100644 --- a/x-pack/plugins/lens/public/xy_visualization/__snapshots__/xy_expression.test.tsx.snap +++ b/x-pack/plugins/lens/public/xy_visualization/__snapshots__/xy_expression.test.tsx.snap @@ -26,6 +26,7 @@ exports[`xy_expression XYChart component it renders area 1`] = ` "visible": true, } } + hide={false} id="x" position="bottom" style={ @@ -65,6 +66,14 @@ exports[`xy_expression XYChart component it renders area 1`] = ` title="a" /> yAxisConfig.forAccessor === accessor)?.axisMode || 'auto'; - const formatter: SerializedFieldFormat = table.columns.find( - (column) => column.id === accessor - )?.formatHint || { id: 'number' }; + let formatter: SerializedFieldFormat = table.columns.find((column) => column.id === accessor) + ?.formatHint || { id: 'number' }; + if (layer.seriesType.includes('percentage') && formatter.id !== 'percent') { + formatter = { + id: 'percent', + params: { + pattern: '0.[00]%', + }, + }; + } series[mode].push({ layer: layer.layerId, accessor, diff --git a/x-pack/plugins/lens/public/xy_visualization/state_helpers.ts b/x-pack/plugins/lens/public/xy_visualization/state_helpers.ts index 2ddb9418abad9..41d18e5199e4c 100644 --- a/x-pack/plugins/lens/public/xy_visualization/state_helpers.ts +++ b/x-pack/plugins/lens/public/xy_visualization/state_helpers.ts @@ -8,7 +8,11 @@ import { EuiIconType } from '@elastic/eui/src/components/icon/icon'; import { SeriesType, visualizationTypes, LayerConfig, YConfig } from './types'; export function isHorizontalSeries(seriesType: SeriesType) { - return seriesType === 'bar_horizontal' || seriesType === 'bar_horizontal_stacked'; + return ( + seriesType === 'bar_horizontal' || + seriesType === 'bar_horizontal_stacked' || + seriesType === 'bar_horizontal_percentage_stacked' + ); } export function isHorizontalChart(layers: Array<{ seriesType: SeriesType }>) { diff --git a/x-pack/plugins/lens/public/xy_visualization/to_expression.test.ts b/x-pack/plugins/lens/public/xy_visualization/to_expression.test.ts index f579085646f6f..825281d6d88c2 100644 --- a/x-pack/plugins/lens/public/xy_visualization/to_expression.test.ts +++ b/x-pack/plugins/lens/public/xy_visualization/to_expression.test.ts @@ -100,25 +100,26 @@ describe('#toExpression', () => { expect(expression.chain[0].arguments.showYAxisTitle[0]).toBe(true); }); - it('should not generate an expression when missing x', () => { - expect( - xyVisualization.toExpression( - { - legend: { position: Position.Bottom, isVisible: true }, - preferredSeriesType: 'bar', - layers: [ - { - layerId: 'first', - seriesType: 'area', - splitAccessor: undefined, - xAccessor: undefined, - accessors: ['a'], - }, - ], - }, - frame.datasourceLayers - ) - ).toBeNull(); + it('should generate an expression without x accessor', () => { + const expression = xyVisualization.toExpression( + { + legend: { position: Position.Bottom, isVisible: true }, + preferredSeriesType: 'bar', + layers: [ + { + layerId: 'first', + seriesType: 'area', + splitAccessor: undefined, + xAccessor: undefined, + accessors: ['a'], + }, + ], + }, + frame.datasourceLayers + ) as Ast; + expect((expression.chain[0].arguments.layers[0] as Ast).chain[0].arguments.xAccessor).toEqual( + [] + ); }); it('should not generate an expression when missing y', () => { diff --git a/x-pack/plugins/lens/public/xy_visualization/to_expression.ts b/x-pack/plugins/lens/public/xy_visualization/to_expression.ts index cd32d4f94c3e5..f64624776186d 100644 --- a/x-pack/plugins/lens/public/xy_visualization/to_expression.ts +++ b/x-pack/plugins/lens/public/xy_visualization/to_expression.ts @@ -84,7 +84,7 @@ export const buildExpression = ( datasourceLayers?: Record ): Ast | null => { const validLayers = state.layers.filter((layer): layer is ValidLayer => - Boolean(layer.xAccessor && layer.accessors.length) + Boolean(layer.accessors.length) ); if (!validLayers.length) { return null; @@ -187,7 +187,7 @@ export const buildExpression = ( hide: [Boolean(layer.hide)], - xAccessor: [layer.xAccessor], + xAccessor: layer.xAccessor ? [layer.xAccessor] : [], yScaleType: [ getScaleType(metadata[layer.layerId][layer.accessors[0]], ScaleType.Ordinal), ], diff --git a/x-pack/plugins/lens/public/xy_visualization/types.ts b/x-pack/plugins/lens/public/xy_visualization/types.ts index 2739ffe42f13f..8438b1f27dd0d 100644 --- a/x-pack/plugins/lens/public/xy_visualization/types.ts +++ b/x-pack/plugins/lens/public/xy_visualization/types.ts @@ -7,13 +7,16 @@ import { Position } from '@elastic/charts'; import { i18n } from '@kbn/i18n'; import { ArgumentType, ExpressionFunctionDefinition } from 'src/plugins/expressions/common'; -import chartAreaSVG from '../assets/chart_area.svg'; -import chartAreaStackedSVG from '../assets/chart_area_stacked.svg'; -import chartBarSVG from '../assets/chart_bar.svg'; -import chartBarStackedSVG from '../assets/chart_bar_stacked.svg'; -import chartBarHorizontalSVG from '../assets/chart_bar_horizontal.svg'; -import chartBarHorizontalStackedSVG from '../assets/chart_bar_horizontal_stacked.svg'; -import chartLineSVG from '../assets/chart_line.svg'; +import { LensIconChartArea } from '../assets/chart_area'; +import { LensIconChartAreaStacked } from '../assets/chart_area_stacked'; +import { LensIconChartAreaPercentage } from '../assets/chart_area_percentage'; +import { LensIconChartBar } from '../assets/chart_bar'; +import { LensIconChartBarStacked } from '../assets/chart_bar_stacked'; +import { LensIconChartBarPercentage } from '../assets/chart_bar_percentage'; +import { LensIconChartBarHorizontal } from '../assets/chart_bar_horizontal'; +import { LensIconChartBarHorizontalStacked } from '../assets/chart_bar_horizontal_stacked'; +import { LensIconChartBarHorizontalPercentage } from '../assets/chart_bar_horizontal_percentage'; +import { LensIconChartLine } from '../assets/chart_line'; import { VisualizationType } from '../index'; import { FittingFunction } from './fitting_functions'; @@ -230,7 +233,15 @@ export const layerConfig: ExpressionFunctionDefinition< }, seriesType: { types: ['string'], - options: ['bar', 'line', 'area', 'bar_stacked', 'area_stacked'], + options: [ + 'bar', + 'line', + 'area', + 'bar_stacked', + 'area_stacked', + 'bar_percentage_stacked', + 'area_percentage_stacked', + ], help: 'The type of chart to display.', }, xScaleType: { @@ -283,8 +294,11 @@ export type SeriesType = | 'line' | 'area' | 'bar_stacked' + | 'bar_percentage_stacked' | 'bar_horizontal_stacked' - | 'area_stacked'; + | 'bar_horizontal_percentage_stacked' + | 'area_stacked' + | 'area_percentage_stacked'; export type YAxisMode = 'auto' | 'left' | 'right'; @@ -343,58 +357,72 @@ export type State = XYState; export const visualizationTypes: VisualizationType[] = [ { id: 'bar', - icon: 'visBarVertical', - largeIcon: chartBarSVG, + icon: LensIconChartBar, label: i18n.translate('xpack.lens.xyVisualization.barLabel', { defaultMessage: 'Bar', }), }, { id: 'bar_horizontal', - icon: 'visBarHorizontal', - largeIcon: chartBarHorizontalSVG, + icon: LensIconChartBarHorizontal, label: i18n.translate('xpack.lens.xyVisualization.barHorizontalLabel', { defaultMessage: 'Horizontal bar', }), }, { id: 'bar_stacked', - icon: 'visBarVerticalStacked', - largeIcon: chartBarStackedSVG, + icon: LensIconChartBarStacked, label: i18n.translate('xpack.lens.xyVisualization.stackedBarLabel', { defaultMessage: 'Stacked bar', }), }, + { + id: 'bar_percentage_stacked', + icon: LensIconChartBarPercentage, + label: i18n.translate('xpack.lens.xyVisualization.stackedPercentageBarLabel', { + defaultMessage: 'Bar percentage', + }), + }, { id: 'bar_horizontal_stacked', - icon: 'visBarHorizontalStacked', - largeIcon: chartBarHorizontalStackedSVG, + icon: LensIconChartBarHorizontalStacked, label: i18n.translate('xpack.lens.xyVisualization.stackedBarHorizontalLabel', { defaultMessage: 'Stacked horizontal bar', }), }, { - id: 'line', - icon: 'visLine', - largeIcon: chartLineSVG, - label: i18n.translate('xpack.lens.xyVisualization.lineLabel', { - defaultMessage: 'Line', + id: 'bar_horizontal_percentage_stacked', + icon: LensIconChartBarHorizontalPercentage, + label: i18n.translate('xpack.lens.xyVisualization.stackedPercentageBarHorizontalLabel', { + defaultMessage: 'Horizontal bar percentage', }), }, { id: 'area', - icon: 'visArea', - largeIcon: chartAreaSVG, + icon: LensIconChartArea, label: i18n.translate('xpack.lens.xyVisualization.areaLabel', { defaultMessage: 'Area', }), }, { id: 'area_stacked', - icon: 'visAreaStacked', - largeIcon: chartAreaStackedSVG, + icon: LensIconChartAreaStacked, label: i18n.translate('xpack.lens.xyVisualization.stackedAreaLabel', { defaultMessage: 'Stacked area', }), }, + { + id: 'area_percentage_stacked', + icon: LensIconChartAreaPercentage, + label: i18n.translate('xpack.lens.xyVisualization.stackedPercentageAreaLabel', { + defaultMessage: 'Area percentage', + }), + }, + { + id: 'line', + icon: LensIconChartLine, + label: i18n.translate('xpack.lens.xyVisualization.lineLabel', { + defaultMessage: 'Line', + }), + }, ]; diff --git a/x-pack/plugins/lens/public/xy_visualization/xy_config_panel.test.tsx b/x-pack/plugins/lens/public/xy_visualization/xy_config_panel.test.tsx index e80bb22c04a69..89a2574026ced 100644 --- a/x-pack/plugins/lens/public/xy_visualization/xy_config_panel.test.tsx +++ b/x-pack/plugins/lens/public/xy_visualization/xy_config_panel.test.tsx @@ -59,9 +59,11 @@ describe('XY Config panels', () => { expect(options!.map(({ id }) => id)).toEqual([ 'bar', 'bar_stacked', - 'line', + 'bar_percentage_stacked', 'area', 'area_stacked', + 'area_percentage_stacked', + 'line', ]); expect(options!.filter(({ isDisabled }) => isDisabled).map(({ id }) => id)).toEqual([]); @@ -83,7 +85,11 @@ describe('XY Config panels', () => { .first() .prop('options') as EuiButtonGroupProps['options']; - expect(options!.map(({ id }) => id)).toEqual(['bar_horizontal', 'bar_horizontal_stacked']); + expect(options!.map(({ id }) => id)).toEqual([ + 'bar_horizontal', + 'bar_horizontal_stacked', + 'bar_horizontal_percentage_stacked', + ]); expect(options!.filter(({ isDisabled }) => isDisabled).map(({ id }) => id)).toEqual([]); }); }); diff --git a/x-pack/plugins/lens/public/xy_visualization/xy_config_panel.tsx b/x-pack/plugins/lens/public/xy_visualization/xy_config_panel.tsx index a2488d123e13a..62fd6e013f20d 100644 --- a/x-pack/plugins/lens/public/xy_visualization/xy_config_panel.tsx +++ b/x-pack/plugins/lens/public/xy_visualization/xy_config_panel.tsx @@ -114,7 +114,6 @@ export function LayerContextMenu(props: VisualizationLayerWidgetProps) { ); }} isIconOnly - buttonSize="compressed" /> ); diff --git a/x-pack/plugins/lens/public/xy_visualization/xy_expression.tsx b/x-pack/plugins/lens/public/xy_visualization/xy_expression.tsx index 31873228fb394..a8c7c8daaf58b 100644 --- a/x-pack/plugins/lens/public/xy_visualization/xy_expression.tsx +++ b/x-pack/plugins/lens/public/xy_visualization/xy_expression.tsx @@ -17,6 +17,7 @@ import { Position, GeometryValue, XYChartSeriesIdentifier, + StackMode, } from '@elastic/charts'; import { I18nProvider } from '@kbn/i18n/react'; import { @@ -229,11 +230,10 @@ export function XYChart({ const filteredLayers = layers.filter(({ layerId, xAccessor, accessors }) => { return !( - !xAccessor || !accessors.length || !data.tables[layerId] || data.tables[layerId].rows.length === 0 || - data.tables[layerId].rows.every((row) => typeof row[xAccessor] === 'undefined') + (xAccessor && data.tables[layerId].rows.every((row) => typeof row[xAccessor] === 'undefined')) ); }); @@ -425,7 +425,7 @@ export function XYChart({ visible: gridlinesVisibilitySettings?.x, strokeWidth: 2, }} - hide={filteredLayers[0].hide} + hide={filteredLayers[0].hide || !filteredLayers[0].xAccessor} tickFormat={(d) => xAxisFormatter.convert(d)} style={{ tickLabel: { @@ -483,8 +483,7 @@ export function XYChart({ // To not display them in the legend, they need to be filtered out. const rows = table.rows.filter( (row) => - xAccessor && - typeof row[xAccessor] !== 'undefined' && + !(xAccessor && typeof row[xAccessor] === 'undefined') && !( splitAccessor && typeof row[splitAccessor] === 'undefined' && @@ -492,21 +491,42 @@ export function XYChart({ ) ); + if (!xAccessor) { + rows.forEach((row) => { + row.unifiedX = i18n.translate('xpack.lens.xyChart.emptyXLabel', { + defaultMessage: '(empty)', + }); + }); + } + const seriesProps: SeriesSpec = { splitSeriesAccessors: splitAccessor ? [splitAccessor] : [], stackAccessors: seriesType.includes('stacked') ? [xAccessor as string] : [], id: `${splitAccessor}-${accessor}`, - xAccessor, + xAccessor: xAccessor || 'unifiedX', yAccessors: [accessor], data: rows, - xScaleType, + xScaleType: xAccessor ? xScaleType : 'ordinal', yScaleType, color: () => getSeriesColor(layer, accessor), groupId: yAxesConfiguration.find((axisConfiguration) => axisConfiguration.series.find((currentSeries) => currentSeries.accessor === accessor) )?.groupId, enableHistogramMode: isHistogram && (seriesType.includes('stacked') || !splitAccessor), + stackMode: seriesType.includes('percentage') ? StackMode.Percentage : undefined, timeZone, + areaSeriesStyle: { + point: { + visible: !xAccessor, + radius: 5, + }, + }, + lineSeriesStyle: { + point: { + visible: !xAccessor, + radius: 5, + }, + }, name(d) { const splitHint = table.columns.find((col) => col.id === splitAccessor)?.formatHint; @@ -545,10 +565,13 @@ export function XYChart({ ); case 'bar': case 'bar_stacked': + case 'bar_percentage_stacked': case 'bar_horizontal': case 'bar_horizontal_stacked': + case 'bar_horizontal_percentage_stacked': return ; case 'area_stacked': + case 'area_percentage_stacked': return ( ); diff --git a/x-pack/plugins/lens/public/xy_visualization/xy_suggestions.test.ts b/x-pack/plugins/lens/public/xy_visualization/xy_suggestions.test.ts index 79e4ed6958193..ea5cff80695a3 100644 --- a/x-pack/plugins/lens/public/xy_visualization/xy_suggestions.test.ts +++ b/x-pack/plugins/lens/public/xy_visualization/xy_suggestions.test.ts @@ -119,6 +119,51 @@ describe('xy_suggestions', () => { ); }); + test('suggests all xy charts without changes to the state when switching among xy charts with malformed table', () => { + (generateId as jest.Mock).mockReturnValueOnce('aaa'); + const suggestions = getSuggestions({ + table: { + isMultiRow: false, + columns: [numCol('bytes')], + layerId: 'first', + changeType: 'unchanged', + }, + keptLayerIds: [], + state: { + legend: { isVisible: true, position: 'bottom' }, + preferredSeriesType: 'bar', + layers: [ + { + layerId: 'first', + seriesType: 'bar', + accessors: ['bytes'], + splitAccessor: undefined, + }, + { + layerId: 'second', + seriesType: 'bar', + accessors: ['bytes'], + splitAccessor: undefined, + }, + ], + }, + }); + + expect(suggestions).toHaveLength(visualizationTypes.length); + expect(suggestions.map(({ state }) => xyVisualization.getVisualizationTypeId(state))).toEqual([ + 'bar', + 'bar_horizontal', + 'bar_stacked', + 'bar_percentage_stacked', + 'bar_horizontal_stacked', + 'bar_horizontal_percentage_stacked', + 'area', + 'area_stacked', + 'area_percentage_stacked', + 'line', + ]); + }); + test('suggests all basic x y charts when switching from another vis', () => { (generateId as jest.Mock).mockReturnValueOnce('aaa'); const suggestions = getSuggestions({ @@ -134,10 +179,13 @@ describe('xy_suggestions', () => { expect(suggestions).toHaveLength(visualizationTypes.length); expect(suggestions.map(({ state }) => xyVisualization.getVisualizationTypeId(state))).toEqual([ 'bar_stacked', + 'line', + 'area_percentage_stacked', 'area_stacked', 'area', - 'line', + 'bar_horizontal_percentage_stacked', 'bar_horizontal_stacked', + 'bar_percentage_stacked', 'bar_horizontal', 'bar', ]); @@ -157,13 +205,27 @@ describe('xy_suggestions', () => { }); expect(suggestions).toHaveLength(visualizationTypes.length); - expect(suggestions.map(({ state }) => state.layers.length)).toEqual([1, 1, 1, 1, 1, 1, 1]); + expect(suggestions.map(({ state }) => state.layers.length)).toEqual([ + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + ]); expect(suggestions.map(({ state }) => xyVisualization.getVisualizationTypeId(state))).toEqual([ 'bar_stacked', + 'line', + 'area_percentage_stacked', 'area_stacked', 'area', - 'line', + 'bar_horizontal_percentage_stacked', 'bar_horizontal_stacked', + 'bar_percentage_stacked', 'bar_horizontal', 'bar', ]); @@ -200,9 +262,12 @@ describe('xy_suggestions', () => { 'bar', 'bar_horizontal', 'bar_stacked', + 'bar_percentage_stacked', 'bar_horizontal_stacked', + 'bar_horizontal_percentage_stacked', 'area', 'area_stacked', + 'area_percentage_stacked', ]); }); @@ -244,9 +309,12 @@ describe('xy_suggestions', () => { 'bar', 'bar_horizontal', 'bar_stacked', + 'bar_percentage_stacked', 'bar_horizontal_stacked', + 'bar_horizontal_percentage_stacked', 'area', 'area_stacked', + 'area_percentage_stacked', ]); expect(suggestions.map(({ state }) => state.layers.map((l) => l.layerId))).toEqual([ ['first', 'second'], @@ -256,6 +324,9 @@ describe('xy_suggestions', () => { ['first', 'second'], ['first', 'second'], ['first', 'second'], + ['first', 'second'], + ['first', 'second'], + ['first', 'second'], ]); }); diff --git a/x-pack/plugins/lens/public/xy_visualization/xy_suggestions.ts b/x-pack/plugins/lens/public/xy_visualization/xy_suggestions.ts index 75dd5a7a579b8..42fc538874b93 100644 --- a/x-pack/plugins/lens/public/xy_visualization/xy_suggestions.ts +++ b/x-pack/plugins/lens/public/xy_visualization/xy_suggestions.ts @@ -45,6 +45,24 @@ export function getSuggestions({ table.columns.every((col) => col.operation.dataType !== 'number') || table.columns.some((col) => !columnSortOrder.hasOwnProperty(col.operation.dataType)) ) { + if (table.changeType === 'unchanged' && state) { + // this isn't a table we would switch to, but we have a state already. In this case, just use the current state for all series types + return visualizationTypes.map((visType) => { + const seriesType = visType.id as SeriesType; + return { + seriesType, + score: 0, + state: { + ...state, + preferredSeriesType: seriesType, + layers: state.layers.map((layer) => ({ ...layer, seriesType })), + }, + previewIcon: getIconForSeries(seriesType), + title: visType.label, + hide: true, + }; + }); + } return []; } @@ -91,6 +109,25 @@ function getSuggestionForColumns( } } +function flipSeriesType(seriesType: SeriesType) { + switch (seriesType) { + case 'bar_horizontal': + return 'bar'; + case 'bar_horizontal_stacked': + return 'bar_stacked'; + case 'bar': + return 'bar_horizontal'; + case 'bar_horizontal_stacked': + return 'bar_stacked'; + case 'bar_horizontal_percentage_stacked': + return 'bar_percentage_stacked'; + case 'bar_percentage_stacked': + return 'bar_horizontal_percentage_stacked'; + default: + return 'bar_horizontal'; + } +} + function getBucketMappings(table: TableSuggestion, currentState?: State) { const currentLayer = currentState && currentState.layers.find(({ layerId }) => layerId === table.layerId); @@ -156,7 +193,7 @@ function getSuggestionsForLayer({ }: { layerId: string; changeType: TableChangeType; - xValue: TableSuggestionColumn; + xValue?: TableSuggestionColumn; yValues: TableSuggestionColumn[]; splitBy?: TableSuggestionColumn; currentState?: State; @@ -164,7 +201,7 @@ function getSuggestionsForLayer({ keptLayerIds: string[]; }): VisualizationSuggestion | Array> { const title = getSuggestionTitle(yValues, xValue, tableLabel); - const seriesType: SeriesType = getSeriesType(currentState, layerId, xValue, changeType); + const seriesType: SeriesType = getSeriesType(currentState, layerId, xValue); const options = { currentState, @@ -182,11 +219,13 @@ function getSuggestionsForLayer({ if (!currentState && changeType === 'unchanged') { // Chart switcher needs to include every chart type return visualizationTypes - .map((visType) => ({ - ...buildSuggestion({ ...options, seriesType: visType.id as SeriesType }), - title: visType.label, - hide: visType.id !== 'bar_stacked', - })) + .map((visType) => { + return { + ...buildSuggestion({ ...options, seriesType: visType.id as SeriesType }), + title: visType.label, + hide: visType.id !== 'bar_stacked', + }; + }) .sort((a, b) => (a.state.preferredSeriesType === 'bar_stacked' ? -1 : 1)); } @@ -199,18 +238,13 @@ function getSuggestionsForLayer({ const sameStateSuggestions: Array> = []; // if current state is using the same data, suggest same chart with different presentational configuration - if (seriesType !== 'line' && xValue.operation.scale === 'ordinal') { + if (seriesType.includes('bar') && (!xValue || xValue.operation.scale === 'ordinal')) { // flip between horizontal/vertical for ordinal scales sameStateSuggestions.push( buildSuggestion({ ...options, title: i18n.translate('xpack.lens.xySuggestions.flipTitle', { defaultMessage: 'Flip' }), - seriesType: - seriesType === 'bar_horizontal' - ? 'bar' - : seriesType === 'bar_horizontal_stacked' - ? 'bar_stacked' - : 'bar_horizontal', + seriesType: flipSeriesType(seriesType), }) ); } else { @@ -231,7 +265,7 @@ function getSuggestionsForLayer({ ); } - if (seriesType !== 'line' && splitBy) { + if (seriesType !== 'line' && splitBy && !seriesType.includes('percentage')) { // flip between stacked/unstacked sameStateSuggestions.push( buildSuggestion({ @@ -248,6 +282,30 @@ function getSuggestionsForLayer({ ); } + if ( + seriesType !== 'line' && + seriesType.includes('stacked') && + !seriesType.includes('percentage') + ) { + const percentageOptions = { ...options }; + if (percentageOptions.xValue?.operation.scale === 'ordinal' && !percentageOptions.splitBy) { + percentageOptions.splitBy = percentageOptions.xValue; + delete percentageOptions.xValue; + } + // percentage suggestion + sameStateSuggestions.push( + buildSuggestion({ + ...options, + // hide the suggestion if split by is missing + hide: !percentageOptions.splitBy, + seriesType: asPercentageSeriesType(seriesType), + title: i18n.translate('xpack.lens.xySuggestions.asPercentageTitle', { + defaultMessage: 'Percentage', + }), + }) + ); + } + // Combine all pre-built suggestions with hidden suggestions for remaining chart types return sameStateSuggestions.concat( visualizationTypes @@ -280,6 +338,19 @@ function toggleStackSeriesType(oldSeriesType: SeriesType) { } } +function asPercentageSeriesType(oldSeriesType: SeriesType) { + switch (oldSeriesType) { + case 'area_stacked': + return 'area_percentage_stacked'; + case 'bar_stacked': + return 'bar_percentage_stacked'; + case 'bar_horizontal_stacked': + return 'bar_horizontal_percentage_stacked'; + default: + return oldSeriesType; + } +} + // Until the area chart rendering bug is fixed, avoid suggesting area charts // https://github.com/elastic/elastic-charts/issues/388 function altSeriesType(oldSeriesType: SeriesType) { @@ -301,8 +372,7 @@ function altSeriesType(oldSeriesType: SeriesType) { function getSeriesType( currentState: XYState | undefined, layerId: string, - xValue: TableSuggestionColumn, - changeType: TableChangeType + xValue?: TableSuggestionColumn ): SeriesType { const defaultType = 'bar_stacked'; @@ -314,7 +384,7 @@ function getSeriesType( // Attempt to keep the seriesType consistent on initial add of a layer // Ordinal scales should always use a bar because there is no interpolation between buckets - if (xValue.operation.scale && xValue.operation.scale === 'ordinal') { + if (xValue && xValue.operation.scale && xValue.operation.scale === 'ordinal') { return closestSeriesType.startsWith('bar') ? closestSeriesType : defaultType; } @@ -323,7 +393,7 @@ function getSeriesType( function getSuggestionTitle( yValues: TableSuggestionColumn[], - xValue: TableSuggestionColumn, + xValue: TableSuggestionColumn | undefined, tableLabel: string | undefined ) { const yTitle = yValues @@ -335,10 +405,14 @@ function getSuggestionTitle( 'A character that can be used for conjunction of multiple enumarated items. Make sure to include spaces around it if needed.', }) ); - const xTitle = xValue.operation.label; + const xTitle = + xValue?.operation.label || + i18n.translate('xpack.lens.xySuggestions.emptyAxisTitle', { + defaultMessage: '(empty)', + }); const title = tableLabel || - (xValue.operation.dataType === 'date' + (xValue?.operation.dataType === 'date' ? i18n.translate('xpack.lens.xySuggestions.dateSuggestion', { defaultMessage: '{yTitle} over {xTitle}', description: @@ -364,24 +438,30 @@ function buildSuggestion({ changeType, xValue, keptLayerIds, + hide, }: { currentState: XYState | undefined; seriesType: SeriesType; title: string; yValues: TableSuggestionColumn[]; - xValue: TableSuggestionColumn; + xValue?: TableSuggestionColumn; splitBy: TableSuggestionColumn | undefined; layerId: string; changeType: TableChangeType; keptLayerIds: string[]; + hide?: boolean; }) { + if (seriesType.includes('percentage') && xValue?.operation.scale === 'ordinal' && !splitBy) { + splitBy = xValue; + xValue = undefined; + } const existingLayer: LayerConfig | {} = getExistingLayer(currentState, layerId) || {}; const accessors = yValues.map((col) => col.columnId); const newLayer = { ...existingLayer, layerId, seriesType, - xAccessor: xValue.columnId, + xAccessor: xValue?.columnId, splitAccessor: splitBy?.columnId, accessors, yConfig: @@ -427,10 +507,11 @@ function buildSuggestion({ title, score: getScore(yValues, splitBy, changeType), hide: + hide ?? // Only advertise very clear changes when XY chart is not active - (!currentState && changeType !== 'unchanged' && changeType !== 'extended') || - // Don't advertise removing dimensions - (currentState && changeType === 'reduced'), + ((!currentState && changeType !== 'unchanged' && changeType !== 'extended') || + // Don't advertise removing dimensions + (currentState && changeType === 'reduced')), state, previewIcon: getIconForSeries(seriesType), }; diff --git a/x-pack/plugins/lens/public/xy_visualization/xy_visualization.test.ts b/x-pack/plugins/lens/public/xy_visualization/xy_visualization.test.ts index 53f7a23dcae98..7cf1830cdc2fa 100644 --- a/x-pack/plugins/lens/public/xy_visualization/xy_visualization.test.ts +++ b/x-pack/plugins/lens/public/xy_visualization/xy_visualization.test.ts @@ -9,6 +9,7 @@ import { Position } from '@elastic/charts'; import { Operation } from '../types'; import { State, SeriesType } from './types'; import { createMockDatasource, createMockFramePublicAPI } from '../editor_frame_service/mocks'; +import { LensIconChartBar } from '../assets/chart_bar'; function exampleState(): State { return { @@ -49,9 +50,7 @@ describe('xy_visualization', () => { it('should show the preferredSeriesType if there are no layers', () => { const desc = xyVisualization.getDescription(mixedState()); - // 'test-file-stub' is a hack, but it at least means we aren't using - // a standard icon here. - expect(desc.icon).toEqual('test-file-stub'); + expect(desc.icon).toEqual(LensIconChartBar); expect(desc.label).toEqual('Bar chart'); }); diff --git a/x-pack/plugins/lens/public/xy_visualization/xy_visualization.tsx b/x-pack/plugins/lens/public/xy_visualization/xy_visualization.tsx index 8c551c575764e..0b8f7e2ed0f11 100644 --- a/x-pack/plugins/lens/public/xy_visualization/xy_visualization.tsx +++ b/x-pack/plugins/lens/public/xy_visualization/xy_visualization.tsx @@ -14,12 +14,13 @@ import { getSuggestions } from './xy_suggestions'; import { LayerContextMenu, XyToolbar, DimensionEditor } from './xy_config_panel'; import { Visualization, OperationMetadata, VisualizationType } from '../types'; import { State, SeriesType, visualizationTypes, LayerConfig } from './types'; -import chartBarStackedSVG from '../assets/chart_bar_stacked.svg'; -import chartMixedSVG from '../assets/chart_mixed_xy.svg'; import { isHorizontalChart } from './state_helpers'; import { toExpression, toPreviewExpression } from './to_expression'; +import { LensIconChartBarStacked } from '../assets/chart_bar_stacked'; +import { LensIconChartMixedXy } from '../assets/chart_mixed_xy'; +import { LensIconChartBarHorizontal } from '../assets/chart_bar_horizontal'; -const defaultIcon = chartBarStackedSVG; +const defaultIcon = LensIconChartBarStacked; const defaultSeriesType = 'bar_stacked'; const isNumericMetric = (op: OperationMetadata) => !op.isBucketed && op.dataType === 'number'; const isBucketed = (op: OperationMetadata) => op.isBucketed; @@ -48,29 +49,27 @@ function getDescription(state?: State) { const visualizationType = getVisualizationType(state); - if (!state.layers.length) { - const preferredType = visualizationType as VisualizationType; + if (visualizationType === 'mixed' && isHorizontalChart(state.layers)) { + return { + icon: LensIconChartBarHorizontal, + label: i18n.translate('xpack.lens.xyVisualization.mixedBarHorizontalLabel', { + defaultMessage: 'Mixed horizontal bar', + }), + }; + } + + if (visualizationType === 'mixed') { return { - icon: preferredType.largeIcon || preferredType.icon, - label: preferredType.label, + icon: LensIconChartMixedXy, + label: i18n.translate('xpack.lens.xyVisualization.mixedLabel', { + defaultMessage: 'Mixed XY', + }), }; } return { - icon: - visualizationType === 'mixed' - ? chartMixedSVG - : visualizationType.largeIcon || visualizationType.icon, - label: - visualizationType === 'mixed' - ? isHorizontalChart(state.layers) - ? i18n.translate('xpack.lens.xyVisualization.mixedBarHorizontalLabel', { - defaultMessage: 'Mixed horizontal bar', - }) - : i18n.translate('xpack.lens.xyVisualization.mixedLabel', { - defaultMessage: 'Mixed XY', - }) - : visualizationType.label, + icon: visualizationType.icon, + label: visualizationType.label, }; } @@ -172,7 +171,7 @@ export const xyVisualization: Visualization = { filterOperations: isBucketed, suggestedPriority: 1, supportsMoreColumns: !layer.xAccessor, - required: true, + required: !layer.seriesType.includes('percentage'), dataTestSubj: 'lnsXY_xDimensionPanel', }, { @@ -197,6 +196,7 @@ export const xyVisualization: Visualization = { suggestedPriority: 0, supportsMoreColumns: !layer.splitAccessor, dataTestSubj: 'lnsXY_splitDimensionPanel', + required: layer.seriesType.includes('percentage'), }, ], }; diff --git a/x-pack/plugins/lens/readme.md b/x-pack/plugins/lens/readme.md index e69ba9ec9506d..98bb60827af42 100644 --- a/x-pack/plugins/lens/readme.md +++ b/x-pack/plugins/lens/readme.md @@ -30,7 +30,7 @@ Lens has a lot of UI elements – to make it easier to refer to them in issues o * **Config panel** Panel to the right showing configuration of the current chart, separated by layers * **Layer panel** One of multiple panels in the config panel, holding configuration for separate layers * **Dimension trigger** Chart dimension like "X axis", "Break down by" or "Slice by" in the config panel - * **Dimension popover** Popover shown when clicking a dimension trigger + * **Dimension container** Container shown when clicking a dimension trigger and contains the dimension settints * **Layer settings popover** Popover shown when clicking the button in the top left of a layer panel * **Workspace panel** Center panel containing the chart preview, title and toolbar * **Chart preview** Full-sized rendered chart in the center of the screen diff --git a/x-pack/plugins/security/public/account_management/account_management_page.test.tsx b/x-pack/plugins/security/public/account_management/account_management_page.test.tsx index e58d8e8421547..b677f6a1fe8bb 100644 --- a/x-pack/plugins/security/public/account_management/account_management_page.test.tsx +++ b/x-pack/plugins/security/public/account_management/account_management_page.test.tsx @@ -115,8 +115,8 @@ describe('', () => { wrapper.update(); }); - expect(wrapper.find('EuiFieldText[data-test-subj="currentPassword"]')).toHaveLength(1); - expect(wrapper.find('EuiFieldText[data-test-subj="newPassword"]')).toHaveLength(1); + expect(wrapper.find('EuiFieldPassword[data-test-subj="currentPassword"]')).toHaveLength(1); + expect(wrapper.find('EuiFieldPassword[data-test-subj="newPassword"]')).toHaveLength(1); }); it(`does not display change password form for users in the saml realm`, async () => { diff --git a/x-pack/plugins/security/public/authentication/login/components/login_form/__snapshots__/login_form.test.tsx.snap b/x-pack/plugins/security/public/authentication/login/components/login_form/__snapshots__/login_form.test.tsx.snap index 08f8034538ac3..99780542b97f4 100644 --- a/x-pack/plugins/security/public/authentication/login/components/login_form/__snapshots__/login_form.test.tsx.snap +++ b/x-pack/plugins/security/public/authentication/login/components/login_form/__snapshots__/login_form.test.tsx.snap @@ -166,6 +166,7 @@ exports[`LoginForm renders as expected 1`] = ` isLoading={false} name="password" onChange={[Function]} + type="dual" value="" /> diff --git a/x-pack/plugins/security/public/authentication/login/components/login_form/login_form.tsx b/x-pack/plugins/security/public/authentication/login/components/login_form/login_form.tsx index a929b50fa1ffa..901d43adb659d 100644 --- a/x-pack/plugins/security/public/authentication/login/components/login_form/login_form.tsx +++ b/x-pack/plugins/security/public/authentication/login/components/login_form/login_form.tsx @@ -221,6 +221,7 @@ export class LoginForm extends Component { id="password" name="password" data-test-subj="loginPassword" + type={'dual'} value={this.state.password} onChange={this.onPasswordChange} disabled={!this.isLoadingState(LoadingStateType.None)} diff --git a/x-pack/plugins/security/public/management/users/components/change_password_form/change_password_form.test.tsx b/x-pack/plugins/security/public/management/users/components/change_password_form/change_password_form.test.tsx index d41a05e00e53c..43eb32853cf63 100644 --- a/x-pack/plugins/security/public/management/users/components/change_password_form/change_password_form.test.tsx +++ b/x-pack/plugins/security/public/management/users/components/change_password_form/change_password_form.test.tsx @@ -3,7 +3,7 @@ * or more contributor license agreements. Licensed under the Elastic License; * you may not use this file except in compliance with the Elastic License. */ -import { EuiFieldText } from '@elastic/eui'; +import { EuiFieldPassword } from '@elastic/eui'; import { ReactWrapper } from 'enzyme'; import React from 'react'; import { mountWithIntl } from 'test_utils/enzyme_helpers'; @@ -14,15 +14,15 @@ import { coreMock } from '../../../../../../../../src/core/public/mocks'; import { userAPIClientMock } from '../../index.mock'; function getCurrentPasswordField(wrapper: ReactWrapper) { - return wrapper.find(EuiFieldText).filter('[data-test-subj="currentPassword"]'); + return wrapper.find(EuiFieldPassword).filter('[data-test-subj="currentPassword"]'); } function getNewPasswordField(wrapper: ReactWrapper) { - return wrapper.find(EuiFieldText).filter('[data-test-subj="newPassword"]'); + return wrapper.find(EuiFieldPassword).filter('[data-test-subj="newPassword"]'); } function getConfirmPasswordField(wrapper: ReactWrapper) { - return wrapper.find(EuiFieldText).filter('[data-test-subj="confirmNewPassword"]'); + return wrapper.find(EuiFieldPassword).filter('[data-test-subj="confirmNewPassword"]'); } describe('', () => { diff --git a/x-pack/plugins/security/public/management/users/components/change_password_form/change_password_form.tsx b/x-pack/plugins/security/public/management/users/components/change_password_form/change_password_form.tsx index 296a8f6c8693f..5d889abdf46ce 100644 --- a/x-pack/plugins/security/public/management/users/components/change_password_form/change_password_form.tsx +++ b/x-pack/plugins/security/public/management/users/components/change_password_form/change_password_form.tsx @@ -6,7 +6,7 @@ import { EuiButton, EuiButtonEmpty, - EuiFieldText, + EuiFieldPassword, EuiFlexGroup, EuiFlexItem, EuiForm, @@ -72,10 +72,10 @@ export class ChangePasswordForm extends Component { /> } > - { /> } > - { /> } > - { + if (value == null) { + return getOrEmptyTagFromValue(value); + } + const maybeDate = getMaybeDate(value); + if (!maybeDate.isValid()) { + return getOrEmptyTagFromValue(value); + } + const date = maybeDate.toDate(); + return ; +}; + +PreferenceFormattedDateFromPrimitive.displayName = 'PreferenceFormattedDateFromPrimitive'; + /** * This function may be passed to `Array.find()` to locate the `P1DT` * configuration (sub) setting, a string array that contains two entries diff --git a/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/store/selectors.ts b/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/store/selectors.ts index 852bc9791fc90..a3eee8063d6f7 100644 --- a/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/store/selectors.ts +++ b/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/store/selectors.ts @@ -72,6 +72,12 @@ export const patternsError = (state: Immutable) => state.patterns const detailsPolicyAppliedResponse = (state: Immutable) => state.policyResponse && state.policyResponse.Endpoint.policy.applied; +/** + * Returns the policy response timestamp from the endpoint after a user modifies a policy. + */ +export const policyResponseTimestamp = (state: Immutable) => + state.policyResponse && state.policyResponse['@timestamp']; + /** * Returns the response configurations from the endpoint after a user modifies a policy. */ diff --git a/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/view/details/endpoint_details.tsx b/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/view/details/endpoint_details.tsx index b76b7e51b2c1b..47f4fbb8830ae 100644 --- a/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/view/details/endpoint_details.tsx +++ b/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/view/details/endpoint_details.tsx @@ -125,7 +125,7 @@ export const EndpointDetails = memo(({ details }: { details: HostMetadata }) => return [ { title: i18n.translate('xpack.securitySolution.endpoint.details.policy', { - defaultMessage: 'Integration', + defaultMessage: 'Integration Policy', }), description: ( <> @@ -140,7 +140,7 @@ export const EndpointDetails = memo(({ details }: { details: HostMetadata }) => }, { title: i18n.translate('xpack.securitySolution.endpoint.details.policyStatus', { - defaultMessage: 'Configuration response', + defaultMessage: 'Policy Response', }), description: ( diff --git a/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/view/details/index.tsx b/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/view/details/index.tsx index a37ddd0bd61d9..43d3b39474fc7 100644 --- a/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/view/details/index.tsx +++ b/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/view/details/index.tsx @@ -32,6 +32,7 @@ import { policyResponseFailedOrWarningActionCount, policyResponseError, policyResponseLoading, + policyResponseTimestamp, } from '../../store/selectors'; import { EndpointDetails } from './endpoint_details'; import { PolicyResponse } from './policy_response'; @@ -41,6 +42,7 @@ import { useNavigateByRouterEventHandler } from '../../../../../common/hooks/end import { getEndpointListPath } from '../../../../common/routing'; import { SecurityPageName } from '../../../../../app/types'; import { useFormatUrl } from '../../../../../common/components/link_to'; +import { PreferenceFormattedDateFromPrimitive } from '../../../../../common/components/formatted_date'; export const EndpointDetailsFlyout = memo(() => { const history = useHistory(); @@ -122,6 +124,7 @@ const PolicyResponseFlyoutPanel = memo<{ const loading = useEndpointSelector(policyResponseLoading); const error = useEndpointSelector(policyResponseError); const { formatUrl } = useFormatUrl(SecurityPageName.administration); + const responseTimestamp = useEndpointSelector(policyResponseTimestamp); const [detailsUri, detailsRoutePath] = useMemo( () => [ formatUrl( @@ -161,16 +164,21 @@ const PolicyResponseFlyoutPanel = memo<{

+ + + + + {error && ( } /> diff --git a/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/view/index.test.tsx b/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/view/index.test.tsx index 14167f25d5b90..2bdf17b806079 100644 --- a/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/view/index.test.tsx +++ b/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/view/index.test.tsx @@ -510,7 +510,7 @@ describe('when on the list page', () => { const renderResult = await renderAndWaitForData(); const linkToReassign = await renderResult.findByTestId('endpointDetailsLinkToIngest'); expect(linkToReassign).not.toBeNull(); - expect(linkToReassign.textContent).toEqual('Reassign Configuration'); + expect(linkToReassign.textContent).toEqual('Reassign Policy'); expect(linkToReassign.getAttribute('href')).toEqual( `/app/ingestManager#/fleet/agents/${agentId}/activity?openReassignFlyout=true` ); @@ -572,7 +572,7 @@ describe('when on the list page', () => { it('should include the sub-panel title', async () => { expect( (await renderResult.findByTestId('endpointDetailsPolicyResponseFlyoutTitle')).textContent - ).toBe('Configuration Response'); + ).toBe('Policy Response'); }); it('should show a configuration section for each protection', async () => { diff --git a/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/view/index.tsx b/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/view/index.tsx index 166f1660bf3d6..ecee2bee0c58b 100644 --- a/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/view/index.tsx +++ b/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/view/index.tsx @@ -270,17 +270,20 @@ export const EndpointList = () => { ); const toRouteUrl = formatUrl(toRoutePath); return ( - + + + ); }, }, { field: 'host_status', + width: '9%', name: i18n.translate('xpack.securitySolution.endpoint.list.hostStatus', { defaultMessage: 'Agent Status', }), @@ -303,27 +306,31 @@ export const EndpointList = () => { }, { field: 'metadata.Endpoint.policy.applied', + width: '15%', name: i18n.translate('xpack.securitySolution.endpoint.list.policy', { - defaultMessage: 'Integration', + defaultMessage: 'Integration Policy', }), truncateText: true, // eslint-disable-next-line react/display-name render: (policy: HostInfo['metadata']['Endpoint']['policy']['applied']) => { return ( - - {policy.name} - + + + {policy.name} + + ); }, }, { field: 'metadata.Endpoint.policy.applied', + width: '9%', name: i18n.translate('xpack.securitySolution.endpoint.list.policyStatus', { - defaultMessage: 'Configuration Status', + defaultMessage: 'Policy Status', }), render: (policy: HostInfo['metadata']['Endpoint']['policy']['applied'], item: HostInfo) => { const toRoutePath = getEndpointDetailsPath({ @@ -350,6 +357,7 @@ export const EndpointList = () => { }, { field: 'metadata.host.os.name', + width: '10%', name: i18n.translate('xpack.securitySolution.endpoint.list.os', { defaultMessage: 'Operating System', }), @@ -375,6 +383,7 @@ export const EndpointList = () => { }, { field: 'metadata.agent.version', + width: '5%', name: i18n.translate('xpack.securitySolution.endpoint.list.endpointVersion', { defaultMessage: 'Version', }), @@ -394,6 +403,7 @@ export const EndpointList = () => { }, { field: '', + width: '5%', name: i18n.translate('xpack.securitySolution.endpoint.list.actions', { defaultMessage: 'Actions', }), diff --git a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/hosts/details/__mocks__/index.ts b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/hosts/details/__mocks__/index.ts index 7403adfd9a659..dbd2591c8af7b 100644 --- a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/hosts/details/__mocks__/index.ts +++ b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/hosts/details/__mocks__/index.ts @@ -5,8 +5,11 @@ */ import { IEsSearchResponse } from '../../../../../../../../../../src/plugins/data/common'; import { + Direction, HostsQueries, HostDetailsRequestOptions, + SortField, + HostsFields, } from '../../../../../../../common/search_strategy'; export const mockOptions: HostDetailsRequestOptions = { @@ -421,8 +424,9 @@ export const mockOptions: HostDetailsRequestOptions = { format: 'date_time', }, ], - factoryQueryType: HostsQueries.authentications, - filterQuery: '{"bool":{"must":[],"filter":[{"match_all":{}}],"should":[],"must_not":[]}}', + factoryQueryType: HostsQueries.details, + filterQuery: + '{"bool":{"must":[],"filter":[{"match_all":{}},{"match_phrase":{"host.name":{"query":"bastion00.siem.estc.dev"}}}],"should":[],"must_not":[]}}', pagination: { activePage: 0, cursorStart: 0, @@ -434,860 +438,15 @@ export const mockOptions: HostDetailsRequestOptions = { from: '2020-09-02T15:17:13.678Z', to: '2020-09-03T15:17:13.678Z', }, - hostName: 'bastion00', -}; - -export const mockSearchStrategyResponse: IEsSearchResponse = { - isPartial: false, - isRunning: false, - rawResponse: { - took: 14, - timed_out: false, - _shards: { total: 21, successful: 21, skipped: 0, failed: 0 }, - hits: { total: -1, max_score: 0, hits: [] }, - aggregations: { - group_by_users: { - doc_count_error_upper_bound: -1, - sum_other_doc_count: 408, - buckets: [ - { - key: 'SYSTEM', - doc_count: 281, - failures: { - meta: {}, - doc_count: 0, - lastFailure: { hits: { total: 0, max_score: 0, hits: [] } }, - }, - successes: { - meta: {}, - doc_count: 4, - lastSuccess: { - hits: { - total: 4, - max_score: 0, - hits: [ - { - _index: 'winlogbeat-8.0.0-2020.09.02-000001', - _id: 'zqY7WXQBA6bGZw2uLeKI', - _score: null, - _source: { - process: { - name: 'services.exe', - pid: 564, - executable: 'C:\\Windows\\System32\\services.exe', - }, - agent: { - build_date: '2020-07-16 09:16:27 +0000 UTC ', - name: 'siem-windows', - commit: '4dcbde39492bdc3843034bba8db811c68cb44b97 ', - id: '05e1bff7-d7a8-416a-8554-aa10288fa07d', - type: 'winlogbeat', - ephemeral_id: '655abd6c-6c33-435d-a2eb-79b2a01e6d61', - version: '8.0.0', - user: { name: 'inside_winlogbeat_user' }, - }, - winlog: { - computer_name: 'siem-windows', - process: { pid: 576, thread: { id: 880 } }, - keywords: ['Audit Success'], - logon: { id: '0x3e7', type: 'Service' }, - channel: 'Security', - event_data: { - LogonGuid: '{00000000-0000-0000-0000-000000000000}', - TargetOutboundDomainName: '-', - VirtualAccount: '%%1843', - LogonType: '5', - IpPort: '-', - TransmittedServices: '-', - SubjectLogonId: '0x3e7', - LmPackageName: '-', - TargetOutboundUserName: '-', - KeyLength: '0', - TargetLogonId: '0x3e7', - RestrictedAdminMode: '-', - SubjectUserName: 'SIEM-WINDOWS$', - TargetLinkedLogonId: '0x0', - ElevatedToken: '%%1842', - SubjectDomainName: 'WORKGROUP', - IpAddress: '-', - ImpersonationLevel: '%%1833', - TargetUserName: 'SYSTEM', - LogonProcessName: 'Advapi ', - TargetDomainName: 'NT AUTHORITY', - SubjectUserSid: 'S-1-5-18', - TargetUserSid: 'S-1-5-18', - AuthenticationPackageName: 'Negotiate', - }, - opcode: 'Info', - version: 2, - record_id: 57818, - task: 'Logon', - event_id: 4624, - provider_guid: '{54849625-5478-4994-a5ba-3e3b0328c30d}', - activity_id: '{d2485217-6bac-0000-8fbb-3f7e2571d601}', - api: 'wineventlog', - provider_name: 'Microsoft-Windows-Security-Auditing', - }, - log: { level: 'information' }, - source: { domain: '-' }, - message: - 'An account was successfully logged on.\n\nSubject:\n\tSecurity ID:\t\tS-1-5-18\n\tAccount Name:\t\tSIEM-WINDOWS$\n\tAccount Domain:\t\tWORKGROUP\n\tLogon ID:\t\t0x3E7\n\nLogon Information:\n\tLogon Type:\t\t5\n\tRestricted Admin Mode:\t-\n\tVirtual Account:\t\tNo\n\tElevated Token:\t\tYes\n\nImpersonation Level:\t\tImpersonation\n\nNew Logon:\n\tSecurity ID:\t\tS-1-5-18\n\tAccount Name:\t\tSYSTEM\n\tAccount Domain:\t\tNT AUTHORITY\n\tLogon ID:\t\t0x3E7\n\tLinked Logon ID:\t\t0x0\n\tNetwork Account Name:\t-\n\tNetwork Account Domain:\t-\n\tLogon GUID:\t\t{00000000-0000-0000-0000-000000000000}\n\nProcess Information:\n\tProcess ID:\t\t0x234\n\tProcess Name:\t\tC:\\Windows\\System32\\services.exe\n\nNetwork Information:\n\tWorkstation Name:\t-\n\tSource Network Address:\t-\n\tSource Port:\t\t-\n\nDetailed Authentication Information:\n\tLogon Process:\t\tAdvapi \n\tAuthentication Package:\tNegotiate\n\tTransited Services:\t-\n\tPackage Name (NTLM only):\t-\n\tKey Length:\t\t0\n\nThis event is generated when a logon session is created. It is generated on the computer that was accessed.\n\nThe subject fields indicate the account on the local system which requested the logon. This is most commonly a service such as the Server service, or a local process such as Winlogon.exe or Services.exe.\n\nThe logon type field indicates the kind of logon that occurred. The most common types are 2 (interactive) and 3 (network).\n\nThe New Logon fields indicate the account for whom the new logon was created, i.e. the account that was logged on.\n\nThe network fields indicate where a remote logon request originated. Workstation name is not always available and may be left blank in some cases.\n\nThe impersonation level field indicates the extent to which a process in the logon session can impersonate.\n\nThe authentication information fields provide detailed information about this specific logon request.\n\t- Logon GUID is a unique identifier that can be used to correlate this event with a KDC event.\n\t- Transited services indicate which intermediate services have participated in this logon request.\n\t- Package name indicates which sub-protocol was used among the NTLM protocols.\n\t- Key length indicates the length of the generated session key. This will be 0 if no session key was requested.', - cloud: { - availability_zone: 'us-central1-c', - instance: { name: 'siem-windows', id: '9156726559029788564' }, - provider: 'gcp', - machine: { type: 'g1-small' }, - project: { id: 'elastic-siem' }, - }, - '@timestamp': '2020-09-04T13:08:02.532Z', - related: { user: ['SYSTEM', 'SIEM-WINDOWS$'] }, - ecs: { version: '1.5.0' }, - host: { - hostname: 'siem-windows', - os: { - build: '17763.1397', - kernel: '10.0.17763.1397 (WinBuild.160101.0800)', - name: 'Windows Server 2019 Datacenter', - family: 'windows', - version: '10.0', - platform: 'windows', - }, - ip: ['fe80::ecf5:decc:3ec3:767e', '10.200.0.15'], - name: 'siem-windows', - id: 'ce1d3c9b-a815-4643-9641-ada0f2c00609', - mac: ['42:01:0a:c8:00:0f'], - architecture: 'x86_64', - }, - event: { - code: 4624, - provider: 'Microsoft-Windows-Security-Auditing', - created: '2020-09-04T13:08:03.638Z', - kind: 'event', - module: 'security', - action: 'logged-in', - category: 'authentication', - type: 'start', - outcome: 'success', - }, - user: { domain: 'NT AUTHORITY', name: 'SYSTEM', id: 'S-1-5-18' }, - }, - sort: [1599224882532], - }, - ], - }, - }, - }, - }, - { - key: 'tsg', - doc_count: 1, - failures: { - doc_count: 0, - lastFailure: { hits: { total: 0, max_score: 0, hits: [] } }, - }, - successes: { - doc_count: 1, - lastSuccess: { - hits: { - total: 1, - max_score: 0, - hits: [ - { - _index: '.ds-logs-system.auth-default-000001', - _id: '9_sfWXQBc39KFIJbIsDh', - _score: null, - _source: { - agent: { - hostname: 'siem-kibana', - name: 'siem-kibana', - id: 'aa3d9dc7-fef1-4c2f-a68d-25785d624e35', - ephemeral_id: 'e503bd85-11c7-4bc9-ae7d-70be1d919fb7', - type: 'filebeat', - version: '7.9.1', - }, - process: { name: 'sshd', pid: 20764 }, - log: { file: { path: '/var/log/auth.log' }, offset: 552463 }, - source: { - geo: { - continent_name: 'Europe', - region_iso_code: 'DE-BE', - city_name: 'Berlin', - country_iso_code: 'DE', - region_name: 'Land Berlin', - location: { lon: 13.3512, lat: 52.5727 }, - }, - as: { number: 6805, organization: { name: 'Telefonica Germany' } }, - port: 57457, - ip: '77.183.42.188', - }, - cloud: { - availability_zone: 'us-east1-b', - instance: { name: 'siem-kibana', id: '5412578377715150143' }, - provider: 'gcp', - machine: { type: 'n1-standard-2' }, - project: { id: 'elastic-beats' }, - }, - input: { type: 'log' }, - '@timestamp': '2020-09-04T11:49:21.000Z', - system: { - auth: { - ssh: { - method: 'publickey', - signature: 'RSA SHA256:vv64JNLzKZWYA9vonnGWuW7zxWhyZrL/BFxyIGbISx8', - event: 'Accepted', - }, - }, - }, - ecs: { version: '1.5.0' }, - data_stream: { namespace: 'default', type: 'logs', dataset: 'system.auth' }, - host: { - hostname: 'siem-kibana', - os: { - kernel: '4.9.0-8-amd64', - codename: 'stretch', - name: 'Debian GNU/Linux', - family: 'debian', - version: '9 (stretch)', - platform: 'debian', - }, - containerized: false, - ip: ['10.142.0.7', 'fe80::4001:aff:fe8e:7'], - name: 'siem-kibana', - id: 'aa7ca589f1b8220002f2fc61c64cfbf1', - mac: ['42:01:0a:8e:00:07'], - architecture: 'x86_64', - }, - event: { - timezone: '+00:00', - action: 'ssh_login', - type: 'authentication_success', - category: 'authentication', - dataset: 'system.auth', - outcome: 'success', - }, - user: { name: 'tsg' }, - }, - sort: [1599220161000], - }, - ], - }, - }, - }, - }, - { - key: 'admin', - doc_count: 23, - failures: { - doc_count: 23, - lastFailure: { - hits: { - total: 23, - max_score: 0, - hits: [ - { - _index: '.ds-logs-system.auth-default-000001', - _id: 'ZfxZWXQBc39KFIJbLN5U', - _score: null, - _source: { - agent: { - hostname: 'siem-kibana', - name: 'siem-kibana', - id: 'aa3d9dc7-fef1-4c2f-a68d-25785d624e35', - ephemeral_id: 'e503bd85-11c7-4bc9-ae7d-70be1d919fb7', - type: 'filebeat', - version: '7.9.1', - }, - process: { name: 'sshd', pid: 22913 }, - log: { file: { path: '/var/log/auth.log' }, offset: 562910 }, - source: { - geo: { - continent_name: 'Asia', - region_iso_code: 'KR-28', - city_name: 'Incheon', - country_iso_code: 'KR', - region_name: 'Incheon', - location: { lon: 126.7288, lat: 37.4562 }, - }, - as: { number: 4766, organization: { name: 'Korea Telecom' } }, - ip: '59.15.3.197', - }, - cloud: { - availability_zone: 'us-east1-b', - instance: { name: 'siem-kibana', id: '5412578377715150143' }, - provider: 'gcp', - machine: { type: 'n1-standard-2' }, - project: { id: 'elastic-beats' }, - }, - input: { type: 'log' }, - '@timestamp': '2020-09-04T13:40:46.000Z', - system: { auth: { ssh: { event: 'Invalid' } } }, - ecs: { version: '1.5.0' }, - data_stream: { namespace: 'default', type: 'logs', dataset: 'system.auth' }, - host: { - hostname: 'siem-kibana', - os: { - kernel: '4.9.0-8-amd64', - codename: 'stretch', - name: 'Debian GNU/Linux', - family: 'debian', - version: '9 (stretch)', - platform: 'debian', - }, - containerized: false, - ip: ['10.142.0.7', 'fe80::4001:aff:fe8e:7'], - name: 'siem-kibana', - id: 'aa7ca589f1b8220002f2fc61c64cfbf1', - mac: ['42:01:0a:8e:00:07'], - architecture: 'x86_64', - }, - event: { - timezone: '+00:00', - action: 'ssh_login', - type: 'authentication_failure', - category: 'authentication', - dataset: 'system.auth', - outcome: 'failure', - }, - user: { name: 'admin' }, - }, - sort: [1599226846000], - }, - ], - }, - }, - }, - successes: { - doc_count: 0, - lastSuccess: { hits: { total: 0, max_score: 0, hits: [] } }, - }, - }, - { - key: 'user', - doc_count: 21, - failures: { - doc_count: 21, - lastFailure: { - hits: { - total: 21, - max_score: 0, - hits: [ - { - _index: 'filebeat-8.0.0-2020.09.02-000001', - _id: 'M_xLWXQBc39KFIJbY7Cb', - _score: null, - _source: { - agent: { - name: 'bastion00.siem.estc.dev', - id: 'f9a321c1-ec27-49fa-aacf-6a50ef6d836f', - type: 'filebeat', - ephemeral_id: '734ee3da-1a4f-4bc9-b400-e0cf0e5eeebc', - version: '8.0.0', - }, - process: { name: 'sshd', pid: 20671 }, - log: { file: { path: '/var/log/auth.log' }, offset: 1028103 }, - source: { - geo: { - continent_name: 'North America', - region_iso_code: 'US-NY', - city_name: 'New York', - country_iso_code: 'US', - region_name: 'New York', - location: { lon: -74, lat: 40.7157 }, - }, - ip: '64.227.88.245', - }, - fileset: { name: 'auth' }, - input: { type: 'log' }, - '@timestamp': '2020-09-04T13:25:43.000Z', - system: { auth: { ssh: { event: 'Invalid' } } }, - ecs: { version: '1.5.0' }, - related: { ip: ['64.227.88.245'], user: ['user'] }, - service: { type: 'system' }, - host: { hostname: 'bastion00', name: 'bastion00.siem.estc.dev' }, - event: { - ingested: '2020-09-04T13:25:47.034172Z', - timezone: '+00:00', - kind: 'event', - module: 'system', - action: 'ssh_login', - type: ['authentication_failure', 'info'], - category: ['authentication'], - dataset: 'system.auth', - outcome: 'failure', - }, - user: { name: 'user' }, - }, - sort: [1599225943000], - }, - ], - }, - }, - }, - successes: { - doc_count: 0, - lastSuccess: { hits: { total: 0, max_score: 0, hits: [] } }, - }, - }, - { - key: 'ubuntu', - doc_count: 18, - failures: { - doc_count: 18, - lastFailure: { - hits: { - total: 18, - max_score: 0, - hits: [ - { - _index: 'filebeat-8.0.0-2020.09.02-000001', - _id: 'nPxKWXQBc39KFIJb7q4w', - _score: null, - _source: { - agent: { - name: 'bastion00.siem.estc.dev', - id: 'f9a321c1-ec27-49fa-aacf-6a50ef6d836f', - ephemeral_id: '734ee3da-1a4f-4bc9-b400-e0cf0e5eeebc', - type: 'filebeat', - version: '8.0.0', - }, - process: { name: 'sshd', pid: 20665 }, - log: { file: { path: '/var/log/auth.log' }, offset: 1027372 }, - source: { - geo: { - continent_name: 'North America', - region_iso_code: 'US-NY', - city_name: 'New York', - country_iso_code: 'US', - region_name: 'New York', - location: { lon: -74, lat: 40.7157 }, - }, - ip: '64.227.88.245', - }, - fileset: { name: 'auth' }, - input: { type: 'log' }, - '@timestamp': '2020-09-04T13:25:07.000Z', - system: { auth: { ssh: { event: 'Invalid' } } }, - ecs: { version: '1.5.0' }, - related: { ip: ['64.227.88.245'], user: ['ubuntu'] }, - service: { type: 'system' }, - host: { hostname: 'bastion00', name: 'bastion00.siem.estc.dev' }, - event: { - ingested: '2020-09-04T13:25:16.974606Z', - timezone: '+00:00', - kind: 'event', - module: 'system', - action: 'ssh_login', - type: ['authentication_failure', 'info'], - category: ['authentication'], - dataset: 'system.auth', - outcome: 'failure', - }, - user: { name: 'ubuntu' }, - }, - sort: [1599225907000], - }, - ], - }, - }, - }, - successes: { - doc_count: 0, - lastSuccess: { hits: { total: 0, max_score: 0, hits: [] } }, - }, - }, - { - key: 'odoo', - doc_count: 17, - failures: { - doc_count: 17, - lastFailure: { - hits: { - total: 17, - max_score: 0, - hits: [ - { - _index: '.ds-logs-system.auth-default-000001', - _id: 'mPsfWXQBc39KFIJbI8HI', - _score: null, - _source: { - agent: { - hostname: 'siem-kibana', - name: 'siem-kibana', - id: 'aa3d9dc7-fef1-4c2f-a68d-25785d624e35', - type: 'filebeat', - ephemeral_id: 'e503bd85-11c7-4bc9-ae7d-70be1d919fb7', - version: '7.9.1', - }, - process: { name: 'sshd', pid: 21506 }, - log: { file: { path: '/var/log/auth.log' }, offset: 556761 }, - source: { - geo: { - continent_name: 'Asia', - region_iso_code: 'IN-DL', - city_name: 'New Delhi', - country_iso_code: 'IN', - region_name: 'National Capital Territory of Delhi', - location: { lon: 77.2245, lat: 28.6358 }, - }, - as: { number: 10029, organization: { name: 'SHYAM SPECTRA PVT LTD' } }, - ip: '180.151.228.166', - }, - cloud: { - availability_zone: 'us-east1-b', - instance: { name: 'siem-kibana', id: '5412578377715150143' }, - provider: 'gcp', - machine: { type: 'n1-standard-2' }, - project: { id: 'elastic-beats' }, - }, - input: { type: 'log' }, - '@timestamp': '2020-09-04T12:26:36.000Z', - system: { auth: { ssh: { event: 'Invalid' } } }, - ecs: { version: '1.5.0' }, - data_stream: { namespace: 'default', type: 'logs', dataset: 'system.auth' }, - host: { - hostname: 'siem-kibana', - os: { - kernel: '4.9.0-8-amd64', - codename: 'stretch', - name: 'Debian GNU/Linux', - family: 'debian', - version: '9 (stretch)', - platform: 'debian', - }, - containerized: false, - ip: ['10.142.0.7', 'fe80::4001:aff:fe8e:7'], - name: 'siem-kibana', - id: 'aa7ca589f1b8220002f2fc61c64cfbf1', - mac: ['42:01:0a:8e:00:07'], - architecture: 'x86_64', - }, - event: { - timezone: '+00:00', - action: 'ssh_login', - type: 'authentication_failure', - category: 'authentication', - dataset: 'system.auth', - outcome: 'failure', - }, - user: { name: 'odoo' }, - }, - sort: [1599222396000], - }, - ], - }, - }, - }, - successes: { - doc_count: 0, - lastSuccess: { hits: { total: 0, max_score: 0, hits: [] } }, - }, - }, - { - key: 'pi', - doc_count: 17, - failures: { - doc_count: 17, - lastFailure: { - hits: { - total: 17, - max_score: 0, - hits: [ - { - _index: 'filebeat-8.0.0-2020.09.02-000001', - _id: 'aaToWHQBA6bGZw2uR-St', - _score: null, - _source: { - agent: { - name: 'bastion00.siem.estc.dev', - id: 'f9a321c1-ec27-49fa-aacf-6a50ef6d836f', - type: 'filebeat', - ephemeral_id: '734ee3da-1a4f-4bc9-b400-e0cf0e5eeebc', - version: '8.0.0', - }, - process: { name: 'sshd', pid: 20475 }, - log: { file: { path: '/var/log/auth.log' }, offset: 1019218 }, - source: { - geo: { - continent_name: 'Europe', - region_iso_code: 'SE-AB', - city_name: 'Stockholm', - country_iso_code: 'SE', - region_name: 'Stockholm', - location: { lon: 17.7833, lat: 59.25 }, - }, - as: { number: 8473, organization: { name: 'Bahnhof AB' } }, - ip: '178.174.148.58', - }, - fileset: { name: 'auth' }, - input: { type: 'log' }, - '@timestamp': '2020-09-04T11:37:22.000Z', - system: { auth: { ssh: { event: 'Invalid' } } }, - ecs: { version: '1.5.0' }, - related: { ip: ['178.174.148.58'], user: ['pi'] }, - service: { type: 'system' }, - host: { hostname: 'bastion00', name: 'bastion00.siem.estc.dev' }, - event: { - ingested: '2020-09-04T11:37:31.797423Z', - timezone: '+00:00', - kind: 'event', - module: 'system', - action: 'ssh_login', - type: ['authentication_failure', 'info'], - category: ['authentication'], - dataset: 'system.auth', - outcome: 'failure', - }, - user: { name: 'pi' }, - }, - sort: [1599219442000], - }, - ], - }, - }, - }, - successes: { - doc_count: 0, - lastSuccess: { hits: { total: 0, max_score: 0, hits: [] } }, - }, - }, - { - key: 'demo', - doc_count: 14, - failures: { - doc_count: 14, - lastFailure: { - hits: { - total: 14, - max_score: 0, - hits: [ - { - _index: 'filebeat-8.0.0-2020.09.02-000001', - _id: 'VaP_V3QBA6bGZw2upUbg', - _score: null, - _source: { - agent: { - name: 'bastion00.siem.estc.dev', - id: 'f9a321c1-ec27-49fa-aacf-6a50ef6d836f', - type: 'filebeat', - ephemeral_id: '734ee3da-1a4f-4bc9-b400-e0cf0e5eeebc', - version: '8.0.0', - }, - process: { name: 'sshd', pid: 19849 }, - log: { file: { path: '/var/log/auth.log' }, offset: 981036 }, - source: { - geo: { - continent_name: 'Europe', - country_iso_code: 'HR', - location: { lon: 15.5, lat: 45.1667 }, - }, - as: { - number: 42864, - organization: { name: 'Giganet Internet Szolgaltato Kft' }, - }, - ip: '45.95.168.157', - }, - fileset: { name: 'auth' }, - input: { type: 'log' }, - '@timestamp': '2020-09-04T07:23:22.000Z', - system: { auth: { ssh: { event: 'Invalid' } } }, - ecs: { version: '1.5.0' }, - related: { ip: ['45.95.168.157'], user: ['demo'] }, - service: { type: 'system' }, - host: { hostname: 'bastion00', name: 'bastion00.siem.estc.dev' }, - event: { - ingested: '2020-09-04T07:23:26.046346Z', - timezone: '+00:00', - kind: 'event', - module: 'system', - action: 'ssh_login', - type: ['authentication_failure', 'info'], - category: ['authentication'], - dataset: 'system.auth', - outcome: 'failure', - }, - user: { name: 'demo' }, - }, - sort: [1599204202000], - }, - ], - }, - }, - }, - successes: { - doc_count: 0, - lastSuccess: { hits: { total: 0, max_score: 0, hits: [] } }, - }, - }, - { - key: 'git', - doc_count: 13, - failures: { - doc_count: 13, - lastFailure: { - hits: { - total: 13, - max_score: 0, - hits: [ - { - _index: '.ds-logs-system.auth-default-000001', - _id: 'PqYfWXQBA6bGZw2uIhVU', - _score: null, - _source: { - agent: { - hostname: 'siem-kibana', - name: 'siem-kibana', - id: 'aa3d9dc7-fef1-4c2f-a68d-25785d624e35', - ephemeral_id: 'e503bd85-11c7-4bc9-ae7d-70be1d919fb7', - type: 'filebeat', - version: '7.9.1', - }, - process: { name: 'sshd', pid: 20396 }, - log: { file: { path: '/var/log/auth.log' }, offset: 550795 }, - source: { - geo: { - continent_name: 'Asia', - region_iso_code: 'CN-BJ', - city_name: 'Beijing', - country_iso_code: 'CN', - region_name: 'Beijing', - location: { lon: 116.3889, lat: 39.9288 }, - }, - as: { - number: 45090, - organization: { - name: 'Shenzhen Tencent Computer Systems Company Limited', - }, - }, - ip: '123.206.30.76', - }, - cloud: { - availability_zone: 'us-east1-b', - instance: { name: 'siem-kibana', id: '5412578377715150143' }, - provider: 'gcp', - machine: { type: 'n1-standard-2' }, - project: { id: 'elastic-beats' }, - }, - input: { type: 'log' }, - '@timestamp': '2020-09-04T11:20:26.000Z', - system: { auth: { ssh: { event: 'Invalid' } } }, - ecs: { version: '1.5.0' }, - data_stream: { namespace: 'default', type: 'logs', dataset: 'system.auth' }, - host: { - hostname: 'siem-kibana', - os: { - kernel: '4.9.0-8-amd64', - codename: 'stretch', - name: 'Debian GNU/Linux', - family: 'debian', - version: '9 (stretch)', - platform: 'debian', - }, - containerized: false, - ip: ['10.142.0.7', 'fe80::4001:aff:fe8e:7'], - name: 'siem-kibana', - id: 'aa7ca589f1b8220002f2fc61c64cfbf1', - mac: ['42:01:0a:8e:00:07'], - architecture: 'x86_64', - }, - event: { - timezone: '+00:00', - action: 'ssh_login', - type: 'authentication_failure', - category: 'authentication', - dataset: 'system.auth', - outcome: 'failure', - }, - user: { name: 'git' }, - }, - sort: [1599218426000], - }, - ], - }, - }, - }, - successes: { - doc_count: 0, - lastSuccess: { hits: { total: 0, max_score: 0, hits: [] } }, - }, - }, - { - key: 'webadmin', - doc_count: 13, - failures: { - doc_count: 13, - lastFailure: { - hits: { - total: 13, - max_score: 0, - hits: [ - { - _index: 'filebeat-8.0.0-2020.09.02-000001', - _id: 'iMABWHQBB-gskclyitP-', - _score: null, - _source: { - agent: { - name: 'bastion00.siem.estc.dev', - id: 'f9a321c1-ec27-49fa-aacf-6a50ef6d836f', - type: 'filebeat', - ephemeral_id: '734ee3da-1a4f-4bc9-b400-e0cf0e5eeebc', - version: '8.0.0', - }, - process: { name: 'sshd', pid: 19870 }, - log: { file: { path: '/var/log/auth.log' }, offset: 984133 }, - source: { - geo: { - continent_name: 'Europe', - country_iso_code: 'HR', - location: { lon: 15.5, lat: 45.1667 }, - }, - as: { - number: 42864, - organization: { name: 'Giganet Internet Szolgaltato Kft' }, - }, - ip: '45.95.168.157', - }, - fileset: { name: 'auth' }, - input: { type: 'log' }, - '@timestamp': '2020-09-04T07:25:28.000Z', - system: { auth: { ssh: { event: 'Invalid' } } }, - ecs: { version: '1.5.0' }, - related: { ip: ['45.95.168.157'], user: ['webadmin'] }, - service: { type: 'system' }, - host: { hostname: 'bastion00', name: 'bastion00.siem.estc.dev' }, - event: { - ingested: '2020-09-04T07:25:30.236651Z', - timezone: '+00:00', - kind: 'event', - module: 'system', - action: 'ssh_login', - type: ['authentication_failure', 'info'], - category: ['authentication'], - dataset: 'system.auth', - outcome: 'failure', - }, - user: { name: 'webadmin' }, - }, - sort: [1599204328000], - }, - ], - }, - }, - }, - successes: { - doc_count: 0, - lastSuccess: { hits: { total: 0, max_score: 0, hits: [] } }, - }, - }, - ], - }, - user_count: { value: 188 }, - }, - }, - total: 21, - loaded: 21, -}; + sort: ({ + direction: Direction.desc, + field: 'success', + } as unknown) as SortField, + params: {}, + hostName: 'bastion00.siem.estc.dev', +} as HostDetailsRequestOptions; -export const formattedSearchStrategyResponse = { +export const mockSearchStrategyResponse: IEsSearchResponse = { isPartial: false, isRunning: false, rawResponse: { @@ -2132,12 +1291,12 @@ export const formattedSearchStrategyResponse = { }, total: 21, loaded: 21, +}; + +export const formattedSearchStrategyResponse = { inspect: { dsl: [ - '{\n "allowNoIndices": true,\n "index": [\n "apm-*-transaction*",\n "auditbeat-*",\n "endgame-*",\n "filebeat-*",\n "logs-*",\n "packetbeat-*",\n "winlogbeat-*"\n ],\n "ignoreUnavailable": true,\n "body": {\n "aggregations": {\n "host_architecture": {\n "terms": {\n "field": "host.architecture",\n "size": 10,\n "order": {\n "timestamp": "desc"\n }\n },\n "aggs": {\n "timestamp": {\n "max": {\n "field": "@timestamp"\n }\n }\n }\n },\n "host_id": {\n "terms": {\n "field": "host.id",\n "size": 10,\n "order": {\n "timestamp": "desc"\n }\n },\n "aggs": {\n "timestamp": {\n "max": {\n "field": "@timestamp"\n }\n }\n }\n },\n "host_ip": {\n "terms": {\n "field": "host.ip",\n "size": 10,\n "order": {\n "timestamp": "desc"\n }\n },\n "aggs": {\n "timestamp": {\n "max": {\n "field": "@timestamp"\n }\n }\n }\n },\n "host_mac": {\n "terms": {\n "field": "host.mac",\n "size": 10,\n "order": {\n "timestamp": "desc"\n }\n },\n "aggs": {\n "timestamp": {\n "max": {\n "field": "@timestamp"\n }\n }\n }\n },\n "host_name": {\n "terms": {\n "field": "host.name",\n "size": 10,\n "order": {\n "timestamp": "desc"\n }\n },\n "aggs": {\n "timestamp": {\n "max": {\n "field": "@timestamp"\n }\n }\n }\n },\n "host_os_family": {\n "terms": {\n "field": "host.os.family",\n "size": 10,\n "order": {\n "timestamp": "desc"\n }\n },\n "aggs": {\n "timestamp": {\n "max": {\n "field": "@timestamp"\n }\n }\n }\n },\n "host_os_name": {\n "terms": {\n "field": "host.os.name",\n "size": 10,\n "order": {\n "timestamp": "desc"\n }\n },\n "aggs": {\n "timestamp": {\n "max": {\n "field": "@timestamp"\n }\n }\n }\n },\n "host_os_platform": {\n "terms": {\n "field": "host.os.platform",\n "size": 10,\n "order": {\n "timestamp": "desc"\n }\n },\n "aggs": {\n "timestamp": {\n "max": {\n "field": "@timestamp"\n }\n }\n }\n },\n "host_os_version": {\n "terms": {\n "field": "host.os.version",\n "size": 10,\n "order": {\n "timestamp": "desc"\n }\n },\n "aggs": {\n "timestamp": {\n "max": {\n "field": "@timestamp"\n }\n }\n }\n },\n "cloud_instance_id": {\n "terms": {\n "field": "cloud.instance.id",\n "size": 10,\n "order": {\n "timestamp": "desc"\n }\n },\n "aggs": {\n "timestamp": {\n "max": {\n "field": "@timestamp"\n }\n }\n }\n },\n "cloud_machine_type": {\n "terms": {\n "field": "cloud.machine.type",\n "size": 10,\n "order": {\n "timestamp": "desc"\n }\n },\n "aggs": {\n "timestamp": {\n "max": {\n "field": "@timestamp"\n }\n }\n }\n },\n "cloud_provider": {\n "terms": {\n "field": "cloud.provider",\n "size": 10,\n "order": {\n "timestamp": "desc"\n }\n },\n "aggs": {\n "timestamp": {\n "max": {\n "field": "@timestamp"\n }\n }\n }\n },\n "cloud_region": {\n "terms": {\n "field": "cloud.region",\n "size": 10,\n "order": {\n "timestamp": "desc"\n }\n },\n "aggs": {\n "timestamp": {\n "max": {\n "field": "@timestamp"\n }\n }\n }\n }\n },\n "query": {\n "bool": {\n "filter": [\n {\n "term": {\n "host.name": "bastion00"\n }\n },\n {\n "range": {\n "@timestamp": {\n "format": "strict_date_optional_time",\n "gte": "2020-09-02T15:17:13.678Z",\n "lte": "2020-09-03T15:17:13.678Z"\n }\n }\n }\n ]\n }\n },\n "size": 0,\n "track_total_hits": false\n }\n}', - ], - response: [ - '{\n "isPartial": false,\n "isRunning": false,\n "rawResponse": {\n "took": 14,\n "timed_out": false,\n "_shards": {\n "total": 21,\n "successful": 21,\n "skipped": 0,\n "failed": 0\n },\n "hits": {\n "total": -1,\n "max_score": 0,\n "hits": []\n },\n "aggregations": {\n "group_by_users": {\n "doc_count_error_upper_bound": -1,\n "sum_other_doc_count": 408,\n "buckets": [\n {\n "key": "SYSTEM",\n "doc_count": 281,\n "failures": {\n "meta": {},\n "doc_count": 0,\n "lastFailure": {\n "hits": {\n "total": 0,\n "max_score": 0,\n "hits": []\n }\n }\n },\n "successes": {\n "meta": {},\n "doc_count": 4,\n "lastSuccess": {\n "hits": {\n "total": 4,\n "max_score": 0,\n "hits": [\n {\n "_index": "winlogbeat-8.0.0-2020.09.02-000001",\n "_id": "zqY7WXQBA6bGZw2uLeKI",\n "_score": null,\n "_source": {\n "process": {\n "name": "services.exe",\n "pid": 564,\n "executable": "C:\\\\Windows\\\\System32\\\\services.exe"\n },\n "agent": {\n "build_date": "2020-07-16 09:16:27 +0000 UTC ",\n "name": "siem-windows",\n "commit": "4dcbde39492bdc3843034bba8db811c68cb44b97 ",\n "id": "05e1bff7-d7a8-416a-8554-aa10288fa07d",\n "type": "winlogbeat",\n "ephemeral_id": "655abd6c-6c33-435d-a2eb-79b2a01e6d61",\n "version": "8.0.0",\n "user": {\n "name": "inside_winlogbeat_user"\n }\n },\n "winlog": {\n "computer_name": "siem-windows",\n "process": {\n "pid": 576,\n "thread": {\n "id": 880\n }\n },\n "keywords": [\n "Audit Success"\n ],\n "logon": {\n "id": "0x3e7",\n "type": "Service"\n },\n "channel": "Security",\n "event_data": {\n "LogonGuid": "{00000000-0000-0000-0000-000000000000}",\n "TargetOutboundDomainName": "-",\n "VirtualAccount": "%%1843",\n "LogonType": "5",\n "IpPort": "-",\n "TransmittedServices": "-",\n "SubjectLogonId": "0x3e7",\n "LmPackageName": "-",\n "TargetOutboundUserName": "-",\n "KeyLength": "0",\n "TargetLogonId": "0x3e7",\n "RestrictedAdminMode": "-",\n "SubjectUserName": "SIEM-WINDOWS$",\n "TargetLinkedLogonId": "0x0",\n "ElevatedToken": "%%1842",\n "SubjectDomainName": "WORKGROUP",\n "IpAddress": "-",\n "ImpersonationLevel": "%%1833",\n "TargetUserName": "SYSTEM",\n "LogonProcessName": "Advapi ",\n "TargetDomainName": "NT AUTHORITY",\n "SubjectUserSid": "S-1-5-18",\n "TargetUserSid": "S-1-5-18",\n "AuthenticationPackageName": "Negotiate"\n },\n "opcode": "Info",\n "version": 2,\n "record_id": 57818,\n "task": "Logon",\n "event_id": 4624,\n "provider_guid": "{54849625-5478-4994-a5ba-3e3b0328c30d}",\n "activity_id": "{d2485217-6bac-0000-8fbb-3f7e2571d601}",\n "api": "wineventlog",\n "provider_name": "Microsoft-Windows-Security-Auditing"\n },\n "log": {\n "level": "information"\n },\n "source": {\n "domain": "-"\n },\n "message": "An account was successfully logged on.\\n\\nSubject:\\n\\tSecurity ID:\\t\\tS-1-5-18\\n\\tAccount Name:\\t\\tSIEM-WINDOWS$\\n\\tAccount Domain:\\t\\tWORKGROUP\\n\\tLogon ID:\\t\\t0x3E7\\n\\nLogon Information:\\n\\tLogon Type:\\t\\t5\\n\\tRestricted Admin Mode:\\t-\\n\\tVirtual Account:\\t\\tNo\\n\\tElevated Token:\\t\\tYes\\n\\nImpersonation Level:\\t\\tImpersonation\\n\\nNew Logon:\\n\\tSecurity ID:\\t\\tS-1-5-18\\n\\tAccount Name:\\t\\tSYSTEM\\n\\tAccount Domain:\\t\\tNT AUTHORITY\\n\\tLogon ID:\\t\\t0x3E7\\n\\tLinked Logon ID:\\t\\t0x0\\n\\tNetwork Account Name:\\t-\\n\\tNetwork Account Domain:\\t-\\n\\tLogon GUID:\\t\\t{00000000-0000-0000-0000-000000000000}\\n\\nProcess Information:\\n\\tProcess ID:\\t\\t0x234\\n\\tProcess Name:\\t\\tC:\\\\Windows\\\\System32\\\\services.exe\\n\\nNetwork Information:\\n\\tWorkstation Name:\\t-\\n\\tSource Network Address:\\t-\\n\\tSource Port:\\t\\t-\\n\\nDetailed Authentication Information:\\n\\tLogon Process:\\t\\tAdvapi \\n\\tAuthentication Package:\\tNegotiate\\n\\tTransited Services:\\t-\\n\\tPackage Name (NTLM only):\\t-\\n\\tKey Length:\\t\\t0\\n\\nThis event is generated when a logon session is created. It is generated on the computer that was accessed.\\n\\nThe subject fields indicate the account on the local system which requested the logon. This is most commonly a service such as the Server service, or a local process such as Winlogon.exe or Services.exe.\\n\\nThe logon type field indicates the kind of logon that occurred. The most common types are 2 (interactive) and 3 (network).\\n\\nThe New Logon fields indicate the account for whom the new logon was created, i.e. the account that was logged on.\\n\\nThe network fields indicate where a remote logon request originated. Workstation name is not always available and may be left blank in some cases.\\n\\nThe impersonation level field indicates the extent to which a process in the logon session can impersonate.\\n\\nThe authentication information fields provide detailed information about this specific logon request.\\n\\t- Logon GUID is a unique identifier that can be used to correlate this event with a KDC event.\\n\\t- Transited services indicate which intermediate services have participated in this logon request.\\n\\t- Package name indicates which sub-protocol was used among the NTLM protocols.\\n\\t- Key length indicates the length of the generated session key. This will be 0 if no session key was requested.",\n "cloud": {\n "availability_zone": "us-central1-c",\n "instance": {\n "name": "siem-windows",\n "id": "9156726559029788564"\n },\n "provider": "gcp",\n "machine": {\n "type": "g1-small"\n },\n "project": {\n "id": "elastic-siem"\n }\n },\n "@timestamp": "2020-09-04T13:08:02.532Z",\n "related": {\n "user": [\n "SYSTEM",\n "SIEM-WINDOWS$"\n ]\n },\n "ecs": {\n "version": "1.5.0"\n },\n "host": {\n "hostname": "siem-windows",\n "os": {\n "build": "17763.1397",\n "kernel": "10.0.17763.1397 (WinBuild.160101.0800)",\n "name": "Windows Server 2019 Datacenter",\n "family": "windows",\n "version": "10.0",\n "platform": "windows"\n },\n "ip": [\n "fe80::ecf5:decc:3ec3:767e",\n "10.200.0.15"\n ],\n "name": "siem-windows",\n "id": "ce1d3c9b-a815-4643-9641-ada0f2c00609",\n "mac": [\n "42:01:0a:c8:00:0f"\n ],\n "architecture": "x86_64"\n },\n "event": {\n "code": 4624,\n "provider": "Microsoft-Windows-Security-Auditing",\n "created": "2020-09-04T13:08:03.638Z",\n "kind": "event",\n "module": "security",\n "action": "logged-in",\n "category": "authentication",\n "type": "start",\n "outcome": "success"\n },\n "user": {\n "domain": "NT AUTHORITY",\n "name": "SYSTEM",\n "id": "S-1-5-18"\n }\n },\n "sort": [\n 1599224882532\n ]\n }\n ]\n }\n }\n }\n },\n {\n "key": "tsg",\n "doc_count": 1,\n "failures": {\n "doc_count": 0,\n "lastFailure": {\n "hits": {\n "total": 0,\n "max_score": 0,\n "hits": []\n }\n }\n },\n "successes": {\n "doc_count": 1,\n "lastSuccess": {\n "hits": {\n "total": 1,\n "max_score": 0,\n "hits": [\n {\n "_index": ".ds-logs-system.auth-default-000001",\n "_id": "9_sfWXQBc39KFIJbIsDh",\n "_score": null,\n "_source": {\n "agent": {\n "hostname": "siem-kibana",\n "name": "siem-kibana",\n "id": "aa3d9dc7-fef1-4c2f-a68d-25785d624e35",\n "ephemeral_id": "e503bd85-11c7-4bc9-ae7d-70be1d919fb7",\n "type": "filebeat",\n "version": "7.9.1"\n },\n "process": {\n "name": "sshd",\n "pid": 20764\n },\n "log": {\n "file": {\n "path": "/var/log/auth.log"\n },\n "offset": 552463\n },\n "source": {\n "geo": {\n "continent_name": "Europe",\n "region_iso_code": "DE-BE",\n "city_name": "Berlin",\n "country_iso_code": "DE",\n "region_name": "Land Berlin",\n "location": {\n "lon": 13.3512,\n "lat": 52.5727\n }\n },\n "as": {\n "number": 6805,\n "organization": {\n "name": "Telefonica Germany"\n }\n },\n "port": 57457,\n "ip": "77.183.42.188"\n },\n "cloud": {\n "availability_zone": "us-east1-b",\n "instance": {\n "name": "siem-kibana",\n "id": "5412578377715150143"\n },\n "provider": "gcp",\n "machine": {\n "type": "n1-standard-2"\n },\n "project": {\n "id": "elastic-beats"\n }\n },\n "input": {\n "type": "log"\n },\n "@timestamp": "2020-09-04T11:49:21.000Z",\n "system": {\n "auth": {\n "ssh": {\n "method": "publickey",\n "signature": "RSA SHA256:vv64JNLzKZWYA9vonnGWuW7zxWhyZrL/BFxyIGbISx8",\n "event": "Accepted"\n }\n }\n },\n "ecs": {\n "version": "1.5.0"\n },\n "data_stream": {\n "namespace": "default",\n "type": "logs",\n "dataset": "system.auth"\n },\n "host": {\n "hostname": "siem-kibana",\n "os": {\n "kernel": "4.9.0-8-amd64",\n "codename": "stretch",\n "name": "Debian GNU/Linux",\n "family": "debian",\n "version": "9 (stretch)",\n "platform": "debian"\n },\n "containerized": false,\n "ip": [\n "10.142.0.7",\n "fe80::4001:aff:fe8e:7"\n ],\n "name": "siem-kibana",\n "id": "aa7ca589f1b8220002f2fc61c64cfbf1",\n "mac": [\n "42:01:0a:8e:00:07"\n ],\n "architecture": "x86_64"\n },\n "event": {\n "timezone": "+00:00",\n "action": "ssh_login",\n "type": "authentication_success",\n "category": "authentication",\n "dataset": "system.auth",\n "outcome": "success"\n },\n "user": {\n "name": "tsg"\n }\n },\n "sort": [\n 1599220161000\n ]\n }\n ]\n }\n }\n }\n },\n {\n "key": "admin",\n "doc_count": 23,\n "failures": {\n "doc_count": 23,\n "lastFailure": {\n "hits": {\n "total": 23,\n "max_score": 0,\n "hits": [\n {\n "_index": ".ds-logs-system.auth-default-000001",\n "_id": "ZfxZWXQBc39KFIJbLN5U",\n "_score": null,\n "_source": {\n "agent": {\n "hostname": "siem-kibana",\n "name": "siem-kibana",\n "id": "aa3d9dc7-fef1-4c2f-a68d-25785d624e35",\n "ephemeral_id": "e503bd85-11c7-4bc9-ae7d-70be1d919fb7",\n "type": "filebeat",\n "version": "7.9.1"\n },\n "process": {\n "name": "sshd",\n "pid": 22913\n },\n "log": {\n "file": {\n "path": "/var/log/auth.log"\n },\n "offset": 562910\n },\n "source": {\n "geo": {\n "continent_name": "Asia",\n "region_iso_code": "KR-28",\n "city_name": "Incheon",\n "country_iso_code": "KR",\n "region_name": "Incheon",\n "location": {\n "lon": 126.7288,\n "lat": 37.4562\n }\n },\n "as": {\n "number": 4766,\n "organization": {\n "name": "Korea Telecom"\n }\n },\n "ip": "59.15.3.197"\n },\n "cloud": {\n "availability_zone": "us-east1-b",\n "instance": {\n "name": "siem-kibana",\n "id": "5412578377715150143"\n },\n "provider": "gcp",\n "machine": {\n "type": "n1-standard-2"\n },\n "project": {\n "id": "elastic-beats"\n }\n },\n "input": {\n "type": "log"\n },\n "@timestamp": "2020-09-04T13:40:46.000Z",\n "system": {\n "auth": {\n "ssh": {\n "event": "Invalid"\n }\n }\n },\n "ecs": {\n "version": "1.5.0"\n },\n "data_stream": {\n "namespace": "default",\n "type": "logs",\n "dataset": "system.auth"\n },\n "host": {\n "hostname": "siem-kibana",\n "os": {\n "kernel": "4.9.0-8-amd64",\n "codename": "stretch",\n "name": "Debian GNU/Linux",\n "family": "debian",\n "version": "9 (stretch)",\n "platform": "debian"\n },\n "containerized": false,\n "ip": [\n "10.142.0.7",\n "fe80::4001:aff:fe8e:7"\n ],\n "name": "siem-kibana",\n "id": "aa7ca589f1b8220002f2fc61c64cfbf1",\n "mac": [\n "42:01:0a:8e:00:07"\n ],\n "architecture": "x86_64"\n },\n "event": {\n "timezone": "+00:00",\n "action": "ssh_login",\n "type": "authentication_failure",\n "category": "authentication",\n "dataset": "system.auth",\n "outcome": "failure"\n },\n "user": {\n "name": "admin"\n }\n },\n "sort": [\n 1599226846000\n ]\n }\n ]\n }\n }\n },\n "successes": {\n "doc_count": 0,\n "lastSuccess": {\n "hits": {\n "total": 0,\n "max_score": 0,\n "hits": []\n }\n }\n }\n },\n {\n "key": "user",\n "doc_count": 21,\n "failures": {\n "doc_count": 21,\n "lastFailure": {\n "hits": {\n "total": 21,\n "max_score": 0,\n "hits": [\n {\n "_index": "filebeat-8.0.0-2020.09.02-000001",\n "_id": "M_xLWXQBc39KFIJbY7Cb",\n "_score": null,\n "_source": {\n "agent": {\n "name": "bastion00.siem.estc.dev",\n "id": "f9a321c1-ec27-49fa-aacf-6a50ef6d836f",\n "type": "filebeat",\n "ephemeral_id": "734ee3da-1a4f-4bc9-b400-e0cf0e5eeebc",\n "version": "8.0.0"\n },\n "process": {\n "name": "sshd",\n "pid": 20671\n },\n "log": {\n "file": {\n "path": "/var/log/auth.log"\n },\n "offset": 1028103\n },\n "source": {\n "geo": {\n "continent_name": "North America",\n "region_iso_code": "US-NY",\n "city_name": "New York",\n "country_iso_code": "US",\n "region_name": "New York",\n "location": {\n "lon": -74,\n "lat": 40.7157\n }\n },\n "ip": "64.227.88.245"\n },\n "fileset": {\n "name": "auth"\n },\n "input": {\n "type": "log"\n },\n "@timestamp": "2020-09-04T13:25:43.000Z",\n "system": {\n "auth": {\n "ssh": {\n "event": "Invalid"\n }\n }\n },\n "ecs": {\n "version": "1.5.0"\n },\n "related": {\n "ip": [\n "64.227.88.245"\n ],\n "user": [\n "user"\n ]\n },\n "service": {\n "type": "system"\n },\n "host": {\n "hostname": "bastion00",\n "name": "bastion00.siem.estc.dev"\n },\n "event": {\n "ingested": "2020-09-04T13:25:47.034172Z",\n "timezone": "+00:00",\n "kind": "event",\n "module": "system",\n "action": "ssh_login",\n "type": [\n "authentication_failure",\n "info"\n ],\n "category": [\n "authentication"\n ],\n "dataset": "system.auth",\n "outcome": "failure"\n },\n "user": {\n "name": "user"\n }\n },\n "sort": [\n 1599225943000\n ]\n }\n ]\n }\n }\n },\n "successes": {\n "doc_count": 0,\n "lastSuccess": {\n "hits": {\n "total": 0,\n "max_score": 0,\n "hits": []\n }\n }\n }\n },\n {\n "key": "ubuntu",\n "doc_count": 18,\n "failures": {\n "doc_count": 18,\n "lastFailure": {\n "hits": {\n "total": 18,\n "max_score": 0,\n "hits": [\n {\n "_index": "filebeat-8.0.0-2020.09.02-000001",\n "_id": "nPxKWXQBc39KFIJb7q4w",\n "_score": null,\n "_source": {\n "agent": {\n "name": "bastion00.siem.estc.dev",\n "id": "f9a321c1-ec27-49fa-aacf-6a50ef6d836f",\n "ephemeral_id": "734ee3da-1a4f-4bc9-b400-e0cf0e5eeebc",\n "type": "filebeat",\n "version": "8.0.0"\n },\n "process": {\n "name": "sshd",\n "pid": 20665\n },\n "log": {\n "file": {\n "path": "/var/log/auth.log"\n },\n "offset": 1027372\n },\n "source": {\n "geo": {\n "continent_name": "North America",\n "region_iso_code": "US-NY",\n "city_name": "New York",\n "country_iso_code": "US",\n "region_name": "New York",\n "location": {\n "lon": -74,\n "lat": 40.7157\n }\n },\n "ip": "64.227.88.245"\n },\n "fileset": {\n "name": "auth"\n },\n "input": {\n "type": "log"\n },\n "@timestamp": "2020-09-04T13:25:07.000Z",\n "system": {\n "auth": {\n "ssh": {\n "event": "Invalid"\n }\n }\n },\n "ecs": {\n "version": "1.5.0"\n },\n "related": {\n "ip": [\n "64.227.88.245"\n ],\n "user": [\n "ubuntu"\n ]\n },\n "service": {\n "type": "system"\n },\n "host": {\n "hostname": "bastion00",\n "name": "bastion00.siem.estc.dev"\n },\n "event": {\n "ingested": "2020-09-04T13:25:16.974606Z",\n "timezone": "+00:00",\n "kind": "event",\n "module": "system",\n "action": "ssh_login",\n "type": [\n "authentication_failure",\n "info"\n ],\n "category": [\n "authentication"\n ],\n "dataset": "system.auth",\n "outcome": "failure"\n },\n "user": {\n "name": "ubuntu"\n }\n },\n "sort": [\n 1599225907000\n ]\n }\n ]\n }\n }\n },\n "successes": {\n "doc_count": 0,\n "lastSuccess": {\n "hits": {\n "total": 0,\n "max_score": 0,\n "hits": []\n }\n }\n }\n },\n {\n "key": "odoo",\n "doc_count": 17,\n "failures": {\n "doc_count": 17,\n "lastFailure": {\n "hits": {\n "total": 17,\n "max_score": 0,\n "hits": [\n {\n "_index": ".ds-logs-system.auth-default-000001",\n "_id": "mPsfWXQBc39KFIJbI8HI",\n "_score": null,\n "_source": {\n "agent": {\n "hostname": "siem-kibana",\n "name": "siem-kibana",\n "id": "aa3d9dc7-fef1-4c2f-a68d-25785d624e35",\n "type": "filebeat",\n "ephemeral_id": "e503bd85-11c7-4bc9-ae7d-70be1d919fb7",\n "version": "7.9.1"\n },\n "process": {\n "name": "sshd",\n "pid": 21506\n },\n "log": {\n "file": {\n "path": "/var/log/auth.log"\n },\n "offset": 556761\n },\n "source": {\n "geo": {\n "continent_name": "Asia",\n "region_iso_code": "IN-DL",\n "city_name": "New Delhi",\n "country_iso_code": "IN",\n "region_name": "National Capital Territory of Delhi",\n "location": {\n "lon": 77.2245,\n "lat": 28.6358\n }\n },\n "as": {\n "number": 10029,\n "organization": {\n "name": "SHYAM SPECTRA PVT LTD"\n }\n },\n "ip": "180.151.228.166"\n },\n "cloud": {\n "availability_zone": "us-east1-b",\n "instance": {\n "name": "siem-kibana",\n "id": "5412578377715150143"\n },\n "provider": "gcp",\n "machine": {\n "type": "n1-standard-2"\n },\n "project": {\n "id": "elastic-beats"\n }\n },\n "input": {\n "type": "log"\n },\n "@timestamp": "2020-09-04T12:26:36.000Z",\n "system": {\n "auth": {\n "ssh": {\n "event": "Invalid"\n }\n }\n },\n "ecs": {\n "version": "1.5.0"\n },\n "data_stream": {\n "namespace": "default",\n "type": "logs",\n "dataset": "system.auth"\n },\n "host": {\n "hostname": "siem-kibana",\n "os": {\n "kernel": "4.9.0-8-amd64",\n "codename": "stretch",\n "name": "Debian GNU/Linux",\n "family": "debian",\n "version": "9 (stretch)",\n "platform": "debian"\n },\n "containerized": false,\n "ip": [\n "10.142.0.7",\n "fe80::4001:aff:fe8e:7"\n ],\n "name": "siem-kibana",\n "id": "aa7ca589f1b8220002f2fc61c64cfbf1",\n "mac": [\n "42:01:0a:8e:00:07"\n ],\n "architecture": "x86_64"\n },\n "event": {\n "timezone": "+00:00",\n "action": "ssh_login",\n "type": "authentication_failure",\n "category": "authentication",\n "dataset": "system.auth",\n "outcome": "failure"\n },\n "user": {\n "name": "odoo"\n }\n },\n "sort": [\n 1599222396000\n ]\n }\n ]\n }\n }\n },\n "successes": {\n "doc_count": 0,\n "lastSuccess": {\n "hits": {\n "total": 0,\n "max_score": 0,\n "hits": []\n }\n }\n }\n },\n {\n "key": "pi",\n "doc_count": 17,\n "failures": {\n "doc_count": 17,\n "lastFailure": {\n "hits": {\n "total": 17,\n "max_score": 0,\n "hits": [\n {\n "_index": "filebeat-8.0.0-2020.09.02-000001",\n "_id": "aaToWHQBA6bGZw2uR-St",\n "_score": null,\n "_source": {\n "agent": {\n "name": "bastion00.siem.estc.dev",\n "id": "f9a321c1-ec27-49fa-aacf-6a50ef6d836f",\n "type": "filebeat",\n "ephemeral_id": "734ee3da-1a4f-4bc9-b400-e0cf0e5eeebc",\n "version": "8.0.0"\n },\n "process": {\n "name": "sshd",\n "pid": 20475\n },\n "log": {\n "file": {\n "path": "/var/log/auth.log"\n },\n "offset": 1019218\n },\n "source": {\n "geo": {\n "continent_name": "Europe",\n "region_iso_code": "SE-AB",\n "city_name": "Stockholm",\n "country_iso_code": "SE",\n "region_name": "Stockholm",\n "location": {\n "lon": 17.7833,\n "lat": 59.25\n }\n },\n "as": {\n "number": 8473,\n "organization": {\n "name": "Bahnhof AB"\n }\n },\n "ip": "178.174.148.58"\n },\n "fileset": {\n "name": "auth"\n },\n "input": {\n "type": "log"\n },\n "@timestamp": "2020-09-04T11:37:22.000Z",\n "system": {\n "auth": {\n "ssh": {\n "event": "Invalid"\n }\n }\n },\n "ecs": {\n "version": "1.5.0"\n },\n "related": {\n "ip": [\n "178.174.148.58"\n ],\n "user": [\n "pi"\n ]\n },\n "service": {\n "type": "system"\n },\n "host": {\n "hostname": "bastion00",\n "name": "bastion00.siem.estc.dev"\n },\n "event": {\n "ingested": "2020-09-04T11:37:31.797423Z",\n "timezone": "+00:00",\n "kind": "event",\n "module": "system",\n "action": "ssh_login",\n "type": [\n "authentication_failure",\n "info"\n ],\n "category": [\n "authentication"\n ],\n "dataset": "system.auth",\n "outcome": "failure"\n },\n "user": {\n "name": "pi"\n }\n },\n "sort": [\n 1599219442000\n ]\n }\n ]\n }\n }\n },\n "successes": {\n "doc_count": 0,\n "lastSuccess": {\n "hits": {\n "total": 0,\n "max_score": 0,\n "hits": []\n }\n }\n }\n },\n {\n "key": "demo",\n "doc_count": 14,\n "failures": {\n "doc_count": 14,\n "lastFailure": {\n "hits": {\n "total": 14,\n "max_score": 0,\n "hits": [\n {\n "_index": "filebeat-8.0.0-2020.09.02-000001",\n "_id": "VaP_V3QBA6bGZw2upUbg",\n "_score": null,\n "_source": {\n "agent": {\n "name": "bastion00.siem.estc.dev",\n "id": "f9a321c1-ec27-49fa-aacf-6a50ef6d836f",\n "type": "filebeat",\n "ephemeral_id": "734ee3da-1a4f-4bc9-b400-e0cf0e5eeebc",\n "version": "8.0.0"\n },\n "process": {\n "name": "sshd",\n "pid": 19849\n },\n "log": {\n "file": {\n "path": "/var/log/auth.log"\n },\n "offset": 981036\n },\n "source": {\n "geo": {\n "continent_name": "Europe",\n "country_iso_code": "HR",\n "location": {\n "lon": 15.5,\n "lat": 45.1667\n }\n },\n "as": {\n "number": 42864,\n "organization": {\n "name": "Giganet Internet Szolgaltato Kft"\n }\n },\n "ip": "45.95.168.157"\n },\n "fileset": {\n "name": "auth"\n },\n "input": {\n "type": "log"\n },\n "@timestamp": "2020-09-04T07:23:22.000Z",\n "system": {\n "auth": {\n "ssh": {\n "event": "Invalid"\n }\n }\n },\n "ecs": {\n "version": "1.5.0"\n },\n "related": {\n "ip": [\n "45.95.168.157"\n ],\n "user": [\n "demo"\n ]\n },\n "service": {\n "type": "system"\n },\n "host": {\n "hostname": "bastion00",\n "name": "bastion00.siem.estc.dev"\n },\n "event": {\n "ingested": "2020-09-04T07:23:26.046346Z",\n "timezone": "+00:00",\n "kind": "event",\n "module": "system",\n "action": "ssh_login",\n "type": [\n "authentication_failure",\n "info"\n ],\n "category": [\n "authentication"\n ],\n "dataset": "system.auth",\n "outcome": "failure"\n },\n "user": {\n "name": "demo"\n }\n },\n "sort": [\n 1599204202000\n ]\n }\n ]\n }\n }\n },\n "successes": {\n "doc_count": 0,\n "lastSuccess": {\n "hits": {\n "total": 0,\n "max_score": 0,\n "hits": []\n }\n }\n }\n },\n {\n "key": "git",\n "doc_count": 13,\n "failures": {\n "doc_count": 13,\n "lastFailure": {\n "hits": {\n "total": 13,\n "max_score": 0,\n "hits": [\n {\n "_index": ".ds-logs-system.auth-default-000001",\n "_id": "PqYfWXQBA6bGZw2uIhVU",\n "_score": null,\n "_source": {\n "agent": {\n "hostname": "siem-kibana",\n "name": "siem-kibana",\n "id": "aa3d9dc7-fef1-4c2f-a68d-25785d624e35",\n "ephemeral_id": "e503bd85-11c7-4bc9-ae7d-70be1d919fb7",\n "type": "filebeat",\n "version": "7.9.1"\n },\n "process": {\n "name": "sshd",\n "pid": 20396\n },\n "log": {\n "file": {\n "path": "/var/log/auth.log"\n },\n "offset": 550795\n },\n "source": {\n "geo": {\n "continent_name": "Asia",\n "region_iso_code": "CN-BJ",\n "city_name": "Beijing",\n "country_iso_code": "CN",\n "region_name": "Beijing",\n "location": {\n "lon": 116.3889,\n "lat": 39.9288\n }\n },\n "as": {\n "number": 45090,\n "organization": {\n "name": "Shenzhen Tencent Computer Systems Company Limited"\n }\n },\n "ip": "123.206.30.76"\n },\n "cloud": {\n "availability_zone": "us-east1-b",\n "instance": {\n "name": "siem-kibana",\n "id": "5412578377715150143"\n },\n "provider": "gcp",\n "machine": {\n "type": "n1-standard-2"\n },\n "project": {\n "id": "elastic-beats"\n }\n },\n "input": {\n "type": "log"\n },\n "@timestamp": "2020-09-04T11:20:26.000Z",\n "system": {\n "auth": {\n "ssh": {\n "event": "Invalid"\n }\n }\n },\n "ecs": {\n "version": "1.5.0"\n },\n "data_stream": {\n "namespace": "default",\n "type": "logs",\n "dataset": "system.auth"\n },\n "host": {\n "hostname": "siem-kibana",\n "os": {\n "kernel": "4.9.0-8-amd64",\n "codename": "stretch",\n "name": "Debian GNU/Linux",\n "family": "debian",\n "version": "9 (stretch)",\n "platform": "debian"\n },\n "containerized": false,\n "ip": [\n "10.142.0.7",\n "fe80::4001:aff:fe8e:7"\n ],\n "name": "siem-kibana",\n "id": "aa7ca589f1b8220002f2fc61c64cfbf1",\n "mac": [\n "42:01:0a:8e:00:07"\n ],\n "architecture": "x86_64"\n },\n "event": {\n "timezone": "+00:00",\n "action": "ssh_login",\n "type": "authentication_failure",\n "category": "authentication",\n "dataset": "system.auth",\n "outcome": "failure"\n },\n "user": {\n "name": "git"\n }\n },\n "sort": [\n 1599218426000\n ]\n }\n ]\n }\n }\n },\n "successes": {\n "doc_count": 0,\n "lastSuccess": {\n "hits": {\n "total": 0,\n "max_score": 0,\n "hits": []\n }\n }\n }\n },\n {\n "key": "webadmin",\n "doc_count": 13,\n "failures": {\n "doc_count": 13,\n "lastFailure": {\n "hits": {\n "total": 13,\n "max_score": 0,\n "hits": [\n {\n "_index": "filebeat-8.0.0-2020.09.02-000001",\n "_id": "iMABWHQBB-gskclyitP-",\n "_score": null,\n "_source": {\n "agent": {\n "name": "bastion00.siem.estc.dev",\n "id": "f9a321c1-ec27-49fa-aacf-6a50ef6d836f",\n "type": "filebeat",\n "ephemeral_id": "734ee3da-1a4f-4bc9-b400-e0cf0e5eeebc",\n "version": "8.0.0"\n },\n "process": {\n "name": "sshd",\n "pid": 19870\n },\n "log": {\n "file": {\n "path": "/var/log/auth.log"\n },\n "offset": 984133\n },\n "source": {\n "geo": {\n "continent_name": "Europe",\n "country_iso_code": "HR",\n "location": {\n "lon": 15.5,\n "lat": 45.1667\n }\n },\n "as": {\n "number": 42864,\n "organization": {\n "name": "Giganet Internet Szolgaltato Kft"\n }\n },\n "ip": "45.95.168.157"\n },\n "fileset": {\n "name": "auth"\n },\n "input": {\n "type": "log"\n },\n "@timestamp": "2020-09-04T07:25:28.000Z",\n "system": {\n "auth": {\n "ssh": {\n "event": "Invalid"\n }\n }\n },\n "ecs": {\n "version": "1.5.0"\n },\n "related": {\n "ip": [\n "45.95.168.157"\n ],\n "user": [\n "webadmin"\n ]\n },\n "service": {\n "type": "system"\n },\n "host": {\n "hostname": "bastion00",\n "name": "bastion00.siem.estc.dev"\n },\n "event": {\n "ingested": "2020-09-04T07:25:30.236651Z",\n "timezone": "+00:00",\n "kind": "event",\n "module": "system",\n "action": "ssh_login",\n "type": [\n "authentication_failure",\n "info"\n ],\n "category": [\n "authentication"\n ],\n "dataset": "system.auth",\n "outcome": "failure"\n },\n "user": {\n "name": "webadmin"\n }\n },\n "sort": [\n 1599204328000\n ]\n }\n ]\n }\n }\n },\n "successes": {\n "doc_count": 0,\n "lastSuccess": {\n "hits": {\n "total": 0,\n "max_score": 0,\n "hits": []\n }\n }\n }\n }\n ]\n },\n "user_count": {\n "value": 188\n }\n }\n },\n "total": 21,\n "loaded": 21\n}', + '{\n "allowNoIndices": true,\n "index": [\n "apm-*-transaction*",\n "auditbeat-*",\n "endgame-*",\n "filebeat-*",\n "logs-*",\n "packetbeat-*",\n "winlogbeat-*"\n ],\n "ignoreUnavailable": true,\n "body": {\n "aggregations": {\n "host_architecture": {\n "terms": {\n "field": "host.architecture",\n "size": 10,\n "order": {\n "timestamp": "desc"\n }\n },\n "aggs": {\n "timestamp": {\n "max": {\n "field": "@timestamp"\n }\n }\n }\n },\n "host_id": {\n "terms": {\n "field": "host.id",\n "size": 10,\n "order": {\n "timestamp": "desc"\n }\n },\n "aggs": {\n "timestamp": {\n "max": {\n "field": "@timestamp"\n }\n }\n }\n },\n "host_ip": {\n "terms": {\n "field": "host.ip",\n "size": 10,\n "order": {\n "timestamp": "desc"\n }\n },\n "aggs": {\n "timestamp": {\n "max": {\n "field": "@timestamp"\n }\n }\n }\n },\n "host_mac": {\n "terms": {\n "field": "host.mac",\n "size": 10,\n "order": {\n "timestamp": "desc"\n }\n },\n "aggs": {\n "timestamp": {\n "max": {\n "field": "@timestamp"\n }\n }\n }\n },\n "host_name": {\n "terms": {\n "field": "host.name",\n "size": 10,\n "order": {\n "timestamp": "desc"\n }\n },\n "aggs": {\n "timestamp": {\n "max": {\n "field": "@timestamp"\n }\n }\n }\n },\n "host_os_family": {\n "terms": {\n "field": "host.os.family",\n "size": 10,\n "order": {\n "timestamp": "desc"\n }\n },\n "aggs": {\n "timestamp": {\n "max": {\n "field": "@timestamp"\n }\n }\n }\n },\n "host_os_name": {\n "terms": {\n "field": "host.os.name",\n "size": 10,\n "order": {\n "timestamp": "desc"\n }\n },\n "aggs": {\n "timestamp": {\n "max": {\n "field": "@timestamp"\n }\n }\n }\n },\n "host_os_platform": {\n "terms": {\n "field": "host.os.platform",\n "size": 10,\n "order": {\n "timestamp": "desc"\n }\n },\n "aggs": {\n "timestamp": {\n "max": {\n "field": "@timestamp"\n }\n }\n }\n },\n "host_os_version": {\n "terms": {\n "field": "host.os.version",\n "size": 10,\n "order": {\n "timestamp": "desc"\n }\n },\n "aggs": {\n "timestamp": {\n "max": {\n "field": "@timestamp"\n }\n }\n }\n },\n "cloud_instance_id": {\n "terms": {\n "field": "cloud.instance.id",\n "size": 10,\n "order": {\n "timestamp": "desc"\n }\n },\n "aggs": {\n "timestamp": {\n "max": {\n "field": "@timestamp"\n }\n }\n }\n },\n "cloud_machine_type": {\n "terms": {\n "field": "cloud.machine.type",\n "size": 10,\n "order": {\n "timestamp": "desc"\n }\n },\n "aggs": {\n "timestamp": {\n "max": {\n "field": "@timestamp"\n }\n }\n }\n },\n "cloud_provider": {\n "terms": {\n "field": "cloud.provider",\n "size": 10,\n "order": {\n "timestamp": "desc"\n }\n },\n "aggs": {\n "timestamp": {\n "max": {\n "field": "@timestamp"\n }\n }\n }\n },\n "cloud_region": {\n "terms": {\n "field": "cloud.region",\n "size": 10,\n "order": {\n "timestamp": "desc"\n }\n },\n "aggs": {\n "timestamp": {\n "max": {\n "field": "@timestamp"\n }\n }\n }\n }\n },\n "query": {\n "bool": {\n "filter": [\n {\n "term": {\n "host.name": "bastion00.siem.estc.dev"\n }\n },\n {\n "range": {\n "@timestamp": {\n "format": "strict_date_optional_time",\n "gte": "2020-09-02T15:17:13.678Z",\n "lte": "2020-09-03T15:17:13.678Z"\n }\n }\n }\n ]\n }\n },\n "size": 0,\n "track_total_hits": false\n }\n}', ], }, hostDetails: {}, @@ -2158,62 +1317,222 @@ export const expectedDsl = { body: { aggregations: { host_architecture: { - terms: { field: 'host.architecture', size: 10, order: { timestamp: 'desc' } }, - aggs: { timestamp: { max: { field: '@timestamp' } } }, + terms: { + field: 'host.architecture', + size: 10, + order: { + timestamp: 'desc', + }, + }, + aggs: { + timestamp: { + max: { + field: '@timestamp', + }, + }, + }, }, host_id: { - terms: { field: 'host.id', size: 10, order: { timestamp: 'desc' } }, - aggs: { timestamp: { max: { field: '@timestamp' } } }, + terms: { + field: 'host.id', + size: 10, + order: { + timestamp: 'desc', + }, + }, + aggs: { + timestamp: { + max: { + field: '@timestamp', + }, + }, + }, }, host_ip: { - terms: { field: 'host.ip', size: 10, order: { timestamp: 'desc' } }, - aggs: { timestamp: { max: { field: '@timestamp' } } }, + terms: { + field: 'host.ip', + size: 10, + order: { + timestamp: 'desc', + }, + }, + aggs: { + timestamp: { + max: { + field: '@timestamp', + }, + }, + }, }, host_mac: { - terms: { field: 'host.mac', size: 10, order: { timestamp: 'desc' } }, - aggs: { timestamp: { max: { field: '@timestamp' } } }, + terms: { + field: 'host.mac', + size: 10, + order: { + timestamp: 'desc', + }, + }, + aggs: { + timestamp: { + max: { + field: '@timestamp', + }, + }, + }, }, host_name: { - terms: { field: 'host.name', size: 10, order: { timestamp: 'desc' } }, - aggs: { timestamp: { max: { field: '@timestamp' } } }, + terms: { + field: 'host.name', + size: 10, + order: { + timestamp: 'desc', + }, + }, + aggs: { + timestamp: { + max: { + field: '@timestamp', + }, + }, + }, }, host_os_family: { - terms: { field: 'host.os.family', size: 10, order: { timestamp: 'desc' } }, - aggs: { timestamp: { max: { field: '@timestamp' } } }, + terms: { + field: 'host.os.family', + size: 10, + order: { + timestamp: 'desc', + }, + }, + aggs: { + timestamp: { + max: { + field: '@timestamp', + }, + }, + }, }, host_os_name: { - terms: { field: 'host.os.name', size: 10, order: { timestamp: 'desc' } }, - aggs: { timestamp: { max: { field: '@timestamp' } } }, + terms: { + field: 'host.os.name', + size: 10, + order: { + timestamp: 'desc', + }, + }, + aggs: { + timestamp: { + max: { + field: '@timestamp', + }, + }, + }, }, host_os_platform: { - terms: { field: 'host.os.platform', size: 10, order: { timestamp: 'desc' } }, - aggs: { timestamp: { max: { field: '@timestamp' } } }, + terms: { + field: 'host.os.platform', + size: 10, + order: { + timestamp: 'desc', + }, + }, + aggs: { + timestamp: { + max: { + field: '@timestamp', + }, + }, + }, }, host_os_version: { - terms: { field: 'host.os.version', size: 10, order: { timestamp: 'desc' } }, - aggs: { timestamp: { max: { field: '@timestamp' } } }, + terms: { + field: 'host.os.version', + size: 10, + order: { + timestamp: 'desc', + }, + }, + aggs: { + timestamp: { + max: { + field: '@timestamp', + }, + }, + }, }, cloud_instance_id: { - terms: { field: 'cloud.instance.id', size: 10, order: { timestamp: 'desc' } }, - aggs: { timestamp: { max: { field: '@timestamp' } } }, + terms: { + field: 'cloud.instance.id', + size: 10, + order: { + timestamp: 'desc', + }, + }, + aggs: { + timestamp: { + max: { + field: '@timestamp', + }, + }, + }, }, cloud_machine_type: { - terms: { field: 'cloud.machine.type', size: 10, order: { timestamp: 'desc' } }, - aggs: { timestamp: { max: { field: '@timestamp' } } }, + terms: { + field: 'cloud.machine.type', + size: 10, + order: { + timestamp: 'desc', + }, + }, + aggs: { + timestamp: { + max: { + field: '@timestamp', + }, + }, + }, }, cloud_provider: { - terms: { field: 'cloud.provider', size: 10, order: { timestamp: 'desc' } }, - aggs: { timestamp: { max: { field: '@timestamp' } } }, + terms: { + field: 'cloud.provider', + size: 10, + order: { + timestamp: 'desc', + }, + }, + aggs: { + timestamp: { + max: { + field: '@timestamp', + }, + }, + }, }, cloud_region: { - terms: { field: 'cloud.region', size: 10, order: { timestamp: 'desc' } }, - aggs: { timestamp: { max: { field: '@timestamp' } } }, + terms: { + field: 'cloud.region', + size: 10, + order: { + timestamp: 'desc', + }, + }, + aggs: { + timestamp: { + max: { + field: '@timestamp', + }, + }, + }, }, }, query: { bool: { filter: [ - { term: { 'host.name': 'bastion00' } }, + { + term: { + 'host.name': 'bastion00.siem.estc.dev', + }, + }, { range: { '@timestamp': { diff --git a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/hosts/details/index.ts b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/hosts/details/index.ts index 616e4ed0bac38..8913f72aad61e 100644 --- a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/hosts/details/index.ts +++ b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/hosts/details/index.ts @@ -29,10 +29,8 @@ export const hostDetails: SecuritySolutionFactory = { const aggregations: HostAggEsItem = get('aggregations', response.rawResponse) || {}; const inspect = { dsl: [inspectStringifyObject(buildHostDetailsQuery(options))], - response: [inspectStringifyObject(response)], }; const formattedHostItem = formatHostItem(aggregations); - return { ...response, inspect, hostDetails: formattedHostItem }; }, }; diff --git a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/hosts/details/query.host_details.dsl.test.ts b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/hosts/details/query.host_details.dsl.test.ts index eab1966434859..ad1fabd156fad 100644 --- a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/hosts/details/query.host_details.dsl.test.ts +++ b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/hosts/details/query.host_details.dsl.test.ts @@ -3,11 +3,11 @@ * or more contributor license agreements. Licensed under the Elastic License; * you may not use this file except in compliance with the Elastic License. */ -import { buildHostDetailsQuery as buildQuery } from './query.host_details.dsl'; +import { buildHostDetailsQuery } from './query.host_details.dsl'; import { mockOptions, expectedDsl } from './__mocks__/'; -describe('buildQuery', () => { +describe('buildHostDetailsQuery', () => { test('build query from options correctly', () => { - expect(buildQuery(mockOptions)).toEqual(expectedDsl); + expect(buildHostDetailsQuery(mockOptions)).toEqual(expectedDsl); }); }); diff --git a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/details/__mocks__/index.ts b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/details/__mocks__/index.ts new file mode 100644 index 0000000000000..fbe007622005c --- /dev/null +++ b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/details/__mocks__/index.ts @@ -0,0 +1,377 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { IEsSearchResponse } from '../../../../../../../../../../src/plugins/data/common'; + +import { + NetworkDetailsRequestOptions, + NetworkQueries, +} from '../../../../../../../common/search_strategy'; + +export const mockOptions: NetworkDetailsRequestOptions = { + defaultIndex: [ + 'apm-*-transaction*', + 'auditbeat-*', + 'endgame-*', + 'filebeat-*', + 'logs-*', + 'packetbeat-*', + 'winlogbeat-*', + ], + docValueFields: [ + { field: '@timestamp', format: 'date_time' }, + { field: 'event.created', format: 'date_time' }, + { field: 'event.end', format: 'date_time' }, + { field: 'event.ingested', format: 'date_time' }, + { field: 'event.start', format: 'date_time' }, + { field: 'file.accessed', format: 'date_time' }, + { field: 'file.created', format: 'date_time' }, + { field: 'file.ctime', format: 'date_time' }, + { field: 'file.mtime', format: 'date_time' }, + { field: 'package.installed', format: 'date_time' }, + { field: 'process.parent.start', format: 'date_time' }, + { field: 'process.start', format: 'date_time' }, + { field: 'system.audit.host.boottime', format: 'date_time' }, + { field: 'system.audit.package.installtime', format: 'date_time' }, + { field: 'system.audit.user.password.last_changed', format: 'date_time' }, + { field: 'tls.client.not_after', format: 'date_time' }, + { field: 'tls.client.not_before', format: 'date_time' }, + { field: 'tls.server.not_after', format: 'date_time' }, + { field: 'tls.server.not_before', format: 'date_time' }, + { field: 'aws.cloudtrail.user_identity.session_context.creation_date', format: 'date_time' }, + { field: 'azure.auditlogs.properties.activity_datetime', format: 'date_time' }, + { field: 'azure.enqueued_time', format: 'date_time' }, + { field: 'azure.signinlogs.properties.created_at', format: 'date_time' }, + { field: 'cef.extensions.agentReceiptTime', format: 'date_time' }, + { field: 'cef.extensions.deviceCustomDate1', format: 'date_time' }, + { field: 'cef.extensions.deviceCustomDate2', format: 'date_time' }, + { field: 'cef.extensions.deviceReceiptTime', format: 'date_time' }, + { field: 'cef.extensions.endTime', format: 'date_time' }, + { field: 'cef.extensions.fileCreateTime', format: 'date_time' }, + { field: 'cef.extensions.fileModificationTime', format: 'date_time' }, + { field: 'cef.extensions.flexDate1', format: 'date_time' }, + { field: 'cef.extensions.managerReceiptTime', format: 'date_time' }, + { field: 'cef.extensions.oldFileCreateTime', format: 'date_time' }, + { field: 'cef.extensions.oldFileModificationTime', format: 'date_time' }, + { field: 'cef.extensions.startTime', format: 'date_time' }, + { field: 'checkpoint.subs_exp', format: 'date_time' }, + { field: 'crowdstrike.event.EndTimestamp', format: 'date_time' }, + { field: 'crowdstrike.event.IncidentEndTime', format: 'date_time' }, + { field: 'crowdstrike.event.IncidentStartTime', format: 'date_time' }, + { field: 'crowdstrike.event.ProcessEndTime', format: 'date_time' }, + { field: 'crowdstrike.event.ProcessStartTime', format: 'date_time' }, + { field: 'crowdstrike.event.StartTimestamp', format: 'date_time' }, + { field: 'crowdstrike.event.Timestamp', format: 'date_time' }, + { field: 'crowdstrike.event.UTCTimestamp', format: 'date_time' }, + { field: 'crowdstrike.metadata.eventCreationTime', format: 'date_time' }, + { field: 'gsuite.admin.email.log_search_filter.end_date', format: 'date_time' }, + { field: 'gsuite.admin.email.log_search_filter.start_date', format: 'date_time' }, + { field: 'gsuite.admin.user.birthdate', format: 'date_time' }, + { field: 'kafka.block_timestamp', format: 'date_time' }, + { field: 'microsoft.defender_atp.lastUpdateTime', format: 'date_time' }, + { field: 'microsoft.defender_atp.resolvedTime', format: 'date_time' }, + { field: 'misp.campaign.first_seen', format: 'date_time' }, + { field: 'misp.campaign.last_seen', format: 'date_time' }, + { field: 'misp.intrusion_set.first_seen', format: 'date_time' }, + { field: 'misp.intrusion_set.last_seen', format: 'date_time' }, + { field: 'misp.observed_data.first_observed', format: 'date_time' }, + { field: 'misp.observed_data.last_observed', format: 'date_time' }, + { field: 'misp.report.published', format: 'date_time' }, + { field: 'misp.threat_indicator.valid_from', format: 'date_time' }, + { field: 'misp.threat_indicator.valid_until', format: 'date_time' }, + { field: 'netflow.collection_time_milliseconds', format: 'date_time' }, + { field: 'netflow.exporter.timestamp', format: 'date_time' }, + { field: 'netflow.flow_end_microseconds', format: 'date_time' }, + { field: 'netflow.flow_end_milliseconds', format: 'date_time' }, + { field: 'netflow.flow_end_nanoseconds', format: 'date_time' }, + { field: 'netflow.flow_end_seconds', format: 'date_time' }, + { field: 'netflow.flow_start_microseconds', format: 'date_time' }, + { field: 'netflow.flow_start_milliseconds', format: 'date_time' }, + { field: 'netflow.flow_start_nanoseconds', format: 'date_time' }, + { field: 'netflow.flow_start_seconds', format: 'date_time' }, + { field: 'netflow.max_export_seconds', format: 'date_time' }, + { field: 'netflow.max_flow_end_microseconds', format: 'date_time' }, + { field: 'netflow.max_flow_end_milliseconds', format: 'date_time' }, + { field: 'netflow.max_flow_end_nanoseconds', format: 'date_time' }, + { field: 'netflow.max_flow_end_seconds', format: 'date_time' }, + { field: 'netflow.min_export_seconds', format: 'date_time' }, + { field: 'netflow.min_flow_start_microseconds', format: 'date_time' }, + { field: 'netflow.min_flow_start_milliseconds', format: 'date_time' }, + { field: 'netflow.min_flow_start_nanoseconds', format: 'date_time' }, + { field: 'netflow.min_flow_start_seconds', format: 'date_time' }, + { field: 'netflow.monitoring_interval_end_milli_seconds', format: 'date_time' }, + { field: 'netflow.monitoring_interval_start_milli_seconds', format: 'date_time' }, + { field: 'netflow.observation_time_microseconds', format: 'date_time' }, + { field: 'netflow.observation_time_milliseconds', format: 'date_time' }, + { field: 'netflow.observation_time_nanoseconds', format: 'date_time' }, + { field: 'netflow.observation_time_seconds', format: 'date_time' }, + { field: 'netflow.system_init_time_milliseconds', format: 'date_time' }, + { field: 'rsa.internal.lc_ctime', format: 'date_time' }, + { field: 'rsa.internal.time', format: 'date_time' }, + { field: 'rsa.time.effective_time', format: 'date_time' }, + { field: 'rsa.time.endtime', format: 'date_time' }, + { field: 'rsa.time.event_queue_time', format: 'date_time' }, + { field: 'rsa.time.event_time', format: 'date_time' }, + { field: 'rsa.time.expire_time', format: 'date_time' }, + { field: 'rsa.time.recorded_time', format: 'date_time' }, + { field: 'rsa.time.stamp', format: 'date_time' }, + { field: 'rsa.time.starttime', format: 'date_time' }, + { field: 'sophos.xg.date', format: 'date_time' }, + { field: 'sophos.xg.eventtime', format: 'date_time' }, + { field: 'sophos.xg.start_time', format: 'date_time' }, + ], + factoryQueryType: NetworkQueries.details, + filterQuery: '{"bool":{"must":[],"filter":[{"match_all":{}}],"should":[],"must_not":[]}}', + ip: '35.196.65.164', +}; + +export const mockSearchStrategyResponse: IEsSearchResponse = { + isPartial: false, + isRunning: false, + rawResponse: { + took: 2620, + timed_out: false, + _shards: { total: 21, successful: 21, skipped: 0, failed: 0 }, + hits: { total: 0, max_score: 0, hits: [] }, + aggregations: { + host: { + doc_count: 0, + results: { hits: { total: { value: 0, relation: 'eq' }, max_score: null, hits: [] } }, + }, + destination: { + meta: {}, + doc_count: 5, + geo: { + meta: {}, + doc_count: 5, + results: { + hits: { + total: { value: 5, relation: 'eq' }, + max_score: null, + hits: [ + { + _index: 'filebeat-8.0.0-2020.09.02-000001', + _id: 'dd4fa2d4bd-1523631609876537', + _score: null, + _source: { + destination: { + geo: { + continent_name: 'North America', + region_iso_code: 'US-VA', + country_iso_code: 'US', + region_name: 'Virginia', + location: { lon: -77.2481, lat: 38.6583 }, + }, + }, + }, + sort: [1599703212208], + }, + ], + }, + }, + }, + as: { + meta: {}, + doc_count: 5, + results: { + hits: { + total: { value: 5, relation: 'eq' }, + max_score: null, + hits: [ + { + _index: 'filebeat-8.0.0-2020.09.02-000001', + _id: 'dd4fa2d4bd-1523631609876537', + _score: null, + _source: { + destination: { as: { number: 15169, organization: { name: 'Google LLC' } } }, + }, + sort: [1599703212208], + }, + ], + }, + }, + }, + lastSeen: { value: 1599703212208, value_as_string: '2020-09-10T02:00:12.208Z' }, + firstSeen: { value: 1598802015355, value_as_string: '2020-08-30T15:40:15.355Z' }, + }, + source: { + meta: {}, + doc_count: 5, + geo: { + meta: {}, + doc_count: 5, + results: { + hits: { + total: { value: 5, relation: 'eq' }, + max_score: null, + hits: [ + { + _index: 'filebeat-8.0.0-2020.09.02-000001', + _id: 'dd4fa2d4bd-1523631486500511', + _score: null, + _source: { + source: { + geo: { + continent_name: 'North America', + region_iso_code: 'US-VA', + country_iso_code: 'US', + region_name: 'Virginia', + location: { lon: -77.2481, lat: 38.6583 }, + }, + }, + }, + sort: [1599703214494], + }, + ], + }, + }, + }, + as: { + meta: {}, + doc_count: 5, + results: { + hits: { + total: { value: 5, relation: 'eq' }, + max_score: null, + hits: [ + { + _index: 'filebeat-8.0.0-2020.09.02-000001', + _id: 'dd4fa2d4bd-1523631486500511', + _score: null, + _source: { + source: { as: { number: 15169, organization: { name: 'Google LLC' } } }, + }, + sort: [1599703214494], + }, + ], + }, + }, + }, + lastSeen: { value: 1599703214494, value_as_string: '2020-09-10T02:00:14.494Z' }, + firstSeen: { value: 1598802015107, value_as_string: '2020-08-30T15:40:15.107Z' }, + }, + }, + }, + total: 21, + loaded: 21, +}; + +export const formattedSearchStrategyResponse = { + ...mockSearchStrategyResponse, + inspect: { + dsl: [ + '{\n "allowNoIndices": true,\n "index": [\n "apm-*-transaction*",\n "auditbeat-*",\n "endgame-*",\n "filebeat-*",\n "logs-*",\n "packetbeat-*",\n "winlogbeat-*"\n ],\n "ignoreUnavailable": true,\n "body": {\n "aggs": {\n "source": {\n "filter": {\n "term": {\n "source.ip": "35.196.65.164"\n }\n },\n "aggs": {\n "firstSeen": {\n "min": {\n "field": "@timestamp"\n }\n },\n "lastSeen": {\n "max": {\n "field": "@timestamp"\n }\n },\n "as": {\n "filter": {\n "exists": {\n "field": "source.as"\n }\n },\n "aggs": {\n "results": {\n "top_hits": {\n "size": 1,\n "_source": [\n "source.as"\n ],\n "sort": [\n {\n "@timestamp": "desc"\n }\n ]\n }\n }\n }\n },\n "geo": {\n "filter": {\n "exists": {\n "field": "source.geo"\n }\n },\n "aggs": {\n "results": {\n "top_hits": {\n "size": 1,\n "_source": [\n "source.geo"\n ],\n "sort": [\n {\n "@timestamp": "desc"\n }\n ]\n }\n }\n }\n }\n }\n },\n "destination": {\n "filter": {\n "term": {\n "destination.ip": "35.196.65.164"\n }\n },\n "aggs": {\n "firstSeen": {\n "min": {\n "field": "@timestamp"\n }\n },\n "lastSeen": {\n "max": {\n "field": "@timestamp"\n }\n },\n "as": {\n "filter": {\n "exists": {\n "field": "destination.as"\n }\n },\n "aggs": {\n "results": {\n "top_hits": {\n "size": 1,\n "_source": [\n "destination.as"\n ],\n "sort": [\n {\n "@timestamp": "desc"\n }\n ]\n }\n }\n }\n },\n "geo": {\n "filter": {\n "exists": {\n "field": "destination.geo"\n }\n },\n "aggs": {\n "results": {\n "top_hits": {\n "size": 1,\n "_source": [\n "destination.geo"\n ],\n "sort": [\n {\n "@timestamp": "desc"\n }\n ]\n }\n }\n }\n }\n }\n },\n "host": {\n "filter": {\n "term": {\n "host.ip": "35.196.65.164"\n }\n },\n "aggs": {\n "results": {\n "top_hits": {\n "size": 1,\n "_source": [\n "host"\n ],\n "sort": [\n {\n "@timestamp": "desc"\n }\n ]\n }\n }\n }\n }\n },\n "query": {\n "bool": {\n "should": []\n }\n },\n "size": 0,\n "track_total_hits": false\n }\n}', + ], + }, + networkDetails: { + source: { + firstSeen: '2020-08-30T15:40:15.107Z', + lastSeen: '2020-09-10T02:00:14.494Z', + autonomousSystem: { number: 15169, organization: { name: 'Google LLC' } }, + geo: { + continent_name: 'North America', + region_iso_code: 'US-VA', + country_iso_code: 'US', + region_name: 'Virginia', + location: { lon: -77.2481, lat: 38.6583 }, + }, + }, + destination: { + firstSeen: '2020-08-30T15:40:15.355Z', + lastSeen: '2020-09-10T02:00:12.208Z', + autonomousSystem: { number: 15169, organization: { name: 'Google LLC' } }, + geo: { + continent_name: 'North America', + region_iso_code: 'US-VA', + country_iso_code: 'US', + region_name: 'Virginia', + location: { lon: -77.2481, lat: 38.6583 }, + }, + }, + host: {}, + }, +}; + +export const expectedDsl = { + allowNoIndices: true, + index: [ + 'apm-*-transaction*', + 'auditbeat-*', + 'endgame-*', + 'filebeat-*', + 'logs-*', + 'packetbeat-*', + 'winlogbeat-*', + ], + ignoreUnavailable: true, + body: { + aggs: { + source: { + filter: { term: { 'source.ip': '35.196.65.164' } }, + aggs: { + firstSeen: { min: { field: '@timestamp' } }, + lastSeen: { max: { field: '@timestamp' } }, + as: { + filter: { exists: { field: 'source.as' } }, + aggs: { + results: { + top_hits: { size: 1, _source: ['source.as'], sort: [{ '@timestamp': 'desc' }] }, + }, + }, + }, + geo: { + filter: { exists: { field: 'source.geo' } }, + aggs: { + results: { + top_hits: { size: 1, _source: ['source.geo'], sort: [{ '@timestamp': 'desc' }] }, + }, + }, + }, + }, + }, + destination: { + filter: { term: { 'destination.ip': '35.196.65.164' } }, + aggs: { + firstSeen: { min: { field: '@timestamp' } }, + lastSeen: { max: { field: '@timestamp' } }, + as: { + filter: { exists: { field: 'destination.as' } }, + aggs: { + results: { + top_hits: { + size: 1, + _source: ['destination.as'], + sort: [{ '@timestamp': 'desc' }], + }, + }, + }, + }, + geo: { + filter: { exists: { field: 'destination.geo' } }, + aggs: { + results: { + top_hits: { + size: 1, + _source: ['destination.geo'], + sort: [{ '@timestamp': 'desc' }], + }, + }, + }, + }, + }, + }, + host: { + filter: { term: { 'host.ip': '35.196.65.164' } }, + aggs: { + results: { top_hits: { size: 1, _source: ['host'], sort: [{ '@timestamp': 'desc' }] } }, + }, + }, + }, + query: { bool: { should: [] } }, + size: 0, + track_total_hits: false, + }, +}; diff --git a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/details/index.test.ts b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/details/index.test.ts new file mode 100644 index 0000000000000..6f54097a76fe7 --- /dev/null +++ b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/details/index.test.ts @@ -0,0 +1,35 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import * as buildQuery from './query.details_network.dsl'; +import { networkDetails } from '.'; +import { + mockOptions, + mockSearchStrategyResponse, + formattedSearchStrategyResponse, +} from './__mocks__'; + +describe('networkDetails search strategy', () => { + const buildNetworkDetailsQuery = jest.spyOn(buildQuery, 'buildNetworkDetailsQuery'); + + afterEach(() => { + buildNetworkDetailsQuery.mockClear(); + }); + + describe('buildDsl', () => { + test('should build dsl query', () => { + networkDetails.buildDsl(mockOptions); + expect(buildNetworkDetailsQuery).toHaveBeenCalledWith(mockOptions); + }); + }); + + describe('parse', () => { + test('should parse data correctly', async () => { + const result = await networkDetails.parse(mockOptions, mockSearchStrategyResponse); + expect(result).toMatchObject(formattedSearchStrategyResponse); + }); + }); +}); diff --git a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/details/query.details_network.dsl.test.ts b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/details/query.details_network.dsl.test.ts new file mode 100644 index 0000000000000..93dca8ee03978 --- /dev/null +++ b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/details/query.details_network.dsl.test.ts @@ -0,0 +1,13 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ +import { buildNetworkDetailsQuery } from './query.details_network.dsl'; +import { mockOptions, expectedDsl } from './__mocks__'; + +describe('buildNetworkDetailsQuery', () => { + test('build query from options correctly', () => { + expect(buildNetworkDetailsQuery(mockOptions)).toEqual(expectedDsl); + }); +}); diff --git a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/dns/__mocks__/index.ts b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/dns/__mocks__/index.ts new file mode 100644 index 0000000000000..f0605c5523fd9 --- /dev/null +++ b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/dns/__mocks__/index.ts @@ -0,0 +1,185 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { IEsSearchResponse } from '../../../../../../../../../../src/plugins/data/common'; + +import { + Direction, + NetworkDnsFields, + NetworkDnsRequestOptions, + NetworkQueries, +} from '../../../../../../../common/search_strategy'; + +export const mockOptions: NetworkDnsRequestOptions = { + defaultIndex: [ + 'apm-*-transaction*', + 'auditbeat-*', + 'endgame-*', + 'filebeat-*', + 'logs-*', + 'packetbeat-*', + 'winlogbeat-*', + ], + factoryQueryType: NetworkQueries.dns, + filterQuery: '{"bool":{"must":[],"filter":[{"match_all":{}}],"should":[],"must_not":[]}}', + isPtrIncluded: false, + pagination: { activePage: 0, cursorStart: 0, fakePossibleCount: 50, querySize: 10 }, + sort: { field: NetworkDnsFields.uniqueDomains, direction: Direction.desc }, + timerange: { interval: '12h', from: '2020-09-13T09:00:43.249Z', to: '2020-09-14T09:00:43.249Z' }, +}; + +export const mockSearchStrategyResponse: IEsSearchResponse = { + isPartial: false, + isRunning: false, + rawResponse: { + took: 28, + timed_out: false, + _shards: { total: 21, successful: 21, skipped: 0, failed: 0 }, + hits: { max_score: 0, hits: [], total: 0 }, + aggregations: { + dns_count: { value: 2 }, + 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_bytes_in: { value: 0 }, + dns_bytes_out: { value: 0 }, + }, + { + key: 'google.internal', + doc_count: 1, + unique_domains: { value: 1 }, + dns_bytes_in: { value: 0 }, + dns_bytes_out: { value: 0 }, + }, + ], + }, + }, + }, + total: 21, + loaded: 21, +}; + +export const formattedSearchStrategyResponse = { + isPartial: false, + isRunning: false, + rawResponse: { + took: 28, + timed_out: false, + _shards: { total: 21, successful: 21, skipped: 0, failed: 0 }, + hits: { max_score: 0, hits: [] }, + aggregations: { + dns_count: { value: 2 }, + 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_bytes_in: { value: 0 }, + dns_bytes_out: { value: 0 }, + }, + { + key: 'google.internal', + doc_count: 1, + unique_domains: { value: 1 }, + dns_bytes_in: { value: 0 }, + dns_bytes_out: { value: 0 }, + }, + ], + }, + }, + }, + total: 21, + loaded: 21, + edges: [ + { + node: { + _id: 'google.com', + dnsBytesIn: 0, + dnsBytesOut: 0, + dnsName: 'google.com', + queryCount: 1, + uniqueDomains: 1, + }, + cursor: { value: 'google.com', tiebreaker: null }, + }, + { + node: { + _id: 'google.internal', + dnsBytesIn: 0, + dnsBytesOut: 0, + dnsName: 'google.internal', + queryCount: 1, + uniqueDomains: 1, + }, + cursor: { value: 'google.internal', tiebreaker: null }, + }, + ], + inspect: { + dsl: [ + '{\n "allowNoIndices": true,\n "index": [\n "apm-*-transaction*",\n "auditbeat-*",\n "endgame-*",\n "filebeat-*",\n "logs-*",\n "packetbeat-*",\n "winlogbeat-*"\n ],\n "ignoreUnavailable": true,\n "body": {\n "aggregations": {\n "dns_count": {\n "cardinality": {\n "field": "dns.question.registered_domain"\n }\n },\n "dns_name_query_count": {\n "terms": {\n "field": "dns.question.registered_domain",\n "size": 10,\n "order": {\n "unique_domains": "desc"\n }\n },\n "aggs": {\n "unique_domains": {\n "cardinality": {\n "field": "dns.question.name"\n }\n },\n "dns_bytes_in": {\n "sum": {\n "field": "source.bytes"\n }\n },\n "dns_bytes_out": {\n "sum": {\n "field": "destination.bytes"\n }\n }\n }\n }\n },\n "query": {\n "bool": {\n "filter": [\n "{\\"bool\\":{\\"must\\":[],\\"filter\\":[{\\"match_all\\":{}}],\\"should\\":[],\\"must_not\\":[]}}",\n {\n "range": {\n "@timestamp": {\n "gte": "2020-09-13T09:00:43.249Z",\n "lte": "2020-09-14T09:00:43.249Z",\n "format": "strict_date_optional_time"\n }\n }\n }\n ],\n "must_not": [\n {\n "term": {\n "dns.question.type": {\n "value": "PTR"\n }\n }\n }\n ]\n }\n }\n },\n "size": 0,\n "track_total_hits": false\n}', + ], + }, + pageInfo: { activePage: 0, fakeTotalCount: 2, showMorePagesIndicator: false }, + totalCount: 2, +}; + +export const expectedDsl = { + allowNoIndices: true, + index: [ + 'apm-*-transaction*', + 'auditbeat-*', + 'endgame-*', + 'filebeat-*', + 'logs-*', + 'packetbeat-*', + 'winlogbeat-*', + ], + ignoreUnavailable: true, + body: { + aggregations: { + dns_count: { cardinality: { field: 'dns.question.registered_domain' } }, + dns_name_query_count: { + terms: { + field: 'dns.question.registered_domain', + size: 10, + order: { unique_domains: 'desc' }, + }, + aggs: { + unique_domains: { cardinality: { field: 'dns.question.name' } }, + dns_bytes_in: { sum: { field: 'source.bytes' } }, + dns_bytes_out: { sum: { field: 'destination.bytes' } }, + }, + }, + }, + query: { + bool: { + filter: [ + '{"bool":{"must":[],"filter":[{"match_all":{}}],"should":[],"must_not":[]}}', + { + range: { + '@timestamp': { + gte: '2020-09-13T09:00:43.249Z', + lte: '2020-09-14T09:00:43.249Z', + 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/network/dns/index.test.ts b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/dns/index.test.ts new file mode 100644 index 0000000000000..22906a1ea138c --- /dev/null +++ b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/dns/index.test.ts @@ -0,0 +1,35 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import * as buildQuery from './query.dns_network.dsl'; +import { networkDns } from '.'; +import { + mockOptions, + mockSearchStrategyResponse, + formattedSearchStrategyResponse, +} from './__mocks__'; + +describe('networkDns search strategy', () => { + const mockBuildDnsQuery = jest.spyOn(buildQuery, 'buildDnsQuery'); + + afterEach(() => { + mockBuildDnsQuery.mockClear(); + }); + + describe('buildDsl', () => { + test('should build dsl query', () => { + networkDns.buildDsl(mockOptions); + expect(mockBuildDnsQuery).toHaveBeenCalledWith(mockOptions); + }); + }); + + describe('parse', () => { + test('should parse data correctly', async () => { + const result = await networkDns.parse(mockOptions, mockSearchStrategyResponse); + expect(result).toMatchObject(formattedSearchStrategyResponse); + }); + }); +}); diff --git a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/dns/query.dns_network.dsl.test.ts b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/dns/query.dns_network.dsl.test.ts new file mode 100644 index 0000000000000..9e95990d13a44 --- /dev/null +++ b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/dns/query.dns_network.dsl.test.ts @@ -0,0 +1,13 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ +import { buildDnsQuery } from './query.dns_network.dsl'; +import { mockOptions, expectedDsl } from './__mocks__'; + +describe('buildDnsQuery', () => { + test('build query from options correctly', () => { + expect(buildDnsQuery(mockOptions)).toEqual(expectedDsl); + }); +}); diff --git a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/http/__mocks__/index.ts b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/http/__mocks__/index.ts new file mode 100644 index 0000000000000..9991d267707b7 --- /dev/null +++ b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/http/__mocks__/index.ts @@ -0,0 +1,670 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { IEsSearchResponse } from '../../../../../../../../../../src/plugins/data/common'; + +import { + Direction, + NetworkDnsFields, + NetworkDnsRequestOptions, + NetworkQueries, + SortField, +} from '../../../../../../../common/search_strategy'; + +export const mockOptions: NetworkDnsRequestOptions = { + defaultIndex: [ + 'apm-*-transaction*', + 'auditbeat-*', + 'endgame-*', + 'filebeat-*', + 'logs-*', + 'packetbeat-*', + 'winlogbeat-*', + ], + factoryQueryType: NetworkQueries.http, + filterQuery: '{"bool":{"must":[],"filter":[{"match_all":{}}],"should":[],"must_not":[]}}', + pagination: { activePage: 0, cursorStart: 0, fakePossibleCount: 50, querySize: 10 }, + sort: { direction: Direction.desc } as SortField, + timerange: { interval: '12h', from: '2020-09-13T09:00:43.249Z', to: '2020-09-14T09:00:43.249Z' }, +} as NetworkDnsRequestOptions; + +export const mockSearchStrategyResponse: IEsSearchResponse = { + isPartial: false, + isRunning: false, + rawResponse: { + took: 422, + timed_out: false, + _shards: { total: 21, successful: 21, skipped: 0, failed: 0 }, + hits: { max_score: 0, hits: [], total: 0 }, + aggregations: { + http_count: { value: 1404 }, + url: { + doc_count_error_upper_bound: 1440, + sum_other_doc_count: 98077, + buckets: [ + { + key: '/_nodes?filter_path=nodes.*.version%2Cnodes.*.http.publish_address%2Cnodes.*.ip', + doc_count: 106704, + methods: { + doc_count_error_upper_bound: 0, + sum_other_doc_count: 0, + buckets: [{ key: 'GET', doc_count: 106704 }], + }, + domains: { + doc_count_error_upper_bound: 0, + sum_other_doc_count: 0, + buckets: [ + { key: 'es.siem.estc.dev:9200', doc_count: 68983 }, + { key: 'es.siem.estc.dev', doc_count: 37721 }, + ], + }, + source: { + hits: { + total: { value: 106704, relation: 'eq' }, + max_score: 0, + hits: [ + { + _index: 'filebeat-8.0.0-2020.09.02-000001', + _id: 'L4wXh3QBc39KFIJbgXrN', + _score: 0, + _source: { + host: { name: 'bastion00.siem.estc.dev' }, + source: { ip: '67.173.227.94' }, + }, + }, + ], + }, + }, + status: { + doc_count_error_upper_bound: 0, + sum_other_doc_count: 0, + buckets: [ + { key: 200, doc_count: 72174 }, + { key: 401, doc_count: 34530 }, + ], + }, + }, + { + key: '/_bulk', + doc_count: 76744, + methods: { + doc_count_error_upper_bound: 0, + sum_other_doc_count: 0, + buckets: [{ key: 'POST', doc_count: 76744 }], + }, + domains: { + doc_count_error_upper_bound: 0, + sum_other_doc_count: 0, + buckets: [ + { key: 'es.siem.estc.dev:9200', doc_count: 76737 }, + { key: 'es.siem.estc.dev', doc_count: 7 }, + ], + }, + source: { + hits: { + total: { value: 76744, relation: 'eq' }, + max_score: 0, + hits: [ + { + _index: 'filebeat-8.0.0-2020.09.02-000001', + _id: 'tEIXh3QBB-gskclyiT2g', + _score: 0, + _source: { + host: { name: 'bastion00.siem.estc.dev' }, + source: { ip: '35.227.65.114' }, + }, + }, + ], + }, + }, + status: { + doc_count_error_upper_bound: 0, + sum_other_doc_count: 0, + buckets: [ + { key: 200, doc_count: 75394 }, + { key: 401, doc_count: 1350 }, + ], + }, + }, + { + key: '/.reporting-*/_search', + doc_count: 58746, + methods: { + doc_count_error_upper_bound: 0, + sum_other_doc_count: 0, + buckets: [{ key: 'POST', doc_count: 58746 }], + }, + domains: { + doc_count_error_upper_bound: 0, + sum_other_doc_count: 0, + buckets: [ + { key: 'es.siem.estc.dev:9200', doc_count: 56305 }, + { key: 'es.siem.estc.dev', doc_count: 2441 }, + ], + }, + source: { + hits: { + total: { value: 58746, relation: 'eq' }, + max_score: 0, + hits: [ + { + _index: 'filebeat-8.0.0-2020.09.02-000001', + _id: 'MYwXh3QBc39KFIJbgXrN', + _score: 0, + _source: { + host: { name: 'bastion00.siem.estc.dev' }, + source: { ip: '67.173.227.94' }, + }, + }, + ], + }, + }, + status: { + doc_count_error_upper_bound: 0, + sum_other_doc_count: 0, + buckets: [{ key: 200, doc_count: 58746 }], + }, + }, + { + key: + '/.kibana-task-manager-xavier-m/_update_by_query?ignore_unavailable=true&refresh=true&max_docs=10&conflicts=proceed', + doc_count: 28715, + methods: { + doc_count_error_upper_bound: 0, + sum_other_doc_count: 0, + buckets: [{ key: 'POST', doc_count: 28715 }], + }, + domains: { + doc_count_error_upper_bound: 0, + sum_other_doc_count: 0, + buckets: [{ key: 'es.siem.estc.dev:9200', doc_count: 28715 }], + }, + source: { + hits: { + total: { value: 28715, relation: 'eq' }, + max_score: 0, + hits: [ + { + _index: 'filebeat-8.0.0-2020.09.02-000001', + _id: 'MIwXh3QBc39KFIJbgXrN', + _score: 0, + _source: { + host: { name: 'bastion00.siem.estc.dev' }, + source: { ip: '24.168.52.229' }, + }, + }, + ], + }, + }, + status: { + doc_count_error_upper_bound: 0, + sum_other_doc_count: 0, + buckets: [{ key: 200, doc_count: 28715 }], + }, + }, + { + key: + '/.kibana-task-manager-andrewg-local-testing-7-9-ff/_update_by_query?ignore_unavailable=true&refresh=true&max_docs=10&conflicts=proceed', + doc_count: 28161, + methods: { + doc_count_error_upper_bound: 0, + sum_other_doc_count: 0, + buckets: [{ key: 'POST', doc_count: 28161 }], + }, + domains: { + doc_count_error_upper_bound: 0, + sum_other_doc_count: 0, + buckets: [{ key: 'es.siem.estc.dev:9200', doc_count: 28161 }], + }, + source: { + hits: { + total: { value: 28161, relation: 'eq' }, + max_score: 0, + hits: [ + { + _index: 'filebeat-8.0.0-2020.09.02-000001', + _id: 'MowXh3QBc39KFIJbgXrN', + _score: 0, + _source: { + host: { name: 'bastion00.siem.estc.dev' }, + source: { ip: '67.173.227.94' }, + }, + }, + ], + }, + }, + status: { + doc_count_error_upper_bound: 0, + sum_other_doc_count: 0, + buckets: [{ key: 200, doc_count: 28161 }], + }, + }, + { + key: '/_security/user/_has_privileges', + doc_count: 23283, + methods: { + doc_count_error_upper_bound: 0, + sum_other_doc_count: 0, + buckets: [{ key: 'POST', doc_count: 23283 }], + }, + domains: { + doc_count_error_upper_bound: 0, + sum_other_doc_count: 0, + buckets: [ + { key: 'es.siem.estc.dev:9200', doc_count: 21601 }, + { key: 'es.siem.estc.dev', doc_count: 1682 }, + ], + }, + source: { + hits: { + total: { value: 23283, relation: 'eq' }, + max_score: 0, + hits: [ + { + _index: 'filebeat-8.0.0-2020.09.02-000001', + _id: '6Ywch3QBc39KFIJbVY_k', + _score: 0, + _source: { + host: { name: 'bastion00.siem.estc.dev' }, + source: { ip: '67.173.227.94' }, + }, + }, + ], + }, + }, + status: { + doc_count_error_upper_bound: 0, + sum_other_doc_count: 0, + buckets: [{ key: 200, doc_count: 23283 }], + }, + }, + { + key: '/_xpack', + doc_count: 20724, + methods: { + doc_count_error_upper_bound: 0, + sum_other_doc_count: 0, + buckets: [{ key: 'GET', doc_count: 20724 }], + }, + domains: { + doc_count_error_upper_bound: 0, + sum_other_doc_count: 0, + buckets: [ + { key: 'es.siem.estc.dev:9200', doc_count: 17289 }, + { key: 'es.siem.estc.dev', doc_count: 3435 }, + ], + }, + source: { + hits: { + total: { value: 20724, relation: 'eq' }, + max_score: 0, + hits: [ + { + _index: 'filebeat-8.0.0-2020.09.02-000001', + _id: 'rkIXh3QBB-gskclyiT2g', + _score: 0, + _source: { + host: { name: 'bastion00.siem.estc.dev' }, + source: { ip: '35.226.77.71' }, + }, + }, + ], + }, + }, + status: { + doc_count_error_upper_bound: 0, + sum_other_doc_count: 0, + buckets: [ + { key: 200, doc_count: 12084 }, + { key: 401, doc_count: 8640 }, + ], + }, + }, + { + key: '/', + doc_count: 18306, + methods: { + doc_count_error_upper_bound: 0, + sum_other_doc_count: 0, + buckets: [ + { key: 'GET', doc_count: 18274 }, + { key: 'HEAD', doc_count: 29 }, + { key: 'POST', doc_count: 3 }, + ], + }, + domains: { + doc_count_error_upper_bound: 0, + sum_other_doc_count: 37, + buckets: [ + { key: 'es.siem.estc.dev', doc_count: 8631 }, + { key: 'es.siem.estc.dev:9200', doc_count: 5757 }, + { key: 'es.siem.estc.dev:443', doc_count: 3858 }, + { key: '35.232.239.42', doc_count: 20 }, + ], + }, + source: { + hits: { + total: { value: 18306, relation: 'eq' }, + max_score: 0, + hits: [ + { + _index: 'filebeat-8.0.0-2020.09.02-000001', + _id: 'JEIYh3QBB-gskclyYEfA', + _score: 0, + _source: { + host: { name: 'bastion00.siem.estc.dev' }, + source: { ip: '35.171.72.245' }, + }, + }, + ], + }, + }, + status: { + doc_count_error_upper_bound: 0, + sum_other_doc_count: 3, + buckets: [ + { key: 401, doc_count: 18220 }, + { key: 404, doc_count: 30 }, + { key: 302, doc_count: 27 }, + { key: 200, doc_count: 26 }, + ], + }, + }, + { + key: '/_monitoring/bulk?system_id=kibana&system_api_version=7&interval=10000ms', + doc_count: 18048, + methods: { + doc_count_error_upper_bound: 0, + sum_other_doc_count: 0, + buckets: [{ key: 'POST', doc_count: 18048 }], + }, + domains: { + doc_count_error_upper_bound: 0, + sum_other_doc_count: 0, + buckets: [ + { key: 'es.siem.estc.dev:9200', doc_count: 17279 }, + { key: 'es.siem.estc.dev', doc_count: 769 }, + ], + }, + source: { + hits: { + total: { value: 18048, relation: 'eq' }, + max_score: 0, + hits: [ + { + _index: 'filebeat-8.0.0-2020.09.02-000001', + _id: 'sUIXh3QBB-gskclyiT2g', + _score: 0, + _source: { + host: { name: 'bastion00.siem.estc.dev' }, + source: { ip: '24.168.52.229' }, + }, + }, + ], + }, + }, + status: { + doc_count_error_upper_bound: 0, + sum_other_doc_count: 0, + buckets: [{ key: 200, doc_count: 18048 }], + }, + }, + { + key: '/s/row-renderer-checking/api/reporting/jobs/count', + doc_count: 14046, + methods: { + doc_count_error_upper_bound: 0, + sum_other_doc_count: 0, + buckets: [{ key: 'GET', doc_count: 14046 }], + }, + domains: { + doc_count_error_upper_bound: 0, + sum_other_doc_count: 0, + buckets: [{ key: 'kibana.siem.estc.dev', doc_count: 14046 }], + }, + source: { + hits: { + total: { value: 14046, relation: 'eq' }, + max_score: 0, + hits: [ + { + _index: 'filebeat-8.0.0-2020.09.02-000001', + _id: 's0IXh3QBB-gskclyiT2g', + _score: 0, + _source: { + host: { name: 'bastion00.siem.estc.dev' }, + source: { ip: '75.134.244.183' }, + }, + }, + ], + }, + }, + status: { + doc_count_error_upper_bound: 0, + sum_other_doc_count: 0, + buckets: [{ key: 200, doc_count: 14046 }], + }, + }, + ], + }, + }, + }, + total: 21, + loaded: 21, +}; + +export const formattedSearchStrategyResponse = { + ...mockSearchStrategyResponse, + edges: [ + { + node: { + _id: '/_nodes?filter_path=nodes.*.version%2Cnodes.*.http.publish_address%2Cnodes.*.ip', + domains: ['es.siem.estc.dev:9200', 'es.siem.estc.dev'], + methods: ['GET'], + statuses: ['200', '401'], + lastHost: 'bastion00.siem.estc.dev', + lastSourceIp: '67.173.227.94', + path: '/_nodes?filter_path=nodes.*.version%2Cnodes.*.http.publish_address%2Cnodes.*.ip', + requestCount: 106704, + }, + cursor: { + value: '/_nodes?filter_path=nodes.*.version%2Cnodes.*.http.publish_address%2Cnodes.*.ip', + tiebreaker: null, + }, + }, + { + node: { + _id: '/_bulk', + domains: ['es.siem.estc.dev:9200', 'es.siem.estc.dev'], + methods: ['POST'], + statuses: ['200', '401'], + lastHost: 'bastion00.siem.estc.dev', + lastSourceIp: '35.227.65.114', + path: '/_bulk', + requestCount: 76744, + }, + cursor: { value: '/_bulk', tiebreaker: null }, + }, + { + node: { + _id: '/.reporting-*/_search', + domains: ['es.siem.estc.dev:9200', 'es.siem.estc.dev'], + methods: ['POST'], + statuses: ['200'], + lastHost: 'bastion00.siem.estc.dev', + lastSourceIp: '67.173.227.94', + path: '/.reporting-*/_search', + requestCount: 58746, + }, + cursor: { value: '/.reporting-*/_search', tiebreaker: null }, + }, + { + node: { + _id: + '/.kibana-task-manager-xavier-m/_update_by_query?ignore_unavailable=true&refresh=true&max_docs=10&conflicts=proceed', + domains: ['es.siem.estc.dev:9200'], + methods: ['POST'], + statuses: ['200'], + lastHost: 'bastion00.siem.estc.dev', + lastSourceIp: '24.168.52.229', + path: + '/.kibana-task-manager-xavier-m/_update_by_query?ignore_unavailable=true&refresh=true&max_docs=10&conflicts=proceed', + requestCount: 28715, + }, + cursor: { + value: + '/.kibana-task-manager-xavier-m/_update_by_query?ignore_unavailable=true&refresh=true&max_docs=10&conflicts=proceed', + tiebreaker: null, + }, + }, + { + node: { + _id: + '/.kibana-task-manager-andrewg-local-testing-7-9-ff/_update_by_query?ignore_unavailable=true&refresh=true&max_docs=10&conflicts=proceed', + domains: ['es.siem.estc.dev:9200'], + methods: ['POST'], + statuses: ['200'], + lastHost: 'bastion00.siem.estc.dev', + lastSourceIp: '67.173.227.94', + path: + '/.kibana-task-manager-andrewg-local-testing-7-9-ff/_update_by_query?ignore_unavailable=true&refresh=true&max_docs=10&conflicts=proceed', + requestCount: 28161, + }, + cursor: { + value: + '/.kibana-task-manager-andrewg-local-testing-7-9-ff/_update_by_query?ignore_unavailable=true&refresh=true&max_docs=10&conflicts=proceed', + tiebreaker: null, + }, + }, + { + node: { + _id: '/_security/user/_has_privileges', + domains: ['es.siem.estc.dev:9200', 'es.siem.estc.dev'], + methods: ['POST'], + statuses: ['200'], + lastHost: 'bastion00.siem.estc.dev', + lastSourceIp: '67.173.227.94', + path: '/_security/user/_has_privileges', + requestCount: 23283, + }, + cursor: { value: '/_security/user/_has_privileges', tiebreaker: null }, + }, + { + node: { + _id: '/_xpack', + domains: ['es.siem.estc.dev:9200', 'es.siem.estc.dev'], + methods: ['GET'], + statuses: ['200', '401'], + lastHost: 'bastion00.siem.estc.dev', + lastSourceIp: '35.226.77.71', + path: '/_xpack', + requestCount: 20724, + }, + cursor: { value: '/_xpack', tiebreaker: null }, + }, + { + node: { + _id: '/', + domains: [ + 'es.siem.estc.dev', + 'es.siem.estc.dev:9200', + 'es.siem.estc.dev:443', + '35.232.239.42', + ], + methods: ['GET', 'HEAD', 'POST'], + statuses: ['401', '404', '302', '200'], + lastHost: 'bastion00.siem.estc.dev', + lastSourceIp: '35.171.72.245', + path: '/', + requestCount: 18306, + }, + cursor: { value: '/', tiebreaker: null }, + }, + { + node: { + _id: '/_monitoring/bulk?system_id=kibana&system_api_version=7&interval=10000ms', + domains: ['es.siem.estc.dev:9200', 'es.siem.estc.dev'], + methods: ['POST'], + statuses: ['200'], + lastHost: 'bastion00.siem.estc.dev', + lastSourceIp: '24.168.52.229', + path: '/_monitoring/bulk?system_id=kibana&system_api_version=7&interval=10000ms', + requestCount: 18048, + }, + cursor: { + value: '/_monitoring/bulk?system_id=kibana&system_api_version=7&interval=10000ms', + tiebreaker: null, + }, + }, + { + node: { + _id: '/s/row-renderer-checking/api/reporting/jobs/count', + domains: ['kibana.siem.estc.dev'], + methods: ['GET'], + statuses: ['200'], + lastHost: 'bastion00.siem.estc.dev', + lastSourceIp: '75.134.244.183', + path: '/s/row-renderer-checking/api/reporting/jobs/count', + requestCount: 14046, + }, + cursor: { value: '/s/row-renderer-checking/api/reporting/jobs/count', tiebreaker: null }, + }, + ], + inspect: { + dsl: [ + '{\n "allowNoIndices": true,\n "index": [\n "apm-*-transaction*",\n "auditbeat-*",\n "endgame-*",\n "filebeat-*",\n "logs-*",\n "packetbeat-*",\n "winlogbeat-*"\n ],\n "ignoreUnavailable": true,\n "body": {\n "aggregations": {\n "http_count": {\n "cardinality": {\n "field": "url.path"\n }\n },\n "url": {\n "terms": {\n "field": "url.path",\n "size": 10,\n "order": {\n "_count": "desc"\n }\n },\n "aggs": {\n "methods": {\n "terms": {\n "field": "http.request.method",\n "size": 4\n }\n },\n "domains": {\n "terms": {\n "field": "url.domain",\n "size": 4\n }\n },\n "status": {\n "terms": {\n "field": "http.response.status_code",\n "size": 4\n }\n },\n "source": {\n "top_hits": {\n "size": 1,\n "_source": {\n "includes": [\n "host.name",\n "source.ip"\n ]\n }\n }\n }\n }\n }\n },\n "query": {\n "bool": {\n "filter": [\n "{\\"bool\\":{\\"must\\":[],\\"filter\\":[{\\"match_all\\":{}}],\\"should\\":[],\\"must_not\\":[]}}",\n {\n "range": {\n "@timestamp": {\n "gte": "2020-09-13T09:00:43.249Z",\n "lte": "2020-09-14T09:00:43.249Z",\n "format": "strict_date_optional_time"\n }\n }\n },\n {\n "exists": {\n "field": "http.request.method"\n }\n }\n ]\n }\n }\n },\n "size": 0,\n "track_total_hits": false\n}', + ], + }, + pageInfo: { activePage: 0, fakeTotalCount: 50, showMorePagesIndicator: true }, + totalCount: 1404, +}; + +export const expectedDsl = { + allowNoIndices: true, + index: [ + 'apm-*-transaction*', + 'auditbeat-*', + 'endgame-*', + 'filebeat-*', + 'logs-*', + 'packetbeat-*', + 'winlogbeat-*', + ], + ignoreUnavailable: true, + body: { + aggregations: { + http_count: { cardinality: { field: 'url.path' } }, + url: { + terms: { field: 'url.path', size: 10, order: { _count: 'desc' } }, + aggs: { + methods: { terms: { field: 'http.request.method', size: 4 } }, + domains: { terms: { field: 'url.domain', size: 4 } }, + status: { terms: { field: 'http.response.status_code', size: 4 } }, + source: { top_hits: { size: 1, _source: { includes: ['host.name', 'source.ip'] } } }, + }, + }, + }, + query: { + bool: { + filter: [ + '{"bool":{"must":[],"filter":[{"match_all":{}}],"should":[],"must_not":[]}}', + { + range: { + '@timestamp': { + gte: '2020-09-13T09:00:43.249Z', + lte: '2020-09-14T09:00:43.249Z', + format: 'strict_date_optional_time', + }, + }, + }, + { exists: { field: 'http.request.method' } }, + ], + }, + }, + }, + size: 0, + track_total_hits: false, +}; diff --git a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/http/index.test.ts b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/http/index.test.ts new file mode 100644 index 0000000000000..47946ee3ed20b --- /dev/null +++ b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/http/index.test.ts @@ -0,0 +1,35 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import * as buildQuery from './query.http_network.dsl'; +import { networkHttp } from '.'; +import { + mockOptions, + mockSearchStrategyResponse, + formattedSearchStrategyResponse, +} from './__mocks__'; + +describe('networkHttp search strategy', () => { + const buildHttpQuery = jest.spyOn(buildQuery, 'buildHttpQuery'); + + afterEach(() => { + buildHttpQuery.mockClear(); + }); + + describe('buildDsl', () => { + test('should build dsl query', () => { + networkHttp.buildDsl(mockOptions); + expect(buildHttpQuery).toHaveBeenCalledWith(mockOptions); + }); + }); + + describe('parse', () => { + test('should parse data correctly', async () => { + const result = await networkHttp.parse(mockOptions, mockSearchStrategyResponse); + expect(result).toMatchObject(formattedSearchStrategyResponse); + }); + }); +}); diff --git a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/http/query.http_network.dsl.test.ts b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/http/query.http_network.dsl.test.ts new file mode 100644 index 0000000000000..1d10b60374a2f --- /dev/null +++ b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/http/query.http_network.dsl.test.ts @@ -0,0 +1,13 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ +import { buildHttpQuery } from './query.http_network.dsl'; +import { mockOptions, expectedDsl } from './__mocks__'; + +describe('buildHttpQuery', () => { + test('build query from options correctly', () => { + expect(buildHttpQuery(mockOptions)).toEqual(expectedDsl); + }); +}); diff --git a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/http/query.http_network.dsl.ts b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/http/query.http_network.dsl.ts index feffe7f70afd9..dcffa60d8aa3c 100644 --- a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/http/query.http_network.dsl.ts +++ b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/http/query.http_network.dsl.ts @@ -69,6 +69,7 @@ export const buildHttpQuery = ({ size: 0, track_total_hits: false, }; + 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 new file mode 100644 index 0000000000000..f901d9f3dab5d --- /dev/null +++ b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/index.test.ts @@ -0,0 +1,41 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ +import { NetworkQueries } from '../../../../../common/search_strategy/security_solution'; + +import { networkFactory } from '.'; +import { networkDetails } from './details'; +import { networkDns } from './dns'; +import { networkHttp } from './http'; +import { networkOverview } from './overview'; +import { networkTls } from './tls'; +import { networkTopCountries } from './top_countries'; +import { networkTopNFlow } from './top_n_flow'; +import { networkUsers } from './users'; + +jest.mock('./details'); +jest.mock('./dns'); +jest.mock('./http'); +jest.mock('./overview'); +jest.mock('./tls'); +jest.mock('./top_countries'); +jest.mock('./top_n_flow'); +jest.mock('./users'); + +describe('networkFactory', () => { + test('should include correct apis', () => { + const expectedNetworkFactory = { + [NetworkQueries.details]: networkDetails, + [NetworkQueries.dns]: networkDns, + [NetworkQueries.http]: networkHttp, + [NetworkQueries.overview]: networkOverview, + [NetworkQueries.tls]: networkTls, + [NetworkQueries.topCountries]: networkTopCountries, + [NetworkQueries.topNFlow]: networkTopNFlow, + [NetworkQueries.users]: networkUsers, + }; + expect(networkFactory).toEqual(expectedNetworkFactory); + }); +}); diff --git a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/overview/__mocks__/index.ts b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/overview/__mocks__/index.ts new file mode 100644 index 0000000000000..8f34d31e49e1d --- /dev/null +++ b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/overview/__mocks__/index.ts @@ -0,0 +1,213 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { IEsSearchResponse } from '../../../../../../../../../../src/plugins/data/common'; + +import { + NetworkOverviewRequestOptions, + NetworkQueries, +} from '../../../../../../../common/search_strategy'; + +export const mockOptions: NetworkOverviewRequestOptions = { + defaultIndex: [ + 'apm-*-transaction*', + 'auditbeat-*', + 'endgame-*', + 'filebeat-*', + 'logs-*', + 'packetbeat-*', + 'winlogbeat-*', + ], + factoryQueryType: NetworkQueries.overview, + filterQuery: + '{"bool":{"must":[],"filter":[{"match_all":{}},{"bool":{"filter":[{"bool":{"should":[{"bool":{"should":[{"exists":{"field":"source.ip"}}],"minimum_should_match":1}},{"bool":{"should":[{"exists":{"field":"destination.ip"}}],"minimum_should_match":1}}],"minimum_should_match":1}}]}}],"should":[],"must_not":[]}}', + timerange: { interval: '12h', from: '2020-09-13T12:54:24.685Z', to: '2020-09-14T12:54:24.685Z' }, +}; + +export const mockSearchStrategyResponse: IEsSearchResponse = { + isPartial: false, + isRunning: false, + rawResponse: { + took: 141, + timed_out: false, + _shards: { + total: 21, + successful: 21, + skipped: 0, + failed: 0, + }, + hits: { + total: 1349108, + max_score: 0, + hits: [], + }, + aggregations: { + unique_zeek_count: { + meta: {}, + doc_count: 0, + }, + unique_packetbeat_count: { + meta: {}, + doc_count: 0, + unique_tls_count: { + meta: {}, + doc_count: 0, + }, + }, + unique_filebeat_count: { + meta: {}, + doc_count: 1278559, + unique_netflow_count: { + doc_count: 0, + }, + unique_cisco_count: { + meta: {}, + doc_count: 0, + }, + unique_panw_count: { + meta: {}, + doc_count: 0, + }, + }, + unique_dns_count: { + meta: {}, + doc_count: 0, + }, + unique_flow_count: { + meta: {}, + doc_count: 0, + }, + unique_socket_count: { + doc_count: 0, + }, + unique_suricata_count: { + meta: {}, + doc_count: 0, + }, + }, + }, + total: 21, + loaded: 21, +}; + +export const formattedSearchStrategyResponse = { + ...mockSearchStrategyResponse, + inspect: { + dsl: [ + '{\n "allowNoIndices": true,\n "index": [\n "apm-*-transaction*",\n "auditbeat-*",\n "endgame-*",\n "filebeat-*",\n "logs-*",\n "packetbeat-*",\n "winlogbeat-*"\n ],\n "ignoreUnavailable": true,\n "body": {\n "aggregations": {\n "unique_flow_count": {\n "filter": {\n "term": {\n "type": "flow"\n }\n }\n },\n "unique_dns_count": {\n "filter": {\n "term": {\n "type": "dns"\n }\n }\n },\n "unique_suricata_count": {\n "filter": {\n "term": {\n "service.type": "suricata"\n }\n }\n },\n "unique_zeek_count": {\n "filter": {\n "term": {\n "service.type": "zeek"\n }\n }\n },\n "unique_socket_count": {\n "filter": {\n "term": {\n "event.dataset": "socket"\n }\n }\n },\n "unique_filebeat_count": {\n "filter": {\n "term": {\n "agent.type": "filebeat"\n }\n },\n "aggs": {\n "unique_netflow_count": {\n "filter": {\n "term": {\n "input.type": "netflow"\n }\n }\n },\n "unique_panw_count": {\n "filter": {\n "term": {\n "event.module": "panw"\n }\n }\n },\n "unique_cisco_count": {\n "filter": {\n "term": {\n "event.module": "cisco"\n }\n }\n }\n }\n },\n "unique_packetbeat_count": {\n "filter": {\n "term": {\n "agent.type": "packetbeat"\n }\n },\n "aggs": {\n "unique_tls_count": {\n "filter": {\n "term": {\n "network.protocol": "tls"\n }\n }\n }\n }\n }\n },\n "query": {\n "bool": {\n "filter": [\n "{\\"bool\\":{\\"must\\":[],\\"filter\\":[{\\"match_all\\":{}},{\\"bool\\":{\\"filter\\":[{\\"bool\\":{\\"should\\":[{\\"bool\\":{\\"should\\":[{\\"exists\\":{\\"field\\":\\"source.ip\\"}}],\\"minimum_should_match\\":1}},{\\"bool\\":{\\"should\\":[{\\"exists\\":{\\"field\\":\\"destination.ip\\"}}],\\"minimum_should_match\\":1}}],\\"minimum_should_match\\":1}}]}}],\\"should\\":[],\\"must_not\\":[]}}",\n {\n "range": {\n "@timestamp": {\n "gte": "2020-09-13T12:54:24.685Z",\n "lte": "2020-09-14T12:54:24.685Z",\n "format": "strict_date_optional_time"\n }\n }\n }\n ]\n }\n },\n "size": 0,\n "track_total_hits": false\n }\n}', + ], + }, + overviewNetwork: { + auditbeatSocket: 0, + filebeatCisco: 0, + filebeatNetflow: 0, + filebeatPanw: 0, + filebeatSuricata: 0, + filebeatZeek: 0, + packetbeatDNS: 0, + packetbeatFlow: 0, + packetbeatTLS: 0, + }, +}; + +export const expectedDsl = { + allowNoIndices: true, + ignoreUnavailable: true, + index: [ + 'apm-*-transaction*', + 'auditbeat-*', + 'endgame-*', + 'filebeat-*', + 'logs-*', + 'packetbeat-*', + 'winlogbeat-*', + ], + body: { + aggregations: { + unique_flow_count: { + filter: { + term: { + type: 'flow', + }, + }, + }, + unique_dns_count: { + filter: { + term: { + type: 'dns', + }, + }, + }, + unique_suricata_count: { + filter: { + term: { + 'service.type': 'suricata', + }, + }, + }, + unique_zeek_count: { + filter: { + term: { + 'service.type': 'zeek', + }, + }, + }, + unique_socket_count: { + filter: { + term: { + 'event.dataset': 'socket', + }, + }, + }, + unique_filebeat_count: { + filter: { + term: { + 'agent.type': 'filebeat', + }, + }, + aggs: { + unique_netflow_count: { + filter: { + term: { + 'input.type': 'netflow', + }, + }, + }, + unique_panw_count: { + filter: { + term: { + 'event.module': 'panw', + }, + }, + }, + unique_cisco_count: { + filter: { + term: { + 'event.module': 'cisco', + }, + }, + }, + }, + }, + unique_packetbeat_count: { + filter: { + term: { + 'agent.type': 'packetbeat', + }, + }, + aggs: { + unique_tls_count: { + filter: { + term: { + 'network.protocol': 'tls', + }, + }, + }, + }, + }, + }, + }, +}; diff --git a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/overview/index.test.ts b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/overview/index.test.ts new file mode 100644 index 0000000000000..14b9fb3c71933 --- /dev/null +++ b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/overview/index.test.ts @@ -0,0 +1,35 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import * as buildQuery from './query.overview_network.dsl'; +import { networkOverview } from '.'; +import { + mockOptions, + mockSearchStrategyResponse, + formattedSearchStrategyResponse, +} from './__mocks__'; + +describe('networkOverview search strategy', () => { + const buildOverviewNetworkQuery = jest.spyOn(buildQuery, 'buildOverviewNetworkQuery'); + + afterEach(() => { + buildOverviewNetworkQuery.mockClear(); + }); + + describe('buildDsl', () => { + test('should build dsl query', () => { + networkOverview.buildDsl(mockOptions); + expect(buildOverviewNetworkQuery).toHaveBeenCalledWith(mockOptions); + }); + }); + + describe('parse', () => { + test('should parse data correctly', async () => { + const result = await networkOverview.parse(mockOptions, mockSearchStrategyResponse); + expect(result).toMatchObject(formattedSearchStrategyResponse); + }); + }); +}); diff --git a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/overview/query.overview_network.dsl.test.ts b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/overview/query.overview_network.dsl.test.ts new file mode 100644 index 0000000000000..553df2ab80e58 --- /dev/null +++ b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/overview/query.overview_network.dsl.test.ts @@ -0,0 +1,13 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ +import { buildOverviewNetworkQuery } from './query.overview_network.dsl'; +import { mockOptions, expectedDsl } from './__mocks__'; + +describe('buildOverviewNetworkQuery', () => { + test('build query from options correctly', () => { + expect(buildOverviewNetworkQuery(mockOptions)).toMatchObject(expectedDsl); + }); +}); diff --git a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/tls/__mocks__/index.ts b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/tls/__mocks__/index.ts new file mode 100644 index 0000000000000..15e2ac3cc0f69 --- /dev/null +++ b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/tls/__mocks__/index.ts @@ -0,0 +1,109 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { IEsSearchResponse } from '../../../../../../../../../../src/plugins/data/common'; + +import { + Direction, + NetworkTlsFields, + NetworkTlsRequestOptions, + NetworkQueries, + FlowTargetSourceDest, +} from '../../../../../../../common/search_strategy'; + +export const mockOptions: NetworkTlsRequestOptions = { + defaultIndex: [ + 'apm-*-transaction*', + 'auditbeat-*', + 'endgame-*', + 'filebeat-*', + 'logs-*', + 'packetbeat-*', + 'winlogbeat-*', + ], + factoryQueryType: NetworkQueries.tls, + filterQuery: '{"bool":{"must":[],"filter":[{"match_all":{}}],"should":[],"must_not":[]}}', + flowTarget: FlowTargetSourceDest.source, + ip: '', + pagination: { activePage: 0, cursorStart: 0, fakePossibleCount: 50, querySize: 10 }, + sort: { field: NetworkTlsFields._id, direction: Direction.desc }, + timerange: { interval: '12h', from: '2020-09-13T09:58:58.637Z', to: '2020-09-14T09:58:58.637Z' }, +}; + +export const mockSearchStrategyResponse: IEsSearchResponse = { + isPartial: false, + isRunning: false, + rawResponse: { + took: 62, + timed_out: false, + _shards: { total: 21, successful: 21, skipped: 0, failed: 0 }, + hits: { total: 0, max_score: 0, hits: [] }, + aggregations: { + sha1: { doc_count_error_upper_bound: 0, sum_other_doc_count: 0, buckets: [] }, + count: { value: 0 }, + }, + }, + total: 21, + loaded: 21, +}; + +export const formattedSearchStrategyResponse = { + ...mockSearchStrategyResponse, + edges: [], + inspect: { + dsl: [ + '{\n "allowNoIndices": true,\n "index": [\n "apm-*-transaction*",\n "auditbeat-*",\n "endgame-*",\n "filebeat-*",\n "logs-*",\n "packetbeat-*",\n "winlogbeat-*"\n ],\n "ignoreUnavailable": true,\n "body": {\n "aggs": {\n "count": {\n "cardinality": {\n "field": "tls.server.hash.sha1"\n }\n },\n "sha1": {\n "terms": {\n "field": "tls.server.hash.sha1",\n "size": 10,\n "order": {\n "_key": "desc"\n }\n },\n "aggs": {\n "issuers": {\n "terms": {\n "field": "tls.server.issuer"\n }\n },\n "subjects": {\n "terms": {\n "field": "tls.server.subject"\n }\n },\n "not_after": {\n "terms": {\n "field": "tls.server.not_after"\n }\n },\n "ja3": {\n "terms": {\n "field": "tls.server.ja3s"\n }\n }\n }\n }\n },\n "query": {\n "bool": {\n "filter": [\n "{\\"bool\\":{\\"must\\":[],\\"filter\\":[{\\"match_all\\":{}}],\\"should\\":[],\\"must_not\\":[]}}",\n {\n "range": {\n "@timestamp": {\n "gte": "2020-09-13T09:58:58.637Z",\n "lte": "2020-09-14T09:58:58.637Z",\n "format": "strict_date_optional_time"\n }\n }\n }\n ]\n }\n },\n "size": 0,\n "track_total_hits": false\n }\n}', + ], + }, + pageInfo: { activePage: 0, fakeTotalCount: 0, showMorePagesIndicator: false }, + totalCount: 0, +}; + +export const expectedDsl = { + allowNoIndices: true, + index: [ + 'apm-*-transaction*', + 'auditbeat-*', + 'endgame-*', + 'filebeat-*', + 'logs-*', + 'packetbeat-*', + 'winlogbeat-*', + ], + ignoreUnavailable: true, + body: { + aggs: { + count: { cardinality: { field: 'tls.server.hash.sha1' } }, + sha1: { + terms: { field: 'tls.server.hash.sha1', size: 10, order: { _key: 'desc' } }, + aggs: { + issuers: { terms: { field: 'tls.server.issuer' } }, + subjects: { terms: { field: 'tls.server.subject' } }, + not_after: { terms: { field: 'tls.server.not_after' } }, + ja3: { terms: { field: 'tls.server.ja3s' } }, + }, + }, + }, + query: { + bool: { + filter: [ + '{"bool":{"must":[],"filter":[{"match_all":{}}],"should":[],"must_not":[]}}', + { + range: { + '@timestamp': { + gte: '2020-09-13T09:58:58.637Z', + lte: '2020-09-14T09:58:58.637Z', + format: 'strict_date_optional_time', + }, + }, + }, + ], + }, + }, + size: 0, + track_total_hits: false, + }, +}; diff --git a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/tls/index.test.ts b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/tls/index.test.ts new file mode 100644 index 0000000000000..b8c2be5bc61f8 --- /dev/null +++ b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/tls/index.test.ts @@ -0,0 +1,35 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import * as buildQuery from './query.tls_network.dsl'; +import { networkTls } from '.'; +import { + mockOptions, + mockSearchStrategyResponse, + formattedSearchStrategyResponse, +} from './__mocks__'; + +describe('networkTls search strategy', () => { + const buildNetworkTlsQuery = jest.spyOn(buildQuery, 'buildNetworkTlsQuery'); + + afterEach(() => { + buildNetworkTlsQuery.mockClear(); + }); + + describe('buildDsl', () => { + test('should build dsl query', () => { + networkTls.buildDsl(mockOptions); + expect(buildNetworkTlsQuery).toHaveBeenCalledWith(mockOptions); + }); + }); + + describe('parse', () => { + test('should parse data correctly', async () => { + const result = await networkTls.parse(mockOptions, mockSearchStrategyResponse); + expect(result).toMatchObject(formattedSearchStrategyResponse); + }); + }); +}); diff --git a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/tls/query.tls_network.dsl.test.ts b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/tls/query.tls_network.dsl.test.ts new file mode 100644 index 0000000000000..39cfcc7ab462e --- /dev/null +++ b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/tls/query.tls_network.dsl.test.ts @@ -0,0 +1,13 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ +import { buildNetworkTlsQuery } from './query.tls_network.dsl'; +import { mockOptions, expectedDsl } from './__mocks__'; + +describe('buildNetworkTlsQuery', () => { + test('build query from options correctly', () => { + expect(buildNetworkTlsQuery(mockOptions)).toEqual(expectedDsl); + }); +}); diff --git a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/top_countries/__mocks__/index.ts b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/top_countries/__mocks__/index.ts new file mode 100644 index 0000000000000..0578d99accbf5 --- /dev/null +++ b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/top_countries/__mocks__/index.ts @@ -0,0 +1,109 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { IEsSearchResponse } from '../../../../../../../../../../src/plugins/data/common'; + +import { + Direction, + NetworkTopCountriesRequestOptions, + NetworkQueries, + FlowTargetSourceDest, + NetworkTopTablesFields, +} from '../../../../../../../common/search_strategy'; + +export const mockOptions: NetworkTopCountriesRequestOptions = { + defaultIndex: [ + 'apm-*-transaction*', + 'auditbeat-*', + 'endgame-*', + 'filebeat-*', + 'logs-*', + 'packetbeat-*', + 'winlogbeat-*', + ], + factoryQueryType: NetworkQueries.topCountries, + filterQuery: '{"bool":{"must":[],"filter":[{"match_all":{}}],"should":[],"must_not":[]}}', + flowTarget: FlowTargetSourceDest.destination, + pagination: { activePage: 0, cursorStart: 0, fakePossibleCount: 50, querySize: 10 }, + sort: { field: NetworkTopTablesFields.bytes_in, direction: Direction.desc }, + timerange: { interval: '12h', from: '2020-09-13T09:58:58.637Z', to: '2020-09-14T09:58:58.637Z' }, +}; + +export const mockSearchStrategyResponse: IEsSearchResponse = { + isPartial: false, + isRunning: false, + rawResponse: { + took: 62, + timed_out: false, + _shards: { total: 21, successful: 21, skipped: 0, failed: 0 }, + hits: { total: 0, max_score: 0, hits: [] }, + aggregations: { + sha1: { doc_count_error_upper_bound: 0, sum_other_doc_count: 0, buckets: [] }, + count: { value: 0 }, + }, + }, + total: 21, + loaded: 21, +}; + +export const formattedSearchStrategyResponse = { + ...mockSearchStrategyResponse, + edges: [], + inspect: { + dsl: [ + '{\n "allowNoIndices": true,\n "index": [\n "apm-*-transaction*",\n "auditbeat-*",\n "endgame-*",\n "filebeat-*",\n "logs-*",\n "packetbeat-*",\n "winlogbeat-*"\n ],\n "ignoreUnavailable": true,\n "body": {\n "aggregations": {\n "top_countries_count": {\n "cardinality": {\n "field": "destination.geo.country_iso_code"\n }\n },\n "destination": {\n "terms": {\n "field": "destination.geo.country_iso_code",\n "size": 10,\n "order": {\n "bytes_in": "desc"\n }\n },\n "aggs": {\n "bytes_in": {\n "sum": {\n "field": "source.bytes"\n }\n },\n "bytes_out": {\n "sum": {\n "field": "destination.bytes"\n }\n },\n "flows": {\n "cardinality": {\n "field": "network.community_id"\n }\n },\n "source_ips": {\n "cardinality": {\n "field": "source.ip"\n }\n },\n "destination_ips": {\n "cardinality": {\n "field": "destination.ip"\n }\n }\n }\n }\n },\n "query": {\n "bool": {\n "filter": [\n "{\\"bool\\":{\\"must\\":[],\\"filter\\":[{\\"match_all\\":{}}],\\"should\\":[],\\"must_not\\":[]}}",\n {\n "range": {\n "@timestamp": {\n "gte": "2020-09-13T09:58:58.637Z",\n "lte": "2020-09-14T09:58:58.637Z",\n "format": "strict_date_optional_time"\n }\n }\n }\n ]\n }\n }\n },\n "size": 0,\n "track_total_hits": false\n}', + ], + }, + pageInfo: { activePage: 0, fakeTotalCount: 0, showMorePagesIndicator: false }, + totalCount: 0, +}; + +export const expectedDsl = { + allowNoIndices: true, + index: [ + 'apm-*-transaction*', + 'auditbeat-*', + 'endgame-*', + 'filebeat-*', + 'logs-*', + 'packetbeat-*', + 'winlogbeat-*', + ], + ignoreUnavailable: true, + body: { + aggregations: { + top_countries_count: { cardinality: { field: 'destination.geo.country_iso_code' } }, + destination: { + terms: { field: 'destination.geo.country_iso_code', size: 10, order: { bytes_in: 'desc' } }, + aggs: { + bytes_in: { sum: { field: 'source.bytes' } }, + bytes_out: { sum: { field: 'destination.bytes' } }, + flows: { cardinality: { field: 'network.community_id' } }, + source_ips: { cardinality: { field: 'source.ip' } }, + destination_ips: { cardinality: { field: 'destination.ip' } }, + }, + }, + }, + query: { + bool: { + filter: [ + '{"bool":{"must":[],"filter":[{"match_all":{}}],"should":[],"must_not":[]}}', + { + range: { + '@timestamp': { + gte: '2020-09-13T09:58:58.637Z', + lte: '2020-09-14T09:58:58.637Z', + format: 'strict_date_optional_time', + }, + }, + }, + ], + }, + }, + }, + size: 0, + track_total_hits: false, +}; diff --git a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/top_countries/index.test.ts b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/top_countries/index.test.ts new file mode 100644 index 0000000000000..65d1306b6946e --- /dev/null +++ b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/top_countries/index.test.ts @@ -0,0 +1,35 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import * as buildQuery from './query.top_countries_network.dsl'; +import { networkTopCountries } from '.'; +import { + mockOptions, + mockSearchStrategyResponse, + formattedSearchStrategyResponse, +} from './__mocks__'; + +describe('networkTopCountries search strategy', () => { + const buildTopCountriesQuery = jest.spyOn(buildQuery, 'buildTopCountriesQuery'); + + afterEach(() => { + buildTopCountriesQuery.mockClear(); + }); + + describe('buildDsl', () => { + test('should build dsl query', () => { + networkTopCountries.buildDsl(mockOptions); + expect(buildTopCountriesQuery).toHaveBeenCalledWith(mockOptions); + }); + }); + + describe('parse', () => { + test('should parse data correctly', async () => { + const result = await networkTopCountries.parse(mockOptions, mockSearchStrategyResponse); + expect(result).toMatchObject(formattedSearchStrategyResponse); + }); + }); +}); diff --git a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/top_countries/index.ts b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/top_countries/index.ts index 5b0ced06f2ee9..ba4565b068eb4 100644 --- a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/top_countries/index.ts +++ b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/top_countries/index.ts @@ -43,7 +43,6 @@ export const networkTopCountries: SecuritySolutionFactory fakeTotalCount; diff --git a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/top_countries/query.top_countries_network.dsl.test.ts b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/top_countries/query.top_countries_network.dsl.test.ts new file mode 100644 index 0000000000000..cba2988aa240e --- /dev/null +++ b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/top_countries/query.top_countries_network.dsl.test.ts @@ -0,0 +1,13 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ +import { buildTopCountriesQuery } from './query.top_countries_network.dsl'; +import { mockOptions, expectedDsl } from './__mocks__'; + +describe('buildTopCountriesQuery', () => { + test('build query from options correctly', () => { + expect(buildTopCountriesQuery(mockOptions)).toEqual(expectedDsl); + }); +}); diff --git a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/top_n_flow/__mocks__/index.ts b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/top_n_flow/__mocks__/index.ts new file mode 100644 index 0000000000000..84c1ca129ecac --- /dev/null +++ b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/top_n_flow/__mocks__/index.ts @@ -0,0 +1,847 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { IEsSearchResponse } from '../../../../../../../../../../src/plugins/data/common'; + +import { + Direction, + NetworkTopNFlowRequestOptions, + NetworkQueries, + NetworkTopTablesFields, + FlowTargetSourceDest, +} from '../../../../../../../common/search_strategy'; + +export const mockOptions: NetworkTopNFlowRequestOptions = { + defaultIndex: [ + 'apm-*-transaction*', + 'auditbeat-*', + 'endgame-*', + 'filebeat-*', + 'logs-*', + 'packetbeat-*', + 'winlogbeat-*', + ], + factoryQueryType: NetworkQueries.topNFlow, + filterQuery: '{"bool":{"must":[],"filter":[{"match_all":{}}],"should":[],"must_not":[]}}', + flowTarget: FlowTargetSourceDest.source, + pagination: { activePage: 0, cursorStart: 0, fakePossibleCount: 50, querySize: 10 }, + sort: { field: NetworkTopTablesFields.bytes_out, direction: Direction.desc }, + timerange: { interval: '12h', from: '2020-09-13T10:16:46.870Z', to: '2020-09-14T10:16:46.870Z' }, +}; + +export const mockSearchStrategyResponse: IEsSearchResponse = { + isPartial: false, + isRunning: false, + rawResponse: { + took: 191, + timed_out: false, + _shards: { total: 21, successful: 21, skipped: 0, failed: 0 }, + hits: { max_score: 0, hits: [], total: 0 }, + aggregations: { + source: { + meta: {}, + doc_count_error_upper_bound: -1, + sum_other_doc_count: 500330, + buckets: [ + { + key: '10.142.0.7', + doc_count: 12116, + bytes_out: { value: 2581835370 }, + flows: { value: 1967 }, + bytes_in: { value: 0 }, + domain: { + doc_count_error_upper_bound: 0, + sum_other_doc_count: 0, + buckets: [ + { + key: 'siem-kibana', + doc_count: 3221, + timestamp: { value: 1600078221017, value_as_string: '2020-09-14T10:10:21.017Z' }, + }, + ], + }, + autonomous_system: { + meta: {}, + doc_count: 0, + top_as: { hits: { total: { value: 0, relation: 'eq' }, max_score: 0, hits: [] } }, + }, + location: { + doc_count: 0, + top_geo: { hits: { total: { value: 0, relation: 'eq' }, max_score: 0, hits: [] } }, + }, + destination_ips: { value: 264 }, + }, + { + key: '35.232.239.42', + doc_count: 2119, + bytes_out: { value: 86968388 }, + flows: { value: 922 }, + bytes_in: { value: 0 }, + domain: { doc_count_error_upper_bound: 0, sum_other_doc_count: 0, buckets: [] }, + autonomous_system: { + doc_count: 2119, + top_as: { + hits: { + total: { value: 2119, relation: 'eq' }, + max_score: 0, + hits: [ + { + _index: 'filebeat-8.0.0-2020.09.02-000001', + _id: 'dd4fa2d4bd-1526378075029582', + _score: 0, + _source: { + source: { as: { number: 15169, organization: { name: 'Google LLC' } } }, + }, + }, + ], + }, + }, + }, + location: { + doc_count: 2119, + top_geo: { + hits: { + total: { value: 2119, relation: 'eq' }, + max_score: 0, + hits: [ + { + _index: 'filebeat-8.0.0-2020.09.02-000001', + _id: 'dd4fa2d4bd-1526378075029582', + _score: 0, + _source: { + source: { + geo: { + continent_name: 'North America', + region_iso_code: 'US-VA', + country_iso_code: 'US', + region_name: 'Virginia', + location: { lon: -77.2481, lat: 38.6583 }, + }, + }, + }, + }, + ], + }, + }, + }, + destination_ips: { value: 1 }, + }, + { + key: '151.101.200.204', + doc_count: 2, + bytes_out: { value: 1394839 }, + flows: { value: 2 }, + bytes_in: { value: 0 }, + domain: { doc_count_error_upper_bound: 0, sum_other_doc_count: 0, buckets: [] }, + autonomous_system: { + doc_count: 2, + top_as: { + hits: { + total: { value: 2, relation: 'eq' }, + max_score: 0, + hits: [ + { + _index: 'filebeat-8.0.0-2020.09.02-000001', + _id: 'dd4fa2d4bd-1527252060367158', + _score: 0, + _source: { + source: { as: { number: 54113, organization: { name: 'Fastly' } } }, + }, + }, + ], + }, + }, + }, + location: { + doc_count: 2, + top_geo: { + hits: { + total: { value: 2, relation: 'eq' }, + max_score: 0, + hits: [ + { + _index: 'filebeat-8.0.0-2020.09.02-000001', + _id: 'dd4fa2d4bd-1527252060367158', + _score: 0, + _source: { + source: { + geo: { + continent_name: 'North America', + region_iso_code: 'US-VA', + city_name: 'Ashburn', + country_iso_code: 'US', + region_name: 'Virginia', + location: { lon: -77.4728, lat: 39.0481 }, + }, + }, + }, + }, + ], + }, + }, + }, + destination_ips: { value: 1 }, + }, + { + key: '91.189.92.39', + doc_count: 1, + bytes_out: { value: 570550 }, + flows: { value: 1 }, + bytes_in: { value: 0 }, + domain: { doc_count_error_upper_bound: 0, sum_other_doc_count: 0, buckets: [] }, + autonomous_system: { + doc_count: 1, + top_as: { + hits: { + total: { value: 1, relation: 'eq' }, + max_score: 0, + hits: [ + { + _index: 'filebeat-8.0.0-2020.09.02-000001', + _id: 'dd4fa2d4bd-1526971840437636', + _score: 0, + _source: { + source: { + as: { number: 41231, organization: { name: 'Canonical Group Limited' } }, + }, + }, + }, + ], + }, + }, + }, + location: { + doc_count: 1, + top_geo: { + hits: { + total: { value: 1, relation: 'eq' }, + max_score: 0, + hits: [ + { + _index: 'filebeat-8.0.0-2020.09.02-000001', + _id: 'dd4fa2d4bd-1526971840437636', + _score: 0, + _source: { + source: { + geo: { + continent_name: 'Europe', + region_iso_code: 'GB-ENG', + city_name: 'London', + country_iso_code: 'GB', + region_name: 'England', + location: { lon: -0.0961, lat: 51.5132 }, + }, + }, + }, + }, + ], + }, + }, + }, + destination_ips: { value: 1 }, + }, + { + key: '10.142.0.5', + doc_count: 514, + bytes_out: { value: 565933 }, + flows: { value: 486 }, + bytes_in: { value: 0 }, + domain: { + doc_count_error_upper_bound: 0, + sum_other_doc_count: 0, + buckets: [ + { + key: 'infraops-docker-data', + doc_count: 514, + timestamp: { value: 1600078218215, value_as_string: '2020-09-14T10:10:18.215Z' }, + }, + ], + }, + autonomous_system: { + doc_count: 0, + top_as: { hits: { total: { value: 0, relation: 'eq' }, max_score: 0, hits: [] } }, + }, + location: { + doc_count: 0, + top_geo: { hits: { total: { value: 0, relation: 'eq' }, max_score: 0, hits: [] } }, + }, + destination_ips: { value: 343 }, + }, + { + key: '151.101.248.204', + doc_count: 6, + bytes_out: { value: 260903 }, + flows: { value: 6 }, + bytes_in: { value: 0 }, + domain: { doc_count_error_upper_bound: 0, sum_other_doc_count: 0, buckets: [] }, + autonomous_system: { + doc_count: 6, + top_as: { + hits: { + total: { value: 6, relation: 'eq' }, + max_score: 0, + hits: [ + { + _index: 'filebeat-8.0.0-2020.09.02-000001', + _id: 'dd4fa2d4bd-1527003062069535', + _score: 0, + _source: { + source: { as: { number: 54113, organization: { name: 'Fastly' } } }, + }, + }, + ], + }, + }, + }, + location: { + doc_count: 6, + top_geo: { + hits: { + total: { value: 6, relation: 'eq' }, + max_score: 0, + hits: [ + { + _index: 'filebeat-8.0.0-2020.09.02-000001', + _id: 'dd4fa2d4bd-1527003062069535', + _score: 0, + _source: { + source: { + geo: { + continent_name: 'North America', + region_iso_code: 'US-VA', + city_name: 'Ashburn', + country_iso_code: 'US', + region_name: 'Virginia', + location: { lon: -77.539, lat: 39.018 }, + }, + }, + }, + }, + ], + }, + }, + }, + destination_ips: { value: 1 }, + }, + { + key: '35.196.129.83', + doc_count: 1, + bytes_out: { value: 164079 }, + flows: { value: 1 }, + bytes_in: { value: 0 }, + domain: { doc_count_error_upper_bound: 0, sum_other_doc_count: 0, buckets: [] }, + autonomous_system: { + doc_count: 1, + top_as: { + hits: { + total: { value: 1, relation: 'eq' }, + max_score: 0, + hits: [ + { + _index: 'filebeat-8.0.0-2020.09.02-000001', + _id: 'dd4fa2d4bd-1526557113311472', + _score: 0, + _source: { + source: { as: { number: 15169, organization: { name: 'Google LLC' } } }, + }, + }, + ], + }, + }, + }, + location: { + doc_count: 1, + top_geo: { + hits: { + total: { value: 1, relation: 'eq' }, + max_score: 0, + hits: [ + { + _index: 'filebeat-8.0.0-2020.09.02-000001', + _id: 'dd4fa2d4bd-1526557113311472', + _score: 0, + _source: { + source: { + geo: { + continent_name: 'North America', + region_iso_code: 'US-VA', + country_iso_code: 'US', + region_name: 'Virginia', + location: { lon: -77.2481, lat: 38.6583 }, + }, + }, + }, + }, + ], + }, + }, + }, + destination_ips: { value: 1 }, + }, + { + key: '151.101.2.217', + doc_count: 24, + bytes_out: { value: 158407 }, + flows: { value: 24 }, + bytes_in: { value: 0 }, + domain: { doc_count_error_upper_bound: 0, sum_other_doc_count: 0, buckets: [] }, + autonomous_system: { + doc_count: 24, + top_as: { + hits: { + total: { value: 24, relation: 'eq' }, + max_score: 0, + hits: [ + { + _index: 'filebeat-8.0.0-2020.09.02-000001', + _id: 'dd4fa2d4bd-1526379128390241', + _score: 0, + _source: { + source: { as: { number: 54113, organization: { name: 'Fastly' } } }, + }, + }, + ], + }, + }, + }, + location: { + doc_count: 24, + top_geo: { + hits: { + total: { value: 24, relation: 'eq' }, + max_score: 0, + hits: [ + { + _index: 'filebeat-8.0.0-2020.09.02-000001', + _id: 'dd4fa2d4bd-1526379128390241', + _score: 0, + _source: { + source: { + geo: { + continent_name: 'North America', + country_iso_code: 'US', + location: { lon: -97.822, lat: 37.751 }, + }, + }, + }, + }, + ], + }, + }, + }, + destination_ips: { value: 1 }, + }, + { + key: '91.189.91.38', + doc_count: 1, + bytes_out: { value: 89031 }, + flows: { value: 1 }, + bytes_in: { value: 0 }, + domain: { doc_count_error_upper_bound: 0, sum_other_doc_count: 0, buckets: [] }, + autonomous_system: { + doc_count: 1, + top_as: { + hits: { + total: { value: 1, relation: 'eq' }, + max_score: 0, + hits: [ + { + _index: 'filebeat-8.0.0-2020.09.02-000001', + _id: 'dd4fa2d4bd-1526555996515551', + _score: 0, + _source: { + source: { + as: { number: 41231, organization: { name: 'Canonical Group Limited' } }, + }, + }, + }, + ], + }, + }, + }, + location: { + doc_count: 1, + top_geo: { + hits: { + total: { value: 1, relation: 'eq' }, + max_score: 0, + hits: [ + { + _index: 'filebeat-8.0.0-2020.09.02-000001', + _id: 'dd4fa2d4bd-1526555996515551', + _score: 0, + _source: { + source: { + geo: { + continent_name: 'North America', + region_iso_code: 'US-MA', + city_name: 'Boston', + country_iso_code: 'US', + region_name: 'Massachusetts', + location: { lon: -71.0631, lat: 42.3562 }, + }, + }, + }, + }, + ], + }, + }, + }, + destination_ips: { value: 1 }, + }, + { + key: '193.228.91.123', + doc_count: 33, + bytes_out: { value: 32170 }, + flows: { value: 33 }, + bytes_in: { value: 0 }, + domain: { doc_count_error_upper_bound: 0, sum_other_doc_count: 0, buckets: [] }, + autonomous_system: { + doc_count: 33, + top_as: { + hits: { + total: { value: 33, relation: 'eq' }, + max_score: 0, + hits: [ + { + _index: 'filebeat-8.0.0-2020.09.02-000001', + _id: 'dd4fa2d4bd-1526584379144248', + _score: 0, + _source: { + source: { as: { number: 133766, organization: { name: 'YHSRV.LLC' } } }, + }, + }, + ], + }, + }, + }, + location: { + doc_count: 33, + top_geo: { + hits: { + total: { value: 33, relation: 'eq' }, + max_score: 0, + hits: [ + { + _index: 'filebeat-8.0.0-2020.09.02-000001', + _id: 'dd4fa2d4bd-1526584379144248', + _score: 0, + _source: { + source: { + geo: { + continent_name: 'North America', + country_iso_code: 'US', + location: { lon: -97.822, lat: 37.751 }, + }, + }, + }, + }, + ], + }, + }, + }, + destination_ips: { value: 2 }, + }, + ], + }, + top_n_flow_count: { value: 738 }, + }, + }, + total: 21, + loaded: 21, +}; + +export const formattedSearchStrategyResponse = { + edges: [ + { + node: { + _id: '10.142.0.7', + source: { + domain: ['siem-kibana'], + ip: '10.142.0.7', + location: null, + autonomous_system: null, + flows: 1967, + destination_ips: 264, + }, + network: { bytes_in: 0, bytes_out: 2581835370 }, + }, + cursor: { value: '10.142.0.7', tiebreaker: null }, + }, + { + node: { + _id: '35.232.239.42', + source: { + domain: [], + ip: '35.232.239.42', + location: { + geo: { + continent_name: 'North America', + region_iso_code: 'US-VA', + country_iso_code: 'US', + region_name: 'Virginia', + location: { lon: -77.2481, lat: 38.6583 }, + }, + flowTarget: 'source', + }, + autonomous_system: { number: 15169, name: 'Google LLC' }, + flows: 922, + destination_ips: 1, + }, + network: { bytes_in: 0, bytes_out: 86968388 }, + }, + cursor: { value: '35.232.239.42', tiebreaker: null }, + }, + { + node: { + _id: '151.101.200.204', + source: { + domain: [], + ip: '151.101.200.204', + location: { + geo: { + continent_name: 'North America', + region_iso_code: 'US-VA', + city_name: 'Ashburn', + country_iso_code: 'US', + region_name: 'Virginia', + location: { lon: -77.4728, lat: 39.0481 }, + }, + flowTarget: 'source', + }, + autonomous_system: { number: 54113, name: 'Fastly' }, + flows: 2, + destination_ips: 1, + }, + network: { bytes_in: 0, bytes_out: 1394839 }, + }, + cursor: { value: '151.101.200.204', tiebreaker: null }, + }, + { + node: { + _id: '91.189.92.39', + source: { + domain: [], + ip: '91.189.92.39', + location: { + geo: { + continent_name: 'Europe', + region_iso_code: 'GB-ENG', + city_name: 'London', + country_iso_code: 'GB', + region_name: 'England', + location: { lon: -0.0961, lat: 51.5132 }, + }, + flowTarget: 'source', + }, + autonomous_system: { number: 41231, name: 'Canonical Group Limited' }, + flows: 1, + destination_ips: 1, + }, + network: { bytes_in: 0, bytes_out: 570550 }, + }, + cursor: { value: '91.189.92.39', tiebreaker: null }, + }, + { + node: { + _id: '10.142.0.5', + source: { + domain: ['infraops-docker-data'], + ip: '10.142.0.5', + location: null, + autonomous_system: null, + flows: 486, + destination_ips: 343, + }, + network: { bytes_in: 0, bytes_out: 565933 }, + }, + cursor: { value: '10.142.0.5', tiebreaker: null }, + }, + { + node: { + _id: '151.101.248.204', + source: { + domain: [], + ip: '151.101.248.204', + location: { + geo: { + continent_name: 'North America', + region_iso_code: 'US-VA', + city_name: 'Ashburn', + country_iso_code: 'US', + region_name: 'Virginia', + location: { lon: -77.539, lat: 39.018 }, + }, + flowTarget: 'source', + }, + autonomous_system: { number: 54113, name: 'Fastly' }, + flows: 6, + destination_ips: 1, + }, + network: { bytes_in: 0, bytes_out: 260903 }, + }, + cursor: { value: '151.101.248.204', tiebreaker: null }, + }, + { + node: { + _id: '35.196.129.83', + source: { + domain: [], + ip: '35.196.129.83', + location: { + geo: { + continent_name: 'North America', + region_iso_code: 'US-VA', + country_iso_code: 'US', + region_name: 'Virginia', + location: { lon: -77.2481, lat: 38.6583 }, + }, + flowTarget: 'source', + }, + autonomous_system: { number: 15169, name: 'Google LLC' }, + flows: 1, + destination_ips: 1, + }, + network: { bytes_in: 0, bytes_out: 164079 }, + }, + cursor: { value: '35.196.129.83', tiebreaker: null }, + }, + { + node: { + _id: '151.101.2.217', + source: { + domain: [], + ip: '151.101.2.217', + location: { + geo: { + continent_name: 'North America', + country_iso_code: 'US', + location: { lon: -97.822, lat: 37.751 }, + }, + flowTarget: 'source', + }, + autonomous_system: { number: 54113, name: 'Fastly' }, + flows: 24, + destination_ips: 1, + }, + network: { bytes_in: 0, bytes_out: 158407 }, + }, + cursor: { value: '151.101.2.217', tiebreaker: null }, + }, + { + node: { + _id: '91.189.91.38', + source: { + domain: [], + ip: '91.189.91.38', + location: { + geo: { + continent_name: 'North America', + region_iso_code: 'US-MA', + city_name: 'Boston', + country_iso_code: 'US', + region_name: 'Massachusetts', + location: { lon: -71.0631, lat: 42.3562 }, + }, + flowTarget: 'source', + }, + autonomous_system: { number: 41231, name: 'Canonical Group Limited' }, + flows: 1, + destination_ips: 1, + }, + network: { bytes_in: 0, bytes_out: 89031 }, + }, + cursor: { value: '91.189.91.38', tiebreaker: null }, + }, + { + node: { + _id: '193.228.91.123', + source: { + domain: [], + ip: '193.228.91.123', + location: { + geo: { + continent_name: 'North America', + country_iso_code: 'US', + location: { lon: -97.822, lat: 37.751 }, + }, + flowTarget: 'source', + }, + autonomous_system: { number: 133766, name: 'YHSRV.LLC' }, + flows: 33, + destination_ips: 2, + }, + network: { bytes_in: 0, bytes_out: 32170 }, + }, + cursor: { value: '193.228.91.123', tiebreaker: null }, + }, + ], + inspect: { + dsl: [ + '{\n "allowNoIndices": true,\n "index": [\n "apm-*-transaction*",\n "auditbeat-*",\n "endgame-*",\n "filebeat-*",\n "logs-*",\n "packetbeat-*",\n "winlogbeat-*"\n ],\n "ignoreUnavailable": true,\n "body": {\n "aggregations": {\n "top_n_flow_count": {\n "cardinality": {\n "field": "source.ip"\n }\n },\n "source": {\n "terms": {\n "field": "source.ip",\n "size": 10,\n "order": {\n "bytes_out": "desc"\n }\n },\n "aggs": {\n "bytes_in": {\n "sum": {\n "field": "destination.bytes"\n }\n },\n "bytes_out": {\n "sum": {\n "field": "source.bytes"\n }\n },\n "domain": {\n "terms": {\n "field": "source.domain",\n "order": {\n "timestamp": "desc"\n }\n },\n "aggs": {\n "timestamp": {\n "max": {\n "field": "@timestamp"\n }\n }\n }\n },\n "location": {\n "filter": {\n "exists": {\n "field": "source.geo"\n }\n },\n "aggs": {\n "top_geo": {\n "top_hits": {\n "_source": "source.geo.*",\n "size": 1\n }\n }\n }\n },\n "autonomous_system": {\n "filter": {\n "exists": {\n "field": "source.as"\n }\n },\n "aggs": {\n "top_as": {\n "top_hits": {\n "_source": "source.as.*",\n "size": 1\n }\n }\n }\n },\n "flows": {\n "cardinality": {\n "field": "network.community_id"\n }\n },\n "destination_ips": {\n "cardinality": {\n "field": "destination.ip"\n }\n }\n }\n }\n },\n "query": {\n "bool": {\n "filter": [\n "{\\"bool\\":{\\"must\\":[],\\"filter\\":[{\\"match_all\\":{}}],\\"should\\":[],\\"must_not\\":[]}}",\n {\n "range": {\n "@timestamp": {\n "gte": "2020-09-13T10:16:46.870Z",\n "lte": "2020-09-14T10:16:46.870Z",\n "format": "strict_date_optional_time"\n }\n }\n }\n ]\n }\n }\n },\n "size": 0,\n "track_total_hits": false\n}', + ], + }, + pageInfo: { activePage: 0, fakeTotalCount: 50, showMorePagesIndicator: true }, + totalCount: 738, +}; + +export const expectedDsl = { + allowNoIndices: true, + index: [ + 'apm-*-transaction*', + 'auditbeat-*', + 'endgame-*', + 'filebeat-*', + 'logs-*', + 'packetbeat-*', + 'winlogbeat-*', + ], + ignoreUnavailable: true, + body: { + aggregations: { + top_n_flow_count: { cardinality: { field: 'source.ip' } }, + source: { + terms: { field: 'source.ip', size: 10, order: { bytes_out: 'desc' } }, + aggs: { + bytes_in: { sum: { field: 'destination.bytes' } }, + bytes_out: { sum: { field: 'source.bytes' } }, + domain: { + terms: { field: 'source.domain', order: { timestamp: 'desc' } }, + aggs: { timestamp: { max: { field: '@timestamp' } } }, + }, + location: { + filter: { exists: { field: 'source.geo' } }, + aggs: { top_geo: { top_hits: { _source: 'source.geo.*', size: 1 } } }, + }, + autonomous_system: { + filter: { exists: { field: 'source.as' } }, + aggs: { top_as: { top_hits: { _source: 'source.as.*', size: 1 } } }, + }, + flows: { cardinality: { field: 'network.community_id' } }, + destination_ips: { cardinality: { field: 'destination.ip' } }, + }, + }, + }, + query: { + bool: { + filter: [ + '{"bool":{"must":[],"filter":[{"match_all":{}}],"should":[],"must_not":[]}}', + { + range: { + '@timestamp': { + gte: '2020-09-13T10:16:46.870Z', + lte: '2020-09-14T10:16:46.870Z', + format: 'strict_date_optional_time', + }, + }, + }, + ], + }, + }, + }, + size: 0, + track_total_hits: false, +}; diff --git a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/top_n_flow/index.test.ts b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/top_n_flow/index.test.ts new file mode 100644 index 0000000000000..fe3213a4e5388 --- /dev/null +++ b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/top_n_flow/index.test.ts @@ -0,0 +1,35 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import * as buildQuery from './query.top_n_flow_network.dsl'; +import { networkTopNFlow } from '.'; +import { + mockOptions, + mockSearchStrategyResponse, + formattedSearchStrategyResponse, +} from './__mocks__'; + +describe('networkTopNFlow search strategy', () => { + const buildTopNFlowQuery = jest.spyOn(buildQuery, 'buildTopNFlowQuery'); + + afterEach(() => { + buildTopNFlowQuery.mockClear(); + }); + + describe('buildDsl', () => { + test('should build dsl query', () => { + networkTopNFlow.buildDsl(mockOptions); + expect(buildTopNFlowQuery).toHaveBeenCalledWith(mockOptions); + }); + }); + + describe('parse', () => { + test('should parse data correctly', async () => { + const result = await networkTopNFlow.parse(mockOptions, mockSearchStrategyResponse); + expect(result).toMatchObject(formattedSearchStrategyResponse); + }); + }); +}); diff --git a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/top_n_flow/query.top_n_flow_network.dsl.test.ts b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/top_n_flow/query.top_n_flow_network.dsl.test.ts new file mode 100644 index 0000000000000..902769ae9a30b --- /dev/null +++ b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/top_n_flow/query.top_n_flow_network.dsl.test.ts @@ -0,0 +1,13 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ +import { buildTopNFlowQuery } from './query.top_n_flow_network.dsl'; +import { mockOptions, expectedDsl } from './__mocks__'; + +describe('buildTopNFlowQuery', () => { + test('build query from options correctly', () => { + expect(buildTopNFlowQuery(mockOptions)).toEqual(expectedDsl); + }); +}); diff --git a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/users/__mocks__/index.ts b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/users/__mocks__/index.ts new file mode 100644 index 0000000000000..3f57de7c78d1a --- /dev/null +++ b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/users/__mocks__/index.ts @@ -0,0 +1,170 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { IEsSearchResponse } from '../../../../../../../../../../src/plugins/data/common'; + +import { + Direction, + NetworkUsersRequestOptions, + NetworkQueries, + NetworkUsersFields, + FlowTarget, +} from '../../../../../../../common/search_strategy'; + +export const mockOptions: NetworkUsersRequestOptions = { + defaultIndex: [ + 'apm-*-transaction*', + 'auditbeat-*', + 'endgame-*', + 'filebeat-*', + 'logs-*', + 'packetbeat-*', + 'winlogbeat-*', + ], + factoryQueryType: NetworkQueries.users, + filterQuery: '{"bool":{"must":[],"filter":[{"match_all":{}}],"should":[],"must_not":[]}}', + flowTarget: FlowTarget.source, + ip: '10.142.0.7', + pagination: { activePage: 0, cursorStart: 0, fakePossibleCount: 50, querySize: 10 }, + sort: { field: NetworkUsersFields.name, direction: Direction.asc }, + timerange: { interval: '12h', from: '2020-09-13T10:16:46.870Z', to: '2020-09-14T10:16:46.870Z' }, +}; + +export const mockSearchStrategyResponse: IEsSearchResponse = { + isPartial: false, + isRunning: false, + rawResponse: { + took: 12, + timed_out: false, + _shards: { total: 21, successful: 21, skipped: 0, failed: 0 }, + hits: { total: 0, max_score: 0, hits: [] }, + aggregations: { + user_count: { value: 3 }, + users: { + doc_count_error_upper_bound: 0, + sum_other_doc_count: 0, + buckets: [ + { + key: '_apt', + doc_count: 34, + groupName: { doc_count_error_upper_bound: 0, sum_other_doc_count: 0, buckets: [] }, + groupId: { doc_count_error_upper_bound: 0, sum_other_doc_count: 0, buckets: [] }, + id: { + doc_count_error_upper_bound: 0, + sum_other_doc_count: 0, + buckets: [{ key: '104', doc_count: 34 }], + }, + }, + { + key: 'root', + doc_count: 8852, + groupName: { doc_count_error_upper_bound: 0, sum_other_doc_count: 0, buckets: [] }, + groupId: { doc_count_error_upper_bound: 0, sum_other_doc_count: 0, buckets: [] }, + id: { + doc_count_error_upper_bound: 0, + sum_other_doc_count: 0, + buckets: [{ key: '0', doc_count: 8852 }], + }, + }, + { + key: 'tsg', + doc_count: 16, + groupName: { doc_count_error_upper_bound: 0, sum_other_doc_count: 0, buckets: [] }, + groupId: { doc_count_error_upper_bound: 0, sum_other_doc_count: 0, buckets: [] }, + id: { + doc_count_error_upper_bound: 0, + sum_other_doc_count: 0, + buckets: [{ key: '1005', doc_count: 16 }], + }, + }, + ], + }, + }, + }, + total: 21, + loaded: 21, +}; + +export const formattedSearchStrategyResponse = { + ...mockSearchStrategyResponse, + edges: [ + { + node: { + _id: '_apt', + user: { id: ['104'], name: '_apt', groupId: [], groupName: [], count: 34 }, + }, + cursor: { value: '_apt', tiebreaker: null }, + }, + { + node: { + _id: 'root', + user: { id: ['0'], name: 'root', groupId: [], groupName: [], count: 8852 }, + }, + cursor: { value: 'root', tiebreaker: null }, + }, + { + node: { + _id: 'tsg', + user: { id: ['1005'], name: 'tsg', groupId: [], groupName: [], count: 16 }, + }, + cursor: { value: 'tsg', tiebreaker: null }, + }, + ], + inspect: { + dsl: [ + '{\n "allowNoIndices": true,\n "index": [\n "apm-*-transaction*",\n "auditbeat-*",\n "endgame-*",\n "filebeat-*",\n "logs-*",\n "packetbeat-*",\n "winlogbeat-*"\n ],\n "ignoreUnavailable": true,\n "body": {\n "aggs": {\n "user_count": {\n "cardinality": {\n "field": "user.name"\n }\n },\n "users": {\n "terms": {\n "field": "user.name",\n "size": 10,\n "order": {\n "_key": "asc"\n }\n },\n "aggs": {\n "id": {\n "terms": {\n "field": "user.id"\n }\n },\n "groupId": {\n "terms": {\n "field": "user.group.id"\n }\n },\n "groupName": {\n "terms": {\n "field": "user.group.name"\n }\n }\n }\n }\n },\n "query": {\n "bool": {\n "filter": [\n "{\\"bool\\":{\\"must\\":[],\\"filter\\":[{\\"match_all\\":{}}],\\"should\\":[],\\"must_not\\":[]}}",\n {\n "range": {\n "@timestamp": {\n "gte": "2020-09-13T10:16:46.870Z",\n "lte": "2020-09-14T10:16:46.870Z",\n "format": "strict_date_optional_time"\n }\n }\n },\n {\n "term": {\n "source.ip": "10.142.0.7"\n }\n }\n ],\n "must_not": [\n {\n "term": {\n "event.category": "authentication"\n }\n }\n ]\n }\n },\n "size": 0,\n "track_total_hits": false\n }\n}', + ], + }, + pageInfo: { activePage: 0, fakeTotalCount: 3, showMorePagesIndicator: false }, + totalCount: 3, +}; + +export const expectedDsl = { + allowNoIndices: true, + body: { + aggs: { + user_count: { cardinality: { field: 'user.name' } }, + users: { + aggs: { + groupId: { terms: { field: 'user.group.id' } }, + groupName: { terms: { field: 'user.group.name' } }, + id: { terms: { field: 'user.id' } }, + }, + terms: { field: 'user.name', order: { _key: 'asc' }, size: 10 }, + }, + }, + query: { + bool: { + filter: [ + '{"bool":{"must":[],"filter":[{"match_all":{}}],"should":[],"must_not":[]}}', + { + range: { + '@timestamp': { + format: 'strict_date_optional_time', + gte: '2020-09-13T10:16:46.870Z', + lte: '2020-09-14T10:16:46.870Z', + }, + }, + }, + { term: { 'source.ip': '10.142.0.7' } }, + ], + must_not: [{ term: { 'event.category': 'authentication' } }], + }, + }, + size: 0, + track_total_hits: false, + }, + ignoreUnavailable: true, + index: [ + 'apm-*-transaction*', + 'auditbeat-*', + 'endgame-*', + 'filebeat-*', + 'logs-*', + 'packetbeat-*', + 'winlogbeat-*', + ], +}; diff --git a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/users/helpers.test.ts b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/users/helpers.test.ts new file mode 100644 index 0000000000000..19ce687cd3f07 --- /dev/null +++ b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/users/helpers.test.ts @@ -0,0 +1,15 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { getUsersEdges } from './helpers'; +import { mockSearchStrategyResponse, formattedSearchStrategyResponse } from './__mocks__'; + +describe('#getUsers', () => { + test('will format edges correctly', () => { + const edges = getUsersEdges(mockSearchStrategyResponse); + expect(edges).toEqual(formattedSearchStrategyResponse.edges); + }); +}); diff --git a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/users/index.test.ts b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/users/index.test.ts new file mode 100644 index 0000000000000..bd98ec0947b35 --- /dev/null +++ b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/users/index.test.ts @@ -0,0 +1,51 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ +import { DEFAULT_MAX_TABLE_QUERY_SIZE } from '../../../../../../common/constants'; +import { NetworkUsersRequestOptions } from '../../../../../../common/search_strategy/security_solution/network'; + +import * as buildQuery from './query.users_network.dsl'; +import { networkUsers } from '.'; +import { + mockOptions, + mockSearchStrategyResponse, + formattedSearchStrategyResponse, +} from './__mocks__'; + +describe('networkUsers search strategy', () => { + const buildUsersQuery = jest.spyOn(buildQuery, 'buildUsersQuery'); + + afterEach(() => { + buildUsersQuery.mockClear(); + }); + + describe('buildDsl', () => { + test('should build dsl query', () => { + networkUsers.buildDsl(mockOptions); + expect(buildUsersQuery).toHaveBeenCalledWith(mockOptions); + }); + + test('should throw error if query size is greater equal than DEFAULT_MAX_TABLE_QUERY_SIZE ', () => { + const overSizeOptions = { + ...mockOptions, + pagination: { + ...mockOptions.pagination, + querySize: DEFAULT_MAX_TABLE_QUERY_SIZE, + }, + } as NetworkUsersRequestOptions; + + expect(() => { + networkUsers.buildDsl(overSizeOptions); + }).toThrowError(`No query size above ${DEFAULT_MAX_TABLE_QUERY_SIZE}`); + }); + }); + + describe('parse', () => { + test('should parse data correctly', async () => { + const result = await networkUsers.parse(mockOptions, mockSearchStrategyResponse); + expect(result).toMatchObject(formattedSearchStrategyResponse); + }); + }); +}); diff --git a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/users/query.users_network.dsl.test.ts b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/users/query.users_network.dsl.test.ts new file mode 100644 index 0000000000000..ce43e1fb49e9f --- /dev/null +++ b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/users/query.users_network.dsl.test.ts @@ -0,0 +1,13 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ +import { buildUsersQuery } from './query.users_network.dsl'; +import { mockOptions, expectedDsl } from './__mocks__'; + +describe('buildUsersQuery', () => { + test('build query from options correctly', () => { + expect(buildUsersQuery(mockOptions)).toEqual(expectedDsl); + }); +}); diff --git a/x-pack/plugins/spaces/server/saved_objects/mappings.ts b/x-pack/plugins/spaces/server/saved_objects/mappings.ts index 3afa7c389927c..875a164e25217 100644 --- a/x-pack/plugins/spaces/server/saved_objects/mappings.ts +++ b/x-pack/plugins/spaces/server/saved_objects/mappings.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { deepFreeze } from '../../../../../src/core/server'; +import { deepFreeze } from '@kbn/std'; export const SpacesSavedObjectMappings = deepFreeze({ properties: { diff --git a/x-pack/plugins/translations/translations/ja-JP.json b/x-pack/plugins/translations/translations/ja-JP.json index 86a132f669f67..0977e99fa0c3c 100644 --- a/x-pack/plugins/translations/translations/ja-JP.json +++ b/x-pack/plugins/translations/translations/ja-JP.json @@ -9559,10 +9559,8 @@ "xpack.lens.editorFrame.emptyWorkspaceHeading": "レンズはビジュアライゼーションを作成するための新しいツールです", "xpack.lens.editorFrame.expandRenderingErrorButton": "エラーの詳細を表示", "xpack.lens.editorFrame.expressionFailure": "表現を正常に実行できませんでした", - "xpack.lens.editorFrame.formatStyleLabel": "書式とスタイル", "xpack.lens.editorFrame.goToForums": "リクエストとフィードバック", "xpack.lens.editorFrame.previewErrorLabel": "レンダリングのプレビューに失敗しました", - "xpack.lens.editorFrame.quickFunctionsLabel": "クイック機能", "xpack.lens.editorFrame.requiredDimensionWarningLabel": "必要な次元", "xpack.lens.editorFrame.suggestionPanelTitle": "提案", "xpack.lens.embeddable.failure": "ビジュアライゼーションを表示できませんでした", @@ -9616,7 +9614,6 @@ "xpack.lens.indexPattern.existenceErrorLabel": "フィールド情報を読み込めません", "xpack.lens.indexPattern.fieldDistributionLabel": "分布", "xpack.lens.indexPattern.fieldItemTooltip": "可視化するには、ドラッグアンドドロップします。", - "xpack.lens.indexPattern.fieldlessOperationLabel": "この関数を使用するには、フィールドを選択してください。", "xpack.lens.indexPattern.fieldPanelEmptyStringValue": "空の文字列", "xpack.lens.indexPattern.fieldPlaceholder": "フィールド", "xpack.lens.indexPattern.fieldStatsButtonLabel": "フィールドプレビューを表示するには、クリックします。可視化するには、ドラッグアンドドロップします。", @@ -9694,7 +9691,6 @@ "xpack.lens.pieChart.legendDisplayLegend": "凡例表示", "xpack.lens.pieChart.nestedLegendLabel": "ネストされた凡例", "xpack.lens.pieChart.numberLabels": "ラベル値", - "xpack.lens.pieChart.percentDecimalsLabel": "割合の小数点桁数", "xpack.lens.pieChart.showCategoriesLabel": "内部または外部", "xpack.lens.pieChart.showFormatterValuesLabel": "値を表示", "xpack.lens.pieChart.showPercentValuesLabel": "割合を表示", diff --git a/x-pack/plugins/translations/translations/zh-CN.json b/x-pack/plugins/translations/translations/zh-CN.json index e860efb487e52..7f8f2a98abae3 100644 --- a/x-pack/plugins/translations/translations/zh-CN.json +++ b/x-pack/plugins/translations/translations/zh-CN.json @@ -9565,10 +9565,8 @@ "xpack.lens.editorFrame.emptyWorkspaceHeading": "Lens 是用于创建可视化的新工具", "xpack.lens.editorFrame.expandRenderingErrorButton": "显示错误的详情", "xpack.lens.editorFrame.expressionFailure": "无法成功执行表达式", - "xpack.lens.editorFrame.formatStyleLabel": "格式和样式", "xpack.lens.editorFrame.goToForums": "提出请求并提供反馈", "xpack.lens.editorFrame.previewErrorLabel": "预览呈现失败", - "xpack.lens.editorFrame.quickFunctionsLabel": "快选函数", "xpack.lens.editorFrame.requiredDimensionWarningLabel": "所需尺寸", "xpack.lens.editorFrame.suggestionPanelTitle": "建议", "xpack.lens.embeddable.failure": "无法显示可视化", @@ -9622,7 +9620,6 @@ "xpack.lens.indexPattern.existenceErrorLabel": "无法加载字段信息", "xpack.lens.indexPattern.fieldDistributionLabel": "分布", "xpack.lens.indexPattern.fieldItemTooltip": "拖放以可视化。", - "xpack.lens.indexPattern.fieldlessOperationLabel": "要使用此函数,请选择字段。", "xpack.lens.indexPattern.fieldPanelEmptyStringValue": "空字符串", "xpack.lens.indexPattern.fieldPlaceholder": "字段", "xpack.lens.indexPattern.fieldStatsButtonLabel": "单击以进行字段预览,或拖放以进行可视化。", @@ -9700,7 +9697,6 @@ "xpack.lens.pieChart.legendDisplayLegend": "图例显示", "xpack.lens.pieChart.nestedLegendLabel": "嵌套图例", "xpack.lens.pieChart.numberLabels": "标签值", - "xpack.lens.pieChart.percentDecimalsLabel": "百分比的小数位数", "xpack.lens.pieChart.showCategoriesLabel": "内部或外部", "xpack.lens.pieChart.showFormatterValuesLabel": "显示值", "xpack.lens.pieChart.showPercentValuesLabel": "显示百分比", diff --git a/x-pack/plugins/ui_actions_enhanced/public/drilldowns/url_drilldown/url_drilldown_scope.ts b/x-pack/plugins/ui_actions_enhanced/public/drilldowns/url_drilldown/url_drilldown_scope.ts index d499812a9d5ae..2c9237fac593f 100644 --- a/x-pack/plugins/ui_actions_enhanced/public/drilldowns/url_drilldown/url_drilldown_scope.ts +++ b/x-pack/plugins/ui_actions_enhanced/public/drilldowns/url_drilldown/url_drilldown_scope.ts @@ -5,8 +5,8 @@ */ import partition from 'lodash/partition'; +import { getFlattenedObject } from '@kbn/std'; import { UrlDrilldownGlobalScope, UrlDrilldownScope } from './types'; -import { getFlattenedObject } from '../../../../../../src/core/public'; export function buildScope< ContextScope extends object = object, diff --git a/x-pack/test/apm_api_integration/basic/tests/observability_overview/has_data.ts b/x-pack/test/apm_api_integration/basic/tests/observability_overview/has_data.ts index 127721e8e2112..6d0d2d3042625 100644 --- a/x-pack/test/apm_api_integration/basic/tests/observability_overview/has_data.ts +++ b/x-pack/test/apm_api_integration/basic/tests/observability_overview/has_data.ts @@ -10,6 +10,8 @@ export default function ApiTest({ getService }: FtrProviderContext) { const supertest = getService('supertest'); const esArchiver = getService('esArchiver'); + const archiveName = 'apm_8.0.0'; + describe('Has data', () => { describe('when data is not loaded', () => { it('returns false when there is no data', async () => { @@ -28,8 +30,8 @@ export default function ApiTest({ getService }: FtrProviderContext) { }); }); describe('when data is loaded', () => { - before(() => esArchiver.load('8.0.0')); - after(() => esArchiver.unload('8.0.0')); + before(() => esArchiver.load(archiveName)); + after(() => esArchiver.unload(archiveName)); it('returns true when there is at least one document on transaction, error or metrics indices', async () => { const response = await supertest.get('/api/apm/observability_overview/has_data'); diff --git a/x-pack/test/apm_api_integration/basic/tests/observability_overview/observability_overview.ts b/x-pack/test/apm_api_integration/basic/tests/observability_overview/observability_overview.ts index 96ac3c3a5e494..6153ddd46a5b4 100644 --- a/x-pack/test/apm_api_integration/basic/tests/observability_overview/observability_overview.ts +++ b/x-pack/test/apm_api_integration/basic/tests/observability_overview/observability_overview.ts @@ -4,6 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ import expect from '@kbn/expect'; +import archives_metadata from '../../../common/archives_metadata'; import { expectSnapshot } from '../../../common/match_snapshot'; import { FtrProviderContext } from '../../../common/ftr_provider_context'; @@ -11,9 +12,12 @@ export default function ApiTest({ getService }: FtrProviderContext) { const supertest = getService('supertest'); const esArchiver = getService('esArchiver'); + const archiveName = 'apm_8.0.0'; + const metadata = archives_metadata[archiveName]; + // url parameters - const start = encodeURIComponent('2020-06-29T06:00:00.000Z'); - const end = encodeURIComponent('2020-06-29T10:00:00.000Z'); + const start = encodeURIComponent(metadata.start); + const end = encodeURIComponent(metadata.end); const bucketSize = '60s'; describe('Observability overview', () => { @@ -23,37 +27,58 @@ export default function ApiTest({ getService }: FtrProviderContext) { `/api/apm/observability_overview?start=${start}&end=${end}&bucketSize=${bucketSize}` ); expect(response.status).to.be(200); - expectSnapshot(response.body).toMatchInline(` - Object { - "serviceCount": 0, - "transactionCoordinates": Array [], - } - `); + + expect(response.body.serviceCount).to.be(0); + expect(response.body.transactionCoordinates.length).to.be(0); }); }); describe('when data is loaded', () => { - before(() => esArchiver.load('8.0.0')); - after(() => esArchiver.unload('8.0.0')); + before(() => esArchiver.load(archiveName)); + after(() => esArchiver.unload(archiveName)); it('returns the service count and transaction coordinates', async () => { const response = await supertest.get( `/api/apm/observability_overview?start=${start}&end=${end}&bucketSize=${bucketSize}` ); expect(response.status).to.be(200); - expectSnapshot(response.body).toMatchInline(` - Object { - "serviceCount": 3, - "transactionCoordinates": Array [ - Object { - "x": 1593413220000, - "y": 0.016666666666666666, - }, - Object { - "x": 1593413280000, - "y": 1.0458333333333334, - }, - ], - } + + expect(response.body.serviceCount).to.be.greaterThan(0); + expect(response.body.transactionCoordinates.length).to.be.greaterThan(0); + + expectSnapshot(response.body.serviceCount).toMatchInline(`7`); + + expectSnapshot(response.body.transactionCoordinates.length).toMatchInline(`60`); + + expectSnapshot( + response.body.transactionCoordinates + .slice(0, 5) + .map(({ x, y }: { x: number; y: number }) => ({ + x: new Date(x).toISOString(), + y, + })) + ).toMatchInline(` + Array [ + Object { + "x": "2020-09-10T06:00:00.000Z", + "y": 1.2166666666666666, + }, + Object { + "x": "2020-09-10T06:01:00.000Z", + "y": 0.5, + }, + Object { + "x": "2020-09-10T06:02:00.000Z", + "y": 1.0333333333333334, + }, + Object { + "x": "2020-09-10T06:03:00.000Z", + "y": 0.55, + }, + Object { + "x": "2020-09-10T06:04:00.000Z", + "y": 1.15, + }, + ] `); }); }); diff --git a/x-pack/test/apm_api_integration/basic/tests/service_maps/service_maps.ts b/x-pack/test/apm_api_integration/basic/tests/service_maps/service_maps.ts index b0e503eb7d1eb..d729680154c1d 100644 --- a/x-pack/test/apm_api_integration/basic/tests/service_maps/service_maps.ts +++ b/x-pack/test/apm_api_integration/basic/tests/service_maps/service_maps.ts @@ -5,22 +5,28 @@ */ import expect from '@kbn/expect'; +import { expectSnapshot } from '../../../common/match_snapshot'; +import archives_metadata from '../../../common/archives_metadata'; import { FtrProviderContext } from '../../../common/ftr_provider_context'; export default function serviceMapsApiTests({ getService }: FtrProviderContext) { const supertest = getService('supertest'); + const archiveName = 'apm_8.0.0'; + const metadata = archives_metadata[archiveName]; + // url parameters - const start = encodeURIComponent('2020-06-29T06:45:00.000Z'); - const end = encodeURIComponent('2020-06-29T06:49:00.000Z'); + const start = encodeURIComponent(metadata.start); + const end = encodeURIComponent(metadata.end); describe('Service Maps', () => { it('is only be available to users with Platinum license (or higher)', async () => { const response = await supertest.get(`/api/apm/service-map?start=${start}&end=${end}`); expect(response.status).to.be(403); - expect(response.body.message).to.be( - "In order to access Service Maps, you must be subscribed to an Elastic Platinum license. With it, you'll have the ability to visualize your entire application stack along with your APM data." + + expectSnapshot(response.body.message).toMatchInline( + `"In order to access Service Maps, you must be subscribed to an Elastic Platinum license. With it, you'll have the ability to visualize your entire application stack along with your APM data."` ); }); }); diff --git a/x-pack/test/apm_api_integration/basic/tests/services/agent_name.ts b/x-pack/test/apm_api_integration/basic/tests/services/agent_name.ts index a87d080e564a2..ee835fde680e0 100644 --- a/x-pack/test/apm_api_integration/basic/tests/services/agent_name.ts +++ b/x-pack/test/apm_api_integration/basic/tests/services/agent_name.ts @@ -39,6 +39,7 @@ export default function ApiTest({ getService }: FtrProviderContext) { ); expect(response.status).to.be(200); + expect(response.body).to.eql({ agentName: 'nodejs' }); }); }); diff --git a/x-pack/test/apm_api_integration/basic/tests/services/top_services.ts b/x-pack/test/apm_api_integration/basic/tests/services/top_services.ts index 116b2987db32a..c5027565fd6b9 100644 --- a/x-pack/test/apm_api_integration/basic/tests/services/top_services.ts +++ b/x-pack/test/apm_api_integration/basic/tests/services/top_services.ts @@ -33,7 +33,9 @@ export default function ApiTest({ getService }: FtrProviderContext) { ); expect(response.status).to.be(200); - expect(response.body).to.eql({ hasHistoricalData: false, hasLegacyData: false, items: [] }); + expect(response.body.hasHistoricalData).to.be(false); + expect(response.body.hasLegacyData).to.be(false); + expect(response.body.items.length).to.be(0); }); }); diff --git a/x-pack/test/apm_api_integration/basic/tests/services/transaction_types.ts b/x-pack/test/apm_api_integration/basic/tests/services/transaction_types.ts index a6c6bad21a8b7..1221ce0198d82 100644 --- a/x-pack/test/apm_api_integration/basic/tests/services/transaction_types.ts +++ b/x-pack/test/apm_api_integration/basic/tests/services/transaction_types.ts @@ -5,6 +5,7 @@ */ import expect from '@kbn/expect'; +import archives_metadata from '../../../common/archives_metadata'; import { expectSnapshot } from '../../../common/match_snapshot'; import { FtrProviderContext } from '../../../../common/ftr_provider_context'; @@ -12,9 +13,12 @@ export default function ApiTest({ getService }: FtrProviderContext) { const supertest = getService('supertest'); const esArchiver = getService('esArchiver'); + const archiveName = 'apm_8.0.0'; + const metadata = archives_metadata[archiveName]; + // url parameters - const start = encodeURIComponent('2020-06-29T06:45:00.000Z'); - const end = encodeURIComponent('2020-06-29T06:49:00.000Z'); + const start = encodeURIComponent(metadata.start); + const end = encodeURIComponent(metadata.end); describe('Transaction types', () => { describe('when data is not loaded ', () => { @@ -30,8 +34,8 @@ export default function ApiTest({ getService }: FtrProviderContext) { }); describe('when data is loaded', () => { - before(() => esArchiver.load('8.0.0')); - after(() => esArchiver.unload('8.0.0')); + before(() => esArchiver.load(archiveName)); + after(() => esArchiver.unload(archiveName)); it('handles empty state', async () => { const response = await supertest.get( @@ -39,11 +43,13 @@ export default function ApiTest({ getService }: FtrProviderContext) { ); expect(response.status).to.be(200); + expect(response.body.transactionTypes.length).to.be.greaterThan(0); + expectSnapshot(response.body).toMatchInline(` Object { "transactionTypes": Array [ - "request", "Worker", + "request", ], } `); diff --git a/x-pack/test/apm_api_integration/basic/tests/settings/agent_configuration.ts b/x-pack/test/apm_api_integration/basic/tests/settings/agent_configuration.ts index 27023d16f57ca..70ddf276ab35c 100644 --- a/x-pack/test/apm_api_integration/basic/tests/settings/agent_configuration.ts +++ b/x-pack/test/apm_api_integration/basic/tests/settings/agent_configuration.ts @@ -6,6 +6,7 @@ import expect from '@kbn/expect'; import { omit, orderBy } from 'lodash'; +import { expectSnapshot } from '../../../common/match_snapshot'; import { AgentConfigurationIntake } from '../../../../../plugins/apm/common/agent_configuration/configuration_types'; import { AgentConfigSearchParams } from '../../../../../plugins/apm/server/routes/settings/agent_configuration'; import { FtrProviderContext } from '../../../common/ftr_provider_context'; @@ -16,6 +17,8 @@ export default function agentConfigurationTests({ getService }: FtrProviderConte const log = getService('log'); const esArchiver = getService('esArchiver'); + const archiveName = 'apm_8.0.0'; + function getServices() { return supertestRead .get(`/api/apm/settings/agent-configuration/services`) @@ -125,31 +128,46 @@ export default function agentConfigurationTests({ getService }: FtrProviderConte }); describe('when data is loaded', () => { - before(() => esArchiver.load('8.0.0')); - after(() => esArchiver.unload('8.0.0')); + before(() => esArchiver.load(archiveName)); + after(() => esArchiver.unload(archiveName)); it('returns all services', async () => { const { body } = await getServices(); - expect(body).to.eql([ - 'ALL_OPTION_VALUE', - 'client', - 'opbeans-dotnet', - 'opbeans-go', - 'opbeans-java', - 'opbeans-node', - 'opbeans-python', - 'opbeans-ruby', - 'opbeans-rum', - ]); + expectSnapshot(body).toMatchInline(` + Array [ + "ALL_OPTION_VALUE", + "opbeans-dotnet", + "opbeans-go", + "opbeans-java", + "opbeans-node", + "opbeans-python", + "opbeans-ruby", + "opbeans-rum", + ] + `); }); - it('returns the environments', async () => { + it('returns the environments, all unconfigured', async () => { const { body } = await getEnvironments('opbeans-node'); - expect(body).to.eql([ - { name: 'ALL_OPTION_VALUE', alreadyConfigured: false }, - { name: 'testing', alreadyConfigured: false }, - { name: 'production', alreadyConfigured: false }, - ]); + + expect(body.map((item: { name: string }) => item.name)).to.contain('ALL_OPTION_VALUE'); + + expect( + body.every((item: { alreadyConfigured: boolean }) => item.alreadyConfigured === false) + ).to.be(true); + + expectSnapshot(body).toMatchInline(` + Array [ + Object { + "alreadyConfigured": false, + "name": "ALL_OPTION_VALUE", + }, + Object { + "alreadyConfigured": false, + "name": "testing", + }, + ] + `); }); it('returns the agent names', async () => { diff --git a/x-pack/test/apm_api_integration/basic/tests/settings/custom_link.ts b/x-pack/test/apm_api_integration/basic/tests/settings/custom_link.ts index 2acc6522bf479..a1c647a854bf6 100644 --- a/x-pack/test/apm_api_integration/basic/tests/settings/custom_link.ts +++ b/x-pack/test/apm_api_integration/basic/tests/settings/custom_link.ts @@ -14,6 +14,8 @@ export default function customLinksTests({ getService }: FtrProviderContext) { const log = getService('log'); const esArchiver = getService('esArchiver'); + const archiveName = 'apm_8.0.0'; + function searchCustomLinks(filters?: any) { const path = URL.format({ pathname: `/api/apm/settings/custom_links`, @@ -142,8 +144,8 @@ export default function customLinksTests({ getService }: FtrProviderContext) { }); describe('transaction', () => { - before(() => esArchiver.load('8.0.0')); - after(() => esArchiver.unload('8.0.0')); + before(() => esArchiver.load(archiveName)); + after(() => esArchiver.unload(archiveName)); it('fetches a transaction sample', async () => { const response = await supertestRead.get( diff --git a/x-pack/test/apm_api_integration/basic/tests/traces/__snapshots__/top_traces.snap b/x-pack/test/apm_api_integration/basic/tests/traces/__snapshots__/top_traces.snap index 5557e0828a338..2d382fa5fa4d3 100644 --- a/x-pack/test/apm_api_integration/basic/tests/traces/__snapshots__/top_traces.snap +++ b/x-pack/test/apm_api_integration/basic/tests/traces/__snapshots__/top_traces.snap @@ -3,301 +3,598 @@ exports[`Top traces when data is loaded returns the correct buckets 1`] = ` Array [ Object { - "averageResponseTime": 2577, + "averageResponseTime": 3853, "impact": 0, "key": Object { - "service.name": "opbeans-node", - "transaction.name": "GET /throw-error", + "service.name": "opbeans-ruby", + "transaction.name": "Api::OrdersController#create", }, - "transactionsPerMinute": 0.5, + "transactionsPerMinute": 0.016666666666666666, }, Object { - "averageResponseTime": 3147, - "impact": 0.06552270160444405, + "averageResponseTime": 5420, + "impact": 0.0013411780236742999, "key": Object { "service.name": "opbeans-java", "transaction.name": "APIRestController#orders", }, - "transactionsPerMinute": 0.5, + "transactionsPerMinute": 0.016666666666666666, }, Object { - "averageResponseTime": 3392.5, - "impact": 0.09374344413758617, + "averageResponseTime": 4135.5, + "impact": 0.0037813174911251156, "key": Object { - "service.name": "opbeans-java", - "transaction.name": "APIRestController#order", + "service.name": "opbeans-node", + "transaction.name": "GET /api/types", }, - "transactionsPerMinute": 0.5, + "transactionsPerMinute": 0.03333333333333333, }, Object { - "averageResponseTime": 4713.5, - "impact": 0.24559517890858723, + "averageResponseTime": 11058, + "impact": 0.006166680064182087, "key": Object { "service.name": "opbeans-java", - "transaction.name": "APIRestController#product", + "transaction.name": "APIRestController#products", }, - "transactionsPerMinute": 0.5, + "transactionsPerMinute": 0.016666666666666666, + }, + Object { + "averageResponseTime": 6014, + "impact": 0.0069968923698388, + "key": Object { + "service.name": "opbeans-go", + "transaction.name": "POST /api/orders", + }, + "transactionsPerMinute": 0.03333333333333333, }, Object { - "averageResponseTime": 4757, - "impact": 0.25059559560997896, + "averageResponseTime": 13540, + "impact": 0.00829099649989339, + "key": Object { + "service.name": "opbeans-python", + "transaction.name": "GET opbeans.views.product", + }, + "transactionsPerMinute": 0.016666666666666666, + }, + Object { + "averageResponseTime": 8710, + "impact": 0.011611845722520248, "key": Object { "service.name": "opbeans-node", - "transaction.name": "GET /api/products/:id/customers", + "transaction.name": "GET /api/types/:id", }, - "transactionsPerMinute": 0.5, + "transactionsPerMinute": 0.03333333333333333, }, Object { - "averageResponseTime": 6787, - "impact": 0.4839483750082622, + "averageResponseTime": 10157, + "impact": 0.014088788415891928, "key": Object { - "service.name": "opbeans-java", - "transaction.name": "APIRestController#products", + "service.name": "opbeans-python", + "transaction.name": "GET opbeans.views.product_type", }, - "transactionsPerMinute": 0.5, + "transactionsPerMinute": 0.03333333333333333, }, Object { - "averageResponseTime": 4749.666666666667, - "impact": 0.5227447114845778, + "averageResponseTime": 6944.333333333333, + "impact": 0.014532994793867014, "key": Object { "service.name": "opbeans-node", "transaction.name": "GET /api/orders/:id", }, - "transactionsPerMinute": 0.75, + "transactionsPerMinute": 0.05, }, Object { - "averageResponseTime": 7624.5, - "impact": 0.5802207655235637, + "averageResponseTime": 8438.333333333334, + "impact": 0.018369089179385976, "key": Object { - "service.name": "opbeans-node", - "transaction.name": "GET /api/orders", + "service.name": "opbeans-java", + "transaction.name": "APIRestController#customer", }, - "transactionsPerMinute": 0.5, + "transactionsPerMinute": 0.05, }, Object { - "averageResponseTime": 5098, - "impact": 0.582807187955318, + "averageResponseTime": 13202, + "impact": 0.019301152273056246, "key": Object { - "service.name": "opbeans-node", - "transaction.name": "GET /api/stats", + "service.name": "opbeans-java", + "transaction.name": "APIRestController#customers", }, - "transactionsPerMinute": 0.75, + "transactionsPerMinute": 0.03333333333333333, }, Object { - "averageResponseTime": 8181, - "impact": 0.6441916136689552, + "averageResponseTime": 9311, + "impact": 0.020609806515684198, "key": Object { "service.name": "opbeans-node", - "transaction.name": "GET /api/types/:id", + "transaction.name": "GET /api/products/:id", }, - "transactionsPerMinute": 0.5, + "transactionsPerMinute": 0.05, }, Object { - "averageResponseTime": 20011, - "impact": 0.853921734857215, + "averageResponseTime": 14019, + "impact": 0.020699674858049102, "key": Object { "service.name": "opbeans-node", - "transaction.name": "POST /api", + "transaction.name": "GET /api/customers/:id", }, - "transactionsPerMinute": 0.25, + "transactionsPerMinute": 0.03333333333333333, + }, + Object { + "averageResponseTime": 28176, + "impact": 0.020817787536585832, + "key": Object { + "service.name": "opbeans-python", + "transaction.name": "POST opbeans.views.post_order", + }, + "transactionsPerMinute": 0.016666666666666666, }, Object { - "averageResponseTime": 6583, - "impact": 1.2172278724376455, + "averageResponseTime": 9298.75, + "impact": 0.02853705020124346, "key": Object { "service.name": "opbeans-node", "transaction.name": "GET /api/products", }, - "transactionsPerMinute": 1, + "transactionsPerMinute": 0.06666666666666667, }, Object { - "averageResponseTime": 33097, - "impact": 1.6060533780113861, + "averageResponseTime": 7441.6, + "impact": 0.028548176757917213, "key": Object { - "service.name": "opbeans-node", - "transaction.name": "GET /api/products/top", + "service.name": "opbeans-java", + "transaction.name": "APIRestController#order", }, - "transactionsPerMinute": 0.25, + "transactionsPerMinute": 0.08333333333333333, }, Object { - "averageResponseTime": 4825, - "impact": 1.6450221426498186, + "averageResponseTime": 6260.166666666667, + "impact": 0.028850305566058266, "key": Object { "service.name": "opbeans-java", "transaction.name": "APIRestController#topProducts", }, - "transactionsPerMinute": 1.75, + "transactionsPerMinute": 0.1, }, Object { - "averageResponseTime": 35846, - "impact": 1.7640550505645587, + "averageResponseTime": 7656.2, + "impact": 0.029466545627989022, "key": Object { - "service.name": "opbeans-node", - "transaction.name": "GET /log-error", + "service.name": "opbeans-java", + "transaction.name": "APIRestController#customerWhoBought", }, - "transactionsPerMinute": 0.25, + "transactionsPerMinute": 0.08333333333333333, + }, + Object { + "averageResponseTime": 7016.5, + "impact": 0.032734329734171834, + "key": Object { + "service.name": "opbeans-ruby", + "transaction.name": "Api::OrdersController#show", + }, + "transactionsPerMinute": 0.1, }, Object { - "averageResponseTime": 3742.153846153846, - "impact": 2.4998634943716573, + "averageResponseTime": 21102.5, + "impact": 0.03282505396551165, + "key": Object { + "service.name": "opbeans-python", + "transaction.name": "GET opbeans.views.customer", + }, + "transactionsPerMinute": 0.03333333333333333, + }, + Object { + "averageResponseTime": 14443.333333333334, + "impact": 0.033787929062278454, "key": Object { "service.name": "opbeans-java", - "transaction.name": "APIRestController#customerWhoBought", + "transaction.name": "APIRestController#stats", }, - "transactionsPerMinute": 3.25, + "transactionsPerMinute": 0.05, }, Object { - "averageResponseTime": 3492.9285714285716, - "impact": 2.5144049360435208, + "averageResponseTime": 2828.0625, + "impact": 0.0354303800051189, "key": Object { - "service.name": "opbeans-node", - "transaction.name": "GET static file", + "service.name": "opbeans-java", + "transaction.name": "ResourceHttpRequestHandler", + }, + "transactionsPerMinute": 0.26666666666666666, + }, + Object { + "averageResponseTime": 9920.8, + "impact": 0.03915777649082508, + "key": Object { + "service.name": "opbeans-java", + "transaction.name": "APIRestController#product", }, - "transactionsPerMinute": 3.5, + "transactionsPerMinute": 0.08333333333333333, }, Object { - "averageResponseTime": 26992.5, - "impact": 2.8066131947777255, + "averageResponseTime": 16860.333333333332, + "impact": 0.03999398001930612, + "key": Object { + "service.name": "opbeans-python", + "transaction.name": "GET opbeans.views.orders", + }, + "transactionsPerMinute": 0.05, + }, + Object { + "averageResponseTime": 10264.8, + "impact": 0.04062990552765966, "key": Object { "service.name": "opbeans-node", + "transaction.name": "GET /api/products/top", + }, + "transactionsPerMinute": 0.08333333333333333, + }, + Object { + "averageResponseTime": 8818.833333333334, + "impact": 0.04198991310878184, + "key": Object { + "service.name": "opbeans-python", + "transaction.name": "GET opbeans.views.order", + }, + "transactionsPerMinute": 0.1, + }, + Object { + "averageResponseTime": 4649.307692307692, + "impact": 0.04843304531185787, + "key": Object { + "service.name": "opbeans-go", + "transaction.name": "GET /api/types/:id", + }, + "transactionsPerMinute": 0.21666666666666667, + }, + Object { + "averageResponseTime": 30425, + "impact": 0.048783103902593536, + "key": Object { + "service.name": "opbeans-python", + "transaction.name": "GET opbeans.views.products", + }, + "transactionsPerMinute": 0.03333333333333333, + }, + Object { + "averageResponseTime": 4215.2, + "impact": 0.05081840788491484, + "key": Object { + "service.name": "opbeans-go", "transaction.name": "GET /api/types", }, - "transactionsPerMinute": 0.5, + "transactionsPerMinute": 0.25, }, Object { - "averageResponseTime": 13516.5, - "impact": 2.8112687551548836, + "averageResponseTime": 7333.777777777777, + "impact": 0.053194355679247865, "key": Object { - "service.name": "opbeans-node", - "transaction.name": "GET /api/products/:id", + "service.name": "opbeans-ruby", + "transaction.name": "Api::StatsController#index", + }, + "transactionsPerMinute": 0.15, + }, + Object { + "averageResponseTime": 7562.111111111111, + "impact": 0.05495320752267524, + "key": Object { + "service.name": "opbeans-ruby", + "transaction.name": "Api::TypesController#index", + }, + "transactionsPerMinute": 0.15, + }, + Object { + "averageResponseTime": 5459.307692307692, + "impact": 0.057445556217595194, + "key": Object { + "service.name": "opbeans-go", + "transaction.name": "GET /api/products", + }, + "transactionsPerMinute": 0.21666666666666667, + }, + Object { + "averageResponseTime": 7248.5, + "impact": 0.058741372125599586, + "key": Object { + "service.name": "opbeans-ruby", + "transaction.name": "Api::TypesController#show", + }, + "transactionsPerMinute": 0.16666666666666666, + }, + Object { + "averageResponseTime": 87771, + "impact": 0.07182449099597951, + "key": Object { + "service.name": "opbeans-python", + "transaction.name": "GET opbeans.views.top_products", + }, + "transactionsPerMinute": 0.016666666666666666, + }, + Object { + "averageResponseTime": 6161.2, + "impact": 0.0758018070623576, + "key": Object { + "service.name": "opbeans-go", + "transaction.name": "GET /api/orders/:id", + }, + "transactionsPerMinute": 0.25, + }, + Object { + "averageResponseTime": 19260.8, + "impact": 0.07912779161883388, + "key": Object { + "service.name": "opbeans-python", + "transaction.name": "GET opbeans.views.product_types", + }, + "transactionsPerMinute": 0.08333333333333333, + }, + Object { + "averageResponseTime": 10632.4, + "impact": 0.08770379914737025, + "key": Object { + "service.name": "opbeans-ruby", + "transaction.name": "Api::ProductsController#show", + }, + "transactionsPerMinute": 0.16666666666666666, + }, + Object { + "averageResponseTime": 54309.5, + "impact": 0.08966806434477453, + "key": Object { + "service.name": "opbeans-python", + "transaction.name": "GET opbeans.views.customers", }, - "transactionsPerMinute": 1, + "transactionsPerMinute": 0.03333333333333333, }, Object { - "averageResponseTime": 20092, - "impact": 3.168195050736987, + "averageResponseTime": 5046.695652173913, + "impact": 0.09604871665268258, + "key": Object { + "service.name": "opbeans-go", + "transaction.name": "GET /api/customers/:id", + }, + "transactionsPerMinute": 0.38333333333333336, + }, + Object { + "averageResponseTime": 20346, + "impact": 0.10118576228005537, "key": Object { "service.name": "opbeans-node", - "transaction.name": "GET /api/customers", + "transaction.name": "GET /api/stats", }, - "transactionsPerMinute": 0.75, + "transactionsPerMinute": 0.1, }, Object { - "averageResponseTime": 15535, - "impact": 3.275330415465657, + "averageResponseTime": 18472.85714285714, + "impact": 0.10737726312450965, "key": Object { - "service.name": "opbeans-java", - "transaction.name": "APIRestController#stats", + "service.name": "opbeans-python", + "transaction.name": "GET opbeans.views.stats", }, - "transactionsPerMinute": 1, + "transactionsPerMinute": 0.11666666666666667, }, Object { - "averageResponseTime": 32667.5, - "impact": 3.458966408120217, + "averageResponseTime": 32662, + "impact": 0.10852244257293098, "key": Object { "service.name": "opbeans-node", - "transaction.name": "GET /log-message", + "transaction.name": "GET /api/customers", }, - "transactionsPerMinute": 0.5, + "transactionsPerMinute": 0.06666666666666667, }, Object { - "averageResponseTime": 16690.75, - "impact": 3.541042213287889, + "averageResponseTime": 13975.7, + "impact": 0.11631873524532996, "key": Object { - "service.name": "opbeans-java", - "transaction.name": "APIRestController#customers", + "service.name": "opbeans-ruby", + "transaction.name": "Api::ProductsController#index", }, - "transactionsPerMinute": 1, + "transactionsPerMinute": 0.16666666666666666, }, Object { - "averageResponseTime": 33500, - "impact": 3.5546640380951287, + "averageResponseTime": 13373.615384615385, + "impact": 0.14550454928955053, "key": Object { - "service.name": "client", - "transaction.name": "/customers", + "service.name": "opbeans-go", + "transaction.name": "GET /api/orders", }, - "transactionsPerMinute": 0.5, + "transactionsPerMinute": 0.21666666666666667, }, Object { - "averageResponseTime": 77000, - "impact": 4.129424578484989, + "averageResponseTime": 19675.333333333332, + "impact": 0.14826136767771575, "key": Object { - "service.name": "client", - "transaction.name": "/products", + "service.name": "opbeans-ruby", + "transaction.name": "Api::OrdersController#index", + }, + "transactionsPerMinute": 0.15, + }, + Object { + "averageResponseTime": 12946.266666666666, + "impact": 0.1629107633721697, + "key": Object { + "service.name": "opbeans-ruby", + "transaction.name": "Api::CustomersController#show", }, "transactionsPerMinute": 0.25, }, Object { - "averageResponseTime": 19370.6, - "impact": 5.270496679320978, + "averageResponseTime": 16506.666666666668, + "impact": 0.16623674792864598, "key": Object { - "service.name": "opbeans-java", - "transaction.name": "APIRestController#customer", + "service.name": "opbeans-go", + "transaction.name": "GET /api/products/:id/customers", }, - "transactionsPerMinute": 1.25, + "transactionsPerMinute": 0.2, }, Object { - "averageResponseTime": 81500, - "impact": 9.072365225837785, + "averageResponseTime": 17101.5, + "impact": 0.1723460834315095, "key": Object { - "service.name": "client", - "transaction.name": "/orders", + "service.name": "opbeans-ruby", + "transaction.name": "Api::ProductsController#top", }, - "transactionsPerMinute": 0.5, + "transactionsPerMinute": 0.2, }, Object { - "averageResponseTime": 14419.42857142857, - "impact": 11.30657439844125, + "averageResponseTime": 15871.3125, + "impact": 0.21404756195574876, "key": Object { - "service.name": "opbeans-java", - "transaction.name": "ResourceHttpRequestHandler", + "service.name": "opbeans-go", + "transaction.name": "GET /api/stats", }, - "transactionsPerMinute": 3.5, + "transactionsPerMinute": 0.26666666666666666, }, Object { - "averageResponseTime": 270684, - "impact": 15.261616628971955, + "averageResponseTime": 11237.785714285714, + "impact": 0.26601457284498453, + "key": Object { + "service.name": "opbeans-ruby", + "transaction.name": "Api::CustomersController#index", + }, + "transactionsPerMinute": 0.4666666666666667, + }, + Object { + "averageResponseTime": 15403.40909090909, + "impact": 0.28674163615023057, + "key": Object { + "service.name": "opbeans-go", + "transaction.name": "GET /api/products/:id", + }, + "transactionsPerMinute": 0.36666666666666664, + }, + Object { + "averageResponseTime": 101902.16666666667, + "impact": 0.5200039055925703, + "key": Object { + "service.name": "opbeans-python", + "transaction.name": "GET opbeans.views.product_customers", + }, + "transactionsPerMinute": 0.1, + }, + Object { + "averageResponseTime": 32236.133333333335, + "impact": 0.82441879318559, "key": Object { "service.name": "opbeans-node", - "transaction.name": "POST /api/orders", + "transaction.name": "GET /api", }, - "transactionsPerMinute": 0.25, + "transactionsPerMinute": 0.5, + }, + Object { + "averageResponseTime": 94012.11111111111, + "impact": 1.445052989113503, + "key": Object { + "service.name": "opbeans-go", + "transaction.name": "GET /api/customers", + }, + "transactionsPerMinute": 0.3, + }, + Object { + "averageResponseTime": 32260.39837398374, + "impact": 3.3928945329783606, + "key": Object { + "service.name": "opbeans-ruby", + "transaction.name": "Rack", + }, + "transactionsPerMinute": 2.05, + }, + Object { + "averageResponseTime": 34207.61666666667, + "impact": 3.5100528953080716, + "key": Object { + "service.name": "opbeans-python", + "transaction.name": "opbeans.tasks.sync_orders", + }, + "transactionsPerMinute": 2, + }, + Object { + "averageResponseTime": 638040, + "impact": 13.648987298470669, + "key": Object { + "service.name": "opbeans-rum", + "transaction.name": "/customers", + }, + "transactionsPerMinute": 0.4166666666666667, }, Object { - "averageResponseTime": 36010.53846153846, - "impact": 26.61043592713186, + "averageResponseTime": 2061418.6666666667, + "impact": 15.875811844928256, "key": Object { "service.name": "opbeans-java", "transaction.name": "DispatcherServlet#doGet", }, - "transactionsPerMinute": 3.25, + "transactionsPerMinute": 0.15, }, Object { - "averageResponseTime": 208000, - "impact": 35.56882613781033, + "averageResponseTime": 847846.1538461539, + "impact": 18.8639188225597, "key": Object { - "service.name": "client", + "service.name": "opbeans-rum", + "transaction.name": "/orders", + }, + "transactionsPerMinute": 0.43333333333333335, + }, + Object { + "averageResponseTime": 1091031.25, + "impact": 29.87835404059707, + "key": Object { + "service.name": "opbeans-rum", + "transaction.name": "/products", + }, + "transactionsPerMinute": 0.5333333333333333, + }, + Object { + "averageResponseTime": 924980.3921568628, + "impact": 40.37240876189292, + "key": Object { + "service.name": "opbeans-rum", "transaction.name": "/dashboard", }, - "transactionsPerMinute": 0.75, + "transactionsPerMinute": 0.85, }, Object { - "averageResponseTime": 49816.15625, - "impact": 91.32732325394932, + "averageResponseTime": 979844.2117647058, + "impact": 71.28092018746297, "key": Object { "service.name": "opbeans-node", - "transaction.name": "GET /api", + "transaction.name": "Process completed order", }, - "transactionsPerMinute": 8, + "transactionsPerMinute": 1.4166666666666667, }, Object { - "averageResponseTime": 1745009, - "impact": 100, + "averageResponseTime": 996808.380952381, + "impact": 71.66191574108551, "key": Object { "service.name": "opbeans-node", "transaction.name": "Process payment", }, - "transactionsPerMinute": 0.25, + "transactionsPerMinute": 1.4, + }, + Object { + "averageResponseTime": 1083442.5568181819, + "impact": 81.59967772014184, + "key": Object { + "service.name": "opbeans-node", + "transaction.name": "Update shipping status", + }, + "transactionsPerMinute": 1.4666666666666666, + }, + Object { + "averageResponseTime": 134550.32361111112, + "impact": 82.91200201469418, + "key": Object { + "service.name": "opbeans-python", + "transaction.name": "opbeans.tasks.update_stats", + }, + "transactionsPerMinute": 12, + }, + Object { + "averageResponseTime": 1600567.6301369863, + "impact": 100, + "key": Object { + "service.name": "opbeans-python", + "transaction.name": "opbeans.tasks.sync_customers", + }, + "transactionsPerMinute": 1.2166666666666666, }, ] `; diff --git a/x-pack/test/apm_api_integration/basic/tests/traces/top_traces.ts b/x-pack/test/apm_api_integration/basic/tests/traces/top_traces.ts index 2935fb8e2839a..da4bd0aa4f0d9 100644 --- a/x-pack/test/apm_api_integration/basic/tests/traces/top_traces.ts +++ b/x-pack/test/apm_api_integration/basic/tests/traces/top_traces.ts @@ -5,6 +5,7 @@ */ import expect from '@kbn/expect'; import { sortBy, omit } from 'lodash'; +import archives_metadata from '../../../common/archives_metadata'; import { expectSnapshot } from '../../../common/match_snapshot'; import { FtrProviderContext } from '../../../../common/ftr_provider_context'; @@ -12,9 +13,12 @@ export default function ApiTest({ getService }: FtrProviderContext) { const supertest = getService('supertest'); const esArchiver = getService('esArchiver'); + const archiveName = 'apm_8.0.0'; + const metadata = archives_metadata[archiveName]; + // url parameters - const start = encodeURIComponent('2020-06-29T06:45:00.000Z'); - const end = encodeURIComponent('2020-06-29T06:49:00.000Z'); + const start = encodeURIComponent(metadata.start); + const end = encodeURIComponent(metadata.end); const uiFilters = encodeURIComponent(JSON.stringify({})); describe('Top traces', () => { @@ -25,32 +29,27 @@ export default function ApiTest({ getService }: FtrProviderContext) { ); expect(response.status).to.be(200); - expectSnapshot(response.body).toMatchInline(` - Object { - "bucketSize": 1000, - "isAggregationAccurate": true, - "items": Array [], - } - `); + expect(response.body.items.length).to.be(0); + expect(response.body.isAggregationAccurate).to.be(true); }); }); describe('when data is loaded', () => { let response: any; before(async () => { - await esArchiver.load('8.0.0'); + await esArchiver.load(archiveName); response = await supertest.get( `/api/apm/traces?start=${start}&end=${end}&uiFilters=${uiFilters}` ); }); - after(() => esArchiver.unload('8.0.0')); + after(() => esArchiver.unload(archiveName)); it('returns the correct status code', async () => { expect(response.status).to.be(200); }); it('returns the correct number of buckets', async () => { - expectSnapshot(response.body.items.length).toMatchInline(`33`); + expectSnapshot(response.body.items.length).toMatchInline(`66`); }); it('returns the correct buckets', async () => { @@ -68,49 +67,49 @@ export default function ApiTest({ getService }: FtrProviderContext) { expectSnapshot(firstItem).toMatchInline(` Object { - "averageResponseTime": 2577, + "averageResponseTime": 3853, "impact": 0, "key": Object { - "service.name": "opbeans-node", - "transaction.name": "GET /throw-error", + "service.name": "opbeans-ruby", + "transaction.name": "Api::OrdersController#create", }, - "transactionsPerMinute": 0.5, + "transactionsPerMinute": 0.016666666666666666, } `); expectSnapshot(lastItem).toMatchInline(` Object { - "averageResponseTime": 1745009, + "averageResponseTime": 1600567.6301369863, "impact": 100, "key": Object { - "service.name": "opbeans-node", - "transaction.name": "Process payment", + "service.name": "opbeans-python", + "transaction.name": "opbeans.tasks.sync_customers", }, - "transactionsPerMinute": 0.25, + "transactionsPerMinute": 1.2166666666666666, } `); expectSnapshot(groups).toMatchInline(` Array [ Object { - "service.name": "opbeans-node", - "transaction.name": "GET /throw-error", + "service.name": "opbeans-ruby", + "transaction.name": "Api::OrdersController#create", }, Object { "service.name": "opbeans-java", "transaction.name": "APIRestController#orders", }, Object { - "service.name": "opbeans-java", - "transaction.name": "APIRestController#order", + "service.name": "opbeans-node", + "transaction.name": "GET /api/types", }, Object { "service.name": "opbeans-java", - "transaction.name": "APIRestController#product", + "transaction.name": "APIRestController#products", }, Object { - "service.name": "opbeans-node", - "transaction.name": "GET /api/products/:id/customers", + "service.name": "opbeans-go", + "transaction.name": "POST /api/orders", }, ] `); diff --git a/x-pack/test/apm_api_integration/basic/tests/transaction_groups/__snapshots__/avg_duration_by_browser.snap b/x-pack/test/apm_api_integration/basic/tests/transaction_groups/__snapshots__/avg_duration_by_browser.snap index 326797919a095..37473ee008b3d 100644 --- a/x-pack/test/apm_api_integration/basic/tests/transaction_groups/__snapshots__/avg_duration_by_browser.snap +++ b/x-pack/test/apm_api_integration/basic/tests/transaction_groups/__snapshots__/avg_duration_by_browser.snap @@ -5,1469 +5,850 @@ Array [ Object { "data": Array [ Object { - "x": 1593413100000, + "x": 1599717600000, + "y": 999000, }, Object { - "x": 1593413101000, + "x": 1599717630000, + "y": 1111000, }, Object { - "x": 1593413102000, + "x": 1599717660000, + "y": 600000, }, Object { - "x": 1593413103000, + "x": 1599717690000, }, Object { - "x": 1593413104000, + "x": 1599717720000, }, Object { - "x": 1593413105000, + "x": 1599717750000, + "y": 1487000, }, Object { - "x": 1593413106000, + "x": 1599717780000, + "y": 312000, }, Object { - "x": 1593413107000, + "x": 1599717810000, }, Object { - "x": 1593413108000, + "x": 1599717840000, }, Object { - "x": 1593413109000, + "x": 1599717870000, + "y": 2073000, }, Object { - "x": 1593413110000, + "x": 1599717900000, + "y": 791333.3333333334, }, Object { - "x": 1593413111000, + "x": 1599717930000, + "y": 604000, }, Object { - "x": 1593413112000, + "x": 1599717960000, }, Object { - "x": 1593413113000, + "x": 1599717990000, + "y": 792000, }, Object { - "x": 1593413114000, + "x": 1599718020000, + "y": 596000, }, Object { - "x": 1593413115000, + "x": 1599718050000, + "y": 661000, }, Object { - "x": 1593413116000, + "x": 1599718080000, }, Object { - "x": 1593413117000, + "x": 1599718110000, + "y": 1016000, }, Object { - "x": 1593413118000, + "x": 1599718140000, + "y": 732000, }, Object { - "x": 1593413119000, + "x": 1599718170000, }, Object { - "x": 1593413120000, + "x": 1599718200000, }, Object { - "x": 1593413121000, + "x": 1599718230000, + "y": 1578000, }, Object { - "x": 1593413122000, + "x": 1599718260000, + "y": 450000, }, Object { - "x": 1593413123000, + "x": 1599718290000, + "y": 911000, }, Object { - "x": 1593413124000, + "x": 1599718320000, }, Object { - "x": 1593413125000, + "x": 1599718350000, + "y": 1599000, }, Object { - "x": 1593413126000, + "x": 1599718380000, + "y": 661000, }, Object { - "x": 1593413127000, + "x": 1599718410000, + "y": 596000, }, Object { - "x": 1593413128000, + "x": 1599718440000, }, Object { - "x": 1593413129000, + "x": 1599718470000, + "y": 823000, }, Object { - "x": 1593413130000, + "x": 1599718500000, + "y": 551666.6666666666, }, Object { - "x": 1593413131000, + "x": 1599718530000, }, Object { - "x": 1593413132000, + "x": 1599718560000, }, Object { - "x": 1593413133000, + "x": 1599718590000, + "y": 1311000, }, Object { - "x": 1593413134000, + "x": 1599718620000, + "y": 574000, }, Object { - "x": 1593413135000, + "x": 1599718650000, }, Object { - "x": 1593413136000, + "x": 1599718680000, }, Object { - "x": 1593413137000, + "x": 1599718710000, + "y": 1806000, }, Object { - "x": 1593413138000, + "x": 1599718740000, + "y": 563000, }, Object { - "x": 1593413139000, + "x": 1599718770000, + "y": 665000, }, Object { - "x": 1593413140000, + "x": 1599718800000, }, Object { - "x": 1593413141000, + "x": 1599718830000, + "y": 1202000, }, Object { - "x": 1593413142000, + "x": 1599718860000, + "y": 542666.6666666666, }, Object { - "x": 1593413143000, + "x": 1599718890000, + "y": 688000, }, Object { - "x": 1593413144000, + "x": 1599718920000, }, Object { - "x": 1593413145000, + "x": 1599718950000, + "y": 995000, }, Object { - "x": 1593413146000, + "x": 1599718980000, + "y": 647000, }, Object { - "x": 1593413147000, + "x": 1599719010000, + "y": 552000, }, Object { - "x": 1593413148000, + "x": 1599719040000, }, Object { - "x": 1593413149000, + "x": 1599719070000, + "y": 1760500, }, Object { - "x": 1593413150000, + "x": 1599719100000, + "y": 556000, }, Object { - "x": 1593413151000, + "x": 1599719130000, + "y": 603000, }, Object { - "x": 1593413152000, + "x": 1599719160000, }, Object { - "x": 1593413153000, + "x": 1599719190000, + "y": 920000, }, Object { - "x": 1593413154000, + "x": 1599719220000, + "y": 523000, }, Object { - "x": 1593413155000, + "x": 1599719250000, }, Object { - "x": 1593413156000, + "x": 1599719280000, }, Object { - "x": 1593413157000, + "x": 1599719310000, + "y": 1074000, }, Object { - "x": 1593413158000, + "x": 1599719340000, + "y": 723500, }, Object { - "x": 1593413159000, + "x": 1599719370000, }, Object { - "x": 1593413160000, + "x": 1599719400000, }, Object { - "x": 1593413161000, + "x": 1599719430000, + "y": 1436000, }, Object { - "x": 1593413162000, + "x": 1599719460000, + "y": 614000, }, Object { - "x": 1593413163000, + "x": 1599719490000, + "y": 789000, }, Object { - "x": 1593413164000, + "x": 1599719520000, }, Object { - "x": 1593413165000, + "x": 1599719550000, + "y": 1919000, }, Object { - "x": 1593413166000, + "x": 1599719580000, + "y": 881000, }, Object { - "x": 1593413167000, + "x": 1599719610000, }, Object { - "x": 1593413168000, + "x": 1599719640000, }, Object { - "x": 1593413169000, + "x": 1599719670000, + "y": 1083000, }, Object { - "x": 1593413170000, + "x": 1599719700000, + "y": 603000, }, Object { - "x": 1593413171000, + "x": 1599719730000, + "y": 906000, }, Object { - "x": 1593413172000, + "x": 1599719760000, }, Object { - "x": 1593413173000, + "x": 1599719790000, + "y": 1222000, }, Object { - "x": 1593413174000, + "x": 1599719820000, + "y": 608000, }, Object { - "x": 1593413175000, + "x": 1599719850000, }, Object { - "x": 1593413176000, + "x": 1599719880000, }, Object { - "x": 1593413177000, + "x": 1599719910000, + "y": 805000, }, Object { - "x": 1593413178000, + "x": 1599719940000, + "y": 477000, }, Object { - "x": 1593413179000, + "x": 1599719970000, + "y": 652000, }, Object { - "x": 1593413180000, + "x": 1599720000000, }, Object { - "x": 1593413181000, + "x": 1599720030000, + "y": 1417000, }, Object { - "x": 1593413182000, + "x": 1599720060000, + "y": 545250, }, Object { - "x": 1593413183000, + "x": 1599720090000, }, Object { - "x": 1593413184000, + "x": 1599720120000, }, Object { - "x": 1593413185000, + "x": 1599720150000, + "y": 1122000, }, Object { - "x": 1593413186000, + "x": 1599720180000, + "y": 686000, }, Object { - "x": 1593413187000, + "x": 1599720210000, + "y": 1978000, }, Object { - "x": 1593413188000, + "x": 1599720240000, + "y": 927000, }, Object { - "x": 1593413189000, + "x": 1599720270000, + "y": 2112500, }, Object { - "x": 1593413190000, + "x": 1599720300000, + "y": 776333.3333333334, }, Object { - "x": 1593413191000, + "x": 1599720330000, }, Object { - "x": 1593413192000, + "x": 1599720360000, }, Object { - "x": 1593413193000, + "x": 1599720390000, + "y": 914000, }, Object { - "x": 1593413194000, + "x": 1599720420000, + "y": 534500, }, Object { - "x": 1593413195000, + "x": 1599720450000, }, Object { - "x": 1593413196000, + "x": 1599720480000, }, Object { - "x": 1593413197000, + "x": 1599720510000, + "y": 930000, }, Object { - "x": 1593413198000, + "x": 1599720540000, + "y": 501000, }, Object { - "x": 1593413199000, + "x": 1599720570000, + "y": 801500, }, Object { - "x": 1593413200000, + "x": 1599720600000, }, Object { - "x": 1593413201000, + "x": 1599720630000, + "y": 698000, }, Object { - "x": 1593413202000, + "x": 1599720660000, + "y": 626000, }, Object { - "x": 1593413203000, + "x": 1599720690000, }, Object { - "x": 1593413204000, + "x": 1599720720000, }, Object { - "x": 1593413205000, + "x": 1599720750000, + "y": 1091000, }, Object { - "x": 1593413206000, + "x": 1599720780000, + "y": 7822000, }, Object { - "x": 1593413207000, + "x": 1599720810000, }, Object { - "x": 1593413208000, + "x": 1599720840000, }, Object { - "x": 1593413209000, + "x": 1599720870000, + "y": 892000, }, Object { - "x": 1593413210000, + "x": 1599720900000, + "y": 591250, }, Object { - "x": 1593413211000, + "x": 1599720930000, }, Object { - "x": 1593413212000, + "x": 1599720960000, }, Object { - "x": 1593413213000, + "x": 1599720990000, + "y": 1096000, }, Object { - "x": 1593413214000, + "x": 1599721020000, + "y": 1087000, }, Object { - "x": 1593413215000, + "x": 1599721050000, }, Object { - "x": 1593413216000, + "x": 1599721080000, }, Object { - "x": 1593413217000, + "x": 1599721110000, + "y": 983000, }, Object { - "x": 1593413218000, + "x": 1599721140000, + "y": 801000, }, Object { - "x": 1593413219000, + "x": 1599721170000, }, Object { - "x": 1593413220000, - }, - Object { - "x": 1593413221000, - }, - Object { - "x": 1593413222000, - }, - Object { - "x": 1593413223000, - }, - Object { - "x": 1593413224000, - }, - Object { - "x": 1593413225000, - }, - Object { - "x": 1593413226000, - }, - Object { - "x": 1593413227000, - }, - Object { - "x": 1593413228000, - }, - Object { - "x": 1593413229000, - }, - Object { - "x": 1593413230000, - }, - Object { - "x": 1593413231000, - }, - Object { - "x": 1593413232000, - }, - Object { - "x": 1593413233000, - }, - Object { - "x": 1593413234000, - }, - Object { - "x": 1593413235000, - }, - Object { - "x": 1593413236000, - }, - Object { - "x": 1593413237000, - }, - Object { - "x": 1593413238000, - }, - Object { - "x": 1593413239000, - }, - Object { - "x": 1593413240000, - }, - Object { - "x": 1593413241000, - }, - Object { - "x": 1593413242000, - }, - Object { - "x": 1593413243000, - }, - Object { - "x": 1593413244000, - }, - Object { - "x": 1593413245000, - }, - Object { - "x": 1593413246000, - }, - Object { - "x": 1593413247000, - }, - Object { - "x": 1593413248000, - }, - Object { - "x": 1593413249000, - }, - Object { - "x": 1593413250000, - }, - Object { - "x": 1593413251000, - }, - Object { - "x": 1593413252000, - }, - Object { - "x": 1593413253000, - }, - Object { - "x": 1593413254000, - }, - Object { - "x": 1593413255000, - }, - Object { - "x": 1593413256000, - }, - Object { - "x": 1593413257000, - }, - Object { - "x": 1593413258000, - }, - Object { - "x": 1593413259000, - }, - Object { - "x": 1593413260000, - }, - Object { - "x": 1593413261000, - }, - Object { - "x": 1593413262000, - }, - Object { - "x": 1593413263000, - }, - Object { - "x": 1593413264000, - }, - Object { - "x": 1593413265000, - }, - Object { - "x": 1593413266000, - }, - Object { - "x": 1593413267000, - }, - Object { - "x": 1593413268000, - }, - Object { - "x": 1593413269000, - }, - Object { - "x": 1593413270000, - }, - Object { - "x": 1593413271000, - }, - Object { - "x": 1593413272000, - }, - Object { - "x": 1593413273000, - }, - Object { - "x": 1593413274000, - }, - Object { - "x": 1593413275000, - }, - Object { - "x": 1593413276000, - }, - Object { - "x": 1593413277000, - }, - Object { - "x": 1593413278000, - }, - Object { - "x": 1593413279000, - }, - Object { - "x": 1593413280000, - }, - Object { - "x": 1593413281000, - }, - Object { - "x": 1593413282000, - }, - Object { - "x": 1593413283000, - }, - Object { - "x": 1593413284000, - }, - Object { - "x": 1593413285000, - }, - Object { - "x": 1593413286000, - }, - Object { - "x": 1593413287000, - "y": 342000, - }, - Object { - "x": 1593413288000, - }, - Object { - "x": 1593413289000, - }, - Object { - "x": 1593413290000, - }, - Object { - "x": 1593413291000, - }, - Object { - "x": 1593413292000, - }, - Object { - "x": 1593413293000, - }, - Object { - "x": 1593413294000, - }, - Object { - "x": 1593413295000, - }, - Object { - "x": 1593413296000, - }, - Object { - "x": 1593413297000, - }, - Object { - "x": 1593413298000, - "y": 173000, - }, - Object { - "x": 1593413299000, - }, - Object { - "x": 1593413300000, - }, - Object { - "x": 1593413301000, - "y": 109000, - }, - Object { - "x": 1593413302000, - }, - Object { - "x": 1593413303000, - }, - Object { - "x": 1593413304000, - }, - Object { - "x": 1593413305000, - }, - Object { - "x": 1593413306000, - }, - Object { - "x": 1593413307000, - }, - Object { - "x": 1593413308000, - }, - Object { - "x": 1593413309000, - }, - Object { - "x": 1593413310000, - }, - Object { - "x": 1593413311000, - }, - Object { - "x": 1593413312000, - }, - Object { - "x": 1593413313000, - }, - Object { - "x": 1593413314000, - }, - Object { - "x": 1593413315000, - }, - Object { - "x": 1593413316000, - }, - Object { - "x": 1593413317000, - }, - Object { - "x": 1593413318000, - "y": 140000, - }, - Object { - "x": 1593413319000, - }, - Object { - "x": 1593413320000, - }, - Object { - "x": 1593413321000, - }, - Object { - "x": 1593413322000, - }, - Object { - "x": 1593413323000, - }, - Object { - "x": 1593413324000, - }, - Object { - "x": 1593413325000, - }, - Object { - "x": 1593413326000, - }, - Object { - "x": 1593413327000, - }, - Object { - "x": 1593413328000, - "y": 77000, - }, - Object { - "x": 1593413329000, - }, - Object { - "x": 1593413330000, - }, - Object { - "x": 1593413331000, - }, - Object { - "x": 1593413332000, - }, - Object { - "x": 1593413333000, - }, - Object { - "x": 1593413334000, - }, - Object { - "x": 1593413335000, - }, - Object { - "x": 1593413336000, - }, - Object { - "x": 1593413337000, - }, - Object { - "x": 1593413338000, - }, - Object { - "x": 1593413339000, - }, - Object { - "x": 1593413340000, + "x": 1599721200000, }, ], - "title": "HeadlessChrome", + "title": "Electron", }, ] `; -exports[`Average duration by browser when data is loaded returns the average duration by browser filtering by transaction name 1`] = ` +exports[`Average duration by browser when data is loaded returns the average duration by browser filtering by transaction name 2`] = ` Array [ Object { "data": Array [ Object { - "x": 1593413100000, - }, - Object { - "x": 1593413101000, - }, - Object { - "x": 1593413102000, - }, - Object { - "x": 1593413103000, - }, - Object { - "x": 1593413104000, - }, - Object { - "x": 1593413105000, - }, - Object { - "x": 1593413106000, - }, - Object { - "x": 1593413107000, - }, - Object { - "x": 1593413108000, - }, - Object { - "x": 1593413109000, - }, - Object { - "x": 1593413110000, - }, - Object { - "x": 1593413111000, - }, - Object { - "x": 1593413112000, - }, - Object { - "x": 1593413113000, - }, - Object { - "x": 1593413114000, - }, - Object { - "x": 1593413115000, - }, - Object { - "x": 1593413116000, - }, - Object { - "x": 1593413117000, - }, - Object { - "x": 1593413118000, - }, - Object { - "x": 1593413119000, - }, - Object { - "x": 1593413120000, - }, - Object { - "x": 1593413121000, - }, - Object { - "x": 1593413122000, - }, - Object { - "x": 1593413123000, - }, - Object { - "x": 1593413124000, - }, - Object { - "x": 1593413125000, - }, - Object { - "x": 1593413126000, - }, - Object { - "x": 1593413127000, - }, - Object { - "x": 1593413128000, - }, - Object { - "x": 1593413129000, - }, - Object { - "x": 1593413130000, - }, - Object { - "x": 1593413131000, - }, - Object { - "x": 1593413132000, - }, - Object { - "x": 1593413133000, - }, - Object { - "x": 1593413134000, - }, - Object { - "x": 1593413135000, - }, - Object { - "x": 1593413136000, - }, - Object { - "x": 1593413137000, - }, - Object { - "x": 1593413138000, - }, - Object { - "x": 1593413139000, - }, - Object { - "x": 1593413140000, - }, - Object { - "x": 1593413141000, - }, - Object { - "x": 1593413142000, - }, - Object { - "x": 1593413143000, - }, - Object { - "x": 1593413144000, - }, - Object { - "x": 1593413145000, - }, - Object { - "x": 1593413146000, - }, - Object { - "x": 1593413147000, - }, - Object { - "x": 1593413148000, - }, - Object { - "x": 1593413149000, - }, - Object { - "x": 1593413150000, - }, - Object { - "x": 1593413151000, - }, - Object { - "x": 1593413152000, - }, - Object { - "x": 1593413153000, - }, - Object { - "x": 1593413154000, - }, - Object { - "x": 1593413155000, - }, - Object { - "x": 1593413156000, - }, - Object { - "x": 1593413157000, - }, - Object { - "x": 1593413158000, - }, - Object { - "x": 1593413159000, - }, - Object { - "x": 1593413160000, - }, - Object { - "x": 1593413161000, - }, - Object { - "x": 1593413162000, - }, - Object { - "x": 1593413163000, - }, - Object { - "x": 1593413164000, - }, - Object { - "x": 1593413165000, - }, - Object { - "x": 1593413166000, - }, - Object { - "x": 1593413167000, - }, - Object { - "x": 1593413168000, - }, - Object { - "x": 1593413169000, - }, - Object { - "x": 1593413170000, - }, - Object { - "x": 1593413171000, - }, - Object { - "x": 1593413172000, - }, - Object { - "x": 1593413173000, - }, - Object { - "x": 1593413174000, - }, - Object { - "x": 1593413175000, - }, - Object { - "x": 1593413176000, - }, - Object { - "x": 1593413177000, - }, - Object { - "x": 1593413178000, - }, - Object { - "x": 1593413179000, - }, - Object { - "x": 1593413180000, - }, - Object { - "x": 1593413181000, - }, - Object { - "x": 1593413182000, - }, - Object { - "x": 1593413183000, - }, - Object { - "x": 1593413184000, - }, - Object { - "x": 1593413185000, - }, - Object { - "x": 1593413186000, - }, - Object { - "x": 1593413187000, - }, - Object { - "x": 1593413188000, - }, - Object { - "x": 1593413189000, - }, - Object { - "x": 1593413190000, - }, - Object { - "x": 1593413191000, - }, - Object { - "x": 1593413192000, - }, - Object { - "x": 1593413193000, - }, - Object { - "x": 1593413194000, - }, - Object { - "x": 1593413195000, - }, - Object { - "x": 1593413196000, - }, - Object { - "x": 1593413197000, - }, - Object { - "x": 1593413198000, - }, - Object { - "x": 1593413199000, - }, - Object { - "x": 1593413200000, - }, - Object { - "x": 1593413201000, - }, - Object { - "x": 1593413202000, - }, - Object { - "x": 1593413203000, - }, - Object { - "x": 1593413204000, - }, - Object { - "x": 1593413205000, - }, - Object { - "x": 1593413206000, - }, - Object { - "x": 1593413207000, - }, - Object { - "x": 1593413208000, - }, - Object { - "x": 1593413209000, - }, - Object { - "x": 1593413210000, - }, - Object { - "x": 1593413211000, - }, - Object { - "x": 1593413212000, - }, - Object { - "x": 1593413213000, - }, - Object { - "x": 1593413214000, - }, - Object { - "x": 1593413215000, - }, - Object { - "x": 1593413216000, - }, - Object { - "x": 1593413217000, - }, - Object { - "x": 1593413218000, - }, - Object { - "x": 1593413219000, - }, - Object { - "x": 1593413220000, + "x": 1599717600000, + "y": 999000, }, Object { - "x": 1593413221000, + "x": 1599717630000, + "y": 1111000, }, Object { - "x": 1593413222000, + "x": 1599717660000, }, Object { - "x": 1593413223000, + "x": 1599717690000, }, Object { - "x": 1593413224000, + "x": 1599717720000, }, Object { - "x": 1593413225000, + "x": 1599717750000, + "y": 1487000, }, Object { - "x": 1593413226000, + "x": 1599717780000, }, Object { - "x": 1593413227000, + "x": 1599717810000, }, Object { - "x": 1593413228000, + "x": 1599717840000, }, Object { - "x": 1593413229000, + "x": 1599717870000, + "y": 1326000, }, Object { - "x": 1593413230000, + "x": 1599717900000, }, Object { - "x": 1593413231000, + "x": 1599717930000, }, Object { - "x": 1593413232000, + "x": 1599717960000, }, Object { - "x": 1593413233000, + "x": 1599717990000, + "y": 792000, }, Object { - "x": 1593413234000, + "x": 1599718020000, }, Object { - "x": 1593413235000, + "x": 1599718050000, }, Object { - "x": 1593413236000, + "x": 1599718080000, }, Object { - "x": 1593413237000, + "x": 1599718110000, + "y": 1016000, }, Object { - "x": 1593413238000, + "x": 1599718140000, }, Object { - "x": 1593413239000, + "x": 1599718170000, }, Object { - "x": 1593413240000, + "x": 1599718200000, }, Object { - "x": 1593413241000, + "x": 1599718230000, + "y": 1578000, }, Object { - "x": 1593413242000, + "x": 1599718260000, }, Object { - "x": 1593413243000, + "x": 1599718290000, }, Object { - "x": 1593413244000, + "x": 1599718320000, }, Object { - "x": 1593413245000, + "x": 1599718350000, + "y": 1020000, }, Object { - "x": 1593413246000, + "x": 1599718380000, }, Object { - "x": 1593413247000, + "x": 1599718410000, }, Object { - "x": 1593413248000, + "x": 1599718440000, }, Object { - "x": 1593413249000, + "x": 1599718470000, + "y": 823000, }, Object { - "x": 1593413250000, + "x": 1599718500000, }, Object { - "x": 1593413251000, + "x": 1599718530000, }, Object { - "x": 1593413252000, + "x": 1599718560000, }, Object { - "x": 1593413253000, + "x": 1599718590000, + "y": 1311000, }, Object { - "x": 1593413254000, + "x": 1599718620000, }, Object { - "x": 1593413255000, + "x": 1599718650000, }, Object { - "x": 1593413256000, + "x": 1599718680000, }, Object { - "x": 1593413257000, + "x": 1599718710000, + "y": 1806000, }, Object { - "x": 1593413258000, + "x": 1599718740000, }, Object { - "x": 1593413259000, + "x": 1599718770000, }, Object { - "x": 1593413260000, + "x": 1599718800000, }, Object { - "x": 1593413261000, + "x": 1599718830000, + "y": 1202000, }, Object { - "x": 1593413262000, + "x": 1599718860000, }, Object { - "x": 1593413263000, + "x": 1599718890000, }, Object { - "x": 1593413264000, + "x": 1599718920000, }, Object { - "x": 1593413265000, + "x": 1599718950000, + "y": 995000, }, Object { - "x": 1593413266000, + "x": 1599718980000, }, Object { - "x": 1593413267000, + "x": 1599719010000, }, Object { - "x": 1593413268000, + "x": 1599719040000, }, Object { - "x": 1593413269000, + "x": 1599719070000, + "y": 1110000, }, Object { - "x": 1593413270000, + "x": 1599719100000, }, Object { - "x": 1593413271000, + "x": 1599719130000, }, Object { - "x": 1593413272000, + "x": 1599719160000, }, Object { - "x": 1593413273000, + "x": 1599719190000, + "y": 920000, }, Object { - "x": 1593413274000, + "x": 1599719220000, }, Object { - "x": 1593413275000, + "x": 1599719250000, }, Object { - "x": 1593413276000, + "x": 1599719280000, }, Object { - "x": 1593413277000, + "x": 1599719310000, + "y": 1074000, }, Object { - "x": 1593413278000, + "x": 1599719340000, }, Object { - "x": 1593413279000, + "x": 1599719370000, }, Object { - "x": 1593413280000, + "x": 1599719400000, }, Object { - "x": 1593413281000, + "x": 1599719430000, + "y": 902000, }, Object { - "x": 1593413282000, + "x": 1599719460000, }, Object { - "x": 1593413283000, + "x": 1599719490000, }, Object { - "x": 1593413284000, + "x": 1599719520000, }, Object { - "x": 1593413285000, + "x": 1599719550000, + "y": 931000, }, Object { - "x": 1593413286000, + "x": 1599719580000, }, Object { - "x": 1593413287000, + "x": 1599719610000, }, Object { - "x": 1593413288000, + "x": 1599719640000, }, Object { - "x": 1593413289000, + "x": 1599719670000, + "y": 1083000, }, Object { - "x": 1593413290000, + "x": 1599719700000, }, Object { - "x": 1593413291000, + "x": 1599719730000, }, Object { - "x": 1593413292000, + "x": 1599719760000, }, Object { - "x": 1593413293000, + "x": 1599719790000, + "y": 1222000, }, Object { - "x": 1593413294000, + "x": 1599719820000, }, Object { - "x": 1593413295000, + "x": 1599719850000, }, Object { - "x": 1593413296000, + "x": 1599719880000, }, Object { - "x": 1593413297000, + "x": 1599719910000, + "y": 805000, }, Object { - "x": 1593413298000, + "x": 1599719940000, }, Object { - "x": 1593413299000, + "x": 1599719970000, }, Object { - "x": 1593413300000, + "x": 1599720000000, }, Object { - "x": 1593413301000, + "x": 1599720030000, + "y": 1417000, }, Object { - "x": 1593413302000, + "x": 1599720060000, }, Object { - "x": 1593413303000, + "x": 1599720090000, }, Object { - "x": 1593413304000, + "x": 1599720120000, }, Object { - "x": 1593413305000, + "x": 1599720150000, + "y": 1122000, }, Object { - "x": 1593413306000, + "x": 1599720180000, }, Object { - "x": 1593413307000, + "x": 1599720210000, }, Object { - "x": 1593413308000, + "x": 1599720240000, + "y": 927000, }, Object { - "x": 1593413309000, + "x": 1599720270000, + "y": 1330000, }, Object { - "x": 1593413310000, + "x": 1599720300000, }, Object { - "x": 1593413311000, + "x": 1599720330000, }, Object { - "x": 1593413312000, + "x": 1599720360000, }, Object { - "x": 1593413313000, + "x": 1599720390000, + "y": 914000, }, Object { - "x": 1593413314000, + "x": 1599720420000, }, Object { - "x": 1593413315000, + "x": 1599720450000, }, Object { - "x": 1593413316000, + "x": 1599720480000, }, Object { - "x": 1593413317000, + "x": 1599720510000, + "y": 930000, }, Object { - "x": 1593413318000, + "x": 1599720540000, }, Object { - "x": 1593413319000, + "x": 1599720570000, }, Object { - "x": 1593413320000, + "x": 1599720600000, }, Object { - "x": 1593413321000, + "x": 1599720630000, + "y": 698000, }, Object { - "x": 1593413322000, + "x": 1599720660000, }, Object { - "x": 1593413323000, + "x": 1599720690000, }, Object { - "x": 1593413324000, + "x": 1599720720000, }, Object { - "x": 1593413325000, + "x": 1599720750000, + "y": 1091000, }, Object { - "x": 1593413326000, + "x": 1599720780000, }, Object { - "x": 1593413327000, + "x": 1599720810000, }, Object { - "x": 1593413328000, - "y": 77000, + "x": 1599720840000, }, Object { - "x": 1593413329000, + "x": 1599720870000, + "y": 892000, }, Object { - "x": 1593413330000, + "x": 1599720900000, }, Object { - "x": 1593413331000, + "x": 1599720930000, }, Object { - "x": 1593413332000, + "x": 1599720960000, }, Object { - "x": 1593413333000, + "x": 1599720990000, + "y": 1096000, }, Object { - "x": 1593413334000, + "x": 1599721020000, }, Object { - "x": 1593413335000, + "x": 1599721050000, }, Object { - "x": 1593413336000, + "x": 1599721080000, }, Object { - "x": 1593413337000, + "x": 1599721110000, + "y": 983000, }, Object { - "x": 1593413338000, + "x": 1599721140000, }, Object { - "x": 1593413339000, + "x": 1599721170000, }, Object { - "x": 1593413340000, + "x": 1599721200000, }, ], - "title": "HeadlessChrome", + "title": "Electron", }, ] `; diff --git a/x-pack/test/apm_api_integration/basic/tests/transaction_groups/__snapshots__/breakdown.snap b/x-pack/test/apm_api_integration/basic/tests/transaction_groups/__snapshots__/breakdown.snap index e204ff41dfa43..516523409a029 100644 --- a/x-pack/test/apm_api_integration/basic/tests/transaction_groups/__snapshots__/breakdown.snap +++ b/x-pack/test/apm_api_integration/basic/tests/transaction_groups/__snapshots__/breakdown.snap @@ -7,182 +7,1970 @@ Object { "color": "#54b399", "data": Array [ Object { - "x": 1593413100000, + "x": 1599717600000, + "y": 0.058823529411764705, + }, + Object { + "x": 1599717630000, + "y": 0.037037037037037035, + }, + Object { + "x": 1599717660000, + "y": null, + }, + Object { + "x": 1599717690000, + "y": 0.07142857142857142, + }, + Object { + "x": 1599717720000, + "y": null, + }, + Object { + "x": 1599717750000, + "y": 0.023787740164684355, + }, + Object { + "x": 1599717780000, + "y": 0.19444444444444445, + }, + Object { + "x": 1599717810000, + "y": 0.1346153846153846, + }, + Object { + "x": 1599717840000, + "y": null, + }, + Object { + "x": 1599717870000, + "y": 0.6666666666666666, + }, + Object { + "x": 1599717900000, + "y": 0.04411764705882353, + }, + Object { + "x": 1599717930000, + "y": 0.30985915492957744, + }, + Object { + "x": 1599717960000, + "y": null, + }, + Object { + "x": 1599717990000, + "y": 0.1183206106870229, + }, + Object { + "x": 1599718020000, + "y": 1, + }, + Object { + "x": 1599718050000, + "y": 0.03389830508474576, + }, + Object { + "x": 1599718080000, + "y": null, + }, + Object { + "x": 1599718110000, + "y": 0.1657754010695187, + }, + Object { + "x": 1599718140000, + "y": null, + }, + Object { + "x": 1599718170000, + "y": 0.0273972602739726, + }, + Object { + "x": 1599718200000, + "y": 0.7272727272727273, + }, + Object { + "x": 1599718230000, + "y": 0.0954356846473029, + }, + Object { + "x": 1599718260000, + "y": null, + }, + Object { + "x": 1599718290000, + "y": null, + }, + Object { + "x": 1599718320000, + "y": null, + }, + Object { + "x": 1599718350000, + "y": 0.1111111111111111, + }, + Object { + "x": 1599718380000, + "y": 0.05555555555555555, + }, + Object { + "x": 1599718410000, + "y": 0.48484848484848486, + }, + Object { + "x": 1599718440000, + "y": null, + }, + Object { + "x": 1599718470000, + "y": 0.4642857142857143, + }, + Object { + "x": 1599718500000, + "y": 0.045454545454545456, + }, + Object { + "x": 1599718530000, + "y": 1, + }, + Object { + "x": 1599718560000, + "y": null, + }, + Object { + "x": 1599718590000, + "y": 0.3469387755102041, + }, + Object { + "x": 1599718620000, + "y": null, + }, + Object { + "x": 1599718650000, + "y": 0.045454545454545456, + }, + Object { + "x": 1599718680000, + "y": null, + }, + Object { + "x": 1599718710000, + "y": 0.02967032967032967, + }, + Object { + "x": 1599718740000, + "y": 0.7910447761194029, + }, + Object { + "x": 1599718770000, + "y": 0.020833333333333332, + }, + Object { + "x": 1599718800000, + "y": 0.3448275862068966, + }, + Object { + "x": 1599718830000, + "y": null, + }, + Object { + "x": 1599718860000, + "y": 0.4107142857142857, + }, + Object { + "x": 1599718890000, + "y": 0.21428571428571427, + }, + Object { + "x": 1599718920000, + "y": null, + }, + Object { + "x": 1599718950000, + "y": 0.3235294117647059, + }, + Object { + "x": 1599718980000, + "y": null, + }, + Object { + "x": 1599719010000, + "y": null, + }, + Object { + "x": 1599719040000, + "y": 0.4642857142857143, + }, + Object { + "x": 1599719070000, + "y": 0.20192307692307693, + }, + Object { + "x": 1599719100000, + "y": 0.4, + }, + Object { + "x": 1599719130000, + "y": 0.28205128205128205, + }, + Object { + "x": 1599719160000, + "y": null, + }, + Object { + "x": 1599719190000, + "y": 0.020223152022315203, + }, + Object { + "x": 1599719220000, + "y": 0.05263157894736842, + }, + Object { + "x": 1599719250000, + "y": 0.19480519480519481, + }, + Object { + "x": 1599719280000, + "y": null, + }, + Object { + "x": 1599719310000, + "y": 0.136986301369863, + }, + Object { + "x": 1599719340000, + "y": 0.3870967741935484, + }, + Object { + "x": 1599719370000, + "y": null, + }, + Object { + "x": 1599719400000, + "y": null, + }, + Object { + "x": 1599719430000, + "y": 0.11141304347826086, + }, + Object { + "x": 1599719460000, + "y": 0.5769230769230769, + }, + Object { + "x": 1599719490000, + "y": null, + }, + Object { + "x": 1599719520000, + "y": 0.041666666666666664, + }, + Object { + "x": 1599719550000, + "y": 0.02857142857142857, + }, + Object { + "x": 1599719580000, + "y": null, + }, + Object { + "x": 1599719610000, + "y": 0.35714285714285715, + }, + Object { + "x": 1599719640000, + "y": null, + }, + Object { + "x": 1599719670000, + "y": 0.2903225806451613, + }, + Object { + "x": 1599719700000, + "y": null, + }, + Object { + "x": 1599719730000, + "y": null, + }, + Object { + "x": 1599719760000, + "y": 0.6222222222222222, + }, + Object { + "x": 1599719790000, + "y": 0.17857142857142858, + }, + Object { + "x": 1599719820000, + "y": null, + }, + Object { + "x": 1599719850000, + "y": 0.4807692307692308, + }, + Object { + "x": 1599719880000, + "y": null, + }, + Object { + "x": 1599719910000, + "y": 0.5348837209302325, + }, + Object { + "x": 1599719940000, + "y": null, + }, + Object { + "x": 1599719970000, + "y": null, + }, + Object { + "x": 1599720000000, + "y": 0.24444444444444444, + }, + Object { + "x": 1599720030000, + "y": 0.4, + }, + Object { + "x": 1599720060000, + "y": null, + }, + Object { + "x": 1599720090000, + "y": 1, + }, + Object { + "x": 1599720120000, + "y": null, + }, + Object { + "x": 1599720150000, + "y": null, + }, + Object { + "x": 1599720180000, + "y": null, + }, + Object { + "x": 1599720210000, + "y": 0.3793103448275862, + }, + Object { + "x": 1599720240000, + "y": null, + }, + Object { + "x": 1599720270000, + "y": 0.20202020202020202, + }, + Object { + "x": 1599720300000, + "y": null, + }, + Object { + "x": 1599720330000, + "y": 0.023121387283236993, + }, + Object { + "x": 1599720360000, + "y": null, + }, + Object { + "x": 1599720390000, + "y": 1, + }, + Object { + "x": 1599720420000, + "y": 0.3076923076923077, + }, + Object { + "x": 1599720450000, + "y": 0.24675324675324675, + }, + Object { + "x": 1599720480000, + "y": null, + }, + Object { + "x": 1599720510000, + "y": 0.875, + }, + Object { + "x": 1599720540000, + "y": 0.47368421052631576, + }, + Object { + "x": 1599720570000, + "y": null, + }, + Object { + "x": 1599720600000, + "y": null, + }, + Object { + "x": 1599720630000, + "y": 0.22580645161290322, + }, + Object { + "x": 1599720660000, + "y": 0.391304347826087, + }, + Object { + "x": 1599720690000, + "y": 0.75, + }, + Object { + "x": 1599720720000, + "y": null, + }, + Object { + "x": 1599720750000, + "y": 0.7804878048780488, + }, + Object { + "x": 1599720780000, + "y": 0.18518518518518517, + }, + Object { + "x": 1599720810000, + "y": 0.24074074074074073, + }, + Object { + "x": 1599720840000, + "y": null, + }, + Object { + "x": 1599720870000, + "y": 1, + }, + Object { + "x": 1599720900000, + "y": 0.1111111111111111, + }, + Object { + "x": 1599720930000, + "y": 0.5161290322580645, + }, + Object { + "x": 1599720960000, + "y": null, + }, + Object { + "x": 1599720990000, + "y": 0.14285714285714285, + }, + Object { + "x": 1599721020000, + "y": 1, + }, + Object { + "x": 1599721050000, + "y": 0.7272727272727273, + }, + Object { + "x": 1599721080000, + "y": null, + }, + Object { + "x": 1599721110000, + "y": 0.059027777777777776, + }, + Object { + "x": 1599721140000, + "y": 0.022727272727272728, + }, + Object { + "x": 1599721170000, "y": null, }, Object { - "x": 1593413130000, - "y": null, + "x": 1599721200000, + "y": null, + }, + ], + "hideLegend": false, + "legendValue": "14%", + "title": "app", + "type": "areaStacked", + }, + Object { + "color": "#6092c0", + "data": Array [ + Object { + "x": 1599717600000, + "y": 0.9411764705882353, + }, + Object { + "x": 1599717630000, + "y": 0.9629629629629629, + }, + Object { + "x": 1599717660000, + "y": null, + }, + Object { + "x": 1599717690000, + "y": 0.9285714285714286, + }, + Object { + "x": 1599717720000, + "y": null, + }, + Object { + "x": 1599717750000, + "y": 0.9734675205855444, + }, + Object { + "x": 1599717780000, + "y": 0.8055555555555556, + }, + Object { + "x": 1599717810000, + "y": 0.8653846153846154, + }, + Object { + "x": 1599717840000, + "y": null, + }, + Object { + "x": 1599717870000, + "y": 0, + }, + Object { + "x": 1599717900000, + "y": 0.9558823529411765, + }, + Object { + "x": 1599717930000, + "y": 0.6901408450704225, + }, + Object { + "x": 1599717960000, + "y": null, + }, + Object { + "x": 1599717990000, + "y": 0.7404580152671756, + }, + Object { + "x": 1599718020000, + "y": 0, + }, + Object { + "x": 1599718050000, + "y": 0.9661016949152542, + }, + Object { + "x": 1599718080000, + "y": null, + }, + Object { + "x": 1599718110000, + "y": 0.6363636363636364, + }, + Object { + "x": 1599718140000, + "y": null, + }, + Object { + "x": 1599718170000, + "y": 0.9726027397260274, + }, + Object { + "x": 1599718200000, + "y": 0, + }, + Object { + "x": 1599718230000, + "y": 0.8921161825726142, + }, + Object { + "x": 1599718260000, + "y": null, + }, + Object { + "x": 1599718290000, + "y": null, + }, + Object { + "x": 1599718320000, + "y": null, + }, + Object { + "x": 1599718350000, + "y": 0.8888888888888888, + }, + Object { + "x": 1599718380000, + "y": 0.9444444444444444, + }, + Object { + "x": 1599718410000, + "y": 0, + }, + Object { + "x": 1599718440000, + "y": null, + }, + Object { + "x": 1599718470000, + "y": 0.38392857142857145, + }, + Object { + "x": 1599718500000, + "y": 0.9545454545454546, + }, + Object { + "x": 1599718530000, + "y": 0, + }, + Object { + "x": 1599718560000, + "y": null, + }, + Object { + "x": 1599718590000, + "y": 0.3877551020408163, + }, + Object { + "x": 1599718620000, + "y": null, + }, + Object { + "x": 1599718650000, + "y": 0.9545454545454546, + }, + Object { + "x": 1599718680000, + "y": null, + }, + Object { + "x": 1599718710000, + "y": 0.9560439560439561, + }, + Object { + "x": 1599718740000, + "y": 0.208955223880597, + }, + Object { + "x": 1599718770000, + "y": 0.9791666666666666, + }, + Object { + "x": 1599718800000, + "y": 0, + }, + Object { + "x": 1599718830000, + "y": null, + }, + Object { + "x": 1599718860000, + "y": 0, + }, + Object { + "x": 1599718890000, + "y": 0.5833333333333334, + }, + Object { + "x": 1599718920000, + "y": null, + }, + Object { + "x": 1599718950000, + "y": 0.5882352941176471, + }, + Object { + "x": 1599718980000, + "y": null, + }, + Object { + "x": 1599719010000, + "y": null, + }, + Object { + "x": 1599719040000, + "y": 0.5357142857142857, + }, + Object { + "x": 1599719070000, + "y": 0.5, + }, + Object { + "x": 1599719100000, + "y": 0, + }, + Object { + "x": 1599719130000, + "y": 0.6410256410256411, + }, + Object { + "x": 1599719160000, + "y": null, + }, + Object { + "x": 1599719190000, + "y": 0.9672245467224547, + }, + Object { + "x": 1599719220000, + "y": 0.9473684210526315, + }, + Object { + "x": 1599719250000, + "y": 0.7922077922077922, + }, + Object { + "x": 1599719280000, + "y": null, + }, + Object { + "x": 1599719310000, + "y": 0.8356164383561644, + }, + Object { + "x": 1599719340000, + "y": 0.1935483870967742, + }, + Object { + "x": 1599719370000, + "y": null, + }, + Object { + "x": 1599719400000, + "y": null, + }, + Object { + "x": 1599719430000, + "y": 0.8777173913043478, + }, + Object { + "x": 1599719460000, + "y": 0.28205128205128205, + }, + Object { + "x": 1599719490000, + "y": null, + }, + Object { + "x": 1599719520000, + "y": 0.9583333333333334, + }, + Object { + "x": 1599719550000, + "y": 0.9714285714285714, + }, + Object { + "x": 1599719580000, + "y": null, + }, + Object { + "x": 1599719610000, + "y": 0, + }, + Object { + "x": 1599719640000, + "y": null, + }, + Object { + "x": 1599719670000, + "y": 0.5725806451612904, + }, + Object { + "x": 1599719700000, + "y": null, + }, + Object { + "x": 1599719730000, + "y": null, + }, + Object { + "x": 1599719760000, + "y": 0.37777777777777777, + }, + Object { + "x": 1599719790000, + "y": 0.5, + }, + Object { + "x": 1599719820000, + "y": null, + }, + Object { + "x": 1599719850000, + "y": 0.5192307692307693, + }, + Object { + "x": 1599719880000, + "y": null, + }, + Object { + "x": 1599719910000, + "y": 0.46511627906976744, + }, + Object { + "x": 1599719940000, + "y": null, + }, + Object { + "x": 1599719970000, + "y": null, + }, + Object { + "x": 1599720000000, + "y": 0.6666666666666666, + }, + Object { + "x": 1599720030000, + "y": 0.45, + }, + Object { + "x": 1599720060000, + "y": null, + }, + Object { + "x": 1599720090000, + "y": 0, + }, + Object { + "x": 1599720120000, + "y": null, + }, + Object { + "x": 1599720150000, + "y": null, + }, + Object { + "x": 1599720180000, + "y": null, + }, + Object { + "x": 1599720210000, + "y": 0, + }, + Object { + "x": 1599720240000, + "y": null, + }, + Object { + "x": 1599720270000, + "y": 0.797979797979798, + }, + Object { + "x": 1599720300000, + "y": null, + }, + Object { + "x": 1599720330000, + "y": 0.976878612716763, + }, + Object { + "x": 1599720360000, + "y": null, + }, + Object { + "x": 1599720390000, + "y": 0, + }, + Object { + "x": 1599720420000, + "y": 0.6410256410256411, + }, + Object { + "x": 1599720450000, + "y": 0.5064935064935064, + }, + Object { + "x": 1599720480000, + "y": null, + }, + Object { + "x": 1599720510000, + "y": 0, + }, + Object { + "x": 1599720540000, + "y": 0, + }, + Object { + "x": 1599720570000, + "y": null, + }, + Object { + "x": 1599720600000, + "y": null, + }, + Object { + "x": 1599720630000, + "y": 0.7258064516129032, + }, + Object { + "x": 1599720660000, + "y": 0, + }, + Object { + "x": 1599720690000, + "y": 0, }, Object { - "x": 1593413160000, + "x": 1599720720000, "y": null, }, Object { - "x": 1593413190000, - "y": null, + "x": 1599720750000, + "y": 0.21951219512195122, + }, + Object { + "x": 1599720780000, + "y": 0.6111111111111112, + }, + Object { + "x": 1599720810000, + "y": 0.6851851851851852, }, Object { - "x": 1593413220000, + "x": 1599720840000, "y": null, }, Object { - "x": 1593413250000, + "x": 1599720870000, + "y": 0, + }, + Object { + "x": 1599720900000, + "y": 0.7, + }, + Object { + "x": 1599720930000, + "y": 0.41935483870967744, + }, + Object { + "x": 1599720960000, "y": null, }, Object { - "x": 1593413280000, + "x": 1599720990000, + "y": 0.7428571428571429, + }, + Object { + "x": 1599721020000, + "y": 0, + }, + Object { + "x": 1599721050000, + "y": 0, + }, + Object { + "x": 1599721080000, "y": null, }, Object { - "x": 1593413310000, - "y": 0.16700861715223636, + "x": 1599721110000, + "y": 0.8506944444444444, + }, + Object { + "x": 1599721140000, + "y": 0.9772727272727273, + }, + Object { + "x": 1599721170000, + "y": null, }, Object { - "x": 1593413340000, + "x": 1599721200000, "y": null, }, ], "hideLegend": false, - "legendValue": "17%", - "title": "app", + "legendValue": "79%", + "title": "http", "type": "areaStacked", }, Object { - "color": "#6092c0", + "color": "#d36086", "data": Array [ Object { - "x": 1593413100000, + "x": 1599717600000, + "y": 0, + }, + Object { + "x": 1599717630000, + "y": 0, + }, + Object { + "x": 1599717660000, "y": null, }, Object { - "x": 1593413130000, + "x": 1599717690000, + "y": 0, + }, + Object { + "x": 1599717720000, "y": null, }, Object { - "x": 1593413160000, + "x": 1599717750000, + "y": 0.0027447392497712718, + }, + Object { + "x": 1599717780000, + "y": 0, + }, + Object { + "x": 1599717810000, + "y": 0, + }, + Object { + "x": 1599717840000, "y": null, }, Object { - "x": 1593413190000, + "x": 1599717870000, + "y": 0.3333333333333333, + }, + Object { + "x": 1599717900000, + "y": 0, + }, + Object { + "x": 1599717930000, + "y": 0, + }, + Object { + "x": 1599717960000, "y": null, }, Object { - "x": 1593413220000, + "x": 1599717990000, + "y": 0.14122137404580154, + }, + Object { + "x": 1599718020000, + "y": 0, + }, + Object { + "x": 1599718050000, + "y": 0, + }, + Object { + "x": 1599718080000, "y": null, }, Object { - "x": 1593413250000, + "x": 1599718110000, + "y": 0.19786096256684493, + }, + Object { + "x": 1599718140000, "y": null, }, Object { - "x": 1593413280000, + "x": 1599718170000, + "y": 0, + }, + Object { + "x": 1599718200000, + "y": 0.2727272727272727, + }, + Object { + "x": 1599718230000, + "y": 0.012448132780082987, + }, + Object { + "x": 1599718260000, "y": null, }, Object { - "x": 1593413310000, - "y": 0.7702092736971686, + "x": 1599718290000, + "y": null, }, Object { - "x": 1593413340000, + "x": 1599718320000, "y": null, }, - ], - "hideLegend": false, - "legendValue": "77%", - "title": "http", - "type": "areaStacked", - }, - Object { - "color": "#d36086", - "data": Array [ Object { - "x": 1593413100000, + "x": 1599718350000, + "y": 0, + }, + Object { + "x": 1599718380000, + "y": 0, + }, + Object { + "x": 1599718410000, + "y": 0.5151515151515151, + }, + Object { + "x": 1599718440000, + "y": null, + }, + Object { + "x": 1599718470000, + "y": 0.15178571428571427, + }, + Object { + "x": 1599718500000, + "y": 0, + }, + Object { + "x": 1599718530000, + "y": 0, + }, + Object { + "x": 1599718560000, + "y": null, + }, + Object { + "x": 1599718590000, + "y": 0.2653061224489796, + }, + Object { + "x": 1599718620000, "y": null, }, Object { - "x": 1593413130000, + "x": 1599718650000, + "y": 0, + }, + Object { + "x": 1599718680000, "y": null, }, Object { - "x": 1593413160000, + "x": 1599718710000, + "y": 0.014285714285714285, + }, + Object { + "x": 1599718740000, + "y": 0, + }, + Object { + "x": 1599718770000, + "y": 0, + }, + Object { + "x": 1599718800000, + "y": 0.6551724137931034, + }, + Object { + "x": 1599718830000, "y": null, }, Object { - "x": 1593413190000, + "x": 1599718860000, + "y": 0.5892857142857143, + }, + Object { + "x": 1599718890000, + "y": 0.20238095238095238, + }, + Object { + "x": 1599718920000, "y": null, }, Object { - "x": 1593413220000, + "x": 1599718950000, + "y": 0.08823529411764706, + }, + Object { + "x": 1599718980000, "y": null, }, Object { - "x": 1593413250000, + "x": 1599719010000, "y": null, }, Object { - "x": 1593413280000, + "x": 1599719040000, + "y": 0, + }, + Object { + "x": 1599719070000, + "y": 0.2980769230769231, + }, + Object { + "x": 1599719100000, + "y": 0.6, + }, + Object { + "x": 1599719130000, + "y": 0.07692307692307693, + }, + Object { + "x": 1599719160000, "y": null, }, Object { - "x": 1593413310000, - "y": 0.0508822322527698, + "x": 1599719190000, + "y": 0.012552301255230125, + }, + Object { + "x": 1599719220000, + "y": 0, + }, + Object { + "x": 1599719250000, + "y": 0.012987012987012988, }, Object { - "x": 1593413340000, + "x": 1599719280000, "y": null, }, - ], - "hideLegend": false, - "legendValue": "5.1%", - "title": "postgresql", - "type": "areaStacked", - }, - Object { - "color": "#9170b8", - "data": Array [ Object { - "x": 1593413100000, + "x": 1599719310000, + "y": 0.0273972602739726, + }, + Object { + "x": 1599719340000, + "y": 0.41935483870967744, + }, + Object { + "x": 1599719370000, "y": null, }, Object { - "x": 1593413130000, + "x": 1599719400000, "y": null, }, Object { - "x": 1593413160000, + "x": 1599719430000, + "y": 0.010869565217391304, + }, + Object { + "x": 1599719460000, + "y": 0.14102564102564102, + }, + Object { + "x": 1599719490000, + "y": null, + }, + Object { + "x": 1599719520000, + "y": 0, + }, + Object { + "x": 1599719550000, + "y": 0, + }, + Object { + "x": 1599719580000, + "y": null, + }, + Object { + "x": 1599719610000, + "y": 0.6428571428571429, + }, + Object { + "x": 1599719640000, + "y": null, + }, + Object { + "x": 1599719670000, + "y": 0.13709677419354838, + }, + Object { + "x": 1599719700000, + "y": null, + }, + Object { + "x": 1599719730000, + "y": null, + }, + Object { + "x": 1599719760000, + "y": 0, + }, + Object { + "x": 1599719790000, + "y": 0.32142857142857145, + }, + Object { + "x": 1599719820000, + "y": null, + }, + Object { + "x": 1599719850000, + "y": 0, + }, + Object { + "x": 1599719880000, + "y": null, + }, + Object { + "x": 1599719910000, + "y": 0, + }, + Object { + "x": 1599719940000, + "y": null, + }, + Object { + "x": 1599719970000, + "y": null, + }, + Object { + "x": 1599720000000, + "y": 0.08888888888888889, + }, + Object { + "x": 1599720030000, + "y": 0.15, + }, + Object { + "x": 1599720060000, + "y": null, + }, + Object { + "x": 1599720090000, + "y": 0, + }, + Object { + "x": 1599720120000, + "y": null, + }, + Object { + "x": 1599720150000, + "y": null, + }, + Object { + "x": 1599720180000, + "y": null, + }, + Object { + "x": 1599720210000, + "y": 0.6206896551724138, + }, + Object { + "x": 1599720240000, + "y": null, + }, + Object { + "x": 1599720270000, + "y": 0, + }, + Object { + "x": 1599720300000, + "y": null, + }, + Object { + "x": 1599720330000, + "y": 0, + }, + Object { + "x": 1599720360000, + "y": null, + }, + Object { + "x": 1599720390000, + "y": 0, + }, + Object { + "x": 1599720420000, + "y": 0.05128205128205128, + }, + Object { + "x": 1599720450000, + "y": 0.24675324675324675, + }, + Object { + "x": 1599720480000, + "y": null, + }, + Object { + "x": 1599720510000, + "y": 0.125, + }, + Object { + "x": 1599720540000, + "y": 0.5263157894736842, + }, + Object { + "x": 1599720570000, + "y": null, + }, + Object { + "x": 1599720600000, "y": null, }, Object { - "x": 1593413190000, + "x": 1599720630000, + "y": 0.04838709677419355, + }, + Object { + "x": 1599720660000, + "y": 0.6086956521739131, + }, + Object { + "x": 1599720690000, + "y": 0.25, + }, + Object { + "x": 1599720720000, "y": null, }, Object { - "x": 1593413220000, + "x": 1599720750000, + "y": 0, + }, + Object { + "x": 1599720780000, + "y": 0.2037037037037037, + }, + Object { + "x": 1599720810000, + "y": 0.07407407407407407, + }, + Object { + "x": 1599720840000, "y": null, }, Object { - "x": 1593413250000, + "x": 1599720870000, + "y": 0, + }, + Object { + "x": 1599720900000, + "y": 0.18888888888888888, + }, + Object { + "x": 1599720930000, + "y": 0.06451612903225806, + }, + Object { + "x": 1599720960000, "y": null, }, Object { - "x": 1593413280000, + "x": 1599720990000, + "y": 0.11428571428571428, + }, + Object { + "x": 1599721020000, + "y": 0, + }, + Object { + "x": 1599721050000, + "y": 0.2727272727272727, + }, + Object { + "x": 1599721080000, "y": null, }, Object { - "x": 1593413310000, - "y": 0.011899876897825195, + "x": 1599721110000, + "y": 0.09027777777777778, }, Object { - "x": 1593413340000, + "x": 1599721140000, + "y": 0, + }, + Object { + "x": 1599721170000, + "y": null, + }, + Object { + "x": 1599721200000, "y": null, }, ], "hideLegend": false, - "legendValue": "1.2%", - "title": "redis", + "legendValue": "6.4%", + "title": "postgresql", "type": "areaStacked", }, ], } `; + +exports[`Breakdown when data is loaded returns the transaction breakdown for a transaction group 9`] = ` +Array [ + Object { + "x": 1599717600000, + "y": 1, + }, + Object { + "x": 1599717630000, + "y": 1, + }, + Object { + "x": 1599717660000, + "y": null, + }, + Object { + "x": 1599717690000, + "y": 1, + }, + Object { + "x": 1599717720000, + "y": null, + }, + Object { + "x": 1599717750000, + "y": 1, + }, + Object { + "x": 1599717780000, + "y": 1, + }, + Object { + "x": 1599717810000, + "y": 1, + }, + Object { + "x": 1599717840000, + "y": null, + }, + Object { + "x": 1599717870000, + "y": null, + }, + Object { + "x": 1599717900000, + "y": 1, + }, + Object { + "x": 1599717930000, + "y": 1, + }, + Object { + "x": 1599717960000, + "y": null, + }, + Object { + "x": 1599717990000, + "y": 1, + }, + Object { + "x": 1599718020000, + "y": null, + }, + Object { + "x": 1599718050000, + "y": 1, + }, + Object { + "x": 1599718080000, + "y": null, + }, + Object { + "x": 1599718110000, + "y": 1, + }, + Object { + "x": 1599718140000, + "y": null, + }, + Object { + "x": 1599718170000, + "y": 1, + }, + Object { + "x": 1599718200000, + "y": null, + }, + Object { + "x": 1599718230000, + "y": 1, + }, + Object { + "x": 1599718260000, + "y": null, + }, + Object { + "x": 1599718290000, + "y": null, + }, + Object { + "x": 1599718320000, + "y": null, + }, + Object { + "x": 1599718350000, + "y": 1, + }, + Object { + "x": 1599718380000, + "y": 1, + }, + Object { + "x": 1599718410000, + "y": null, + }, + Object { + "x": 1599718440000, + "y": null, + }, + Object { + "x": 1599718470000, + "y": 1, + }, + Object { + "x": 1599718500000, + "y": 1, + }, + Object { + "x": 1599718530000, + "y": null, + }, + Object { + "x": 1599718560000, + "y": null, + }, + Object { + "x": 1599718590000, + "y": 1, + }, + Object { + "x": 1599718620000, + "y": null, + }, + Object { + "x": 1599718650000, + "y": 1, + }, + Object { + "x": 1599718680000, + "y": null, + }, + Object { + "x": 1599718710000, + "y": 1, + }, + Object { + "x": 1599718740000, + "y": 1, + }, + Object { + "x": 1599718770000, + "y": 1, + }, + Object { + "x": 1599718800000, + "y": null, + }, + Object { + "x": 1599718830000, + "y": null, + }, + Object { + "x": 1599718860000, + "y": null, + }, + Object { + "x": 1599718890000, + "y": 1, + }, + Object { + "x": 1599718920000, + "y": null, + }, + Object { + "x": 1599718950000, + "y": 1, + }, + Object { + "x": 1599718980000, + "y": null, + }, + Object { + "x": 1599719010000, + "y": null, + }, + Object { + "x": 1599719040000, + "y": 1, + }, + Object { + "x": 1599719070000, + "y": 1, + }, + Object { + "x": 1599719100000, + "y": null, + }, + Object { + "x": 1599719130000, + "y": 1, + }, + Object { + "x": 1599719160000, + "y": null, + }, + Object { + "x": 1599719190000, + "y": 1, + }, + Object { + "x": 1599719220000, + "y": 1, + }, + Object { + "x": 1599719250000, + "y": 1, + }, + Object { + "x": 1599719280000, + "y": null, + }, + Object { + "x": 1599719310000, + "y": 1, + }, + Object { + "x": 1599719340000, + "y": 1, + }, + Object { + "x": 1599719370000, + "y": null, + }, + Object { + "x": 1599719400000, + "y": null, + }, + Object { + "x": 1599719430000, + "y": 1, + }, + Object { + "x": 1599719460000, + "y": 1, + }, + Object { + "x": 1599719490000, + "y": null, + }, + Object { + "x": 1599719520000, + "y": 1, + }, + Object { + "x": 1599719550000, + "y": 1, + }, + Object { + "x": 1599719580000, + "y": null, + }, + Object { + "x": 1599719610000, + "y": null, + }, + Object { + "x": 1599719640000, + "y": null, + }, + Object { + "x": 1599719670000, + "y": 1, + }, + Object { + "x": 1599719700000, + "y": null, + }, + Object { + "x": 1599719730000, + "y": null, + }, + Object { + "x": 1599719760000, + "y": 1, + }, + Object { + "x": 1599719790000, + "y": 1, + }, + Object { + "x": 1599719820000, + "y": null, + }, + Object { + "x": 1599719850000, + "y": 1, + }, + Object { + "x": 1599719880000, + "y": null, + }, + Object { + "x": 1599719910000, + "y": 1, + }, + Object { + "x": 1599719940000, + "y": null, + }, + Object { + "x": 1599719970000, + "y": null, + }, + Object { + "x": 1599720000000, + "y": 1, + }, + Object { + "x": 1599720030000, + "y": 1, + }, + Object { + "x": 1599720060000, + "y": null, + }, + Object { + "x": 1599720090000, + "y": null, + }, + Object { + "x": 1599720120000, + "y": null, + }, + Object { + "x": 1599720150000, + "y": null, + }, + Object { + "x": 1599720180000, + "y": null, + }, + Object { + "x": 1599720210000, + "y": null, + }, + Object { + "x": 1599720240000, + "y": null, + }, + Object { + "x": 1599720270000, + "y": 1, + }, + Object { + "x": 1599720300000, + "y": null, + }, + Object { + "x": 1599720330000, + "y": 1, + }, + Object { + "x": 1599720360000, + "y": null, + }, + Object { + "x": 1599720390000, + "y": null, + }, + Object { + "x": 1599720420000, + "y": 1, + }, + Object { + "x": 1599720450000, + "y": 1, + }, + Object { + "x": 1599720480000, + "y": null, + }, + Object { + "x": 1599720510000, + "y": null, + }, + Object { + "x": 1599720540000, + "y": null, + }, + Object { + "x": 1599720570000, + "y": null, + }, + Object { + "x": 1599720600000, + "y": null, + }, + Object { + "x": 1599720630000, + "y": 1, + }, + Object { + "x": 1599720660000, + "y": null, + }, + Object { + "x": 1599720690000, + "y": null, + }, + Object { + "x": 1599720720000, + "y": null, + }, + Object { + "x": 1599720750000, + "y": 1, + }, + Object { + "x": 1599720780000, + "y": 1, + }, + Object { + "x": 1599720810000, + "y": 1, + }, + Object { + "x": 1599720840000, + "y": null, + }, + Object { + "x": 1599720870000, + "y": null, + }, + Object { + "x": 1599720900000, + "y": 1, + }, + Object { + "x": 1599720930000, + "y": 1, + }, + Object { + "x": 1599720960000, + "y": null, + }, + Object { + "x": 1599720990000, + "y": 1, + }, + Object { + "x": 1599721020000, + "y": null, + }, + Object { + "x": 1599721050000, + "y": null, + }, + Object { + "x": 1599721080000, + "y": null, + }, + Object { + "x": 1599721110000, + "y": 1, + }, + Object { + "x": 1599721140000, + "y": 1, + }, + Object { + "x": 1599721170000, + "y": null, + }, + Object { + "x": 1599721200000, + "y": null, + }, +] +`; diff --git a/x-pack/test/apm_api_integration/basic/tests/transaction_groups/__snapshots__/top_transaction_groups.snap b/x-pack/test/apm_api_integration/basic/tests/transaction_groups/__snapshots__/top_transaction_groups.snap index 16a5640c5305b..0a656d5c728a2 100644 --- a/x-pack/test/apm_api_integration/basic/tests/transaction_groups/__snapshots__/top_transaction_groups.snap +++ b/x-pack/test/apm_api_integration/basic/tests/transaction_groups/__snapshots__/top_transaction_groups.snap @@ -3,130 +3,95 @@ exports[`Top transaction groups when data is loaded returns the correct buckets (when ignoring samples) 1`] = ` Array [ Object { - "averageResponseTime": 2577, + "averageResponseTime": 2612, "impact": 0, - "key": "GET /throw-error", - "p95": 3224, - "transactionsPerMinute": 0.5, - }, - Object { - "averageResponseTime": 4757, - "impact": 0.20830834986820673, - "key": "GET /api/products/:id/customers", - "p95": 5616, - "transactionsPerMinute": 0.5, - }, - Object { - "averageResponseTime": 4749.666666666667, - "impact": 0.43453312891085794, - "key": "GET /api/orders/:id", - "p95": 7184, - "transactionsPerMinute": 0.75, + "key": "POST /api/orders", + "p95": 2608, + "transactionsPerMinute": 0.016666666666666666, }, Object { - "averageResponseTime": 8181, - "impact": 0.5354862351657939, + "averageResponseTime": 8710, + "impact": 0.21594473634705155, "key": "GET /api/types/:id", - "p95": 10080, - "transactionsPerMinute": 0.5, - }, - Object { - "averageResponseTime": 20011, - "impact": 0.7098250353192541, - "key": "POST /api", - "p95": 19968, - "transactionsPerMinute": 0.25, - }, - Object { - "averageResponseTime": 35846, - "impact": 1.466376117925459, - "key": "GET /log-error", - "p95": 35840, - "transactionsPerMinute": 0.25, + "p95": 8832, + "transactionsPerMinute": 0.03333333333333333, }, Object { - "averageResponseTime": 7105.333333333333, - "impact": 1.7905918202662048, - "key": "GET /api/stats", - "p95": 15136, - "transactionsPerMinute": 1.5, + "averageResponseTime": 15469, + "impact": 0.41307743123761353, + "key": "GET /api/products/:id/customers", + "p95": 17728, + "transactionsPerMinute": 0.03333333333333333, }, Object { - "averageResponseTime": 22958.5, - "impact": 1.9475397398343375, - "key": "GET /api/products/top", - "p95": 33216, - "transactionsPerMinute": 0.5, + "averageResponseTime": 11161.5, + "impact": 0.6129808919240927, + "key": "GET /api/customers/:id", + "p95": 16096, + "transactionsPerMinute": 0.06666666666666667, }, Object { - "averageResponseTime": 3492.9285714285716, - "impact": 2.0901067389184496, - "key": "GET static file", - "p95": 11900, - "transactionsPerMinute": 3.5, + "averageResponseTime": 8115.166666666667, + "impact": 0.6719690374213795, + "key": "GET /api/types", + "p95": 12336, + "transactionsPerMinute": 0.1, }, Object { - "averageResponseTime": 26992.5, - "impact": 2.3330057413794503, - "key": "GET /api/types", - "p95": 45248, - "transactionsPerMinute": 0.5, + "averageResponseTime": 10863.6, + "impact": 0.7540274539141442, + "key": "GET /api/orders/:id", + "p95": 20192, + "transactionsPerMinute": 0.08333333333333333, }, Object { - "averageResponseTime": 13516.5, - "impact": 2.3368756900811305, + "averageResponseTime": 9906, + "impact": 0.8286631346694258, "key": "GET /api/products/:id", - "p95": 37856, - "transactionsPerMinute": 1, + "p95": 13280, + "transactionsPerMinute": 0.1, }, Object { - "averageResponseTime": 8585, - "impact": 2.624924094061731, + "averageResponseTime": 8524.454545454546, + "impact": 1.329340513991638, "key": "GET /api/products", - "p95": 22112, - "transactionsPerMinute": 1.75, + "p95": 14256, + "transactionsPerMinute": 0.18333333333333332, }, Object { - "averageResponseTime": 7615.625, - "impact": 2.6645791239678345, + "averageResponseTime": 12947, + "impact": 1.472355777994578, "key": "GET /api/orders", - "p95": 11616, - "transactionsPerMinute": 2, + "p95": 25584, + "transactionsPerMinute": 0.13333333333333333, }, Object { - "averageResponseTime": 3262.95, - "impact": 2.8716452680799467, - "key": "GET /*", - "p95": 4472, - "transactionsPerMinute": 5, - }, - Object { - "averageResponseTime": 32667.5, - "impact": 2.875276331059301, - "key": "GET /log-message", - "p95": 38528, - "transactionsPerMinute": 0.5, + "averageResponseTime": 11307.75, + "impact": 2.6003199505345393, + "key": "GET /api/products/top", + "p95": 16304, + "transactionsPerMinute": 0.26666666666666666, }, Object { - "averageResponseTime": 16896.8, - "impact": 3.790160870423129, + "averageResponseTime": 26755.666666666668, + "impact": 4.644036801602961, "key": "GET /api/customers", - "p95": 26432, - "transactionsPerMinute": 1.25, + "p95": 39104, + "transactionsPerMinute": 0.2, }, Object { - "averageResponseTime": 270684, - "impact": 12.686265169840583, - "key": "POST /api/orders", - "p95": 270336, - "transactionsPerMinute": 0.25, + "averageResponseTime": 17851.384615384617, + "impact": 6.730394279972759, + "key": "GET /api/stats", + "p95": 24416, + "transactionsPerMinute": 0.43333333333333335, }, Object { - "averageResponseTime": 51175.73170731707, + "averageResponseTime": 61249.30357142857, "impact": 100, "key": "GET /api", - "p95": 259040, - "transactionsPerMinute": 10.25, + "p95": 162784, + "transactionsPerMinute": 1.8666666666666667, }, ] `; diff --git a/x-pack/test/apm_api_integration/basic/tests/transaction_groups/__snapshots__/transaction_charts.snap b/x-pack/test/apm_api_integration/basic/tests/transaction_groups/__snapshots__/transaction_charts.snap index 0ac7741396fd4..c4b9e1ad6c931 100644 --- a/x-pack/test/apm_api_integration/basic/tests/transaction_groups/__snapshots__/transaction_charts.snap +++ b/x-pack/test/apm_api_integration/basic/tests/transaction_groups/__snapshots__/transaction_charts.snap @@ -1,7755 +1,3425 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`Transaction charts when data is loaded returns the transaction charts 1`] = ` +exports[`Transaction charts when data is loaded returns the correct data 4`] = ` Object { "apmTimeseries": Object { - "overallAvgDuration": 38682.52419354839, + "overallAvgDuration": 578297.1431623931, "responseTimes": Object { "avg": Array [ Object { - "x": 1593413100000, - "y": null, + "x": 1599717600000, + "y": 311706, }, Object { - "x": 1593413101000, - "y": null, + "x": 1599717630000, + "y": 885570.5, }, Object { - "x": 1593413102000, - "y": null, + "x": 1599717660000, + "y": 388852.6666666667, }, Object { - "x": 1593413103000, - "y": null, + "x": 1599717690000, + "y": 503725.75, }, Object { - "x": 1593413104000, - "y": null, + "x": 1599717720000, + "y": 647100.2857142857, }, Object { - "x": 1593413105000, - "y": null, + "x": 1599717750000, + "y": 658360.4285714285, }, Object { - "x": 1593413106000, - "y": null, + "x": 1599717780000, + "y": 308246.25, }, Object { - "x": 1593413107000, - "y": null, + "x": 1599717810000, + "y": 1104229.3333333333, }, Object { - "x": 1593413108000, - "y": null, + "x": 1599717840000, + "y": 438727.6666666667, }, Object { - "x": 1593413109000, - "y": null, + "x": 1599717870000, + "y": 475918, }, Object { - "x": 1593413110000, - "y": null, + "x": 1599717900000, + "y": 254092.33333333334, }, Object { - "x": 1593413111000, - "y": null, + "x": 1599717930000, + "y": 1103846.6666666667, }, Object { - "x": 1593413112000, - "y": null, + "x": 1599717960000, + "y": 70868.8, }, Object { - "x": 1593413113000, - "y": null, + "x": 1599717990000, + "y": 384811.5, }, Object { - "x": 1593413114000, - "y": null, + "x": 1599718020000, + "y": 1139810, }, Object { - "x": 1593413115000, - "y": null, + "x": 1599718050000, + "y": 938950, }, Object { - "x": 1593413116000, - "y": null, + "x": 1599718080000, + "y": 286195.4285714286, }, Object { - "x": 1593413117000, - "y": null, + "x": 1599718110000, + "y": 373445.5, }, Object { - "x": 1593413118000, - "y": null, + "x": 1599718140000, + "y": 747249.6, }, Object { - "x": 1593413119000, - "y": null, + "x": 1599718170000, + "y": 1110552.6666666667, }, Object { - "x": 1593413120000, - "y": null, + "x": 1599718200000, + "y": 206614.66666666666, }, Object { - "x": 1593413121000, - "y": null, + "x": 1599718230000, + "y": 412294, }, Object { - "x": 1593413122000, - "y": null, + "x": 1599718260000, + "y": 643594, }, Object { - "x": 1593413123000, - "y": null, + "x": 1599718290000, + "y": 973397.5, }, Object { - "x": 1593413124000, - "y": null, + "x": 1599718320000, + "y": 521419, }, Object { - "x": 1593413125000, - "y": null, + "x": 1599718350000, + "y": 543694.3333333334, }, Object { - "x": 1593413126000, - "y": null, + "x": 1599718380000, + "y": 503212.8, }, Object { - "x": 1593413127000, - "y": null, + "x": 1599718410000, + "y": 1516441.5, }, Object { - "x": 1593413128000, - "y": null, + "x": 1599718440000, + "y": 457890.2, }, Object { - "x": 1593413129000, - "y": null, + "x": 1599718470000, + "y": 160177.55555555556, }, Object { - "x": 1593413130000, - "y": null, + "x": 1599718500000, + "y": 497083.6666666667, }, Object { - "x": 1593413131000, - "y": null, + "x": 1599718530000, + "y": 1276293, }, Object { - "x": 1593413132000, - "y": null, + "x": 1599718560000, + "y": 194131.8, }, Object { - "x": 1593413133000, - "y": null, + "x": 1599718590000, + "y": 1177525, }, Object { - "x": 1593413134000, - "y": null, + "x": 1599718620000, + "y": 504225.2, }, Object { - "x": 1593413135000, - "y": null, + "x": 1599718650000, + "y": 1397496, }, Object { - "x": 1593413136000, - "y": null, + "x": 1599718680000, + "y": 523145, }, Object { - "x": 1593413137000, - "y": null, + "x": 1599718710000, + "y": 355926.6, }, Object { - "x": 1593413138000, - "y": null, + "x": 1599718740000, + "y": 615277, }, Object { - "x": 1593413139000, - "y": null, + "x": 1599718770000, + "y": 725578, }, Object { - "x": 1593413140000, - "y": null, + "x": 1599718800000, + "y": 1721893.5, }, Object { - "x": 1593413141000, - "y": null, + "x": 1599718830000, + "y": 579859.75, }, Object { - "x": 1593413142000, - "y": null, + "x": 1599718860000, + "y": 371836.6, }, Object { - "x": 1593413143000, - "y": null, + "x": 1599718890000, + "y": 1192755.5, }, Object { - "x": 1593413144000, - "y": null, + "x": 1599718920000, + "y": 288524, }, Object { - "x": 1593413145000, - "y": null, + "x": 1599718950000, + "y": 1220730, }, Object { - "x": 1593413146000, - "y": null, + "x": 1599718980000, + "y": 591210.6666666666, }, Object { - "x": 1593413147000, - "y": null, + "x": 1599719010000, + "y": 601443.6666666666, }, Object { - "x": 1593413148000, - "y": null, + "x": 1599719040000, + "y": 225148, }, Object { - "x": 1593413149000, - "y": null, + "x": 1599719070000, + "y": 885271.5, }, Object { - "x": 1593413150000, - "y": null, + "x": 1599719100000, + "y": 578708.25, }, Object { - "x": 1593413151000, - "y": null, + "x": 1599719130000, + "y": 979768.3333333334, }, Object { - "x": 1593413152000, - "y": null, + "x": 1599719160000, + "y": 334608.71428571426, }, Object { - "x": 1593413153000, - "y": null, + "x": 1599719190000, + "y": 555571, }, Object { - "x": 1593413154000, - "y": null, + "x": 1599719220000, + "y": 249780.66666666666, }, Object { - "x": 1593413155000, + "x": 1599719250000, "y": null, }, Object { - "x": 1593413156000, - "y": null, + "x": 1599719280000, + "y": 510084, }, Object { - "x": 1593413157000, - "y": null, + "x": 1599719310000, + "y": 14228.333333333334, }, Object { - "x": 1593413158000, - "y": null, + "x": 1599719340000, + "y": 1056348.5, }, Object { - "x": 1593413159000, - "y": null, + "x": 1599719370000, + "y": 1150066, }, Object { - "x": 1593413160000, - "y": null, + "x": 1599719400000, + "y": 456110.5833333333, }, Object { - "x": 1593413161000, - "y": null, + "x": 1599719430000, + "y": 333431, }, Object { - "x": 1593413162000, - "y": null, + "x": 1599719460000, + "y": 1157360.6666666667, }, Object { - "x": 1593413163000, - "y": null, + "x": 1599719490000, + "y": 687888.75, }, Object { - "x": 1593413164000, - "y": null, + "x": 1599719520000, + "y": 574561, }, Object { - "x": 1593413165000, - "y": null, + "x": 1599719550000, + "y": 893728, }, Object { - "x": 1593413166000, - "y": null, + "x": 1599719580000, + "y": 773178.4, }, Object { - "x": 1593413167000, - "y": null, + "x": 1599719610000, + "y": 928312, }, Object { - "x": 1593413168000, - "y": null, + "x": 1599719640000, + "y": 371156.14285714284, }, Object { - "x": 1593413169000, - "y": null, + "x": 1599719670000, + "y": 464665.6666666667, }, Object { - "x": 1593413170000, + "x": 1599719700000, "y": null, }, Object { - "x": 1593413171000, - "y": null, + "x": 1599719730000, + "y": 426927.5, }, Object { - "x": 1593413172000, - "y": null, + "x": 1599719760000, + "y": 552956.7142857143, }, Object { - "x": 1593413173000, - "y": null, + "x": 1599719790000, + "y": 1099390, }, Object { - "x": 1593413174000, - "y": null, + "x": 1599719820000, + "y": 675592.75, }, Object { - "x": 1593413175000, - "y": null, + "x": 1599719850000, + "y": 1212971, }, Object { - "x": 1593413176000, - "y": null, + "x": 1599719880000, + "y": 169532.16666666666, }, Object { - "x": 1593413177000, - "y": null, + "x": 1599719910000, + "y": 1116040.6666666667, }, Object { - "x": 1593413178000, - "y": null, + "x": 1599719940000, + "y": 832511.3333333334, }, Object { - "x": 1593413179000, - "y": null, + "x": 1599719970000, + "y": 838424.75, }, Object { - "x": 1593413180000, - "y": null, + "x": 1599720000000, + "y": 705166, }, Object { - "x": 1593413181000, - "y": null, + "x": 1599720030000, + "y": 881526.3333333334, }, Object { - "x": 1593413182000, - "y": null, + "x": 1599720060000, + "y": 493560.5, }, Object { - "x": 1593413183000, - "y": null, + "x": 1599720090000, + "y": 1272019, }, Object { - "x": 1593413184000, - "y": null, + "x": 1599720120000, + "y": 1571697, }, Object { - "x": 1593413185000, - "y": null, + "x": 1599720150000, + "y": 947327.6666666666, }, Object { - "x": 1593413186000, - "y": null, + "x": 1599720180000, + "y": 770506, }, Object { - "x": 1593413187000, - "y": null, + "x": 1599720210000, + "y": 1476976, }, Object { - "x": 1593413188000, - "y": null, + "x": 1599720240000, + "y": 394579.5714285714, }, Object { - "x": 1593413189000, - "y": null, + "x": 1599720270000, + "y": 793661, }, Object { - "x": 1593413190000, - "y": null, + "x": 1599720300000, + "y": 698110.25, }, Object { - "x": 1593413191000, - "y": null, + "x": 1599720330000, + "y": 1623979, }, Object { - "x": 1593413192000, - "y": null, + "x": 1599720360000, + "y": 766940, }, Object { - "x": 1593413193000, - "y": null, + "x": 1599720390000, + "y": 516763.3, }, Object { - "x": 1593413194000, - "y": null, + "x": 1599720420000, + "y": 227079.66666666666, }, Object { - "x": 1593413195000, - "y": null, + "x": 1599720450000, + "y": 1235171, }, Object { - "x": 1593413196000, - "y": null, + "x": 1599720480000, + "y": 1110705.3333333333, }, Object { - "x": 1593413197000, - "y": null, + "x": 1599720510000, + "y": 457118, }, Object { - "x": 1593413198000, - "y": null, + "x": 1599720540000, + "y": 1113258, }, Object { - "x": 1593413199000, - "y": null, + "x": 1599720570000, + "y": 780817, }, Object { - "x": 1593413200000, - "y": null, + "x": 1599720600000, + "y": 396914.6666666667, }, Object { - "x": 1593413201000, - "y": null, + "x": 1599720630000, + "y": 323583.1666666667, }, Object { - "x": 1593413202000, - "y": null, + "x": 1599720660000, + "y": 788903.3333333334, }, Object { - "x": 1593413203000, - "y": null, + "x": 1599720690000, + "y": 339649, }, Object { - "x": 1593413204000, - "y": null, + "x": 1599720720000, + "y": 501015, }, Object { - "x": 1593413205000, - "y": null, + "x": 1599720750000, + "y": 501758.5, }, Object { - "x": 1593413206000, - "y": null, + "x": 1599720780000, + "y": 776868, }, Object { - "x": 1593413207000, - "y": null, + "x": 1599720810000, + "y": 1198145, }, Object { - "x": 1593413208000, - "y": null, + "x": 1599720840000, + "y": 561771.6666666666, }, Object { - "x": 1593413209000, - "y": null, + "x": 1599720870000, + "y": 594213.3333333334, }, Object { - "x": 1593413210000, - "y": null, + "x": 1599720900000, + "y": 188626.5, }, Object { - "x": 1593413211000, - "y": null, + "x": 1599720930000, + "y": 970632, }, Object { - "x": 1593413212000, - "y": null, + "x": 1599720960000, + "y": 750907.2, }, Object { - "x": 1593413213000, - "y": null, + "x": 1599720990000, + "y": 851925.25, }, Object { - "x": 1593413214000, - "y": null, + "x": 1599721020000, + "y": 774642.5, }, Object { - "x": 1593413215000, - "y": null, + "x": 1599721050000, + "y": 322259.5, }, Object { - "x": 1593413216000, - "y": null, + "x": 1599721080000, + "y": 369298.28571428574, }, Object { - "x": 1593413217000, - "y": null, + "x": 1599721110000, + "y": 657293.6666666666, }, Object { - "x": 1593413218000, - "y": null, + "x": 1599721140000, + "y": 479701.3333333333, }, Object { - "x": 1593413219000, - "y": null, + "x": 1599721170000, + "y": 1037489, }, Object { - "x": 1593413220000, + "x": 1599721200000, "y": null, }, + ], + "p95": Array [ Object { - "x": 1593413221000, - "y": null, + "x": 1599717600000, + "y": 483072, }, Object { - "x": 1593413222000, - "y": null, + "x": 1599717630000, + "y": 1310592, }, Object { - "x": 1593413223000, - "y": null, + "x": 1599717660000, + "y": 970688, }, Object { - "x": 1593413224000, - "y": null, + "x": 1599717690000, + "y": 814080, }, Object { - "x": 1593413225000, - "y": null, + "x": 1599717720000, + "y": 1449920, }, Object { - "x": 1593413226000, - "y": null, + "x": 1599717750000, + "y": 1302496, }, Object { - "x": 1593413227000, - "y": null, + "x": 1599717780000, + "y": 622464, }, Object { - "x": 1593413228000, - "y": null, + "x": 1599717810000, + "y": 1323008, }, Object { - "x": 1593413229000, - "y": null, + "x": 1599717840000, + "y": 1003456, }, Object { - "x": 1593413230000, - "y": null, + "x": 1599717870000, + "y": 1195904, }, Object { - "x": 1593413231000, - "y": null, + "x": 1599717900000, + "y": 692096, }, Object { - "x": 1593413232000, - "y": null, + "x": 1599717930000, + "y": 1904640, }, Object { - "x": 1593413233000, - "y": null, + "x": 1599717960000, + "y": 268224, }, Object { - "x": 1593413234000, - "y": null, + "x": 1599717990000, + "y": 1171424, }, Object { - "x": 1593413235000, - "y": null, + "x": 1599718020000, + "y": 1908480, }, Object { - "x": 1593413236000, - "y": null, + "x": 1599718050000, + "y": 937984, }, Object { - "x": 1593413237000, - "y": null, + "x": 1599718080000, + "y": 982912, }, Object { - "x": 1593413238000, - "y": null, + "x": 1599718110000, + "y": 733120, }, Object { - "x": 1593413239000, - "y": null, + "x": 1599718140000, + "y": 1736576, }, Object { - "x": 1593413240000, - "y": null, + "x": 1599718170000, + "y": 1748992, }, Object { - "x": 1593413241000, - "y": null, + "x": 1599718200000, + "y": 970720, }, Object { - "x": 1593413242000, - "y": null, + "x": 1599718230000, + "y": 1540032, }, Object { - "x": 1593413243000, - "y": null, + "x": 1599718260000, + "y": 796672, }, Object { - "x": 1593413244000, - "y": null, + "x": 1599718290000, + "y": 1134592, }, Object { - "x": 1593413245000, - "y": null, + "x": 1599718320000, + "y": 1875904, }, Object { - "x": 1593413246000, - "y": null, + "x": 1599718350000, + "y": 1253312, }, Object { - "x": 1593413247000, - "y": null, + "x": 1599718380000, + "y": 1048512, }, Object { - "x": 1593413248000, - "y": null, + "x": 1599718410000, + "y": 1654784, }, Object { - "x": 1593413249000, - "y": null, + "x": 1599718440000, + "y": 1368048, }, Object { - "x": 1593413250000, - "y": null, + "x": 1599718470000, + "y": 745456, }, Object { - "x": 1593413251000, - "y": null, + "x": 1599718500000, + "y": 1277696, }, Object { - "x": 1593413252000, - "y": null, + "x": 1599718530000, + "y": 1699840, }, Object { - "x": 1593413253000, - "y": null, + "x": 1599718560000, + "y": 1851376, }, Object { - "x": 1593413254000, - "y": null, + "x": 1599718590000, + "y": 1277952, }, Object { - "x": 1593413255000, - "y": null, + "x": 1599718620000, + "y": 1384320, }, Object { - "x": 1593413256000, - "y": null, + "x": 1599718650000, + "y": 1392640, }, Object { - "x": 1593413257000, - "y": null, + "x": 1599718680000, + "y": 1785792, }, Object { - "x": 1593413258000, - "y": null, + "x": 1599718710000, + "y": 1236928, }, Object { - "x": 1593413259000, - "y": null, + "x": 1599718740000, + "y": 1138176, }, Object { - "x": 1593413260000, - "y": null, + "x": 1599718770000, + "y": 1474432, }, Object { - "x": 1593413261000, - "y": null, + "x": 1599718800000, + "y": 1875968, }, Object { - "x": 1593413262000, - "y": null, + "x": 1599718830000, + "y": 1703920, }, Object { - "x": 1593413263000, - "y": null, + "x": 1599718860000, + "y": 1466240, }, Object { - "x": 1593413264000, - "y": null, + "x": 1599718890000, + "y": 1286144, }, Object { - "x": 1593413265000, - "y": null, + "x": 1599718920000, + "y": 831424, }, Object { - "x": 1593413266000, - "y": null, + "x": 1599718950000, + "y": 1253376, }, Object { - "x": 1593413267000, - "y": null, + "x": 1599718980000, + "y": 822272, }, Object { - "x": 1593413268000, - "y": null, + "x": 1599719010000, + "y": 1540032, }, Object { - "x": 1593413269000, - "y": null, + "x": 1599719040000, + "y": 1269728, }, Object { - "x": 1593413270000, - "y": null, + "x": 1599719070000, + "y": 1531872, }, Object { - "x": 1593413271000, - "y": null, + "x": 1599719100000, + "y": 1507264, }, Object { - "x": 1593413272000, - "y": 45093, + "x": 1599719130000, + "y": 1216512, }, Object { - "x": 1593413273000, - "y": 7498, + "x": 1599719160000, + "y": 909248, }, Object { - "x": 1593413274000, - "y": null, + "x": 1599719190000, + "y": 1097600, }, Object { - "x": 1593413275000, - "y": null, + "x": 1599719220000, + "y": 786416, }, Object { - "x": 1593413276000, + "x": 1599719250000, "y": null, }, Object { - "x": 1593413277000, - "y": 37709, + "x": 1599719280000, + "y": 1212352, }, Object { - "x": 1593413278000, - "y": null, + "x": 1599719310000, + "y": 19040, }, Object { - "x": 1593413279000, - "y": null, + "x": 1599719340000, + "y": 1077248, }, Object { - "x": 1593413280000, - "y": null, + "x": 1599719370000, + "y": 1146880, }, Object { - "x": 1593413281000, - "y": 33097, + "x": 1599719400000, + "y": 1777600, }, Object { - "x": 1593413282000, - "y": null, + "x": 1599719430000, + "y": 1261504, }, Object { - "x": 1593413283000, - "y": null, + "x": 1599719460000, + "y": 1617920, }, Object { - "x": 1593413284000, - "y": 388507, + "x": 1599719490000, + "y": 1105664, }, Object { - "x": 1593413285000, - "y": 42331.5, + "x": 1599719520000, + "y": 1163008, }, Object { - "x": 1593413286000, - "y": 99104.25, + "x": 1599719550000, + "y": 892928, }, Object { - "x": 1593413287000, - "y": 18939.5, + "x": 1599719580000, + "y": 1343360, }, Object { - "x": 1593413288000, - "y": 23229.5, + "x": 1599719610000, + "y": 925696, }, Object { - "x": 1593413289000, - "y": 11318, + "x": 1599719640000, + "y": 1277936, }, Object { - "x": 1593413290000, - "y": 15651.25, + "x": 1599719670000, + "y": 1499072, }, Object { - "x": 1593413291000, - "y": 2376, + "x": 1599719700000, + "y": null, }, Object { - "x": 1593413292000, - "y": 7796, + "x": 1599719730000, + "y": 1204096, }, Object { - "x": 1593413293000, - "y": 7571, + "x": 1599719760000, + "y": 1572800, }, Object { - "x": 1593413294000, - "y": 4219.333333333333, + "x": 1599719790000, + "y": 1097728, }, Object { - "x": 1593413295000, - "y": 6827.5, + "x": 1599719820000, + "y": 1376128, }, Object { - "x": 1593413296000, - "y": 10415.5, + "x": 1599719850000, + "y": 1277952, }, Object { - "x": 1593413297000, - "y": 10082, + "x": 1599719880000, + "y": 815072, }, Object { - "x": 1593413298000, - "y": 6459.375, + "x": 1599719910000, + "y": 1765376, }, Object { - "x": 1593413299000, - "y": 3131.5, + "x": 1599719940000, + "y": 937984, }, Object { - "x": 1593413300000, - "y": 6713.333333333333, + "x": 1599719970000, + "y": 1687488, }, Object { - "x": 1593413301000, - "y": 8800, + "x": 1599720000000, + "y": 1212352, }, Object { - "x": 1593413302000, - "y": 3743.5, + "x": 1599720030000, + "y": 1441728, }, Object { - "x": 1593413303000, - "y": 9239.5, + "x": 1599720060000, + "y": 970624, }, Object { - "x": 1593413304000, - "y": 8402, + "x": 1599720090000, + "y": 1409024, }, Object { - "x": 1593413305000, - "y": 20520.666666666668, + "x": 1599720120000, + "y": 1564672, }, Object { - "x": 1593413306000, - "y": 9319.5, + "x": 1599720150000, + "y": 1447936, }, Object { - "x": 1593413307000, - "y": 7694.333333333333, + "x": 1599720180000, + "y": 1195904, }, Object { - "x": 1593413308000, - "y": 20131, + "x": 1599720210000, + "y": 1474560, }, Object { - "x": 1593413309000, - "y": 439937.75, + "x": 1599720240000, + "y": 1220544, }, Object { - "x": 1593413310000, - "y": 11933, + "x": 1599720270000, + "y": 1261504, }, Object { - "x": 1593413311000, - "y": 18670.5, + "x": 1599720300000, + "y": 1712064, }, Object { - "x": 1593413312000, - "y": 9232, + "x": 1599720330000, + "y": 1622016, }, Object { - "x": 1593413313000, - "y": 7602, + "x": 1599720360000, + "y": 1245120, }, Object { - "x": 1593413314000, - "y": 10428.8, + "x": 1599720390000, + "y": 1646560, }, Object { - "x": 1593413315000, - "y": 8405.25, + "x": 1599720420000, + "y": 970688, }, Object { - "x": 1593413316000, - "y": 10654.5, + "x": 1599720450000, + "y": 1228800, }, Object { - "x": 1593413317000, - "y": 10250, + "x": 1599720480000, + "y": 1191936, }, Object { - "x": 1593413318000, - "y": 5775, + "x": 1599720510000, + "y": 1572832, }, Object { - "x": 1593413319000, - "y": 137867, + "x": 1599720540000, + "y": 1200128, }, Object { - "x": 1593413320000, - "y": 5694.333333333333, + "x": 1599720570000, + "y": 1071104, }, Object { - "x": 1593413321000, - "y": 6115, + "x": 1599720600000, + "y": 1130368, }, Object { - "x": 1593413322000, - "y": 1832.5, + "x": 1599720630000, + "y": 933824, }, Object { - "x": 1593413323000, - "y": null, + "x": 1599720660000, + "y": 1220544, }, Object { - "x": 1593413324000, - "y": null, + "x": 1599720690000, + "y": 337920, }, Object { - "x": 1593413325000, - "y": null, + "x": 1599720720000, + "y": 1032128, }, Object { - "x": 1593413326000, - "y": null, + "x": 1599720750000, + "y": 1736672, }, Object { - "x": 1593413327000, - "y": null, + "x": 1599720780000, + "y": 1843136, }, Object { - "x": 1593413328000, - "y": null, + "x": 1599720810000, + "y": 1404928, }, Object { - "x": 1593413329000, - "y": null, + "x": 1599720840000, + "y": 1036160, }, Object { - "x": 1593413330000, - "y": null, + "x": 1599720870000, + "y": 1351552, }, Object { - "x": 1593413331000, - "y": null, + "x": 1599720900000, + "y": 720864, }, Object { - "x": 1593413332000, - "y": null, + "x": 1599720930000, + "y": 966656, }, Object { - "x": 1593413333000, - "y": null, + "x": 1599720960000, + "y": 1892224, }, Object { - "x": 1593413334000, - "y": null, + "x": 1599720990000, + "y": 1384320, }, Object { - "x": 1593413335000, - "y": null, + "x": 1599721020000, + "y": 1540032, }, Object { - "x": 1593413336000, - "y": null, + "x": 1599721050000, + "y": 451584, }, Object { - "x": 1593413337000, - "y": null, + "x": 1599721080000, + "y": 1228768, }, Object { - "x": 1593413338000, - "y": null, + "x": 1599721110000, + "y": 927744, }, Object { - "x": 1593413339000, - "y": null, + "x": 1599721140000, + "y": 1048320, }, Object { - "x": 1593413340000, + "x": 1599721170000, + "y": 1363968, + }, + Object { + "x": 1599721200000, "y": null, }, ], - "p95": Array [ + "p99": Array [ Object { - "x": 1593413100000, - "y": null, + "x": 1599717600000, + "y": 483072, }, Object { - "x": 1593413101000, - "y": null, + "x": 1599717630000, + "y": 1310592, }, Object { - "x": 1593413102000, - "y": null, + "x": 1599717660000, + "y": 970688, }, Object { - "x": 1593413103000, - "y": null, + "x": 1599717690000, + "y": 814080, }, Object { - "x": 1593413104000, - "y": null, + "x": 1599717720000, + "y": 1449920, }, Object { - "x": 1593413105000, - "y": null, + "x": 1599717750000, + "y": 1302496, }, Object { - "x": 1593413106000, - "y": null, + "x": 1599717780000, + "y": 622464, }, Object { - "x": 1593413107000, - "y": null, + "x": 1599717810000, + "y": 1323008, }, Object { - "x": 1593413108000, - "y": null, + "x": 1599717840000, + "y": 1003456, }, Object { - "x": 1593413109000, - "y": null, + "x": 1599717870000, + "y": 1195904, }, Object { - "x": 1593413110000, - "y": null, + "x": 1599717900000, + "y": 692096, }, Object { - "x": 1593413111000, - "y": null, + "x": 1599717930000, + "y": 1904640, }, Object { - "x": 1593413112000, - "y": null, + "x": 1599717960000, + "y": 268224, }, Object { - "x": 1593413113000, - "y": null, + "x": 1599717990000, + "y": 1171424, }, Object { - "x": 1593413114000, - "y": null, + "x": 1599718020000, + "y": 1908480, }, Object { - "x": 1593413115000, - "y": null, + "x": 1599718050000, + "y": 937984, }, Object { - "x": 1593413116000, - "y": null, + "x": 1599718080000, + "y": 982912, }, Object { - "x": 1593413117000, - "y": null, + "x": 1599718110000, + "y": 733120, }, Object { - "x": 1593413118000, - "y": null, + "x": 1599718140000, + "y": 1736576, }, Object { - "x": 1593413119000, - "y": null, + "x": 1599718170000, + "y": 1748992, }, Object { - "x": 1593413120000, - "y": null, + "x": 1599718200000, + "y": 970720, }, Object { - "x": 1593413121000, - "y": null, + "x": 1599718230000, + "y": 1540032, }, Object { - "x": 1593413122000, - "y": null, + "x": 1599718260000, + "y": 796672, }, Object { - "x": 1593413123000, - "y": null, + "x": 1599718290000, + "y": 1134592, }, Object { - "x": 1593413124000, - "y": null, + "x": 1599718320000, + "y": 1875904, }, Object { - "x": 1593413125000, - "y": null, + "x": 1599718350000, + "y": 1253312, }, Object { - "x": 1593413126000, - "y": null, + "x": 1599718380000, + "y": 1048512, }, Object { - "x": 1593413127000, - "y": null, + "x": 1599718410000, + "y": 1654784, }, Object { - "x": 1593413128000, - "y": null, + "x": 1599718440000, + "y": 1368048, }, Object { - "x": 1593413129000, - "y": null, + "x": 1599718470000, + "y": 745456, }, Object { - "x": 1593413130000, - "y": null, + "x": 1599718500000, + "y": 1277696, }, Object { - "x": 1593413131000, - "y": null, + "x": 1599718530000, + "y": 1699840, }, Object { - "x": 1593413132000, - "y": null, + "x": 1599718560000, + "y": 1851376, }, Object { - "x": 1593413133000, - "y": null, + "x": 1599718590000, + "y": 1277952, }, Object { - "x": 1593413134000, - "y": null, + "x": 1599718620000, + "y": 1384320, }, Object { - "x": 1593413135000, - "y": null, + "x": 1599718650000, + "y": 1392640, }, Object { - "x": 1593413136000, - "y": null, + "x": 1599718680000, + "y": 1785792, }, Object { - "x": 1593413137000, - "y": null, + "x": 1599718710000, + "y": 1236928, }, Object { - "x": 1593413138000, - "y": null, + "x": 1599718740000, + "y": 1138176, }, Object { - "x": 1593413139000, - "y": null, + "x": 1599718770000, + "y": 1474432, }, Object { - "x": 1593413140000, - "y": null, + "x": 1599718800000, + "y": 1875968, }, Object { - "x": 1593413141000, - "y": null, + "x": 1599718830000, + "y": 1703920, }, Object { - "x": 1593413142000, - "y": null, + "x": 1599718860000, + "y": 1466240, }, Object { - "x": 1593413143000, - "y": null, + "x": 1599718890000, + "y": 1286144, }, Object { - "x": 1593413144000, - "y": null, + "x": 1599718920000, + "y": 831424, }, Object { - "x": 1593413145000, - "y": null, + "x": 1599718950000, + "y": 1253376, }, Object { - "x": 1593413146000, - "y": null, + "x": 1599718980000, + "y": 822272, }, Object { - "x": 1593413147000, - "y": null, + "x": 1599719010000, + "y": 1540032, }, Object { - "x": 1593413148000, - "y": null, + "x": 1599719040000, + "y": 1269728, }, Object { - "x": 1593413149000, - "y": null, + "x": 1599719070000, + "y": 1531872, }, Object { - "x": 1593413150000, - "y": null, + "x": 1599719100000, + "y": 1507264, }, Object { - "x": 1593413151000, - "y": null, + "x": 1599719130000, + "y": 1216512, }, Object { - "x": 1593413152000, - "y": null, + "x": 1599719160000, + "y": 909248, }, Object { - "x": 1593413153000, - "y": null, + "x": 1599719190000, + "y": 1097600, }, Object { - "x": 1593413154000, - "y": null, + "x": 1599719220000, + "y": 786416, }, Object { - "x": 1593413155000, + "x": 1599719250000, "y": null, }, Object { - "x": 1593413156000, - "y": null, + "x": 1599719280000, + "y": 1212352, }, Object { - "x": 1593413157000, - "y": null, - }, - Object { - "x": 1593413158000, - "y": null, - }, - Object { - "x": 1593413159000, - "y": null, - }, - Object { - "x": 1593413160000, - "y": null, - }, - Object { - "x": 1593413161000, - "y": null, - }, - Object { - "x": 1593413162000, - "y": null, - }, - Object { - "x": 1593413163000, - "y": null, - }, - Object { - "x": 1593413164000, - "y": null, - }, - Object { - "x": 1593413165000, - "y": null, - }, - Object { - "x": 1593413166000, - "y": null, - }, - Object { - "x": 1593413167000, - "y": null, - }, - Object { - "x": 1593413168000, - "y": null, - }, - Object { - "x": 1593413169000, - "y": null, - }, - Object { - "x": 1593413170000, - "y": null, - }, - Object { - "x": 1593413171000, - "y": null, - }, - Object { - "x": 1593413172000, - "y": null, - }, - Object { - "x": 1593413173000, - "y": null, - }, - Object { - "x": 1593413174000, - "y": null, - }, - Object { - "x": 1593413175000, - "y": null, - }, - Object { - "x": 1593413176000, - "y": null, - }, - Object { - "x": 1593413177000, - "y": null, - }, - Object { - "x": 1593413178000, - "y": null, - }, - Object { - "x": 1593413179000, - "y": null, - }, - Object { - "x": 1593413180000, - "y": null, - }, - Object { - "x": 1593413181000, - "y": null, - }, - Object { - "x": 1593413182000, - "y": null, - }, - Object { - "x": 1593413183000, - "y": null, - }, - Object { - "x": 1593413184000, - "y": null, - }, - Object { - "x": 1593413185000, - "y": null, - }, - Object { - "x": 1593413186000, - "y": null, - }, - Object { - "x": 1593413187000, - "y": null, - }, - Object { - "x": 1593413188000, - "y": null, - }, - Object { - "x": 1593413189000, - "y": null, - }, - Object { - "x": 1593413190000, - "y": null, - }, - Object { - "x": 1593413191000, - "y": null, - }, - Object { - "x": 1593413192000, - "y": null, - }, - Object { - "x": 1593413193000, - "y": null, - }, - Object { - "x": 1593413194000, - "y": null, - }, - Object { - "x": 1593413195000, - "y": null, - }, - Object { - "x": 1593413196000, - "y": null, - }, - Object { - "x": 1593413197000, - "y": null, - }, - Object { - "x": 1593413198000, - "y": null, - }, - Object { - "x": 1593413199000, - "y": null, - }, - Object { - "x": 1593413200000, - "y": null, - }, - Object { - "x": 1593413201000, - "y": null, - }, - Object { - "x": 1593413202000, - "y": null, - }, - Object { - "x": 1593413203000, - "y": null, - }, - Object { - "x": 1593413204000, - "y": null, - }, - Object { - "x": 1593413205000, - "y": null, - }, - Object { - "x": 1593413206000, - "y": null, - }, - Object { - "x": 1593413207000, - "y": null, - }, - Object { - "x": 1593413208000, - "y": null, - }, - Object { - "x": 1593413209000, - "y": null, - }, - Object { - "x": 1593413210000, - "y": null, - }, - Object { - "x": 1593413211000, - "y": null, - }, - Object { - "x": 1593413212000, - "y": null, - }, - Object { - "x": 1593413213000, - "y": null, - }, - Object { - "x": 1593413214000, - "y": null, - }, - Object { - "x": 1593413215000, - "y": null, - }, - Object { - "x": 1593413216000, - "y": null, - }, - Object { - "x": 1593413217000, - "y": null, - }, - Object { - "x": 1593413218000, - "y": null, - }, - Object { - "x": 1593413219000, - "y": null, - }, - Object { - "x": 1593413220000, - "y": null, - }, - Object { - "x": 1593413221000, - "y": null, - }, - Object { - "x": 1593413222000, - "y": null, - }, - Object { - "x": 1593413223000, - "y": null, - }, - Object { - "x": 1593413224000, - "y": null, + "x": 1599719310000, + "y": 19040, }, Object { - "x": 1593413225000, - "y": null, + "x": 1599719340000, + "y": 1077248, }, Object { - "x": 1593413226000, - "y": null, + "x": 1599719370000, + "y": 1146880, }, Object { - "x": 1593413227000, - "y": null, + "x": 1599719400000, + "y": 1908672, }, Object { - "x": 1593413228000, - "y": null, + "x": 1599719430000, + "y": 1261504, }, Object { - "x": 1593413229000, - "y": null, + "x": 1599719460000, + "y": 1617920, }, Object { - "x": 1593413230000, - "y": null, + "x": 1599719490000, + "y": 1105664, }, Object { - "x": 1593413231000, - "y": null, + "x": 1599719520000, + "y": 1163008, }, Object { - "x": 1593413232000, - "y": null, + "x": 1599719550000, + "y": 892928, }, Object { - "x": 1593413233000, - "y": null, + "x": 1599719580000, + "y": 1343360, }, Object { - "x": 1593413234000, - "y": null, + "x": 1599719610000, + "y": 925696, }, Object { - "x": 1593413235000, - "y": null, + "x": 1599719640000, + "y": 1277936, }, Object { - "x": 1593413236000, - "y": null, + "x": 1599719670000, + "y": 1499072, }, Object { - "x": 1593413237000, + "x": 1599719700000, "y": null, }, Object { - "x": 1593413238000, - "y": null, + "x": 1599719730000, + "y": 1204096, }, Object { - "x": 1593413239000, - "y": null, + "x": 1599719760000, + "y": 1572800, }, Object { - "x": 1593413240000, - "y": null, + "x": 1599719790000, + "y": 1097728, }, Object { - "x": 1593413241000, - "y": null, + "x": 1599719820000, + "y": 1376128, }, Object { - "x": 1593413242000, - "y": null, + "x": 1599719850000, + "y": 1277952, }, Object { - "x": 1593413243000, - "y": null, + "x": 1599719880000, + "y": 815072, }, Object { - "x": 1593413244000, - "y": null, + "x": 1599719910000, + "y": 1765376, }, Object { - "x": 1593413245000, - "y": null, + "x": 1599719940000, + "y": 937984, }, Object { - "x": 1593413246000, - "y": null, + "x": 1599719970000, + "y": 1687488, }, Object { - "x": 1593413247000, - "y": null, + "x": 1599720000000, + "y": 1212352, }, Object { - "x": 1593413248000, - "y": null, + "x": 1599720030000, + "y": 1441728, }, Object { - "x": 1593413249000, - "y": null, + "x": 1599720060000, + "y": 970624, }, Object { - "x": 1593413250000, - "y": null, + "x": 1599720090000, + "y": 1409024, }, Object { - "x": 1593413251000, - "y": null, + "x": 1599720120000, + "y": 1564672, }, Object { - "x": 1593413252000, - "y": null, + "x": 1599720150000, + "y": 1447936, }, Object { - "x": 1593413253000, - "y": null, + "x": 1599720180000, + "y": 1195904, }, Object { - "x": 1593413254000, - "y": null, + "x": 1599720210000, + "y": 1474560, }, Object { - "x": 1593413255000, - "y": null, + "x": 1599720240000, + "y": 1220544, }, Object { - "x": 1593413256000, - "y": null, + "x": 1599720270000, + "y": 1261504, }, Object { - "x": 1593413257000, - "y": null, + "x": 1599720300000, + "y": 1712064, }, Object { - "x": 1593413258000, - "y": null, + "x": 1599720330000, + "y": 1622016, }, Object { - "x": 1593413259000, - "y": null, + "x": 1599720360000, + "y": 1245120, }, Object { - "x": 1593413260000, - "y": null, + "x": 1599720390000, + "y": 1646560, }, Object { - "x": 1593413261000, - "y": null, + "x": 1599720420000, + "y": 970688, }, Object { - "x": 1593413262000, - "y": null, + "x": 1599720450000, + "y": 1228800, }, Object { - "x": 1593413263000, - "y": null, + "x": 1599720480000, + "y": 1191936, }, Object { - "x": 1593413264000, - "y": null, + "x": 1599720510000, + "y": 1572832, }, Object { - "x": 1593413265000, - "y": null, + "x": 1599720540000, + "y": 1200128, }, Object { - "x": 1593413266000, - "y": null, + "x": 1599720570000, + "y": 1071104, }, Object { - "x": 1593413267000, - "y": null, + "x": 1599720600000, + "y": 1130368, }, Object { - "x": 1593413268000, - "y": null, + "x": 1599720630000, + "y": 933824, }, Object { - "x": 1593413269000, - "y": null, + "x": 1599720660000, + "y": 1220544, }, Object { - "x": 1593413270000, - "y": null, + "x": 1599720690000, + "y": 337920, }, Object { - "x": 1593413271000, - "y": null, + "x": 1599720720000, + "y": 1032128, }, Object { - "x": 1593413272000, - "y": 45056, + "x": 1599720750000, + "y": 1736672, }, Object { - "x": 1593413273000, - "y": 10080, + "x": 1599720780000, + "y": 1843136, }, Object { - "x": 1593413274000, - "y": null, + "x": 1599720810000, + "y": 1404928, }, Object { - "x": 1593413275000, - "y": null, + "x": 1599720840000, + "y": 1036160, }, Object { - "x": 1593413276000, - "y": null, + "x": 1599720870000, + "y": 1351552, }, Object { - "x": 1593413277000, - "y": 37632, + "x": 1599720900000, + "y": 720864, }, Object { - "x": 1593413278000, - "y": null, + "x": 1599720930000, + "y": 966656, }, Object { - "x": 1593413279000, - "y": null, + "x": 1599720960000, + "y": 1892224, }, Object { - "x": 1593413280000, - "y": null, + "x": 1599720990000, + "y": 1384320, }, Object { - "x": 1593413281000, - "y": 33024, + "x": 1599721020000, + "y": 1540032, }, Object { - "x": 1593413282000, - "y": null, + "x": 1599721050000, + "y": 451584, }, Object { - "x": 1593413283000, - "y": null, + "x": 1599721080000, + "y": 1228768, }, Object { - "x": 1593413284000, - "y": 761728, - }, - Object { - "x": 1593413285000, - "y": 81904, - }, - Object { - "x": 1593413286000, - "y": 358384, - }, - Object { - "x": 1593413287000, - "y": 36088, - }, - Object { - "x": 1593413288000, - "y": 44536, - }, - Object { - "x": 1593413289000, - "y": 11648, - }, - Object { - "x": 1593413290000, - "y": 31984, - }, - Object { - "x": 1593413291000, - "y": 2920, - }, - Object { - "x": 1593413292000, - "y": 9312, - }, - Object { - "x": 1593413293000, - "y": 10912, - }, - Object { - "x": 1593413294000, - "y": 6392, - }, - Object { - "x": 1593413295000, - "y": 11704, - }, - Object { - "x": 1593413296000, - "y": 10816, - }, - Object { - "x": 1593413297000, - "y": 12000, - }, - Object { - "x": 1593413298000, - "y": 15164, - }, - Object { - "x": 1593413299000, - "y": 3216, - }, - Object { - "x": 1593413300000, - "y": 9584, - }, - Object { - "x": 1593413301000, - "y": 21240, - }, - Object { - "x": 1593413302000, - "y": 5624, - }, - Object { - "x": 1593413303000, - "y": 11360, - }, - Object { - "x": 1593413304000, - "y": 12320, - }, - Object { - "x": 1593413305000, - "y": 38640, - }, - Object { - "x": 1593413306000, - "y": 9728, - }, - Object { - "x": 1593413307000, - "y": 17016, - }, - Object { - "x": 1593413308000, - "y": 26848, - }, - Object { - "x": 1593413309000, - "y": 1753072, - }, - Object { - "x": 1593413310000, - "y": 16992, - }, - Object { - "x": 1593413311000, - "y": 26560, - }, - Object { - "x": 1593413312000, - "y": 11232, - }, - Object { - "x": 1593413313000, - "y": 11424, - }, - Object { - "x": 1593413314000, - "y": 16096, - }, - Object { - "x": 1593413315000, - "y": 18800, - }, - Object { - "x": 1593413316000, - "y": 12672, - }, - Object { - "x": 1593413317000, - "y": 24316, - }, - Object { - "x": 1593413318000, - "y": 8944, - }, - Object { - "x": 1593413319000, - "y": 272352, - }, - Object { - "x": 1593413320000, - "y": 7992, - }, - Object { - "x": 1593413321000, - "y": 8368, - }, - Object { - "x": 1593413322000, - "y": 1928, - }, - Object { - "x": 1593413323000, - "y": null, - }, - Object { - "x": 1593413324000, - "y": null, - }, - Object { - "x": 1593413325000, - "y": null, - }, - Object { - "x": 1593413326000, - "y": null, - }, - Object { - "x": 1593413327000, - "y": null, - }, - Object { - "x": 1593413328000, - "y": null, - }, - Object { - "x": 1593413329000, - "y": null, - }, - Object { - "x": 1593413330000, - "y": null, - }, - Object { - "x": 1593413331000, - "y": null, - }, - Object { - "x": 1593413332000, - "y": null, - }, - Object { - "x": 1593413333000, - "y": null, - }, - Object { - "x": 1593413334000, - "y": null, - }, - Object { - "x": 1593413335000, - "y": null, - }, - Object { - "x": 1593413336000, - "y": null, - }, - Object { - "x": 1593413337000, - "y": null, - }, - Object { - "x": 1593413338000, - "y": null, - }, - Object { - "x": 1593413339000, - "y": null, - }, - Object { - "x": 1593413340000, - "y": null, - }, - ], - "p99": Array [ - Object { - "x": 1593413100000, - "y": null, - }, - Object { - "x": 1593413101000, - "y": null, - }, - Object { - "x": 1593413102000, - "y": null, - }, - Object { - "x": 1593413103000, - "y": null, - }, - Object { - "x": 1593413104000, - "y": null, - }, - Object { - "x": 1593413105000, - "y": null, - }, - Object { - "x": 1593413106000, - "y": null, - }, - Object { - "x": 1593413107000, - "y": null, - }, - Object { - "x": 1593413108000, - "y": null, - }, - Object { - "x": 1593413109000, - "y": null, - }, - Object { - "x": 1593413110000, - "y": null, - }, - Object { - "x": 1593413111000, - "y": null, - }, - Object { - "x": 1593413112000, - "y": null, - }, - Object { - "x": 1593413113000, - "y": null, - }, - Object { - "x": 1593413114000, - "y": null, - }, - Object { - "x": 1593413115000, - "y": null, - }, - Object { - "x": 1593413116000, - "y": null, - }, - Object { - "x": 1593413117000, - "y": null, - }, - Object { - "x": 1593413118000, - "y": null, - }, - Object { - "x": 1593413119000, - "y": null, - }, - Object { - "x": 1593413120000, - "y": null, - }, - Object { - "x": 1593413121000, - "y": null, - }, - Object { - "x": 1593413122000, - "y": null, - }, - Object { - "x": 1593413123000, - "y": null, - }, - Object { - "x": 1593413124000, - "y": null, - }, - Object { - "x": 1593413125000, - "y": null, - }, - Object { - "x": 1593413126000, - "y": null, - }, - Object { - "x": 1593413127000, - "y": null, - }, - Object { - "x": 1593413128000, - "y": null, - }, - Object { - "x": 1593413129000, - "y": null, - }, - Object { - "x": 1593413130000, - "y": null, - }, - Object { - "x": 1593413131000, - "y": null, - }, - Object { - "x": 1593413132000, - "y": null, - }, - Object { - "x": 1593413133000, - "y": null, - }, - Object { - "x": 1593413134000, - "y": null, - }, - Object { - "x": 1593413135000, - "y": null, - }, - Object { - "x": 1593413136000, - "y": null, - }, - Object { - "x": 1593413137000, - "y": null, - }, - Object { - "x": 1593413138000, - "y": null, - }, - Object { - "x": 1593413139000, - "y": null, - }, - Object { - "x": 1593413140000, - "y": null, - }, - Object { - "x": 1593413141000, - "y": null, - }, - Object { - "x": 1593413142000, - "y": null, - }, - Object { - "x": 1593413143000, - "y": null, - }, - Object { - "x": 1593413144000, - "y": null, - }, - Object { - "x": 1593413145000, - "y": null, - }, - Object { - "x": 1593413146000, - "y": null, - }, - Object { - "x": 1593413147000, - "y": null, - }, - Object { - "x": 1593413148000, - "y": null, - }, - Object { - "x": 1593413149000, - "y": null, - }, - Object { - "x": 1593413150000, - "y": null, - }, - Object { - "x": 1593413151000, - "y": null, - }, - Object { - "x": 1593413152000, - "y": null, - }, - Object { - "x": 1593413153000, - "y": null, - }, - Object { - "x": 1593413154000, - "y": null, - }, - Object { - "x": 1593413155000, - "y": null, - }, - Object { - "x": 1593413156000, - "y": null, - }, - Object { - "x": 1593413157000, - "y": null, - }, - Object { - "x": 1593413158000, - "y": null, - }, - Object { - "x": 1593413159000, - "y": null, - }, - Object { - "x": 1593413160000, - "y": null, - }, - Object { - "x": 1593413161000, - "y": null, - }, - Object { - "x": 1593413162000, - "y": null, - }, - Object { - "x": 1593413163000, - "y": null, - }, - Object { - "x": 1593413164000, - "y": null, - }, - Object { - "x": 1593413165000, - "y": null, - }, - Object { - "x": 1593413166000, - "y": null, - }, - Object { - "x": 1593413167000, - "y": null, - }, - Object { - "x": 1593413168000, - "y": null, - }, - Object { - "x": 1593413169000, - "y": null, - }, - Object { - "x": 1593413170000, - "y": null, - }, - Object { - "x": 1593413171000, - "y": null, - }, - Object { - "x": 1593413172000, - "y": null, - }, - Object { - "x": 1593413173000, - "y": null, - }, - Object { - "x": 1593413174000, - "y": null, - }, - Object { - "x": 1593413175000, - "y": null, - }, - Object { - "x": 1593413176000, - "y": null, - }, - Object { - "x": 1593413177000, - "y": null, - }, - Object { - "x": 1593413178000, - "y": null, - }, - Object { - "x": 1593413179000, - "y": null, - }, - Object { - "x": 1593413180000, - "y": null, - }, - Object { - "x": 1593413181000, - "y": null, - }, - Object { - "x": 1593413182000, - "y": null, - }, - Object { - "x": 1593413183000, - "y": null, - }, - Object { - "x": 1593413184000, - "y": null, - }, - Object { - "x": 1593413185000, - "y": null, - }, - Object { - "x": 1593413186000, - "y": null, - }, - Object { - "x": 1593413187000, - "y": null, - }, - Object { - "x": 1593413188000, - "y": null, - }, - Object { - "x": 1593413189000, - "y": null, - }, - Object { - "x": 1593413190000, - "y": null, - }, - Object { - "x": 1593413191000, - "y": null, - }, - Object { - "x": 1593413192000, - "y": null, - }, - Object { - "x": 1593413193000, - "y": null, - }, - Object { - "x": 1593413194000, - "y": null, - }, - Object { - "x": 1593413195000, - "y": null, - }, - Object { - "x": 1593413196000, - "y": null, - }, - Object { - "x": 1593413197000, - "y": null, - }, - Object { - "x": 1593413198000, - "y": null, - }, - Object { - "x": 1593413199000, - "y": null, - }, - Object { - "x": 1593413200000, - "y": null, - }, - Object { - "x": 1593413201000, - "y": null, - }, - Object { - "x": 1593413202000, - "y": null, - }, - Object { - "x": 1593413203000, - "y": null, - }, - Object { - "x": 1593413204000, - "y": null, - }, - Object { - "x": 1593413205000, - "y": null, - }, - Object { - "x": 1593413206000, - "y": null, - }, - Object { - "x": 1593413207000, - "y": null, - }, - Object { - "x": 1593413208000, - "y": null, - }, - Object { - "x": 1593413209000, - "y": null, - }, - Object { - "x": 1593413210000, - "y": null, - }, - Object { - "x": 1593413211000, - "y": null, - }, - Object { - "x": 1593413212000, - "y": null, - }, - Object { - "x": 1593413213000, - "y": null, - }, - Object { - "x": 1593413214000, - "y": null, - }, - Object { - "x": 1593413215000, - "y": null, - }, - Object { - "x": 1593413216000, - "y": null, - }, - Object { - "x": 1593413217000, - "y": null, - }, - Object { - "x": 1593413218000, - "y": null, - }, - Object { - "x": 1593413219000, - "y": null, - }, - Object { - "x": 1593413220000, - "y": null, - }, - Object { - "x": 1593413221000, - "y": null, - }, - Object { - "x": 1593413222000, - "y": null, - }, - Object { - "x": 1593413223000, - "y": null, - }, - Object { - "x": 1593413224000, - "y": null, - }, - Object { - "x": 1593413225000, - "y": null, - }, - Object { - "x": 1593413226000, - "y": null, - }, - Object { - "x": 1593413227000, - "y": null, - }, - Object { - "x": 1593413228000, - "y": null, - }, - Object { - "x": 1593413229000, - "y": null, - }, - Object { - "x": 1593413230000, - "y": null, - }, - Object { - "x": 1593413231000, - "y": null, - }, - Object { - "x": 1593413232000, - "y": null, - }, - Object { - "x": 1593413233000, - "y": null, - }, - Object { - "x": 1593413234000, - "y": null, - }, - Object { - "x": 1593413235000, - "y": null, - }, - Object { - "x": 1593413236000, - "y": null, - }, - Object { - "x": 1593413237000, - "y": null, - }, - Object { - "x": 1593413238000, - "y": null, - }, - Object { - "x": 1593413239000, - "y": null, - }, - Object { - "x": 1593413240000, - "y": null, - }, - Object { - "x": 1593413241000, - "y": null, - }, - Object { - "x": 1593413242000, - "y": null, - }, - Object { - "x": 1593413243000, - "y": null, - }, - Object { - "x": 1593413244000, - "y": null, - }, - Object { - "x": 1593413245000, - "y": null, - }, - Object { - "x": 1593413246000, - "y": null, - }, - Object { - "x": 1593413247000, - "y": null, - }, - Object { - "x": 1593413248000, - "y": null, - }, - Object { - "x": 1593413249000, - "y": null, - }, - Object { - "x": 1593413250000, - "y": null, - }, - Object { - "x": 1593413251000, - "y": null, - }, - Object { - "x": 1593413252000, - "y": null, - }, - Object { - "x": 1593413253000, - "y": null, - }, - Object { - "x": 1593413254000, - "y": null, - }, - Object { - "x": 1593413255000, - "y": null, - }, - Object { - "x": 1593413256000, - "y": null, - }, - Object { - "x": 1593413257000, - "y": null, - }, - Object { - "x": 1593413258000, - "y": null, - }, - Object { - "x": 1593413259000, - "y": null, - }, - Object { - "x": 1593413260000, - "y": null, - }, - Object { - "x": 1593413261000, - "y": null, - }, - Object { - "x": 1593413262000, - "y": null, - }, - Object { - "x": 1593413263000, - "y": null, - }, - Object { - "x": 1593413264000, - "y": null, - }, - Object { - "x": 1593413265000, - "y": null, - }, - Object { - "x": 1593413266000, - "y": null, - }, - Object { - "x": 1593413267000, - "y": null, - }, - Object { - "x": 1593413268000, - "y": null, - }, - Object { - "x": 1593413269000, - "y": null, - }, - Object { - "x": 1593413270000, - "y": null, - }, - Object { - "x": 1593413271000, - "y": null, - }, - Object { - "x": 1593413272000, - "y": 45056, - }, - Object { - "x": 1593413273000, - "y": 10080, - }, - Object { - "x": 1593413274000, - "y": null, - }, - Object { - "x": 1593413275000, - "y": null, - }, - Object { - "x": 1593413276000, - "y": null, - }, - Object { - "x": 1593413277000, - "y": 37632, - }, - Object { - "x": 1593413278000, - "y": null, - }, - Object { - "x": 1593413279000, - "y": null, - }, - Object { - "x": 1593413280000, - "y": null, - }, - Object { - "x": 1593413281000, - "y": 33024, - }, - Object { - "x": 1593413282000, - "y": null, - }, - Object { - "x": 1593413283000, - "y": null, - }, - Object { - "x": 1593413284000, - "y": 761728, - }, - Object { - "x": 1593413285000, - "y": 81904, - }, - Object { - "x": 1593413286000, - "y": 358384, - }, - Object { - "x": 1593413287000, - "y": 36088, - }, - Object { - "x": 1593413288000, - "y": 44536, - }, - Object { - "x": 1593413289000, - "y": 11648, - }, - Object { - "x": 1593413290000, - "y": 31984, - }, - Object { - "x": 1593413291000, - "y": 2920, - }, - Object { - "x": 1593413292000, - "y": 9312, - }, - Object { - "x": 1593413293000, - "y": 10912, - }, - Object { - "x": 1593413294000, - "y": 6392, - }, - Object { - "x": 1593413295000, - "y": 11704, - }, - Object { - "x": 1593413296000, - "y": 10816, - }, - Object { - "x": 1593413297000, - "y": 12000, - }, - Object { - "x": 1593413298000, - "y": 15164, - }, - Object { - "x": 1593413299000, - "y": 3216, - }, - Object { - "x": 1593413300000, - "y": 9584, - }, - Object { - "x": 1593413301000, - "y": 21240, - }, - Object { - "x": 1593413302000, - "y": 5624, - }, - Object { - "x": 1593413303000, - "y": 11360, - }, - Object { - "x": 1593413304000, - "y": 12320, - }, - Object { - "x": 1593413305000, - "y": 38640, - }, - Object { - "x": 1593413306000, - "y": 9728, - }, - Object { - "x": 1593413307000, - "y": 17016, - }, - Object { - "x": 1593413308000, - "y": 26848, - }, - Object { - "x": 1593413309000, - "y": 1753072, - }, - Object { - "x": 1593413310000, - "y": 16992, - }, - Object { - "x": 1593413311000, - "y": 26560, - }, - Object { - "x": 1593413312000, - "y": 11232, - }, - Object { - "x": 1593413313000, - "y": 11424, - }, - Object { - "x": 1593413314000, - "y": 16096, - }, - Object { - "x": 1593413315000, - "y": 18800, - }, - Object { - "x": 1593413316000, - "y": 12672, - }, - Object { - "x": 1593413317000, - "y": 24316, - }, - Object { - "x": 1593413318000, - "y": 8944, - }, - Object { - "x": 1593413319000, - "y": 272352, - }, - Object { - "x": 1593413320000, - "y": 7992, - }, - Object { - "x": 1593413321000, - "y": 8368, - }, - Object { - "x": 1593413322000, - "y": 1928, - }, - Object { - "x": 1593413323000, - "y": null, - }, - Object { - "x": 1593413324000, - "y": null, - }, - Object { - "x": 1593413325000, - "y": null, - }, - Object { - "x": 1593413326000, - "y": null, - }, - Object { - "x": 1593413327000, - "y": null, - }, - Object { - "x": 1593413328000, - "y": null, - }, - Object { - "x": 1593413329000, - "y": null, - }, - Object { - "x": 1593413330000, - "y": null, - }, - Object { - "x": 1593413331000, - "y": null, - }, - Object { - "x": 1593413332000, - "y": null, - }, - Object { - "x": 1593413333000, - "y": null, - }, - Object { - "x": 1593413334000, - "y": null, - }, - Object { - "x": 1593413335000, - "y": null, - }, - Object { - "x": 1593413336000, - "y": null, - }, - Object { - "x": 1593413337000, - "y": null, - }, - Object { - "x": 1593413338000, - "y": null, - }, - Object { - "x": 1593413339000, - "y": null, - }, - Object { - "x": 1593413340000, - "y": null, - }, - ], - }, - "tpmBuckets": Array [ - Object { - "avg": 24.75, - "dataPoints": Array [ - Object { - "x": 1593413100000, - "y": 0, - }, - Object { - "x": 1593413101000, - "y": 0, - }, - Object { - "x": 1593413102000, - "y": 0, - }, - Object { - "x": 1593413103000, - "y": 0, - }, - Object { - "x": 1593413104000, - "y": 0, - }, - Object { - "x": 1593413105000, - "y": 0, - }, - Object { - "x": 1593413106000, - "y": 0, - }, - Object { - "x": 1593413107000, - "y": 0, - }, - Object { - "x": 1593413108000, - "y": 0, - }, - Object { - "x": 1593413109000, - "y": 0, - }, - Object { - "x": 1593413110000, - "y": 0, - }, - Object { - "x": 1593413111000, - "y": 0, - }, - Object { - "x": 1593413112000, - "y": 0, - }, - Object { - "x": 1593413113000, - "y": 0, - }, - Object { - "x": 1593413114000, - "y": 0, - }, - Object { - "x": 1593413115000, - "y": 0, - }, - Object { - "x": 1593413116000, - "y": 0, - }, - Object { - "x": 1593413117000, - "y": 0, - }, - Object { - "x": 1593413118000, - "y": 0, - }, - Object { - "x": 1593413119000, - "y": 0, - }, - Object { - "x": 1593413120000, - "y": 0, - }, - Object { - "x": 1593413121000, - "y": 0, - }, - Object { - "x": 1593413122000, - "y": 0, - }, - Object { - "x": 1593413123000, - "y": 0, - }, - Object { - "x": 1593413124000, - "y": 0, - }, - Object { - "x": 1593413125000, - "y": 0, - }, - Object { - "x": 1593413126000, - "y": 0, - }, - Object { - "x": 1593413127000, - "y": 0, - }, - Object { - "x": 1593413128000, - "y": 0, - }, - Object { - "x": 1593413129000, - "y": 0, - }, - Object { - "x": 1593413130000, - "y": 0, - }, - Object { - "x": 1593413131000, - "y": 0, - }, - Object { - "x": 1593413132000, - "y": 0, - }, - Object { - "x": 1593413133000, - "y": 0, - }, - Object { - "x": 1593413134000, - "y": 0, - }, - Object { - "x": 1593413135000, - "y": 0, - }, - Object { - "x": 1593413136000, - "y": 0, - }, - Object { - "x": 1593413137000, - "y": 0, - }, - Object { - "x": 1593413138000, - "y": 0, - }, - Object { - "x": 1593413139000, - "y": 0, - }, - Object { - "x": 1593413140000, - "y": 0, - }, - Object { - "x": 1593413141000, - "y": 0, - }, - Object { - "x": 1593413142000, - "y": 0, - }, - Object { - "x": 1593413143000, - "y": 0, - }, - Object { - "x": 1593413144000, - "y": 0, - }, - Object { - "x": 1593413145000, - "y": 0, - }, - Object { - "x": 1593413146000, - "y": 0, - }, - Object { - "x": 1593413147000, - "y": 0, - }, - Object { - "x": 1593413148000, - "y": 0, - }, - Object { - "x": 1593413149000, - "y": 0, - }, - Object { - "x": 1593413150000, - "y": 0, - }, - Object { - "x": 1593413151000, - "y": 0, - }, - Object { - "x": 1593413152000, - "y": 0, - }, - Object { - "x": 1593413153000, - "y": 0, - }, - Object { - "x": 1593413154000, - "y": 0, - }, - Object { - "x": 1593413155000, - "y": 0, - }, - Object { - "x": 1593413156000, - "y": 0, - }, - Object { - "x": 1593413157000, - "y": 0, - }, - Object { - "x": 1593413158000, - "y": 0, - }, - Object { - "x": 1593413159000, - "y": 0, - }, - Object { - "x": 1593413160000, - "y": 0, - }, - Object { - "x": 1593413161000, - "y": 0, - }, - Object { - "x": 1593413162000, - "y": 0, - }, - Object { - "x": 1593413163000, - "y": 0, - }, - Object { - "x": 1593413164000, - "y": 0, - }, - Object { - "x": 1593413165000, - "y": 0, - }, - Object { - "x": 1593413166000, - "y": 0, - }, - Object { - "x": 1593413167000, - "y": 0, - }, - Object { - "x": 1593413168000, - "y": 0, - }, - Object { - "x": 1593413169000, - "y": 0, - }, - Object { - "x": 1593413170000, - "y": 0, - }, - Object { - "x": 1593413171000, - "y": 0, - }, - Object { - "x": 1593413172000, - "y": 0, - }, - Object { - "x": 1593413173000, - "y": 0, - }, - Object { - "x": 1593413174000, - "y": 0, - }, - Object { - "x": 1593413175000, - "y": 0, - }, - Object { - "x": 1593413176000, - "y": 0, - }, - Object { - "x": 1593413177000, - "y": 0, - }, - Object { - "x": 1593413178000, - "y": 0, - }, - Object { - "x": 1593413179000, - "y": 0, - }, - Object { - "x": 1593413180000, - "y": 0, - }, - Object { - "x": 1593413181000, - "y": 0, - }, - Object { - "x": 1593413182000, - "y": 0, - }, - Object { - "x": 1593413183000, - "y": 0, - }, - Object { - "x": 1593413184000, - "y": 0, - }, - Object { - "x": 1593413185000, - "y": 0, - }, - Object { - "x": 1593413186000, - "y": 0, - }, - Object { - "x": 1593413187000, - "y": 0, - }, - Object { - "x": 1593413188000, - "y": 0, - }, - Object { - "x": 1593413189000, - "y": 0, - }, - Object { - "x": 1593413190000, - "y": 0, - }, - Object { - "x": 1593413191000, - "y": 0, - }, - Object { - "x": 1593413192000, - "y": 0, - }, - Object { - "x": 1593413193000, - "y": 0, - }, - Object { - "x": 1593413194000, - "y": 0, - }, - Object { - "x": 1593413195000, - "y": 0, - }, - Object { - "x": 1593413196000, - "y": 0, - }, - Object { - "x": 1593413197000, - "y": 0, - }, - Object { - "x": 1593413198000, - "y": 0, - }, - Object { - "x": 1593413199000, - "y": 0, - }, - Object { - "x": 1593413200000, - "y": 0, - }, - Object { - "x": 1593413201000, - "y": 0, - }, - Object { - "x": 1593413202000, - "y": 0, - }, - Object { - "x": 1593413203000, - "y": 0, - }, - Object { - "x": 1593413204000, - "y": 0, - }, - Object { - "x": 1593413205000, - "y": 0, - }, - Object { - "x": 1593413206000, - "y": 0, - }, - Object { - "x": 1593413207000, - "y": 0, - }, - Object { - "x": 1593413208000, - "y": 0, - }, - Object { - "x": 1593413209000, - "y": 0, - }, - Object { - "x": 1593413210000, - "y": 0, - }, - Object { - "x": 1593413211000, - "y": 0, - }, - Object { - "x": 1593413212000, - "y": 0, - }, - Object { - "x": 1593413213000, - "y": 0, - }, - Object { - "x": 1593413214000, - "y": 0, - }, - Object { - "x": 1593413215000, - "y": 0, - }, - Object { - "x": 1593413216000, - "y": 0, - }, - Object { - "x": 1593413217000, - "y": 0, - }, - Object { - "x": 1593413218000, - "y": 0, - }, - Object { - "x": 1593413219000, - "y": 0, - }, - Object { - "x": 1593413220000, - "y": 0, - }, - Object { - "x": 1593413221000, - "y": 0, - }, - Object { - "x": 1593413222000, - "y": 0, - }, - Object { - "x": 1593413223000, - "y": 0, - }, - Object { - "x": 1593413224000, - "y": 0, - }, - Object { - "x": 1593413225000, - "y": 0, - }, - Object { - "x": 1593413226000, - "y": 0, - }, - Object { - "x": 1593413227000, - "y": 0, - }, - Object { - "x": 1593413228000, - "y": 0, - }, - Object { - "x": 1593413229000, - "y": 0, - }, - Object { - "x": 1593413230000, - "y": 0, - }, - Object { - "x": 1593413231000, - "y": 0, - }, - Object { - "x": 1593413232000, - "y": 0, - }, - Object { - "x": 1593413233000, - "y": 0, - }, - Object { - "x": 1593413234000, - "y": 0, - }, - Object { - "x": 1593413235000, - "y": 0, - }, - Object { - "x": 1593413236000, - "y": 0, - }, - Object { - "x": 1593413237000, - "y": 0, - }, - Object { - "x": 1593413238000, - "y": 0, - }, - Object { - "x": 1593413239000, - "y": 0, - }, - Object { - "x": 1593413240000, - "y": 0, - }, - Object { - "x": 1593413241000, - "y": 0, - }, - Object { - "x": 1593413242000, - "y": 0, - }, - Object { - "x": 1593413243000, - "y": 0, - }, - Object { - "x": 1593413244000, - "y": 0, - }, - Object { - "x": 1593413245000, - "y": 0, - }, - Object { - "x": 1593413246000, - "y": 0, - }, - Object { - "x": 1593413247000, - "y": 0, - }, - Object { - "x": 1593413248000, - "y": 0, - }, - Object { - "x": 1593413249000, - "y": 0, - }, - Object { - "x": 1593413250000, - "y": 0, - }, - Object { - "x": 1593413251000, - "y": 0, - }, - Object { - "x": 1593413252000, - "y": 0, - }, - Object { - "x": 1593413253000, - "y": 0, - }, - Object { - "x": 1593413254000, - "y": 0, - }, - Object { - "x": 1593413255000, - "y": 0, - }, - Object { - "x": 1593413256000, - "y": 0, - }, - Object { - "x": 1593413257000, - "y": 0, - }, - Object { - "x": 1593413258000, - "y": 0, - }, - Object { - "x": 1593413259000, - "y": 0, - }, - Object { - "x": 1593413260000, - "y": 0, - }, - Object { - "x": 1593413261000, - "y": 0, - }, - Object { - "x": 1593413262000, - "y": 0, - }, - Object { - "x": 1593413263000, - "y": 0, - }, - Object { - "x": 1593413264000, - "y": 0, - }, - Object { - "x": 1593413265000, - "y": 0, - }, - Object { - "x": 1593413266000, - "y": 0, - }, - Object { - "x": 1593413267000, - "y": 0, - }, - Object { - "x": 1593413268000, - "y": 0, - }, - Object { - "x": 1593413269000, - "y": 0, - }, - Object { - "x": 1593413270000, - "y": 0, - }, - Object { - "x": 1593413271000, - "y": 0, - }, - Object { - "x": 1593413272000, - "y": 1, - }, - Object { - "x": 1593413273000, - "y": 2, - }, - Object { - "x": 1593413274000, - "y": 0, - }, - Object { - "x": 1593413275000, - "y": 0, - }, - Object { - "x": 1593413276000, - "y": 0, - }, - Object { - "x": 1593413277000, - "y": 1, - }, - Object { - "x": 1593413278000, - "y": 0, - }, - Object { - "x": 1593413279000, - "y": 0, - }, - Object { - "x": 1593413280000, - "y": 0, - }, - Object { - "x": 1593413281000, - "y": 1, - }, - Object { - "x": 1593413282000, - "y": 0, - }, - Object { - "x": 1593413283000, - "y": 0, - }, - Object { - "x": 1593413284000, - "y": 2, - }, - Object { - "x": 1593413285000, - "y": 2, - }, - Object { - "x": 1593413286000, - "y": 7, - }, - Object { - "x": 1593413287000, - "y": 1, - }, - Object { - "x": 1593413288000, - "y": 2, - }, - Object { - "x": 1593413289000, - "y": 1, - }, - Object { - "x": 1593413290000, - "y": 4, - }, - Object { - "x": 1593413291000, - "y": 2, - }, - Object { - "x": 1593413292000, - "y": 1, - }, - Object { - "x": 1593413293000, - "y": 2, - }, - Object { - "x": 1593413294000, - "y": 3, - }, - Object { - "x": 1593413295000, - "y": 2, - }, - Object { - "x": 1593413296000, - "y": 2, - }, - Object { - "x": 1593413297000, - "y": 2, - }, - Object { - "x": 1593413298000, - "y": 6, - }, - Object { - "x": 1593413299000, - "y": 1, - }, - Object { - "x": 1593413300000, - "y": 2, - }, - Object { - "x": 1593413301000, - "y": 3, - }, - Object { - "x": 1593413302000, - "y": 2, - }, - Object { - "x": 1593413303000, - "y": 2, - }, - Object { - "x": 1593413304000, - "y": 2, - }, - Object { - "x": 1593413305000, - "y": 1, - }, - Object { - "x": 1593413306000, - "y": 2, - }, - Object { - "x": 1593413307000, - "y": 3, - }, - Object { - "x": 1593413308000, - "y": 2, - }, - Object { - "x": 1593413309000, - "y": 2, - }, - Object { - "x": 1593413310000, - "y": 2, - }, - Object { - "x": 1593413311000, - "y": 1, - }, - Object { - "x": 1593413312000, - "y": 3, - }, - Object { - "x": 1593413313000, - "y": 3, - }, - Object { - "x": 1593413314000, - "y": 5, - }, - Object { - "x": 1593413315000, - "y": 2, - }, - Object { - "x": 1593413316000, - "y": 2, - }, - Object { - "x": 1593413317000, - "y": 6, - }, - Object { - "x": 1593413318000, - "y": 2, - }, - Object { - "x": 1593413319000, - "y": 2, - }, - Object { - "x": 1593413320000, - "y": 2, - }, - Object { - "x": 1593413321000, - "y": 2, - }, - Object { - "x": 1593413322000, - "y": 1, - }, - Object { - "x": 1593413323000, - "y": 0, - }, - Object { - "x": 1593413324000, - "y": 0, - }, - Object { - "x": 1593413325000, - "y": 0, - }, - Object { - "x": 1593413326000, - "y": 0, - }, - Object { - "x": 1593413327000, - "y": 0, - }, - Object { - "x": 1593413328000, - "y": 0, - }, - Object { - "x": 1593413329000, - "y": 0, - }, - Object { - "x": 1593413330000, - "y": 0, - }, - Object { - "x": 1593413331000, - "y": 0, - }, - Object { - "x": 1593413332000, - "y": 0, - }, - Object { - "x": 1593413333000, - "y": 0, - }, - Object { - "x": 1593413334000, - "y": 0, - }, - Object { - "x": 1593413335000, - "y": 0, - }, - Object { - "x": 1593413336000, - "y": 0, - }, - Object { - "x": 1593413337000, - "y": 0, - }, - Object { - "x": 1593413338000, - "y": 0, - }, - Object { - "x": 1593413339000, - "y": 0, - }, - Object { - "x": 1593413340000, - "y": 0, - }, - ], - "key": "HTTP 2xx", - }, - Object { - "avg": 1.75, - "dataPoints": Array [ - Object { - "x": 1593413100000, - "y": 0, - }, - Object { - "x": 1593413101000, - "y": 0, - }, - Object { - "x": 1593413102000, - "y": 0, - }, - Object { - "x": 1593413103000, - "y": 0, - }, - Object { - "x": 1593413104000, - "y": 0, - }, - Object { - "x": 1593413105000, - "y": 0, - }, - Object { - "x": 1593413106000, - "y": 0, - }, - Object { - "x": 1593413107000, - "y": 0, - }, - Object { - "x": 1593413108000, - "y": 0, - }, - Object { - "x": 1593413109000, - "y": 0, - }, - Object { - "x": 1593413110000, - "y": 0, - }, - Object { - "x": 1593413111000, - "y": 0, - }, - Object { - "x": 1593413112000, - "y": 0, - }, - Object { - "x": 1593413113000, - "y": 0, - }, - Object { - "x": 1593413114000, - "y": 0, - }, - Object { - "x": 1593413115000, - "y": 0, - }, - Object { - "x": 1593413116000, - "y": 0, - }, - Object { - "x": 1593413117000, - "y": 0, - }, - Object { - "x": 1593413118000, - "y": 0, - }, - Object { - "x": 1593413119000, - "y": 0, - }, - Object { - "x": 1593413120000, - "y": 0, - }, - Object { - "x": 1593413121000, - "y": 0, - }, - Object { - "x": 1593413122000, - "y": 0, - }, - Object { - "x": 1593413123000, - "y": 0, - }, - Object { - "x": 1593413124000, - "y": 0, - }, - Object { - "x": 1593413125000, - "y": 0, - }, - Object { - "x": 1593413126000, - "y": 0, - }, - Object { - "x": 1593413127000, - "y": 0, - }, - Object { - "x": 1593413128000, - "y": 0, - }, - Object { - "x": 1593413129000, - "y": 0, - }, - Object { - "x": 1593413130000, - "y": 0, - }, - Object { - "x": 1593413131000, - "y": 0, - }, - Object { - "x": 1593413132000, - "y": 0, - }, - Object { - "x": 1593413133000, - "y": 0, - }, - Object { - "x": 1593413134000, - "y": 0, - }, - Object { - "x": 1593413135000, - "y": 0, - }, - Object { - "x": 1593413136000, - "y": 0, - }, - Object { - "x": 1593413137000, - "y": 0, - }, - Object { - "x": 1593413138000, - "y": 0, - }, - Object { - "x": 1593413139000, - "y": 0, - }, - Object { - "x": 1593413140000, - "y": 0, - }, - Object { - "x": 1593413141000, - "y": 0, - }, - Object { - "x": 1593413142000, - "y": 0, - }, - Object { - "x": 1593413143000, - "y": 0, - }, - Object { - "x": 1593413144000, - "y": 0, - }, - Object { - "x": 1593413145000, - "y": 0, - }, - Object { - "x": 1593413146000, - "y": 0, - }, - Object { - "x": 1593413147000, - "y": 0, - }, - Object { - "x": 1593413148000, - "y": 0, - }, - Object { - "x": 1593413149000, - "y": 0, - }, - Object { - "x": 1593413150000, - "y": 0, - }, - Object { - "x": 1593413151000, - "y": 0, - }, - Object { - "x": 1593413152000, - "y": 0, - }, - Object { - "x": 1593413153000, - "y": 0, - }, - Object { - "x": 1593413154000, - "y": 0, - }, - Object { - "x": 1593413155000, - "y": 0, - }, - Object { - "x": 1593413156000, - "y": 0, - }, - Object { - "x": 1593413157000, - "y": 0, - }, - Object { - "x": 1593413158000, - "y": 0, - }, - Object { - "x": 1593413159000, - "y": 0, - }, - Object { - "x": 1593413160000, - "y": 0, - }, - Object { - "x": 1593413161000, - "y": 0, - }, - Object { - "x": 1593413162000, - "y": 0, - }, - Object { - "x": 1593413163000, - "y": 0, - }, - Object { - "x": 1593413164000, - "y": 0, - }, - Object { - "x": 1593413165000, - "y": 0, - }, - Object { - "x": 1593413166000, - "y": 0, - }, - Object { - "x": 1593413167000, - "y": 0, - }, - Object { - "x": 1593413168000, - "y": 0, - }, - Object { - "x": 1593413169000, - "y": 0, - }, - Object { - "x": 1593413170000, - "y": 0, - }, - Object { - "x": 1593413171000, - "y": 0, - }, - Object { - "x": 1593413172000, - "y": 0, - }, - Object { - "x": 1593413173000, - "y": 0, - }, - Object { - "x": 1593413174000, - "y": 0, - }, - Object { - "x": 1593413175000, - "y": 0, - }, - Object { - "x": 1593413176000, - "y": 0, - }, - Object { - "x": 1593413177000, - "y": 0, - }, - Object { - "x": 1593413178000, - "y": 0, - }, - Object { - "x": 1593413179000, - "y": 0, - }, - Object { - "x": 1593413180000, - "y": 0, - }, - Object { - "x": 1593413181000, - "y": 0, - }, - Object { - "x": 1593413182000, - "y": 0, - }, - Object { - "x": 1593413183000, - "y": 0, - }, - Object { - "x": 1593413184000, - "y": 0, - }, - Object { - "x": 1593413185000, - "y": 0, - }, - Object { - "x": 1593413186000, - "y": 0, - }, - Object { - "x": 1593413187000, - "y": 0, - }, - Object { - "x": 1593413188000, - "y": 0, - }, - Object { - "x": 1593413189000, - "y": 0, - }, - Object { - "x": 1593413190000, - "y": 0, - }, - Object { - "x": 1593413191000, - "y": 0, - }, - Object { - "x": 1593413192000, - "y": 0, - }, - Object { - "x": 1593413193000, - "y": 0, - }, - Object { - "x": 1593413194000, - "y": 0, - }, - Object { - "x": 1593413195000, - "y": 0, - }, - Object { - "x": 1593413196000, - "y": 0, - }, - Object { - "x": 1593413197000, - "y": 0, - }, - Object { - "x": 1593413198000, - "y": 0, - }, - Object { - "x": 1593413199000, - "y": 0, - }, - Object { - "x": 1593413200000, - "y": 0, - }, - Object { - "x": 1593413201000, - "y": 0, - }, - Object { - "x": 1593413202000, - "y": 0, - }, - Object { - "x": 1593413203000, - "y": 0, - }, - Object { - "x": 1593413204000, - "y": 0, - }, - Object { - "x": 1593413205000, - "y": 0, - }, - Object { - "x": 1593413206000, - "y": 0, - }, - Object { - "x": 1593413207000, - "y": 0, - }, - Object { - "x": 1593413208000, - "y": 0, - }, - Object { - "x": 1593413209000, - "y": 0, - }, - Object { - "x": 1593413210000, - "y": 0, - }, - Object { - "x": 1593413211000, - "y": 0, - }, - Object { - "x": 1593413212000, - "y": 0, - }, - Object { - "x": 1593413213000, - "y": 0, - }, - Object { - "x": 1593413214000, - "y": 0, - }, - Object { - "x": 1593413215000, - "y": 0, - }, - Object { - "x": 1593413216000, - "y": 0, - }, - Object { - "x": 1593413217000, - "y": 0, - }, - Object { - "x": 1593413218000, - "y": 0, - }, - Object { - "x": 1593413219000, - "y": 0, - }, - Object { - "x": 1593413220000, - "y": 0, - }, - Object { - "x": 1593413221000, - "y": 0, - }, - Object { - "x": 1593413222000, - "y": 0, - }, - Object { - "x": 1593413223000, - "y": 0, - }, - Object { - "x": 1593413224000, - "y": 0, - }, - Object { - "x": 1593413225000, - "y": 0, - }, - Object { - "x": 1593413226000, - "y": 0, - }, - Object { - "x": 1593413227000, - "y": 0, - }, - Object { - "x": 1593413228000, - "y": 0, - }, - Object { - "x": 1593413229000, - "y": 0, - }, - Object { - "x": 1593413230000, - "y": 0, - }, - Object { - "x": 1593413231000, - "y": 0, - }, - Object { - "x": 1593413232000, - "y": 0, - }, - Object { - "x": 1593413233000, - "y": 0, - }, - Object { - "x": 1593413234000, - "y": 0, - }, - Object { - "x": 1593413235000, - "y": 0, - }, - Object { - "x": 1593413236000, - "y": 0, - }, - Object { - "x": 1593413237000, - "y": 0, - }, - Object { - "x": 1593413238000, - "y": 0, - }, - Object { - "x": 1593413239000, - "y": 0, - }, - Object { - "x": 1593413240000, - "y": 0, - }, - Object { - "x": 1593413241000, - "y": 0, - }, - Object { - "x": 1593413242000, - "y": 0, - }, - Object { - "x": 1593413243000, - "y": 0, - }, - Object { - "x": 1593413244000, - "y": 0, - }, - Object { - "x": 1593413245000, - "y": 0, - }, - Object { - "x": 1593413246000, - "y": 0, - }, - Object { - "x": 1593413247000, - "y": 0, - }, - Object { - "x": 1593413248000, - "y": 0, - }, - Object { - "x": 1593413249000, - "y": 0, - }, - Object { - "x": 1593413250000, - "y": 0, - }, - Object { - "x": 1593413251000, - "y": 0, - }, - Object { - "x": 1593413252000, - "y": 0, - }, - Object { - "x": 1593413253000, - "y": 0, - }, - Object { - "x": 1593413254000, - "y": 0, - }, - Object { - "x": 1593413255000, - "y": 0, - }, - Object { - "x": 1593413256000, - "y": 0, - }, - Object { - "x": 1593413257000, - "y": 0, - }, - Object { - "x": 1593413258000, - "y": 0, - }, - Object { - "x": 1593413259000, - "y": 0, - }, - Object { - "x": 1593413260000, - "y": 0, - }, - Object { - "x": 1593413261000, - "y": 0, - }, - Object { - "x": 1593413262000, - "y": 0, - }, - Object { - "x": 1593413263000, - "y": 0, - }, - Object { - "x": 1593413264000, - "y": 0, - }, - Object { - "x": 1593413265000, - "y": 0, - }, - Object { - "x": 1593413266000, - "y": 0, - }, - Object { - "x": 1593413267000, - "y": 0, - }, - Object { - "x": 1593413268000, - "y": 0, - }, - Object { - "x": 1593413269000, - "y": 0, - }, - Object { - "x": 1593413270000, - "y": 0, - }, - Object { - "x": 1593413271000, - "y": 0, - }, - Object { - "x": 1593413272000, - "y": 0, - }, - Object { - "x": 1593413273000, - "y": 0, - }, - Object { - "x": 1593413274000, - "y": 0, - }, - Object { - "x": 1593413275000, - "y": 0, - }, - Object { - "x": 1593413276000, - "y": 0, - }, - Object { - "x": 1593413277000, - "y": 0, - }, - Object { - "x": 1593413278000, - "y": 0, - }, - Object { - "x": 1593413279000, - "y": 0, - }, - Object { - "x": 1593413280000, - "y": 0, - }, - Object { - "x": 1593413281000, - "y": 0, - }, - Object { - "x": 1593413282000, - "y": 0, - }, - Object { - "x": 1593413283000, - "y": 0, - }, - Object { - "x": 1593413284000, - "y": 0, - }, - Object { - "x": 1593413285000, - "y": 0, - }, - Object { - "x": 1593413286000, - "y": 0, - }, - Object { - "x": 1593413287000, - "y": 0, - }, - Object { - "x": 1593413288000, - "y": 0, - }, - Object { - "x": 1593413289000, - "y": 0, - }, - Object { - "x": 1593413290000, - "y": 0, - }, - Object { - "x": 1593413291000, - "y": 0, - }, - Object { - "x": 1593413292000, - "y": 0, - }, - Object { - "x": 1593413293000, - "y": 0, - }, - Object { - "x": 1593413294000, - "y": 0, - }, - Object { - "x": 1593413295000, - "y": 0, - }, - Object { - "x": 1593413296000, - "y": 0, - }, - Object { - "x": 1593413297000, - "y": 0, - }, - Object { - "x": 1593413298000, - "y": 2, - }, - Object { - "x": 1593413299000, - "y": 0, - }, - Object { - "x": 1593413300000, - "y": 0, - }, - Object { - "x": 1593413301000, - "y": 3, - }, - Object { - "x": 1593413302000, - "y": 0, - }, - Object { - "x": 1593413303000, - "y": 0, - }, - Object { - "x": 1593413304000, - "y": 0, - }, - Object { - "x": 1593413305000, - "y": 0, - }, - Object { - "x": 1593413306000, - "y": 0, - }, - Object { - "x": 1593413307000, - "y": 0, - }, - Object { - "x": 1593413308000, - "y": 0, - }, - Object { - "x": 1593413309000, - "y": 0, - }, - Object { - "x": 1593413310000, - "y": 0, - }, - Object { - "x": 1593413311000, - "y": 0, - }, - Object { - "x": 1593413312000, - "y": 0, - }, - Object { - "x": 1593413313000, - "y": 0, - }, - Object { - "x": 1593413314000, - "y": 0, - }, - Object { - "x": 1593413315000, - "y": 0, - }, - Object { - "x": 1593413316000, - "y": 0, - }, - Object { - "x": 1593413317000, - "y": 2, - }, - Object { - "x": 1593413318000, - "y": 0, - }, - Object { - "x": 1593413319000, - "y": 0, - }, - Object { - "x": 1593413320000, - "y": 0, - }, - Object { - "x": 1593413321000, - "y": 0, - }, - Object { - "x": 1593413322000, - "y": 0, - }, - Object { - "x": 1593413323000, - "y": 0, - }, - Object { - "x": 1593413324000, - "y": 0, - }, - Object { - "x": 1593413325000, - "y": 0, - }, - Object { - "x": 1593413326000, - "y": 0, - }, - Object { - "x": 1593413327000, - "y": 0, - }, - Object { - "x": 1593413328000, - "y": 0, - }, - Object { - "x": 1593413329000, - "y": 0, - }, - Object { - "x": 1593413330000, - "y": 0, - }, - Object { - "x": 1593413331000, - "y": 0, - }, - Object { - "x": 1593413332000, - "y": 0, - }, - Object { - "x": 1593413333000, - "y": 0, - }, - Object { - "x": 1593413334000, - "y": 0, - }, - Object { - "x": 1593413335000, - "y": 0, - }, - Object { - "x": 1593413336000, - "y": 0, - }, - Object { - "x": 1593413337000, - "y": 0, - }, - Object { - "x": 1593413338000, - "y": 0, - }, - Object { - "x": 1593413339000, - "y": 0, - }, - Object { - "x": 1593413340000, - "y": 0, - }, - ], - "key": "HTTP 3xx", - }, - Object { - "avg": 2, - "dataPoints": Array [ - Object { - "x": 1593413100000, - "y": 0, - }, - Object { - "x": 1593413101000, - "y": 0, - }, - Object { - "x": 1593413102000, - "y": 0, - }, - Object { - "x": 1593413103000, - "y": 0, - }, - Object { - "x": 1593413104000, - "y": 0, - }, - Object { - "x": 1593413105000, - "y": 0, - }, - Object { - "x": 1593413106000, - "y": 0, - }, - Object { - "x": 1593413107000, - "y": 0, - }, - Object { - "x": 1593413108000, - "y": 0, - }, - Object { - "x": 1593413109000, - "y": 0, - }, - Object { - "x": 1593413110000, - "y": 0, - }, - Object { - "x": 1593413111000, - "y": 0, - }, - Object { - "x": 1593413112000, - "y": 0, - }, - Object { - "x": 1593413113000, - "y": 0, - }, - Object { - "x": 1593413114000, - "y": 0, - }, - Object { - "x": 1593413115000, - "y": 0, - }, - Object { - "x": 1593413116000, - "y": 0, - }, - Object { - "x": 1593413117000, - "y": 0, - }, - Object { - "x": 1593413118000, - "y": 0, - }, - Object { - "x": 1593413119000, - "y": 0, - }, - Object { - "x": 1593413120000, - "y": 0, - }, - Object { - "x": 1593413121000, - "y": 0, - }, - Object { - "x": 1593413122000, - "y": 0, - }, - Object { - "x": 1593413123000, - "y": 0, - }, - Object { - "x": 1593413124000, - "y": 0, - }, - Object { - "x": 1593413125000, - "y": 0, - }, - Object { - "x": 1593413126000, - "y": 0, - }, - Object { - "x": 1593413127000, - "y": 0, - }, - Object { - "x": 1593413128000, - "y": 0, - }, - Object { - "x": 1593413129000, - "y": 0, - }, - Object { - "x": 1593413130000, - "y": 0, - }, - Object { - "x": 1593413131000, - "y": 0, - }, - Object { - "x": 1593413132000, - "y": 0, - }, - Object { - "x": 1593413133000, - "y": 0, - }, - Object { - "x": 1593413134000, - "y": 0, - }, - Object { - "x": 1593413135000, - "y": 0, - }, - Object { - "x": 1593413136000, - "y": 0, - }, - Object { - "x": 1593413137000, - "y": 0, - }, - Object { - "x": 1593413138000, - "y": 0, - }, - Object { - "x": 1593413139000, - "y": 0, - }, - Object { - "x": 1593413140000, - "y": 0, - }, - Object { - "x": 1593413141000, - "y": 0, - }, - Object { - "x": 1593413142000, - "y": 0, - }, - Object { - "x": 1593413143000, - "y": 0, - }, - Object { - "x": 1593413144000, - "y": 0, - }, - Object { - "x": 1593413145000, - "y": 0, - }, - Object { - "x": 1593413146000, - "y": 0, - }, - Object { - "x": 1593413147000, - "y": 0, - }, - Object { - "x": 1593413148000, - "y": 0, - }, - Object { - "x": 1593413149000, - "y": 0, - }, - Object { - "x": 1593413150000, - "y": 0, - }, - Object { - "x": 1593413151000, - "y": 0, - }, - Object { - "x": 1593413152000, - "y": 0, - }, - Object { - "x": 1593413153000, - "y": 0, - }, - Object { - "x": 1593413154000, - "y": 0, - }, - Object { - "x": 1593413155000, - "y": 0, - }, - Object { - "x": 1593413156000, - "y": 0, - }, - Object { - "x": 1593413157000, - "y": 0, - }, - Object { - "x": 1593413158000, - "y": 0, - }, - Object { - "x": 1593413159000, - "y": 0, - }, - Object { - "x": 1593413160000, - "y": 0, - }, - Object { - "x": 1593413161000, - "y": 0, - }, - Object { - "x": 1593413162000, - "y": 0, - }, - Object { - "x": 1593413163000, - "y": 0, - }, - Object { - "x": 1593413164000, - "y": 0, - }, - Object { - "x": 1593413165000, - "y": 0, - }, - Object { - "x": 1593413166000, - "y": 0, - }, - Object { - "x": 1593413167000, - "y": 0, - }, - Object { - "x": 1593413168000, - "y": 0, - }, - Object { - "x": 1593413169000, - "y": 0, - }, - Object { - "x": 1593413170000, - "y": 0, - }, - Object { - "x": 1593413171000, - "y": 0, - }, - Object { - "x": 1593413172000, - "y": 0, - }, - Object { - "x": 1593413173000, - "y": 0, - }, - Object { - "x": 1593413174000, - "y": 0, - }, - Object { - "x": 1593413175000, - "y": 0, - }, - Object { - "x": 1593413176000, - "y": 0, - }, - Object { - "x": 1593413177000, - "y": 0, - }, - Object { - "x": 1593413178000, - "y": 0, - }, - Object { - "x": 1593413179000, - "y": 0, - }, - Object { - "x": 1593413180000, - "y": 0, - }, - Object { - "x": 1593413181000, - "y": 0, - }, - Object { - "x": 1593413182000, - "y": 0, - }, - Object { - "x": 1593413183000, - "y": 0, - }, - Object { - "x": 1593413184000, - "y": 0, - }, - Object { - "x": 1593413185000, - "y": 0, - }, - Object { - "x": 1593413186000, - "y": 0, - }, - Object { - "x": 1593413187000, - "y": 0, - }, - Object { - "x": 1593413188000, - "y": 0, - }, - Object { - "x": 1593413189000, - "y": 0, - }, - Object { - "x": 1593413190000, - "y": 0, - }, - Object { - "x": 1593413191000, - "y": 0, - }, - Object { - "x": 1593413192000, - "y": 0, - }, - Object { - "x": 1593413193000, - "y": 0, - }, - Object { - "x": 1593413194000, - "y": 0, - }, - Object { - "x": 1593413195000, - "y": 0, - }, - Object { - "x": 1593413196000, - "y": 0, - }, - Object { - "x": 1593413197000, - "y": 0, - }, - Object { - "x": 1593413198000, - "y": 0, - }, - Object { - "x": 1593413199000, - "y": 0, - }, - Object { - "x": 1593413200000, - "y": 0, - }, - Object { - "x": 1593413201000, - "y": 0, - }, - Object { - "x": 1593413202000, - "y": 0, - }, - Object { - "x": 1593413203000, - "y": 0, - }, - Object { - "x": 1593413204000, - "y": 0, - }, - Object { - "x": 1593413205000, - "y": 0, - }, - Object { - "x": 1593413206000, - "y": 0, - }, - Object { - "x": 1593413207000, - "y": 0, - }, - Object { - "x": 1593413208000, - "y": 0, - }, - Object { - "x": 1593413209000, - "y": 0, - }, - Object { - "x": 1593413210000, - "y": 0, - }, - Object { - "x": 1593413211000, - "y": 0, - }, - Object { - "x": 1593413212000, - "y": 0, - }, - Object { - "x": 1593413213000, - "y": 0, - }, - Object { - "x": 1593413214000, - "y": 0, - }, - Object { - "x": 1593413215000, - "y": 0, - }, - Object { - "x": 1593413216000, - "y": 0, - }, - Object { - "x": 1593413217000, - "y": 0, - }, - Object { - "x": 1593413218000, - "y": 0, - }, - Object { - "x": 1593413219000, - "y": 0, - }, - Object { - "x": 1593413220000, - "y": 0, - }, - Object { - "x": 1593413221000, - "y": 0, - }, - Object { - "x": 1593413222000, - "y": 0, - }, - Object { - "x": 1593413223000, - "y": 0, - }, - Object { - "x": 1593413224000, - "y": 0, - }, - Object { - "x": 1593413225000, - "y": 0, - }, - Object { - "x": 1593413226000, - "y": 0, - }, - Object { - "x": 1593413227000, - "y": 0, - }, - Object { - "x": 1593413228000, - "y": 0, - }, - Object { - "x": 1593413229000, - "y": 0, - }, - Object { - "x": 1593413230000, - "y": 0, - }, - Object { - "x": 1593413231000, - "y": 0, - }, - Object { - "x": 1593413232000, - "y": 0, - }, - Object { - "x": 1593413233000, - "y": 0, - }, - Object { - "x": 1593413234000, - "y": 0, - }, - Object { - "x": 1593413235000, - "y": 0, - }, - Object { - "x": 1593413236000, - "y": 0, - }, - Object { - "x": 1593413237000, - "y": 0, - }, - Object { - "x": 1593413238000, - "y": 0, - }, - Object { - "x": 1593413239000, - "y": 0, - }, - Object { - "x": 1593413240000, - "y": 0, - }, - Object { - "x": 1593413241000, - "y": 0, - }, - Object { - "x": 1593413242000, - "y": 0, - }, - Object { - "x": 1593413243000, - "y": 0, - }, - Object { - "x": 1593413244000, - "y": 0, - }, - Object { - "x": 1593413245000, - "y": 0, - }, - Object { - "x": 1593413246000, - "y": 0, - }, - Object { - "x": 1593413247000, - "y": 0, - }, - Object { - "x": 1593413248000, - "y": 0, - }, - Object { - "x": 1593413249000, - "y": 0, - }, - Object { - "x": 1593413250000, - "y": 0, - }, - Object { - "x": 1593413251000, - "y": 0, - }, - Object { - "x": 1593413252000, - "y": 0, - }, - Object { - "x": 1593413253000, - "y": 0, - }, - Object { - "x": 1593413254000, - "y": 0, - }, - Object { - "x": 1593413255000, - "y": 0, - }, - Object { - "x": 1593413256000, - "y": 0, - }, - Object { - "x": 1593413257000, - "y": 0, - }, - Object { - "x": 1593413258000, - "y": 0, - }, - Object { - "x": 1593413259000, - "y": 0, - }, - Object { - "x": 1593413260000, - "y": 0, - }, - Object { - "x": 1593413261000, - "y": 0, - }, - Object { - "x": 1593413262000, - "y": 0, - }, - Object { - "x": 1593413263000, - "y": 0, - }, - Object { - "x": 1593413264000, - "y": 0, - }, - Object { - "x": 1593413265000, - "y": 0, - }, - Object { - "x": 1593413266000, - "y": 0, - }, - Object { - "x": 1593413267000, - "y": 0, - }, - Object { - "x": 1593413268000, - "y": 0, - }, - Object { - "x": 1593413269000, - "y": 0, - }, - Object { - "x": 1593413270000, - "y": 0, - }, - Object { - "x": 1593413271000, - "y": 0, - }, - Object { - "x": 1593413272000, - "y": 0, - }, - Object { - "x": 1593413273000, - "y": 0, - }, - Object { - "x": 1593413274000, - "y": 0, - }, - Object { - "x": 1593413275000, - "y": 0, - }, - Object { - "x": 1593413276000, - "y": 0, - }, - Object { - "x": 1593413277000, - "y": 0, - }, - Object { - "x": 1593413278000, - "y": 0, - }, - Object { - "x": 1593413279000, - "y": 0, - }, - Object { - "x": 1593413280000, - "y": 0, - }, - Object { - "x": 1593413281000, - "y": 0, - }, - Object { - "x": 1593413282000, - "y": 0, - }, - Object { - "x": 1593413283000, - "y": 0, - }, - Object { - "x": 1593413284000, - "y": 0, - }, - Object { - "x": 1593413285000, - "y": 0, - }, - Object { - "x": 1593413286000, - "y": 0, - }, - Object { - "x": 1593413287000, - "y": 0, - }, - Object { - "x": 1593413288000, - "y": 0, - }, - Object { - "x": 1593413289000, - "y": 1, - }, - Object { - "x": 1593413290000, - "y": 0, - }, - Object { - "x": 1593413291000, - "y": 0, - }, - Object { - "x": 1593413292000, - "y": 1, - }, - Object { - "x": 1593413293000, - "y": 0, - }, - Object { - "x": 1593413294000, - "y": 0, - }, - Object { - "x": 1593413295000, - "y": 0, - }, - Object { - "x": 1593413296000, - "y": 0, - }, - Object { - "x": 1593413297000, - "y": 0, - }, - Object { - "x": 1593413298000, - "y": 0, - }, - Object { - "x": 1593413299000, - "y": 0, - }, - Object { - "x": 1593413300000, - "y": 1, - }, - Object { - "x": 1593413301000, - "y": 0, - }, - Object { - "x": 1593413302000, - "y": 0, - }, - Object { - "x": 1593413303000, - "y": 0, - }, - Object { - "x": 1593413304000, - "y": 0, - }, - Object { - "x": 1593413305000, - "y": 1, - }, - Object { - "x": 1593413306000, - "y": 0, - }, - Object { - "x": 1593413307000, - "y": 0, - }, - Object { - "x": 1593413308000, - "y": 0, - }, - Object { - "x": 1593413309000, - "y": 1, - }, - Object { - "x": 1593413310000, - "y": 1, - }, - Object { - "x": 1593413311000, - "y": 0, - }, - Object { - "x": 1593413312000, - "y": 0, - }, - Object { - "x": 1593413313000, - "y": 0, - }, - Object { - "x": 1593413314000, - "y": 0, - }, - Object { - "x": 1593413315000, - "y": 1, - }, - Object { - "x": 1593413316000, - "y": 0, - }, - Object { - "x": 1593413317000, - "y": 0, - }, - Object { - "x": 1593413318000, - "y": 0, - }, + "x": 1599721110000, + "y": 927744, + }, + Object { + "x": 1599721140000, + "y": 1048320, + }, + Object { + "x": 1599721170000, + "y": 1363968, + }, + Object { + "x": 1599721200000, + "y": null, + }, + ], + }, + "tpmBuckets": Array [ + Object { + "avg": 3.183333333333333, + "dataPoints": Array [ Object { - "x": 1593413319000, + "x": 1599717600000, "y": 0, }, Object { - "x": 1593413320000, + "x": 1599717630000, "y": 1, }, Object { - "x": 1593413321000, - "y": 0, - }, - Object { - "x": 1593413322000, - "y": 0, - }, - Object { - "x": 1593413323000, - "y": 0, - }, - Object { - "x": 1593413324000, - "y": 0, - }, - Object { - "x": 1593413325000, - "y": 0, - }, - Object { - "x": 1593413326000, - "y": 0, - }, - Object { - "x": 1593413327000, - "y": 0, - }, - Object { - "x": 1593413328000, - "y": 0, - }, - Object { - "x": 1593413329000, - "y": 0, - }, - Object { - "x": 1593413330000, - "y": 0, - }, - Object { - "x": 1593413331000, - "y": 0, - }, - Object { - "x": 1593413332000, - "y": 0, - }, - Object { - "x": 1593413333000, - "y": 0, + "x": 1599717660000, + "y": 2, }, Object { - "x": 1593413334000, + "x": 1599717690000, "y": 0, }, Object { - "x": 1593413335000, - "y": 0, + "x": 1599717720000, + "y": 3, }, Object { - "x": 1593413336000, - "y": 0, + "x": 1599717750000, + "y": 3, }, Object { - "x": 1593413337000, - "y": 0, + "x": 1599717780000, + "y": 2, }, Object { - "x": 1593413338000, + "x": 1599717810000, "y": 0, }, Object { - "x": 1593413339000, - "y": 0, + "x": 1599717840000, + "y": 1, }, Object { - "x": 1593413340000, - "y": 0, + "x": 1599717870000, + "y": 2, }, - ], - "key": "HTTP 4xx", - }, - Object { - "avg": 2.25, - "dataPoints": Array [ Object { - "x": 1593413100000, - "y": 0, + "x": 1599717900000, + "y": 2, }, Object { - "x": 1593413101000, + "x": 1599717930000, "y": 0, }, Object { - "x": 1593413102000, - "y": 0, + "x": 1599717960000, + "y": 4, }, Object { - "x": 1593413103000, - "y": 0, + "x": 1599717990000, + "y": 4, }, Object { - "x": 1593413104000, - "y": 0, + "x": 1599718020000, + "y": 1, }, Object { - "x": 1593413105000, + "x": 1599718050000, "y": 0, }, Object { - "x": 1593413106000, - "y": 0, + "x": 1599718080000, + "y": 5, }, Object { - "x": 1593413107000, - "y": 0, + "x": 1599718110000, + "y": 1, }, Object { - "x": 1593413108000, - "y": 0, + "x": 1599718140000, + "y": 2, }, Object { - "x": 1593413109000, + "x": 1599718170000, "y": 0, }, Object { - "x": 1593413110000, - "y": 0, + "x": 1599718200000, + "y": 6, }, Object { - "x": 1593413111000, - "y": 0, + "x": 1599718230000, + "y": 2, }, Object { - "x": 1593413112000, + "x": 1599718260000, "y": 0, }, Object { - "x": 1593413113000, + "x": 1599718290000, "y": 0, }, Object { - "x": 1593413114000, - "y": 0, + "x": 1599718320000, + "y": 2, }, Object { - "x": 1593413115000, - "y": 0, + "x": 1599718350000, + "y": 3, }, Object { - "x": 1593413116000, - "y": 0, + "x": 1599718380000, + "y": 2, }, Object { - "x": 1593413117000, + "x": 1599718410000, "y": 0, }, Object { - "x": 1593413118000, - "y": 0, + "x": 1599718440000, + "y": 3, }, Object { - "x": 1593413119000, - "y": 0, + "x": 1599718470000, + "y": 6, }, Object { - "x": 1593413120000, - "y": 0, + "x": 1599718500000, + "y": 1, }, Object { - "x": 1593413121000, + "x": 1599718530000, "y": 0, }, Object { - "x": 1593413122000, - "y": 0, + "x": 1599718560000, + "y": 7, }, Object { - "x": 1593413123000, + "x": 1599718590000, "y": 0, }, Object { - "x": 1593413124000, - "y": 0, + "x": 1599718620000, + "y": 2, }, Object { - "x": 1593413125000, + "x": 1599718650000, "y": 0, }, Object { - "x": 1593413126000, - "y": 0, + "x": 1599718680000, + "y": 3, }, Object { - "x": 1593413127000, - "y": 0, + "x": 1599718710000, + "y": 2, }, Object { - "x": 1593413128000, - "y": 0, + "x": 1599718740000, + "y": 1, }, Object { - "x": 1593413129000, - "y": 0, + "x": 1599718770000, + "y": 1, }, Object { - "x": 1593413130000, + "x": 1599718800000, "y": 0, }, Object { - "x": 1593413131000, - "y": 0, + "x": 1599718830000, + "y": 4, }, Object { - "x": 1593413132000, - "y": 0, + "x": 1599718860000, + "y": 1, }, Object { - "x": 1593413133000, + "x": 1599718890000, "y": 0, }, Object { - "x": 1593413134000, - "y": 0, + "x": 1599718920000, + "y": 2, }, Object { - "x": 1593413135000, + "x": 1599718950000, "y": 0, }, Object { - "x": 1593413136000, + "x": 1599718980000, "y": 0, }, Object { - "x": 1593413137000, - "y": 0, + "x": 1599719010000, + "y": 3, }, Object { - "x": 1593413138000, - "y": 0, + "x": 1599719040000, + "y": 4, }, Object { - "x": 1593413139000, - "y": 0, + "x": 1599719070000, + "y": 1, }, Object { - "x": 1593413140000, - "y": 0, + "x": 1599719100000, + "y": 2, }, Object { - "x": 1593413141000, + "x": 1599719130000, "y": 0, }, Object { - "x": 1593413142000, - "y": 0, + "x": 1599719160000, + "y": 6, }, Object { - "x": 1593413143000, - "y": 0, + "x": 1599719190000, + "y": 1, }, Object { - "x": 1593413144000, - "y": 0, + "x": 1599719220000, + "y": 5, }, Object { - "x": 1593413145000, + "x": 1599719250000, "y": 0, }, Object { - "x": 1593413146000, - "y": 0, + "x": 1599719280000, + "y": 2, }, Object { - "x": 1593413147000, - "y": 0, + "x": 1599719310000, + "y": 3, }, Object { - "x": 1593413148000, + "x": 1599719340000, "y": 0, }, Object { - "x": 1593413149000, + "x": 1599719370000, "y": 0, }, Object { - "x": 1593413150000, - "y": 0, + "x": 1599719400000, + "y": 6, }, Object { - "x": 1593413151000, - "y": 0, + "x": 1599719430000, + "y": 3, }, Object { - "x": 1593413152000, + "x": 1599719460000, "y": 0, }, Object { - "x": 1593413153000, - "y": 0, + "x": 1599719490000, + "y": 1, }, Object { - "x": 1593413154000, - "y": 0, + "x": 1599719520000, + "y": 1, }, Object { - "x": 1593413155000, + "x": 1599719550000, "y": 0, }, Object { - "x": 1593413156000, - "y": 0, + "x": 1599719580000, + "y": 1, }, Object { - "x": 1593413157000, + "x": 1599719610000, "y": 0, }, Object { - "x": 1593413158000, - "y": 0, + "x": 1599719640000, + "y": 4, }, Object { - "x": 1593413159000, - "y": 0, + "x": 1599719670000, + "y": 2, }, Object { - "x": 1593413160000, + "x": 1599719700000, "y": 0, }, Object { - "x": 1593413161000, - "y": 0, + "x": 1599719730000, + "y": 2, }, Object { - "x": 1593413162000, - "y": 0, + "x": 1599719760000, + "y": 3, }, Object { - "x": 1593413163000, + "x": 1599719790000, "y": 0, }, Object { - "x": 1593413164000, - "y": 0, + "x": 1599719820000, + "y": 2, }, Object { - "x": 1593413165000, + "x": 1599719850000, "y": 0, }, Object { - "x": 1593413166000, - "y": 0, + "x": 1599719880000, + "y": 4, }, Object { - "x": 1593413167000, + "x": 1599719910000, "y": 0, }, Object { - "x": 1593413168000, + "x": 1599719940000, "y": 0, }, Object { - "x": 1593413169000, - "y": 0, + "x": 1599719970000, + "y": 1, }, Object { - "x": 1593413170000, - "y": 0, + "x": 1599720000000, + "y": 1, }, Object { - "x": 1593413171000, - "y": 0, + "x": 1599720030000, + "y": 1, }, Object { - "x": 1593413172000, - "y": 0, + "x": 1599720060000, + "y": 1, }, Object { - "x": 1593413173000, + "x": 1599720090000, "y": 0, }, Object { - "x": 1593413174000, + "x": 1599720120000, "y": 0, }, Object { - "x": 1593413175000, + "x": 1599720150000, "y": 0, }, Object { - "x": 1593413176000, - "y": 0, + "x": 1599720180000, + "y": 1, }, Object { - "x": 1593413177000, + "x": 1599720210000, "y": 0, }, Object { - "x": 1593413178000, - "y": 0, + "x": 1599720240000, + "y": 4, }, Object { - "x": 1593413179000, - "y": 0, + "x": 1599720270000, + "y": 1, }, Object { - "x": 1593413180000, - "y": 0, + "x": 1599720300000, + "y": 2, }, Object { - "x": 1593413181000, + "x": 1599720330000, "y": 0, }, Object { - "x": 1593413182000, - "y": 0, + "x": 1599720360000, + "y": 1, }, Object { - "x": 1593413183000, - "y": 0, + "x": 1599720390000, + "y": 5, }, Object { - "x": 1593413184000, - "y": 0, + "x": 1599720420000, + "y": 4, }, Object { - "x": 1593413185000, + "x": 1599720450000, "y": 0, }, Object { - "x": 1593413186000, + "x": 1599720480000, "y": 0, }, Object { - "x": 1593413187000, - "y": 0, + "x": 1599720510000, + "y": 3, }, Object { - "x": 1593413188000, + "x": 1599720540000, "y": 0, }, Object { - "x": 1593413189000, + "x": 1599720570000, "y": 0, }, Object { - "x": 1593413190000, - "y": 0, + "x": 1599720600000, + "y": 2, }, Object { - "x": 1593413191000, - "y": 0, + "x": 1599720630000, + "y": 3, }, Object { - "x": 1593413192000, - "y": 0, + "x": 1599720660000, + "y": 1, }, Object { - "x": 1593413193000, + "x": 1599720690000, "y": 0, }, Object { - "x": 1593413194000, - "y": 0, + "x": 1599720720000, + "y": 2, }, Object { - "x": 1593413195000, - "y": 0, + "x": 1599720750000, + "y": 4, }, Object { - "x": 1593413196000, - "y": 0, + "x": 1599720780000, + "y": 2, }, Object { - "x": 1593413197000, + "x": 1599720810000, "y": 0, }, Object { - "x": 1593413198000, - "y": 0, + "x": 1599720840000, + "y": 1, }, Object { - "x": 1593413199000, - "y": 0, + "x": 1599720870000, + "y": 3, }, Object { - "x": 1593413200000, - "y": 0, + "x": 1599720900000, + "y": 3, }, Object { - "x": 1593413201000, + "x": 1599720930000, "y": 0, }, Object { - "x": 1593413202000, - "y": 0, + "x": 1599720960000, + "y": 1, }, Object { - "x": 1593413203000, - "y": 0, + "x": 1599720990000, + "y": 1, }, Object { - "x": 1593413204000, - "y": 0, + "x": 1599721020000, + "y": 1, }, Object { - "x": 1593413205000, + "x": 1599721050000, "y": 0, }, Object { - "x": 1593413206000, - "y": 0, + "x": 1599721080000, + "y": 4, }, Object { - "x": 1593413207000, + "x": 1599721110000, "y": 0, }, Object { - "x": 1593413208000, - "y": 0, + "x": 1599721140000, + "y": 1, }, Object { - "x": 1593413209000, + "x": 1599721170000, "y": 0, }, Object { - "x": 1593413210000, + "x": 1599721200000, "y": 0, }, + ], + "key": "HTTP 2xx", + }, + Object { + "avg": 0.21666666666666667, + "dataPoints": Array [ Object { - "x": 1593413211000, + "x": 1599717600000, "y": 0, }, Object { - "x": 1593413212000, + "x": 1599717630000, "y": 0, }, Object { - "x": 1593413213000, + "x": 1599717660000, "y": 0, }, Object { - "x": 1593413214000, + "x": 1599717690000, "y": 0, }, Object { - "x": 1593413215000, - "y": 0, + "x": 1599717720000, + "y": 1, }, Object { - "x": 1593413216000, + "x": 1599717750000, "y": 0, }, Object { - "x": 1593413217000, + "x": 1599717780000, "y": 0, }, Object { - "x": 1593413218000, + "x": 1599717810000, "y": 0, }, Object { - "x": 1593413219000, + "x": 1599717840000, "y": 0, }, Object { - "x": 1593413220000, + "x": 1599717870000, "y": 0, }, Object { - "x": 1593413221000, + "x": 1599717900000, "y": 0, }, Object { - "x": 1593413222000, + "x": 1599717930000, "y": 0, }, Object { - "x": 1593413223000, + "x": 1599717960000, "y": 0, }, Object { - "x": 1593413224000, + "x": 1599717990000, "y": 0, }, Object { - "x": 1593413225000, + "x": 1599718020000, "y": 0, }, Object { - "x": 1593413226000, + "x": 1599718050000, "y": 0, }, Object { - "x": 1593413227000, + "x": 1599718080000, "y": 0, }, Object { - "x": 1593413228000, + "x": 1599718110000, "y": 0, }, Object { - "x": 1593413229000, + "x": 1599718140000, "y": 0, }, Object { - "x": 1593413230000, + "x": 1599718170000, "y": 0, }, Object { - "x": 1593413231000, - "y": 0, + "x": 1599718200000, + "y": 1, }, Object { - "x": 1593413232000, + "x": 1599718230000, "y": 0, }, Object { - "x": 1593413233000, + "x": 1599718260000, "y": 0, }, Object { - "x": 1593413234000, + "x": 1599718290000, "y": 0, }, Object { - "x": 1593413235000, + "x": 1599718320000, "y": 0, }, Object { - "x": 1593413236000, + "x": 1599718350000, "y": 0, }, Object { - "x": 1593413237000, + "x": 1599718380000, "y": 0, }, Object { - "x": 1593413238000, + "x": 1599718410000, "y": 0, }, Object { - "x": 1593413239000, + "x": 1599718440000, "y": 0, }, Object { - "x": 1593413240000, - "y": 0, + "x": 1599718470000, + "y": 1, }, Object { - "x": 1593413241000, + "x": 1599718500000, "y": 0, }, Object { - "x": 1593413242000, + "x": 1599718530000, "y": 0, }, Object { - "x": 1593413243000, - "y": 0, + "x": 1599718560000, + "y": 2, }, Object { - "x": 1593413244000, + "x": 1599718590000, "y": 0, }, Object { - "x": 1593413245000, + "x": 1599718620000, "y": 0, }, Object { - "x": 1593413246000, + "x": 1599718650000, "y": 0, }, Object { - "x": 1593413247000, - "y": 0, + "x": 1599718680000, + "y": 2, }, Object { - "x": 1593413248000, + "x": 1599718710000, "y": 0, }, Object { - "x": 1593413249000, + "x": 1599718740000, "y": 0, }, Object { - "x": 1593413250000, + "x": 1599718770000, "y": 0, }, Object { - "x": 1593413251000, + "x": 1599718800000, "y": 0, }, Object { - "x": 1593413252000, + "x": 1599718830000, "y": 0, }, Object { - "x": 1593413253000, + "x": 1599718860000, "y": 0, }, Object { - "x": 1593413254000, + "x": 1599718890000, "y": 0, }, Object { - "x": 1593413255000, + "x": 1599718920000, "y": 0, }, Object { - "x": 1593413256000, + "x": 1599718950000, "y": 0, }, Object { - "x": 1593413257000, + "x": 1599718980000, "y": 0, }, Object { - "x": 1593413258000, + "x": 1599719010000, "y": 0, }, Object { - "x": 1593413259000, - "y": 0, + "x": 1599719040000, + "y": 1, }, Object { - "x": 1593413260000, + "x": 1599719070000, "y": 0, }, Object { - "x": 1593413261000, + "x": 1599719100000, "y": 0, }, Object { - "x": 1593413262000, + "x": 1599719130000, "y": 0, }, Object { - "x": 1593413263000, + "x": 1599719160000, "y": 0, }, Object { - "x": 1593413264000, + "x": 1599719190000, "y": 0, }, Object { - "x": 1593413265000, + "x": 1599719220000, "y": 0, }, Object { - "x": 1593413266000, + "x": 1599719250000, "y": 0, }, Object { - "x": 1593413267000, + "x": 1599719280000, "y": 0, }, Object { - "x": 1593413268000, + "x": 1599719310000, "y": 0, }, Object { - "x": 1593413269000, + "x": 1599719340000, "y": 0, }, Object { - "x": 1593413270000, + "x": 1599719370000, "y": 0, }, Object { - "x": 1593413271000, - "y": 0, + "x": 1599719400000, + "y": 2, }, Object { - "x": 1593413272000, + "x": 1599719430000, "y": 0, }, Object { - "x": 1593413273000, + "x": 1599719460000, "y": 0, }, Object { - "x": 1593413274000, + "x": 1599719490000, "y": 0, }, Object { - "x": 1593413275000, + "x": 1599719520000, "y": 0, }, Object { - "x": 1593413276000, + "x": 1599719550000, "y": 0, }, Object { - "x": 1593413277000, + "x": 1599719580000, "y": 0, }, Object { - "x": 1593413278000, + "x": 1599719610000, "y": 0, }, Object { - "x": 1593413279000, - "y": 0, + "x": 1599719640000, + "y": 1, }, Object { - "x": 1593413280000, - "y": 0, + "x": 1599719670000, + "y": 1, }, Object { - "x": 1593413281000, + "x": 1599719700000, "y": 0, }, Object { - "x": 1593413282000, + "x": 1599719730000, "y": 0, }, Object { - "x": 1593413283000, + "x": 1599719760000, "y": 0, }, Object { - "x": 1593413284000, + "x": 1599719790000, "y": 0, }, Object { - "x": 1593413285000, + "x": 1599719820000, "y": 0, }, Object { - "x": 1593413286000, - "y": 1, - }, - Object { - "x": 1593413287000, - "y": 1, - }, - Object { - "x": 1593413288000, + "x": 1599719850000, "y": 0, }, Object { - "x": 1593413289000, + "x": 1599719880000, "y": 0, }, Object { - "x": 1593413290000, + "x": 1599719910000, "y": 0, }, Object { - "x": 1593413291000, + "x": 1599719940000, "y": 0, }, Object { - "x": 1593413292000, + "x": 1599719970000, "y": 0, }, Object { - "x": 1593413293000, + "x": 1599720000000, "y": 0, }, Object { - "x": 1593413294000, + "x": 1599720030000, "y": 0, }, Object { - "x": 1593413295000, + "x": 1599720060000, "y": 0, }, Object { - "x": 1593413296000, + "x": 1599720090000, "y": 0, }, Object { - "x": 1593413297000, + "x": 1599720120000, "y": 0, }, Object { - "x": 1593413298000, + "x": 1599720150000, "y": 0, }, Object { - "x": 1593413299000, - "y": 1, - }, - Object { - "x": 1593413300000, + "x": 1599720180000, "y": 0, }, Object { - "x": 1593413301000, - "y": 1, - }, - Object { - "x": 1593413302000, + "x": 1599720210000, "y": 0, }, Object { - "x": 1593413303000, + "x": 1599720240000, "y": 0, }, Object { - "x": 1593413304000, + "x": 1599720270000, "y": 0, }, Object { - "x": 1593413305000, - "y": 1, - }, - Object { - "x": 1593413306000, + "x": 1599720300000, "y": 0, }, Object { - "x": 1593413307000, + "x": 1599720330000, "y": 0, }, Object { - "x": 1593413308000, - "y": 1, - }, - Object { - "x": 1593413309000, + "x": 1599720360000, "y": 0, }, Object { - "x": 1593413310000, + "x": 1599720390000, "y": 0, }, Object { - "x": 1593413311000, - "y": 1, - }, - Object { - "x": 1593413312000, + "x": 1599720420000, "y": 0, }, Object { - "x": 1593413313000, + "x": 1599720450000, "y": 0, }, Object { - "x": 1593413314000, + "x": 1599720480000, "y": 0, }, Object { - "x": 1593413315000, - "y": 1, - }, - Object { - "x": 1593413316000, + "x": 1599720510000, "y": 0, }, Object { - "x": 1593413317000, + "x": 1599720540000, "y": 0, }, Object { - "x": 1593413318000, + "x": 1599720570000, "y": 0, }, Object { - "x": 1593413319000, + "x": 1599720600000, "y": 0, }, Object { - "x": 1593413320000, + "x": 1599720630000, "y": 0, }, Object { - "x": 1593413321000, + "x": 1599720660000, "y": 0, }, Object { - "x": 1593413322000, - "y": 1, - }, - Object { - "x": 1593413323000, + "x": 1599720690000, "y": 0, }, Object { - "x": 1593413324000, + "x": 1599720720000, "y": 0, }, Object { - "x": 1593413325000, + "x": 1599720750000, "y": 0, }, Object { - "x": 1593413326000, + "x": 1599720780000, "y": 0, }, Object { - "x": 1593413327000, + "x": 1599720810000, "y": 0, }, Object { - "x": 1593413328000, + "x": 1599720840000, "y": 0, }, Object { - "x": 1593413329000, + "x": 1599720870000, "y": 0, }, Object { - "x": 1593413330000, + "x": 1599720900000, "y": 0, }, Object { - "x": 1593413331000, + "x": 1599720930000, "y": 0, }, Object { - "x": 1593413332000, - "y": 0, + "x": 1599720960000, + "y": 1, }, Object { - "x": 1593413333000, + "x": 1599720990000, "y": 0, }, Object { - "x": 1593413334000, + "x": 1599721020000, "y": 0, }, Object { - "x": 1593413335000, + "x": 1599721050000, "y": 0, }, Object { - "x": 1593413336000, + "x": 1599721080000, "y": 0, }, Object { - "x": 1593413337000, + "x": 1599721110000, "y": 0, }, Object { - "x": 1593413338000, + "x": 1599721140000, "y": 0, }, Object { - "x": 1593413339000, + "x": 1599721170000, "y": 0, }, Object { - "x": 1593413340000, + "x": 1599721200000, "y": 0, }, ], - "key": "HTTP 5xx", + "key": "HTTP 4xx", }, Object { - "avg": 0.25, + "avg": 0.11666666666666667, "dataPoints": Array [ Object { - "x": 1593413100000, - "y": 0, + "x": 1599717600000, + "y": 1, }, Object { - "x": 1593413101000, + "x": 1599717630000, "y": 0, }, Object { - "x": 1593413102000, + "x": 1599717660000, "y": 0, }, Object { - "x": 1593413103000, + "x": 1599717690000, "y": 0, }, Object { - "x": 1593413104000, + "x": 1599717720000, "y": 0, }, Object { - "x": 1593413105000, + "x": 1599717750000, "y": 0, }, Object { - "x": 1593413106000, + "x": 1599717780000, "y": 0, }, Object { - "x": 1593413107000, + "x": 1599717810000, "y": 0, }, Object { - "x": 1593413108000, + "x": 1599717840000, "y": 0, }, Object { - "x": 1593413109000, + "x": 1599717870000, "y": 0, }, Object { - "x": 1593413110000, + "x": 1599717900000, "y": 0, }, Object { - "x": 1593413111000, + "x": 1599717930000, "y": 0, }, Object { - "x": 1593413112000, + "x": 1599717960000, "y": 0, }, Object { - "x": 1593413113000, + "x": 1599717990000, "y": 0, }, Object { - "x": 1593413114000, + "x": 1599718020000, "y": 0, }, Object { - "x": 1593413115000, + "x": 1599718050000, "y": 0, }, Object { - "x": 1593413116000, + "x": 1599718080000, "y": 0, }, Object { - "x": 1593413117000, + "x": 1599718110000, "y": 0, }, Object { - "x": 1593413118000, + "x": 1599718140000, "y": 0, }, Object { - "x": 1593413119000, + "x": 1599718170000, "y": 0, }, Object { - "x": 1593413120000, + "x": 1599718200000, "y": 0, }, Object { - "x": 1593413121000, - "y": 0, + "x": 1599718230000, + "y": 1, }, Object { - "x": 1593413122000, + "x": 1599718260000, "y": 0, }, Object { - "x": 1593413123000, + "x": 1599718290000, "y": 0, }, Object { - "x": 1593413124000, + "x": 1599718320000, "y": 0, }, Object { - "x": 1593413125000, + "x": 1599718350000, "y": 0, }, Object { - "x": 1593413126000, + "x": 1599718380000, "y": 0, }, Object { - "x": 1593413127000, + "x": 1599718410000, "y": 0, }, Object { - "x": 1593413128000, + "x": 1599718440000, "y": 0, }, Object { - "x": 1593413129000, + "x": 1599718470000, "y": 0, }, Object { - "x": 1593413130000, + "x": 1599718500000, "y": 0, }, Object { - "x": 1593413131000, + "x": 1599718530000, "y": 0, }, Object { - "x": 1593413132000, + "x": 1599718560000, "y": 0, }, Object { - "x": 1593413133000, + "x": 1599718590000, "y": 0, }, Object { - "x": 1593413134000, + "x": 1599718620000, "y": 0, }, Object { - "x": 1593413135000, + "x": 1599718650000, "y": 0, }, Object { - "x": 1593413136000, + "x": 1599718680000, "y": 0, }, Object { - "x": 1593413137000, - "y": 0, + "x": 1599718710000, + "y": 1, }, Object { - "x": 1593413138000, + "x": 1599718740000, "y": 0, }, Object { - "x": 1593413139000, + "x": 1599718770000, "y": 0, }, Object { - "x": 1593413140000, + "x": 1599718800000, "y": 0, }, Object { - "x": 1593413141000, + "x": 1599718830000, "y": 0, }, Object { - "x": 1593413142000, - "y": 0, + "x": 1599718860000, + "y": 2, }, Object { - "x": 1593413143000, + "x": 1599718890000, "y": 0, }, Object { - "x": 1593413144000, + "x": 1599718920000, "y": 0, }, Object { - "x": 1593413145000, + "x": 1599718950000, "y": 0, }, Object { - "x": 1593413146000, + "x": 1599718980000, "y": 0, }, Object { - "x": 1593413147000, + "x": 1599719010000, "y": 0, }, Object { - "x": 1593413148000, + "x": 1599719040000, "y": 0, }, Object { - "x": 1593413149000, + "x": 1599719070000, "y": 0, }, Object { - "x": 1593413150000, + "x": 1599719100000, "y": 0, }, Object { - "x": 1593413151000, + "x": 1599719130000, "y": 0, }, Object { - "x": 1593413152000, + "x": 1599719160000, "y": 0, }, Object { - "x": 1593413153000, + "x": 1599719190000, "y": 0, }, Object { - "x": 1593413154000, + "x": 1599719220000, "y": 0, }, Object { - "x": 1593413155000, + "x": 1599719250000, "y": 0, }, Object { - "x": 1593413156000, + "x": 1599719280000, "y": 0, }, Object { - "x": 1593413157000, + "x": 1599719310000, "y": 0, }, Object { - "x": 1593413158000, + "x": 1599719340000, "y": 0, }, Object { - "x": 1593413159000, + "x": 1599719370000, "y": 0, }, Object { - "x": 1593413160000, + "x": 1599719400000, "y": 0, }, Object { - "x": 1593413161000, + "x": 1599719430000, "y": 0, }, Object { - "x": 1593413162000, + "x": 1599719460000, "y": 0, }, Object { - "x": 1593413163000, + "x": 1599719490000, "y": 0, }, Object { - "x": 1593413164000, + "x": 1599719520000, "y": 0, }, Object { - "x": 1593413165000, + "x": 1599719550000, "y": 0, }, Object { - "x": 1593413166000, + "x": 1599719580000, "y": 0, }, Object { - "x": 1593413167000, + "x": 1599719610000, "y": 0, }, Object { - "x": 1593413168000, + "x": 1599719640000, "y": 0, }, Object { - "x": 1593413169000, + "x": 1599719670000, "y": 0, }, Object { - "x": 1593413170000, + "x": 1599719700000, "y": 0, }, Object { - "x": 1593413171000, + "x": 1599719730000, "y": 0, }, Object { - "x": 1593413172000, + "x": 1599719760000, "y": 0, }, Object { - "x": 1593413173000, + "x": 1599719790000, "y": 0, }, Object { - "x": 1593413174000, + "x": 1599719820000, "y": 0, }, Object { - "x": 1593413175000, + "x": 1599719850000, "y": 0, }, Object { - "x": 1593413176000, + "x": 1599719880000, "y": 0, }, Object { - "x": 1593413177000, + "x": 1599719910000, "y": 0, }, Object { - "x": 1593413178000, + "x": 1599719940000, "y": 0, }, Object { - "x": 1593413179000, - "y": 0, + "x": 1599719970000, + "y": 1, }, Object { - "x": 1593413180000, + "x": 1599720000000, "y": 0, }, Object { - "x": 1593413181000, + "x": 1599720030000, "y": 0, }, Object { - "x": 1593413182000, + "x": 1599720060000, "y": 0, }, Object { - "x": 1593413183000, + "x": 1599720090000, "y": 0, }, Object { - "x": 1593413184000, + "x": 1599720120000, "y": 0, }, Object { - "x": 1593413185000, + "x": 1599720150000, "y": 0, }, Object { - "x": 1593413186000, + "x": 1599720180000, "y": 0, }, Object { - "x": 1593413187000, + "x": 1599720210000, "y": 0, }, Object { - "x": 1593413188000, + "x": 1599720240000, "y": 0, }, Object { - "x": 1593413189000, + "x": 1599720270000, "y": 0, }, Object { - "x": 1593413190000, + "x": 1599720300000, "y": 0, }, Object { - "x": 1593413191000, + "x": 1599720330000, "y": 0, }, Object { - "x": 1593413192000, + "x": 1599720360000, "y": 0, }, Object { - "x": 1593413193000, + "x": 1599720390000, "y": 0, }, Object { - "x": 1593413194000, + "x": 1599720420000, "y": 0, }, Object { - "x": 1593413195000, + "x": 1599720450000, "y": 0, }, Object { - "x": 1593413196000, + "x": 1599720480000, "y": 0, }, Object { - "x": 1593413197000, + "x": 1599720510000, "y": 0, }, Object { - "x": 1593413198000, + "x": 1599720540000, "y": 0, }, Object { - "x": 1593413199000, + "x": 1599720570000, "y": 0, }, Object { - "x": 1593413200000, + "x": 1599720600000, "y": 0, }, Object { - "x": 1593413201000, + "x": 1599720630000, "y": 0, }, Object { - "x": 1593413202000, + "x": 1599720660000, "y": 0, }, Object { - "x": 1593413203000, + "x": 1599720690000, "y": 0, }, Object { - "x": 1593413204000, + "x": 1599720720000, "y": 0, }, Object { - "x": 1593413205000, + "x": 1599720750000, "y": 0, }, Object { - "x": 1593413206000, + "x": 1599720780000, "y": 0, }, Object { - "x": 1593413207000, + "x": 1599720810000, "y": 0, }, Object { - "x": 1593413208000, + "x": 1599720840000, "y": 0, }, Object { - "x": 1593413209000, + "x": 1599720870000, "y": 0, }, Object { - "x": 1593413210000, + "x": 1599720900000, "y": 0, }, Object { - "x": 1593413211000, + "x": 1599720930000, "y": 0, }, Object { - "x": 1593413212000, + "x": 1599720960000, "y": 0, }, Object { - "x": 1593413213000, + "x": 1599720990000, "y": 0, }, Object { - "x": 1593413214000, + "x": 1599721020000, "y": 0, }, Object { - "x": 1593413215000, + "x": 1599721050000, "y": 0, }, Object { - "x": 1593413216000, - "y": 0, + "x": 1599721080000, + "y": 1, }, Object { - "x": 1593413217000, + "x": 1599721110000, "y": 0, }, Object { - "x": 1593413218000, + "x": 1599721140000, "y": 0, }, Object { - "x": 1593413219000, + "x": 1599721170000, "y": 0, }, Object { - "x": 1593413220000, + "x": 1599721200000, "y": 0, }, + ], + "key": "HTTP 5xx", + }, + Object { + "avg": 4.283333333333333, + "dataPoints": Array [ Object { - "x": 1593413221000, - "y": 0, + "x": 1599717600000, + "y": 2, }, Object { - "x": 1593413222000, - "y": 0, + "x": 1599717630000, + "y": 3, }, Object { - "x": 1593413223000, - "y": 0, + "x": 1599717660000, + "y": 1, }, Object { - "x": 1593413224000, - "y": 0, + "x": 1599717690000, + "y": 4, }, Object { - "x": 1593413225000, - "y": 0, + "x": 1599717720000, + "y": 3, }, Object { - "x": 1593413226000, - "y": 0, + "x": 1599717750000, + "y": 4, }, Object { - "x": 1593413227000, - "y": 0, + "x": 1599717780000, + "y": 2, }, Object { - "x": 1593413228000, - "y": 0, + "x": 1599717810000, + "y": 3, }, Object { - "x": 1593413229000, - "y": 0, + "x": 1599717840000, + "y": 2, }, Object { - "x": 1593413230000, - "y": 0, + "x": 1599717870000, + "y": 2, }, Object { - "x": 1593413231000, - "y": 0, + "x": 1599717900000, + "y": 1, }, Object { - "x": 1593413232000, - "y": 0, + "x": 1599717930000, + "y": 3, }, Object { - "x": 1593413233000, - "y": 0, + "x": 1599717960000, + "y": 1, }, Object { - "x": 1593413234000, - "y": 0, + "x": 1599717990000, + "y": 2, }, Object { - "x": 1593413235000, - "y": 0, + "x": 1599718020000, + "y": 3, }, Object { - "x": 1593413236000, - "y": 0, + "x": 1599718050000, + "y": 1, }, Object { - "x": 1593413237000, - "y": 0, + "x": 1599718080000, + "y": 2, }, Object { - "x": 1593413238000, - "y": 0, + "x": 1599718110000, + "y": 1, }, Object { - "x": 1593413239000, - "y": 0, + "x": 1599718140000, + "y": 3, }, Object { - "x": 1593413240000, - "y": 0, + "x": 1599718170000, + "y": 3, }, Object { - "x": 1593413241000, - "y": 0, + "x": 1599718200000, + "y": 2, }, Object { - "x": 1593413242000, - "y": 0, + "x": 1599718230000, + "y": 2, }, Object { - "x": 1593413243000, - "y": 0, + "x": 1599718260000, + "y": 2, }, Object { - "x": 1593413244000, - "y": 0, + "x": 1599718290000, + "y": 2, }, Object { - "x": 1593413245000, - "y": 0, + "x": 1599718320000, + "y": 2, }, Object { - "x": 1593413246000, - "y": 0, + "x": 1599718350000, + "y": 3, }, Object { - "x": 1593413247000, - "y": 0, + "x": 1599718380000, + "y": 3, }, Object { - "x": 1593413248000, - "y": 0, + "x": 1599718410000, + "y": 2, }, Object { - "x": 1593413249000, - "y": 0, + "x": 1599718440000, + "y": 2, }, Object { - "x": 1593413250000, - "y": 0, + "x": 1599718470000, + "y": 2, }, Object { - "x": 1593413251000, - "y": 0, + "x": 1599718500000, + "y": 2, }, Object { - "x": 1593413252000, - "y": 0, + "x": 1599718530000, + "y": 3, }, Object { - "x": 1593413253000, - "y": 0, + "x": 1599718560000, + "y": 1, }, Object { - "x": 1593413254000, - "y": 0, + "x": 1599718590000, + "y": 3, }, Object { - "x": 1593413255000, - "y": 0, + "x": 1599718620000, + "y": 3, }, Object { - "x": 1593413256000, - "y": 0, + "x": 1599718650000, + "y": 1, }, Object { - "x": 1593413257000, - "y": 0, + "x": 1599718680000, + "y": 3, }, Object { - "x": 1593413258000, - "y": 0, + "x": 1599718710000, + "y": 2, }, Object { - "x": 1593413259000, - "y": 0, + "x": 1599718740000, + "y": 1, }, Object { - "x": 1593413260000, - "y": 0, + "x": 1599718770000, + "y": 2, }, Object { - "x": 1593413261000, - "y": 0, + "x": 1599718800000, + "y": 2, }, Object { - "x": 1593413262000, - "y": 0, + "x": 1599718830000, + "y": 4, }, Object { - "x": 1593413263000, - "y": 0, + "x": 1599718860000, + "y": 2, }, Object { - "x": 1593413264000, - "y": 0, + "x": 1599718890000, + "y": 2, }, Object { - "x": 1593413265000, - "y": 0, + "x": 1599718920000, + "y": 1, }, Object { - "x": 1593413266000, - "y": 0, + "x": 1599718950000, + "y": 2, }, Object { - "x": 1593413267000, - "y": 0, + "x": 1599718980000, + "y": 3, }, Object { - "x": 1593413268000, - "y": 0, + "x": 1599719010000, + "y": 3, }, Object { - "x": 1593413269000, - "y": 0, + "x": 1599719040000, + "y": 1, }, Object { - "x": 1593413270000, - "y": 0, + "x": 1599719070000, + "y": 3, }, Object { - "x": 1593413271000, - "y": 0, + "x": 1599719100000, + "y": 2, }, Object { - "x": 1593413272000, - "y": 0, + "x": 1599719130000, + "y": 3, }, Object { - "x": 1593413273000, - "y": 0, + "x": 1599719160000, + "y": 1, }, Object { - "x": 1593413274000, - "y": 0, + "x": 1599719190000, + "y": 1, }, Object { - "x": 1593413275000, - "y": 0, + "x": 1599719220000, + "y": 4, }, Object { - "x": 1593413276000, + "x": 1599719250000, "y": 0, }, Object { - "x": 1593413277000, - "y": 0, + "x": 1599719280000, + "y": 4, }, Object { - "x": 1593413278000, + "x": 1599719310000, "y": 0, }, Object { - "x": 1593413279000, - "y": 0, + "x": 1599719340000, + "y": 2, }, Object { - "x": 1593413280000, - "y": 0, + "x": 1599719370000, + "y": 1, }, Object { - "x": 1593413281000, - "y": 0, + "x": 1599719400000, + "y": 4, }, Object { - "x": 1593413282000, - "y": 0, + "x": 1599719430000, + "y": 1, }, Object { - "x": 1593413283000, - "y": 0, + "x": 1599719460000, + "y": 3, }, Object { - "x": 1593413284000, - "y": 0, + "x": 1599719490000, + "y": 3, }, Object { - "x": 1593413285000, - "y": 0, + "x": 1599719520000, + "y": 2, }, Object { - "x": 1593413286000, - "y": 0, + "x": 1599719550000, + "y": 1, }, Object { - "x": 1593413287000, - "y": 0, + "x": 1599719580000, + "y": 4, }, Object { - "x": 1593413288000, - "y": 0, + "x": 1599719610000, + "y": 1, }, Object { - "x": 1593413289000, - "y": 0, + "x": 1599719640000, + "y": 2, }, Object { - "x": 1593413290000, - "y": 0, + "x": 1599719670000, + "y": 3, }, Object { - "x": 1593413291000, + "x": 1599719700000, "y": 0, }, Object { - "x": 1593413292000, - "y": 0, + "x": 1599719730000, + "y": 2, }, Object { - "x": 1593413293000, - "y": 0, + "x": 1599719760000, + "y": 4, }, Object { - "x": 1593413294000, - "y": 0, + "x": 1599719790000, + "y": 1, }, Object { - "x": 1593413295000, - "y": 0, + "x": 1599719820000, + "y": 2, }, Object { - "x": 1593413296000, - "y": 0, + "x": 1599719850000, + "y": 2, }, Object { - "x": 1593413297000, - "y": 0, + "x": 1599719880000, + "y": 2, }, Object { - "x": 1593413298000, - "y": 0, + "x": 1599719910000, + "y": 3, }, Object { - "x": 1593413299000, - "y": 0, + "x": 1599719940000, + "y": 3, }, Object { - "x": 1593413300000, - "y": 0, + "x": 1599719970000, + "y": 2, }, Object { - "x": 1593413301000, - "y": 0, + "x": 1599720000000, + "y": 2, }, Object { - "x": 1593413302000, - "y": 0, + "x": 1599720030000, + "y": 2, }, Object { - "x": 1593413303000, - "y": 0, + "x": 1599720060000, + "y": 1, }, Object { - "x": 1593413304000, - "y": 0, + "x": 1599720090000, + "y": 2, }, Object { - "x": 1593413305000, - "y": 0, + "x": 1599720120000, + "y": 1, }, Object { - "x": 1593413306000, - "y": 0, + "x": 1599720150000, + "y": 3, }, Object { - "x": 1593413307000, - "y": 0, + "x": 1599720180000, + "y": 2, }, Object { - "x": 1593413308000, - "y": 0, + "x": 1599720210000, + "y": 1, }, Object { - "x": 1593413309000, - "y": 1, + "x": 1599720240000, + "y": 3, }, Object { - "x": 1593413310000, - "y": 0, + "x": 1599720270000, + "y": 3, }, Object { - "x": 1593413311000, - "y": 0, + "x": 1599720300000, + "y": 2, }, Object { - "x": 1593413312000, - "y": 0, + "x": 1599720330000, + "y": 1, }, Object { - "x": 1593413313000, - "y": 0, + "x": 1599720360000, + "y": 2, }, Object { - "x": 1593413314000, - "y": 0, + "x": 1599720390000, + "y": 5, }, Object { - "x": 1593413315000, - "y": 0, + "x": 1599720420000, + "y": 2, }, Object { - "x": 1593413316000, - "y": 0, + "x": 1599720450000, + "y": 1, }, Object { - "x": 1593413317000, - "y": 0, + "x": 1599720480000, + "y": 3, }, Object { - "x": 1593413318000, - "y": 0, + "x": 1599720510000, + "y": 2, }, Object { - "x": 1593413319000, - "y": 0, + "x": 1599720540000, + "y": 2, }, Object { - "x": 1593413320000, - "y": 0, + "x": 1599720570000, + "y": 2, }, Object { - "x": 1593413321000, - "y": 0, + "x": 1599720600000, + "y": 1, }, Object { - "x": 1593413322000, - "y": 0, + "x": 1599720630000, + "y": 3, }, Object { - "x": 1593413323000, - "y": 0, + "x": 1599720660000, + "y": 2, }, Object { - "x": 1593413324000, - "y": 0, + "x": 1599720690000, + "y": 1, }, Object { - "x": 1593413325000, - "y": 0, + "x": 1599720720000, + "y": 2, }, Object { - "x": 1593413326000, - "y": 0, + "x": 1599720750000, + "y": 2, }, Object { - "x": 1593413327000, - "y": 0, + "x": 1599720780000, + "y": 2, }, Object { - "x": 1593413328000, - "y": 0, + "x": 1599720810000, + "y": 2, }, Object { - "x": 1593413329000, - "y": 0, + "x": 1599720840000, + "y": 2, }, Object { - "x": 1593413330000, - "y": 0, + "x": 1599720870000, + "y": 3, }, Object { - "x": 1593413331000, - "y": 0, + "x": 1599720900000, + "y": 1, }, Object { - "x": 1593413332000, - "y": 0, + "x": 1599720930000, + "y": 1, }, Object { - "x": 1593413333000, - "y": 0, + "x": 1599720960000, + "y": 3, }, Object { - "x": 1593413334000, - "y": 0, + "x": 1599720990000, + "y": 3, }, Object { - "x": 1593413335000, - "y": 0, + "x": 1599721020000, + "y": 1, }, Object { - "x": 1593413336000, - "y": 0, + "x": 1599721050000, + "y": 2, }, Object { - "x": 1593413337000, - "y": 0, + "x": 1599721080000, + "y": 2, }, Object { - "x": 1593413338000, - "y": 0, + "x": 1599721110000, + "y": 3, }, Object { - "x": 1593413339000, - "y": 0, + "x": 1599721140000, + "y": 2, + }, + Object { + "x": 1599721170000, + "y": 2, }, Object { - "x": 1593413340000, + "x": 1599721200000, "y": 0, }, ], diff --git a/x-pack/test/apm_api_integration/basic/tests/transaction_groups/avg_duration_by_browser.ts b/x-pack/test/apm_api_integration/basic/tests/transaction_groups/avg_duration_by_browser.ts index 21f3aaa04a7b3..087bf1f0655e6 100644 --- a/x-pack/test/apm_api_integration/basic/tests/transaction_groups/avg_duration_by_browser.ts +++ b/x-pack/test/apm_api_integration/basic/tests/transaction_groups/avg_duration_by_browser.ts @@ -4,6 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ import expect from '@kbn/expect'; +import archives_metadata from '../../../common/archives_metadata'; import { expectSnapshot } from '../../../common/match_snapshot'; import { FtrProviderContext } from '../../../common/ftr_provider_context'; @@ -11,8 +12,11 @@ export default function ApiTest({ getService }: FtrProviderContext) { const supertest = getService('supertest'); const esArchiver = getService('esArchiver'); - const start = encodeURIComponent('2020-06-29T06:45:00.000Z'); - const end = encodeURIComponent('2020-06-29T06:49:00.000Z'); + const archiveName = 'apm_8.0.0'; + const metadata = archives_metadata[archiveName]; + + const start = encodeURIComponent(metadata.start); + const end = encodeURIComponent(metadata.end); const transactionName = '/products'; const uiFilters = encodeURIComponent(JSON.stringify({})); @@ -28,23 +32,34 @@ export default function ApiTest({ getService }: FtrProviderContext) { }); describe('when data is loaded', () => { - before(() => esArchiver.load('8.0.0')); - after(() => esArchiver.unload('8.0.0')); + before(() => esArchiver.load(archiveName)); + after(() => esArchiver.unload(archiveName)); it('returns the average duration by browser', async () => { const response = await supertest.get( - `/api/apm/services/client/transaction_groups/avg_duration_by_browser?start=${start}&end=${end}&uiFilters=${uiFilters}` + `/api/apm/services/opbeans-rum/transaction_groups/avg_duration_by_browser?start=${start}&end=${end}&uiFilters=${uiFilters}` ); expect(response.status).to.be(200); + + expect(response.body.length).to.be.greaterThan(0); + expectSnapshot(response.body).toMatch(); + + expectSnapshot(response.body.length).toMatchInline(`1`); }); + it('returns the average duration by browser filtering by transaction name', async () => { const response = await supertest.get( - `/api/apm/services/client/transaction_groups/avg_duration_by_browser?start=${start}&end=${end}&uiFilters=${uiFilters}&transactionName=${transactionName}` + `/api/apm/services/opbeans-rum/transaction_groups/avg_duration_by_browser?start=${start}&end=${end}&uiFilters=${uiFilters}&transactionName=${transactionName}` ); expect(response.status).to.be(200); + + expect(response.body.length).to.be.greaterThan(0); + + expectSnapshot(response.body.length).toMatchInline(`1`); + expectSnapshot(response.body).toMatch(); }); }); diff --git a/x-pack/test/apm_api_integration/basic/tests/transaction_groups/breakdown.ts b/x-pack/test/apm_api_integration/basic/tests/transaction_groups/breakdown.ts index 4e1b1e57fba0f..27e26bebd825b 100644 --- a/x-pack/test/apm_api_integration/basic/tests/transaction_groups/breakdown.ts +++ b/x-pack/test/apm_api_integration/basic/tests/transaction_groups/breakdown.ts @@ -4,6 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ import expect from '@kbn/expect'; +import archives_metadata from '../../../common/archives_metadata'; import { expectSnapshot } from '../../../common/match_snapshot'; import { FtrProviderContext } from '../../../common/ftr_provider_context'; @@ -11,8 +12,11 @@ export default function ApiTest({ getService }: FtrProviderContext) { const supertest = getService('supertest'); const esArchiver = getService('esArchiver'); - const start = encodeURIComponent('2020-06-29T06:45:00.000Z'); - const end = encodeURIComponent('2020-06-29T06:49:00.000Z'); + const archiveName = 'apm_8.0.0'; + const metadata = archives_metadata[archiveName]; + + const start = encodeURIComponent(metadata.start); + const end = encodeURIComponent(metadata.end); const transactionType = 'request'; const transactionName = 'GET /api'; const uiFilters = encodeURIComponent(JSON.stringify({})); @@ -29,8 +33,8 @@ export default function ApiTest({ getService }: FtrProviderContext) { }); describe('when data is loaded', () => { - before(() => esArchiver.load('8.0.0')); - after(() => esArchiver.unload('8.0.0')); + before(() => esArchiver.load(archiveName)); + after(() => esArchiver.unload(archiveName)); it('returns the transaction breakdown for a service', async () => { const response = await supertest.get( @@ -46,45 +50,46 @@ export default function ApiTest({ getService }: FtrProviderContext) { ); expect(response.status).to.be(200); + const { timeseries } = response.body; + + const numberOfSeries = timeseries.length; + + expectSnapshot(numberOfSeries).toMatchInline(`1`); + const { title, color, type, data, hideLegend, legendValue } = timeseries[0]; - expectSnapshot(data).toMatchInline(` + const nonNullDataPoints = data.filter((y: number | null) => y !== null); + + expectSnapshot(nonNullDataPoints.length).toMatchInline(`121`); + + expectSnapshot( + data.slice(0, 5).map(({ x, y }: { x: number; y: number | null }) => { + return { + x: new Date(x ?? NaN).toISOString(), + y, + }; + }) + ).toMatchInline(` Array [ Object { - "x": 1593413100000, - "y": null, - }, - Object { - "x": 1593413130000, - "y": null, - }, - Object { - "x": 1593413160000, - "y": null, - }, - Object { - "x": 1593413190000, - "y": null, - }, - Object { - "x": 1593413220000, - "y": null, + "x": "2020-09-10T06:00:00.000Z", + "y": 1, }, Object { - "x": 1593413250000, - "y": null, + "x": "2020-09-10T06:00:30.000Z", + "y": 1, }, Object { - "x": 1593413280000, + "x": "2020-09-10T06:01:00.000Z", "y": null, }, Object { - "x": 1593413310000, + "x": "2020-09-10T06:01:30.000Z", "y": 1, }, Object { - "x": 1593413340000, + "x": "2020-09-10T06:02:00.000Z", "y": null, }, ] @@ -95,6 +100,8 @@ export default function ApiTest({ getService }: FtrProviderContext) { expectSnapshot(type).toMatchInline(`"areaStacked"`); expectSnapshot(hideLegend).toMatchInline(`false`); expectSnapshot(legendValue).toMatchInline(`"100%"`); + + expectSnapshot(data).toMatch(); }); it('returns the transaction breakdown sorted by name', async () => { const response = await supertest.get( @@ -108,7 +115,6 @@ export default function ApiTest({ getService }: FtrProviderContext) { "app", "http", "postgresql", - "redis", ] `); }); diff --git a/x-pack/test/apm_api_integration/basic/tests/transaction_groups/error_rate.ts b/x-pack/test/apm_api_integration/basic/tests/transaction_groups/error_rate.ts index cf23883612b7c..c7e84bd5270ee 100644 --- a/x-pack/test/apm_api_integration/basic/tests/transaction_groups/error_rate.ts +++ b/x-pack/test/apm_api_integration/basic/tests/transaction_groups/error_rate.ts @@ -5,6 +5,7 @@ */ import expect from '@kbn/expect'; import { first, last } from 'lodash'; +import archives_metadata from '../../../common/archives_metadata'; import { expectSnapshot } from '../../../common/match_snapshot'; import { FtrProviderContext } from '../../../common/ftr_provider_context'; @@ -12,9 +13,12 @@ export default function ApiTest({ getService }: FtrProviderContext) { const supertest = getService('supertest'); const esArchiver = getService('esArchiver'); + const archiveName = 'apm_8.0.0'; + const metadata = archives_metadata[archiveName]; + // url parameters - const start = encodeURIComponent('2020-08-26T11:00:00.000Z'); - const end = encodeURIComponent('2020-08-26T11:30:00.000Z'); + const start = encodeURIComponent(metadata.start); + const end = encodeURIComponent(metadata.end); const uiFilters = encodeURIComponent(JSON.stringify({})); describe('Error rate', () => { @@ -24,16 +28,16 @@ export default function ApiTest({ getService }: FtrProviderContext) { `/api/apm/services/opbeans-java/transaction_groups/error_rate?start=${start}&end=${end}&uiFilters=${uiFilters}` ); expect(response.status).to.be(200); - expect(response.body).to.eql({ - noHits: true, - erroneousTransactionsRate: [], - average: null, - }); + + expect(response.body.noHits).to.be(true); + + expect(response.body.erroneousTransactionsRate.length).to.be(0); + expect(response.body.average).to.be(null); }); }); describe('when data is loaded', () => { - before(() => esArchiver.load('8.0.0')); - after(() => esArchiver.unload('8.0.0')); + before(() => esArchiver.load(archiveName)); + after(() => esArchiver.unload(archiveName)); describe('returns the transaction error rate', () => { let errorRateResponse: { @@ -50,26 +54,26 @@ export default function ApiTest({ getService }: FtrProviderContext) { it('has the correct start date', () => { expectSnapshot( new Date(first(errorRateResponse.erroneousTransactionsRate)?.x ?? NaN).toISOString() - ).toMatchInline(`"2020-08-26T11:00:00.000Z"`); + ).toMatchInline(`"2020-09-10T06:00:00.000Z"`); }); it('has the correct end date', () => { expectSnapshot( new Date(last(errorRateResponse.erroneousTransactionsRate)?.x ?? NaN).toISOString() - ).toMatchInline(`"2020-08-26T11:30:00.000Z"`); + ).toMatchInline(`"2020-09-10T07:00:00.000Z"`); }); it('has the correct number of buckets', () => { - expectSnapshot(errorRateResponse.erroneousTransactionsRate.length).toMatchInline(`61`); + expectSnapshot(errorRateResponse.erroneousTransactionsRate.length).toMatchInline(`121`); }); it('has the correct calculation for average', () => { - expectSnapshot(errorRateResponse.average).toMatchInline(`0.18894993894993897`); + expectSnapshot(errorRateResponse.average).toMatchInline(`0.16097046413502106`); }); it('has the correct error rate', () => { expectSnapshot(first(errorRateResponse.erroneousTransactionsRate)?.y).toMatchInline( - `0.5` + `0.6666666666666666` ); }); }); diff --git a/x-pack/test/apm_api_integration/basic/tests/transaction_groups/top_transaction_groups.ts b/x-pack/test/apm_api_integration/basic/tests/transaction_groups/top_transaction_groups.ts index cebf27ecdff2b..e944235ac41a8 100644 --- a/x-pack/test/apm_api_integration/basic/tests/transaction_groups/top_transaction_groups.ts +++ b/x-pack/test/apm_api_integration/basic/tests/transaction_groups/top_transaction_groups.ts @@ -5,6 +5,7 @@ */ import expect from '@kbn/expect'; import { sortBy } from 'lodash'; +import archives_metadata from '../../../common/archives_metadata'; import { expectSnapshot } from '../../../common/match_snapshot'; import { FtrProviderContext } from '../../../../common/ftr_provider_context'; @@ -20,9 +21,12 @@ export default function ApiTest({ getService }: FtrProviderContext) { const supertest = getService('supertest'); const esArchiver = getService('esArchiver'); + const archiveName = 'apm_8.0.0'; + const metadata = archives_metadata[archiveName]; + // url parameters - const start = encodeURIComponent('2020-06-29T06:45:00.000Z'); - const end = encodeURIComponent('2020-06-29T06:49:00.000Z'); + const start = encodeURIComponent(metadata.start); + const end = encodeURIComponent(metadata.end); const uiFilters = encodeURIComponent(JSON.stringify({})); const transactionType = 'request'; @@ -34,39 +38,37 @@ export default function ApiTest({ getService }: FtrProviderContext) { ); expect(response.status).to.be(200); - expectSnapshot(response.body).toMatchInline(` - Object { - "bucketSize": 1000, - "isAggregationAccurate": true, - "items": Array [], - } - `); + + expect(response.body.isAggregationAccurate).to.be(true); + expect(response.body.items.length).to.be(0); }); }); describe('when data is loaded', () => { let response: any; before(async () => { - await esArchiver.load('8.0.0'); + await esArchiver.load(archiveName); response = await supertest.get( `/api/apm/services/opbeans-node/transaction_groups?start=${start}&end=${end}&uiFilters=${uiFilters}&transactionType=${transactionType}` ); }); - after(() => esArchiver.unload('8.0.0')); + after(() => esArchiver.unload(archiveName)); - it('returns the correct status code', async () => { + it('returns the correct metadata', () => { expect(response.status).to.be(200); + expect(response.body.isAggregationAccurate).to.be(true); + expect(response.body.items.length).to.be.greaterThan(0); }); - it('returns the correct number of buckets', async () => { - expectSnapshot(response.body.items.length).toMatchInline(`18`); + it('returns the correct number of buckets', () => { + expectSnapshot(response.body.items.length).toMatchInline(`13`); }); - it('returns the correct buckets (when ignoring samples)', async () => { + it('returns the correct buckets (when ignoring samples)', () => { expectSnapshot(omitSampleFromTransactionGroups(response.body.items)).toMatch(); }); - it('returns the correct buckets and samples', async () => { + it('returns the correct buckets and samples', () => { // sample should provide enough information to deeplink to a transaction detail page response.body.items.forEach((item: any) => { expect(item.sample.trace.id).to.be.an('string'); diff --git a/x-pack/test/apm_api_integration/basic/tests/transaction_groups/transaction_charts.ts b/x-pack/test/apm_api_integration/basic/tests/transaction_groups/transaction_charts.ts index a8418fe2860a3..43504a4ec401e 100644 --- a/x-pack/test/apm_api_integration/basic/tests/transaction_groups/transaction_charts.ts +++ b/x-pack/test/apm_api_integration/basic/tests/transaction_groups/transaction_charts.ts @@ -4,6 +4,8 @@ * you may not use this file except in compliance with the Elastic License. */ import expect from '@kbn/expect'; +import archives_metadata from '../../../common/archives_metadata'; +import { PromiseReturnType } from '../../../../../plugins/apm/typings/common'; import { expectSnapshot } from '../../../common/match_snapshot'; import { FtrProviderContext } from '../../../../common/ftr_provider_context'; @@ -11,9 +13,12 @@ export default function ApiTest({ getService }: FtrProviderContext) { const supertest = getService('supertest'); const esArchiver = getService('esArchiver'); + const archiveName = 'apm_8.0.0'; + const metadata = archives_metadata[archiveName]; + // url parameters - const start = encodeURIComponent('2020-06-29T06:45:00.000Z'); - const end = encodeURIComponent('2020-06-29T06:49:00.000Z'); + const start = encodeURIComponent(metadata.start); + const end = encodeURIComponent(metadata.end); const uiFilters = encodeURIComponent(JSON.stringify({})); describe('Transaction charts', () => { @@ -24,32 +29,44 @@ export default function ApiTest({ getService }: FtrProviderContext) { ); expect(response.status).to.be(200); - expectSnapshot(response.body).toMatchInline(` - Object { - "apmTimeseries": Object { - "overallAvgDuration": null, - "responseTimes": Object { - "avg": Array [], - "p95": Array [], - "p99": Array [], - }, - "tpmBuckets": Array [], - }, - } - `); + + expect(response.body.apmTimeseries.overallAvgDuration).to.be(null); + expect(response.body.apmTimeseries.responseTimes.avg.length).to.be(0); + expect(response.body.apmTimeseries.responseTimes.p95.length).to.be(0); + expect(response.body.apmTimeseries.responseTimes.p99.length).to.be(0); + expect(response.body.apmTimeseries.tpmBuckets.length).to.be(0); }); }); describe('when data is loaded', () => { - before(() => esArchiver.load('8.0.0')); - after(() => esArchiver.unload('8.0.0')); + before(() => esArchiver.load(archiveName)); + after(() => esArchiver.unload(archiveName)); - it('returns the transaction charts', async () => { - const response = await supertest.get( + let response: PromiseReturnType; + + before(async () => { + response = await supertest.get( `/api/apm/services/opbeans-node/transaction_groups/charts?start=${start}&end=${end}&uiFilters=${uiFilters}` ); + }); + it('returns some data', async () => { expect(response.status).to.be(200); + + expect(response.body.apmTimeseries.overallAvgDuration).not.to.be(null); + expect(response.body.apmTimeseries.responseTimes.avg.length).to.be.greaterThan(0); + expect(response.body.apmTimeseries.responseTimes.p95.length).to.be.greaterThan(0); + expect(response.body.apmTimeseries.responseTimes.p99.length).to.be.greaterThan(0); + expect(response.body.apmTimeseries.tpmBuckets.length).to.be.greaterThan(0); + }); + + it('returns the correct data', () => { + expectSnapshot(response.body.apmTimeseries.overallAvgDuration).toMatchInline( + `578297.1431623931` + ); + expectSnapshot(response.body.apmTimeseries.responseTimes.avg.length).toMatchInline(`121`); + expectSnapshot(response.body.apmTimeseries.tpmBuckets.length).toMatchInline(`4`); + expectSnapshot(response.body).toMatch(); }); }); diff --git a/x-pack/test/apm_api_integration/common/match_snapshot.ts b/x-pack/test/apm_api_integration/common/match_snapshot.ts index a8cb0418583af..4ac812a0ee168 100644 --- a/x-pack/test/apm_api_integration/common/match_snapshot.ts +++ b/x-pack/test/apm_api_integration/common/match_snapshot.ts @@ -12,6 +12,7 @@ import prettier from 'prettier'; // @ts-expect-error import babelTraverse from '@babel/traverse'; import { Suite, Test } from 'mocha'; +import { flatten } from 'lodash'; type ISnapshotState = InstanceType; @@ -143,18 +144,24 @@ Error.prepareStackTrace = (error, structuredStackTrace) => { } }; +function recursivelyGetTestsFromSuite(suite: Suite): Test[] { + return suite.tests.concat(flatten(suite.suites.map((s) => recursivelyGetTestsFromSuite(s)))); +} + function getSnapshotState(file: string, test: Test) { const dirname = path.dirname(file); const filename = path.basename(file); - let parent = test.parent; - const testsInFile: Test[] = []; + let parent: Suite | undefined = test.parent; - while (parent) { - testsInFile.push(...parent.tests); + while (parent && parent.parent?.file === file) { parent = parent.parent; } + if (!parent) { + throw new Error('Top-level suite not found'); + } + const snapshotState = new SnapshotState( path.join(dirname + `/__snapshots__/` + filename.replace(path.extname(filename), '.snap')), { @@ -164,7 +171,7 @@ function getSnapshotState(file: string, test: Test) { } ); - return { snapshotState, testsInFile }; + return { snapshotState, testsInFile: recursivelyGetTestsFromSuite(parent) }; } export function expectSnapshot(received: any) { diff --git a/x-pack/test/apm_api_integration/trial/tests/service_maps/__snapshots__/service_maps.snap b/x-pack/test/apm_api_integration/trial/tests/service_maps/__snapshots__/service_maps.snap new file mode 100644 index 0000000000000..859f928c211a4 --- /dev/null +++ b/x-pack/test/apm_api_integration/trial/tests/service_maps/__snapshots__/service_maps.snap @@ -0,0 +1,1393 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Service Maps with a trial license /api/apm/service-map when there is data returns the correct data 3`] = ` +Array [ + Object { + "data": Object { + "id": "opbeans-go~>postgresql", + "source": "opbeans-go", + "sourceData": Object { + "agent.name": "go", + "id": "opbeans-go", + "service.environment": "testing", + "service.name": "opbeans-go", + }, + "target": ">postgresql", + "targetData": Object { + "id": ">postgresql", + "label": "postgresql", + "span.destination.service.resource": "postgresql", + "span.subtype": "postgresql", + "span.type": "db", + }, + }, + }, + Object { + "data": Object { + "bidirectional": true, + "id": "opbeans-go~opbeans-node", + "source": "opbeans-go", + "sourceData": Object { + "agent.name": "go", + "id": "opbeans-go", + "service.environment": "testing", + "service.name": "opbeans-go", + }, + "target": "opbeans-node", + "targetData": Object { + "agent.name": "nodejs", + "id": "opbeans-node", + "service.environment": "testing", + "service.name": "opbeans-node", + }, + }, + }, + Object { + "data": Object { + "bidirectional": true, + "id": "opbeans-go~opbeans-python", + "source": "opbeans-go", + "sourceData": Object { + "agent.name": "go", + "id": "opbeans-go", + "service.environment": "testing", + "service.name": "opbeans-go", + }, + "target": "opbeans-python", + "targetData": Object { + "agent.name": "python", + "id": "opbeans-python", + "service.environment": "production", + "service.name": "opbeans-python", + }, + }, + }, + Object { + "data": Object { + "id": "opbeans-go~opbeans-ruby", + "source": "opbeans-go", + "sourceData": Object { + "agent.name": "go", + "id": "opbeans-go", + "service.environment": "testing", + "service.name": "opbeans-go", + }, + "target": "opbeans-ruby", + "targetData": Object { + "agent.name": "ruby", + "id": "opbeans-ruby", + "service.environment": "production", + "service.name": "opbeans-ruby", + }, + }, + }, + Object { + "data": Object { + "id": "opbeans-java~>postgresql", + "source": "opbeans-java", + "sourceData": Object { + "agent.name": "java", + "id": "opbeans-java", + "service.environment": "production", + "service.name": "opbeans-java", + "serviceAnomalyStats": Object { + "actualValue": 1707977.2499999995, + "anomalyScore": 0.12232533657975532, + "jobId": "apm-production-229a-high_mean_transaction_duration", + "transactionType": "request", + }, + }, + "target": ">postgresql", + "targetData": Object { + "id": ">postgresql", + "label": "postgresql", + "span.destination.service.resource": "postgresql", + "span.subtype": "postgresql", + "span.type": "db", + }, + }, + }, + Object { + "data": Object { + "bidirectional": true, + "id": "opbeans-java~opbeans-node", + "source": "opbeans-java", + "sourceData": Object { + "agent.name": "java", + "id": "opbeans-java", + "service.environment": "production", + "service.name": "opbeans-java", + "serviceAnomalyStats": Object { + "actualValue": 1707977.2499999995, + "anomalyScore": 0.12232533657975532, + "jobId": "apm-production-229a-high_mean_transaction_duration", + "transactionType": "request", + }, + }, + "target": "opbeans-node", + "targetData": Object { + "agent.name": "nodejs", + "id": "opbeans-node", + "service.environment": "testing", + "service.name": "opbeans-node", + }, + }, + }, + Object { + "data": Object { + "bidirectional": true, + "id": "opbeans-java~opbeans-python", + "source": "opbeans-java", + "sourceData": Object { + "agent.name": "java", + "id": "opbeans-java", + "service.environment": "production", + "service.name": "opbeans-java", + "serviceAnomalyStats": Object { + "actualValue": 1707977.2499999995, + "anomalyScore": 0.12232533657975532, + "jobId": "apm-production-229a-high_mean_transaction_duration", + "transactionType": "request", + }, + }, + "target": "opbeans-python", + "targetData": Object { + "agent.name": "python", + "id": "opbeans-python", + "service.environment": "production", + "service.name": "opbeans-python", + }, + }, + }, + Object { + "data": Object { + "bidirectional": true, + "id": "opbeans-java~opbeans-ruby", + "source": "opbeans-java", + "sourceData": Object { + "agent.name": "java", + "id": "opbeans-java", + "service.environment": "production", + "service.name": "opbeans-java", + "serviceAnomalyStats": Object { + "actualValue": 1707977.2499999995, + "anomalyScore": 0.12232533657975532, + "jobId": "apm-production-229a-high_mean_transaction_duration", + "transactionType": "request", + }, + }, + "target": "opbeans-ruby", + "targetData": Object { + "agent.name": "ruby", + "id": "opbeans-ruby", + "service.environment": "production", + "service.name": "opbeans-ruby", + }, + }, + }, + Object { + "data": Object { + "id": "opbeans-node~>postgresql", + "source": "opbeans-node", + "sourceData": Object { + "agent.name": "nodejs", + "id": "opbeans-node", + "service.environment": "testing", + "service.name": "opbeans-node", + }, + "target": ">postgresql", + "targetData": Object { + "id": ">postgresql", + "label": "postgresql", + "span.destination.service.resource": "postgresql", + "span.subtype": "postgresql", + "span.type": "db", + }, + }, + }, + Object { + "data": Object { + "id": "opbeans-node~opbeans-go", + "isInverseEdge": true, + "source": "opbeans-node", + "sourceData": Object { + "agent.name": "nodejs", + "id": "opbeans-node", + "service.environment": "testing", + "service.name": "opbeans-node", + }, + "target": "opbeans-go", + "targetData": Object { + "agent.name": "go", + "id": "opbeans-go", + "service.environment": "testing", + "service.name": "opbeans-go", + }, + }, + }, + Object { + "data": Object { + "id": "opbeans-node~opbeans-java", + "isInverseEdge": true, + "source": "opbeans-node", + "sourceData": Object { + "agent.name": "nodejs", + "id": "opbeans-node", + "service.environment": "testing", + "service.name": "opbeans-node", + }, + "target": "opbeans-java", + "targetData": Object { + "agent.name": "java", + "id": "opbeans-java", + "service.environment": "production", + "service.name": "opbeans-java", + "serviceAnomalyStats": Object { + "actualValue": 1707977.2499999995, + "anomalyScore": 0.12232533657975532, + "jobId": "apm-production-229a-high_mean_transaction_duration", + "transactionType": "request", + }, + }, + }, + }, + Object { + "data": Object { + "bidirectional": true, + "id": "opbeans-node~opbeans-python", + "source": "opbeans-node", + "sourceData": Object { + "agent.name": "nodejs", + "id": "opbeans-node", + "service.environment": "testing", + "service.name": "opbeans-node", + }, + "target": "opbeans-python", + "targetData": Object { + "agent.name": "python", + "id": "opbeans-python", + "service.environment": "production", + "service.name": "opbeans-python", + }, + }, + }, + Object { + "data": Object { + "id": "opbeans-python~>elasticsearch", + "source": "opbeans-python", + "sourceData": Object { + "agent.name": "python", + "id": "opbeans-python", + "service.environment": "production", + "service.name": "opbeans-python", + }, + "target": ">elasticsearch", + "targetData": Object { + "id": ">elasticsearch", + "label": "elasticsearch", + "span.destination.service.resource": "elasticsearch", + "span.subtype": "elasticsearch", + "span.type": "db", + }, + }, + }, + Object { + "data": Object { + "id": "opbeans-python~>postgresql", + "source": "opbeans-python", + "sourceData": Object { + "agent.name": "python", + "id": "opbeans-python", + "service.environment": "production", + "service.name": "opbeans-python", + }, + "target": ">postgresql", + "targetData": Object { + "id": ">postgresql", + "label": "postgresql", + "span.destination.service.resource": "postgresql", + "span.subtype": "postgresql", + "span.type": "db", + }, + }, + }, + Object { + "data": Object { + "id": "opbeans-python~>redis", + "source": "opbeans-python", + "sourceData": Object { + "agent.name": "python", + "id": "opbeans-python", + "service.environment": "production", + "service.name": "opbeans-python", + }, + "target": ">redis", + "targetData": Object { + "id": ">redis", + "label": "redis", + "span.destination.service.resource": "redis", + "span.subtype": "redis", + "span.type": "db", + }, + }, + }, + Object { + "data": Object { + "id": "opbeans-python~opbeans-go", + "isInverseEdge": true, + "source": "opbeans-python", + "sourceData": Object { + "agent.name": "python", + "id": "opbeans-python", + "service.environment": "production", + "service.name": "opbeans-python", + }, + "target": "opbeans-go", + "targetData": Object { + "agent.name": "go", + "id": "opbeans-go", + "service.environment": "testing", + "service.name": "opbeans-go", + }, + }, + }, + Object { + "data": Object { + "id": "opbeans-python~opbeans-java", + "isInverseEdge": true, + "source": "opbeans-python", + "sourceData": Object { + "agent.name": "python", + "id": "opbeans-python", + "service.environment": "production", + "service.name": "opbeans-python", + }, + "target": "opbeans-java", + "targetData": Object { + "agent.name": "java", + "id": "opbeans-java", + "service.environment": "production", + "service.name": "opbeans-java", + "serviceAnomalyStats": Object { + "actualValue": 1707977.2499999995, + "anomalyScore": 0.12232533657975532, + "jobId": "apm-production-229a-high_mean_transaction_duration", + "transactionType": "request", + }, + }, + }, + }, + Object { + "data": Object { + "id": "opbeans-python~opbeans-node", + "isInverseEdge": true, + "source": "opbeans-python", + "sourceData": Object { + "agent.name": "python", + "id": "opbeans-python", + "service.environment": "production", + "service.name": "opbeans-python", + }, + "target": "opbeans-node", + "targetData": Object { + "agent.name": "nodejs", + "id": "opbeans-node", + "service.environment": "testing", + "service.name": "opbeans-node", + }, + }, + }, + Object { + "data": Object { + "bidirectional": true, + "id": "opbeans-python~opbeans-ruby", + "source": "opbeans-python", + "sourceData": Object { + "agent.name": "python", + "id": "opbeans-python", + "service.environment": "production", + "service.name": "opbeans-python", + }, + "target": "opbeans-ruby", + "targetData": Object { + "agent.name": "ruby", + "id": "opbeans-ruby", + "service.environment": "production", + "service.name": "opbeans-ruby", + }, + }, + }, + Object { + "data": Object { + "id": "opbeans-ruby~>postgresql", + "source": "opbeans-ruby", + "sourceData": Object { + "agent.name": "ruby", + "id": "opbeans-ruby", + "service.environment": "production", + "service.name": "opbeans-ruby", + }, + "target": ">postgresql", + "targetData": Object { + "id": ">postgresql", + "label": "postgresql", + "span.destination.service.resource": "postgresql", + "span.subtype": "postgresql", + "span.type": "db", + }, + }, + }, + Object { + "data": Object { + "id": "opbeans-ruby~opbeans-java", + "isInverseEdge": true, + "source": "opbeans-ruby", + "sourceData": Object { + "agent.name": "ruby", + "id": "opbeans-ruby", + "service.environment": "production", + "service.name": "opbeans-ruby", + }, + "target": "opbeans-java", + "targetData": Object { + "agent.name": "java", + "id": "opbeans-java", + "service.environment": "production", + "service.name": "opbeans-java", + "serviceAnomalyStats": Object { + "actualValue": 1707977.2499999995, + "anomalyScore": 0.12232533657975532, + "jobId": "apm-production-229a-high_mean_transaction_duration", + "transactionType": "request", + }, + }, + }, + }, + Object { + "data": Object { + "id": "opbeans-ruby~opbeans-node", + "source": "opbeans-ruby", + "sourceData": Object { + "agent.name": "ruby", + "id": "opbeans-ruby", + "service.environment": "production", + "service.name": "opbeans-ruby", + }, + "target": "opbeans-node", + "targetData": Object { + "agent.name": "nodejs", + "id": "opbeans-node", + "service.environment": "testing", + "service.name": "opbeans-node", + }, + }, + }, + Object { + "data": Object { + "id": "opbeans-ruby~opbeans-python", + "isInverseEdge": true, + "source": "opbeans-ruby", + "sourceData": Object { + "agent.name": "ruby", + "id": "opbeans-ruby", + "service.environment": "production", + "service.name": "opbeans-ruby", + }, + "target": "opbeans-python", + "targetData": Object { + "agent.name": "python", + "id": "opbeans-python", + "service.environment": "production", + "service.name": "opbeans-python", + }, + }, + }, + Object { + "data": Object { + "id": "opbeans-rum~opbeans-go", + "source": "opbeans-rum", + "sourceData": Object { + "agent.name": "rum-js", + "id": "opbeans-rum", + "service.environment": "testing", + "service.name": "opbeans-rum", + }, + "target": "opbeans-go", + "targetData": Object { + "agent.name": "go", + "id": "opbeans-go", + "service.environment": "testing", + "service.name": "opbeans-go", + }, + }, + }, + Object { + "data": Object { + "id": "opbeans-rum~opbeans-java", + "source": "opbeans-rum", + "sourceData": Object { + "agent.name": "rum-js", + "id": "opbeans-rum", + "service.environment": "testing", + "service.name": "opbeans-rum", + }, + "target": "opbeans-java", + "targetData": Object { + "agent.name": "java", + "id": "opbeans-java", + "service.environment": "production", + "service.name": "opbeans-java", + "serviceAnomalyStats": Object { + "actualValue": 1707977.2499999995, + "anomalyScore": 0.12232533657975532, + "jobId": "apm-production-229a-high_mean_transaction_duration", + "transactionType": "request", + }, + }, + }, + }, + Object { + "data": Object { + "id": "opbeans-rum~opbeans-node", + "source": "opbeans-rum", + "sourceData": Object { + "agent.name": "rum-js", + "id": "opbeans-rum", + "service.environment": "testing", + "service.name": "opbeans-rum", + }, + "target": "opbeans-node", + "targetData": Object { + "agent.name": "nodejs", + "id": "opbeans-node", + "service.environment": "testing", + "service.name": "opbeans-node", + }, + }, + }, + Object { + "data": Object { + "id": "opbeans-rum~opbeans-python", + "source": "opbeans-rum", + "sourceData": Object { + "agent.name": "rum-js", + "id": "opbeans-rum", + "service.environment": "testing", + "service.name": "opbeans-rum", + }, + "target": "opbeans-python", + "targetData": Object { + "agent.name": "python", + "id": "opbeans-python", + "service.environment": "production", + "service.name": "opbeans-python", + }, + }, + }, + Object { + "data": Object { + "id": "opbeans-rum~opbeans-ruby", + "source": "opbeans-rum", + "sourceData": Object { + "agent.name": "rum-js", + "id": "opbeans-rum", + "service.environment": "testing", + "service.name": "opbeans-rum", + }, + "target": "opbeans-ruby", + "targetData": Object { + "agent.name": "ruby", + "id": "opbeans-ruby", + "service.environment": "production", + "service.name": "opbeans-ruby", + }, + }, + }, + Object { + "data": Object { + "agent.name": "rum-js", + "id": "opbeans-rum", + "service.environment": "testing", + "service.name": "opbeans-rum", + }, + }, + Object { + "data": Object { + "agent.name": "go", + "id": "opbeans-go", + "service.environment": "testing", + "service.name": "opbeans-go", + }, + }, + Object { + "data": Object { + "agent.name": "nodejs", + "id": "opbeans-node", + "service.environment": "testing", + "service.name": "opbeans-node", + }, + }, + Object { + "data": Object { + "agent.name": "python", + "id": "opbeans-python", + "service.environment": "production", + "service.name": "opbeans-python", + }, + }, + Object { + "data": Object { + "agent.name": "ruby", + "id": "opbeans-ruby", + "service.environment": "production", + "service.name": "opbeans-ruby", + }, + }, + Object { + "data": Object { + "id": ">postgresql", + "label": "postgresql", + "span.destination.service.resource": "postgresql", + "span.subtype": "postgresql", + "span.type": "db", + }, + }, + Object { + "data": Object { + "id": ">elasticsearch", + "label": "elasticsearch", + "span.destination.service.resource": "elasticsearch", + "span.subtype": "elasticsearch", + "span.type": "db", + }, + }, + Object { + "data": Object { + "agent.name": "java", + "id": "opbeans-java", + "service.environment": "production", + "service.name": "opbeans-java", + "serviceAnomalyStats": Object { + "actualValue": 1707977.2499999995, + "anomalyScore": 0.12232533657975532, + "jobId": "apm-production-229a-high_mean_transaction_duration", + "transactionType": "request", + }, + }, + }, + Object { + "data": Object { + "id": ">redis", + "label": "redis", + "span.destination.service.resource": "redis", + "span.subtype": "redis", + "span.type": "db", + }, + }, + Object { + "data": Object { + "agent.name": "dotnet", + "id": "opbeans-dotnet", + "service.environment": null, + "service.name": "opbeans-dotnet", + }, + }, +] +`; + +exports[`Service Maps with a trial license when there is data with anomalies returns the correct anomaly stats 3`] = ` +Object { + "elements": Array [ + Object { + "data": Object { + "id": "opbeans-go~>postgresql", + "source": "opbeans-go", + "sourceData": Object { + "agent.name": "go", + "id": "opbeans-go", + "service.environment": "testing", + "service.name": "opbeans-go", + }, + "target": ">postgresql", + "targetData": Object { + "id": ">postgresql", + "label": "postgresql", + "span.destination.service.resource": "postgresql", + "span.subtype": "postgresql", + "span.type": "db", + }, + }, + }, + Object { + "data": Object { + "bidirectional": true, + "id": "opbeans-go~opbeans-node", + "source": "opbeans-go", + "sourceData": Object { + "agent.name": "go", + "id": "opbeans-go", + "service.environment": "testing", + "service.name": "opbeans-go", + }, + "target": "opbeans-node", + "targetData": Object { + "agent.name": "nodejs", + "id": "opbeans-node", + "service.environment": "testing", + "service.name": "opbeans-node", + }, + }, + }, + Object { + "data": Object { + "bidirectional": true, + "id": "opbeans-go~opbeans-python", + "source": "opbeans-go", + "sourceData": Object { + "agent.name": "go", + "id": "opbeans-go", + "service.environment": "testing", + "service.name": "opbeans-go", + }, + "target": "opbeans-python", + "targetData": Object { + "agent.name": "python", + "id": "opbeans-python", + "service.environment": "production", + "service.name": "opbeans-python", + }, + }, + }, + Object { + "data": Object { + "id": "opbeans-go~opbeans-ruby", + "source": "opbeans-go", + "sourceData": Object { + "agent.name": "go", + "id": "opbeans-go", + "service.environment": "testing", + "service.name": "opbeans-go", + }, + "target": "opbeans-ruby", + "targetData": Object { + "agent.name": "ruby", + "id": "opbeans-ruby", + "service.environment": "production", + "service.name": "opbeans-ruby", + }, + }, + }, + Object { + "data": Object { + "id": "opbeans-java~>postgresql", + "source": "opbeans-java", + "sourceData": Object { + "agent.name": "java", + "id": "opbeans-java", + "service.environment": "production", + "service.name": "opbeans-java", + "serviceAnomalyStats": Object { + "actualValue": 1707977.2499999995, + "anomalyScore": 0.12232533657975532, + "jobId": "apm-production-229a-high_mean_transaction_duration", + "transactionType": "request", + }, + }, + "target": ">postgresql", + "targetData": Object { + "id": ">postgresql", + "label": "postgresql", + "span.destination.service.resource": "postgresql", + "span.subtype": "postgresql", + "span.type": "db", + }, + }, + }, + Object { + "data": Object { + "bidirectional": true, + "id": "opbeans-java~opbeans-node", + "source": "opbeans-java", + "sourceData": Object { + "agent.name": "java", + "id": "opbeans-java", + "service.environment": "production", + "service.name": "opbeans-java", + "serviceAnomalyStats": Object { + "actualValue": 1707977.2499999995, + "anomalyScore": 0.12232533657975532, + "jobId": "apm-production-229a-high_mean_transaction_duration", + "transactionType": "request", + }, + }, + "target": "opbeans-node", + "targetData": Object { + "agent.name": "nodejs", + "id": "opbeans-node", + "service.environment": "testing", + "service.name": "opbeans-node", + }, + }, + }, + Object { + "data": Object { + "bidirectional": true, + "id": "opbeans-java~opbeans-python", + "source": "opbeans-java", + "sourceData": Object { + "agent.name": "java", + "id": "opbeans-java", + "service.environment": "production", + "service.name": "opbeans-java", + "serviceAnomalyStats": Object { + "actualValue": 1707977.2499999995, + "anomalyScore": 0.12232533657975532, + "jobId": "apm-production-229a-high_mean_transaction_duration", + "transactionType": "request", + }, + }, + "target": "opbeans-python", + "targetData": Object { + "agent.name": "python", + "id": "opbeans-python", + "service.environment": "production", + "service.name": "opbeans-python", + }, + }, + }, + Object { + "data": Object { + "bidirectional": true, + "id": "opbeans-java~opbeans-ruby", + "source": "opbeans-java", + "sourceData": Object { + "agent.name": "java", + "id": "opbeans-java", + "service.environment": "production", + "service.name": "opbeans-java", + "serviceAnomalyStats": Object { + "actualValue": 1707977.2499999995, + "anomalyScore": 0.12232533657975532, + "jobId": "apm-production-229a-high_mean_transaction_duration", + "transactionType": "request", + }, + }, + "target": "opbeans-ruby", + "targetData": Object { + "agent.name": "ruby", + "id": "opbeans-ruby", + "service.environment": "production", + "service.name": "opbeans-ruby", + }, + }, + }, + Object { + "data": Object { + "id": "opbeans-node~>postgresql", + "source": "opbeans-node", + "sourceData": Object { + "agent.name": "nodejs", + "id": "opbeans-node", + "service.environment": "testing", + "service.name": "opbeans-node", + }, + "target": ">postgresql", + "targetData": Object { + "id": ">postgresql", + "label": "postgresql", + "span.destination.service.resource": "postgresql", + "span.subtype": "postgresql", + "span.type": "db", + }, + }, + }, + Object { + "data": Object { + "id": "opbeans-node~opbeans-go", + "isInverseEdge": true, + "source": "opbeans-node", + "sourceData": Object { + "agent.name": "nodejs", + "id": "opbeans-node", + "service.environment": "testing", + "service.name": "opbeans-node", + }, + "target": "opbeans-go", + "targetData": Object { + "agent.name": "go", + "id": "opbeans-go", + "service.environment": "testing", + "service.name": "opbeans-go", + }, + }, + }, + Object { + "data": Object { + "id": "opbeans-node~opbeans-java", + "isInverseEdge": true, + "source": "opbeans-node", + "sourceData": Object { + "agent.name": "nodejs", + "id": "opbeans-node", + "service.environment": "testing", + "service.name": "opbeans-node", + }, + "target": "opbeans-java", + "targetData": Object { + "agent.name": "java", + "id": "opbeans-java", + "service.environment": "production", + "service.name": "opbeans-java", + "serviceAnomalyStats": Object { + "actualValue": 1707977.2499999995, + "anomalyScore": 0.12232533657975532, + "jobId": "apm-production-229a-high_mean_transaction_duration", + "transactionType": "request", + }, + }, + }, + }, + Object { + "data": Object { + "bidirectional": true, + "id": "opbeans-node~opbeans-python", + "source": "opbeans-node", + "sourceData": Object { + "agent.name": "nodejs", + "id": "opbeans-node", + "service.environment": "testing", + "service.name": "opbeans-node", + }, + "target": "opbeans-python", + "targetData": Object { + "agent.name": "python", + "id": "opbeans-python", + "service.environment": "production", + "service.name": "opbeans-python", + }, + }, + }, + Object { + "data": Object { + "id": "opbeans-python~>elasticsearch", + "source": "opbeans-python", + "sourceData": Object { + "agent.name": "python", + "id": "opbeans-python", + "service.environment": "production", + "service.name": "opbeans-python", + }, + "target": ">elasticsearch", + "targetData": Object { + "id": ">elasticsearch", + "label": "elasticsearch", + "span.destination.service.resource": "elasticsearch", + "span.subtype": "elasticsearch", + "span.type": "db", + }, + }, + }, + Object { + "data": Object { + "id": "opbeans-python~>postgresql", + "source": "opbeans-python", + "sourceData": Object { + "agent.name": "python", + "id": "opbeans-python", + "service.environment": "production", + "service.name": "opbeans-python", + }, + "target": ">postgresql", + "targetData": Object { + "id": ">postgresql", + "label": "postgresql", + "span.destination.service.resource": "postgresql", + "span.subtype": "postgresql", + "span.type": "db", + }, + }, + }, + Object { + "data": Object { + "id": "opbeans-python~>redis", + "source": "opbeans-python", + "sourceData": Object { + "agent.name": "python", + "id": "opbeans-python", + "service.environment": "production", + "service.name": "opbeans-python", + }, + "target": ">redis", + "targetData": Object { + "id": ">redis", + "label": "redis", + "span.destination.service.resource": "redis", + "span.subtype": "redis", + "span.type": "db", + }, + }, + }, + Object { + "data": Object { + "id": "opbeans-python~opbeans-go", + "isInverseEdge": true, + "source": "opbeans-python", + "sourceData": Object { + "agent.name": "python", + "id": "opbeans-python", + "service.environment": "production", + "service.name": "opbeans-python", + }, + "target": "opbeans-go", + "targetData": Object { + "agent.name": "go", + "id": "opbeans-go", + "service.environment": "testing", + "service.name": "opbeans-go", + }, + }, + }, + Object { + "data": Object { + "id": "opbeans-python~opbeans-java", + "isInverseEdge": true, + "source": "opbeans-python", + "sourceData": Object { + "agent.name": "python", + "id": "opbeans-python", + "service.environment": "production", + "service.name": "opbeans-python", + }, + "target": "opbeans-java", + "targetData": Object { + "agent.name": "java", + "id": "opbeans-java", + "service.environment": "production", + "service.name": "opbeans-java", + "serviceAnomalyStats": Object { + "actualValue": 1707977.2499999995, + "anomalyScore": 0.12232533657975532, + "jobId": "apm-production-229a-high_mean_transaction_duration", + "transactionType": "request", + }, + }, + }, + }, + Object { + "data": Object { + "id": "opbeans-python~opbeans-node", + "isInverseEdge": true, + "source": "opbeans-python", + "sourceData": Object { + "agent.name": "python", + "id": "opbeans-python", + "service.environment": "production", + "service.name": "opbeans-python", + }, + "target": "opbeans-node", + "targetData": Object { + "agent.name": "nodejs", + "id": "opbeans-node", + "service.environment": "testing", + "service.name": "opbeans-node", + }, + }, + }, + Object { + "data": Object { + "bidirectional": true, + "id": "opbeans-python~opbeans-ruby", + "source": "opbeans-python", + "sourceData": Object { + "agent.name": "python", + "id": "opbeans-python", + "service.environment": "production", + "service.name": "opbeans-python", + }, + "target": "opbeans-ruby", + "targetData": Object { + "agent.name": "ruby", + "id": "opbeans-ruby", + "service.environment": "production", + "service.name": "opbeans-ruby", + }, + }, + }, + Object { + "data": Object { + "id": "opbeans-ruby~>postgresql", + "source": "opbeans-ruby", + "sourceData": Object { + "agent.name": "ruby", + "id": "opbeans-ruby", + "service.environment": "production", + "service.name": "opbeans-ruby", + }, + "target": ">postgresql", + "targetData": Object { + "id": ">postgresql", + "label": "postgresql", + "span.destination.service.resource": "postgresql", + "span.subtype": "postgresql", + "span.type": "db", + }, + }, + }, + Object { + "data": Object { + "id": "opbeans-ruby~opbeans-java", + "isInverseEdge": true, + "source": "opbeans-ruby", + "sourceData": Object { + "agent.name": "ruby", + "id": "opbeans-ruby", + "service.environment": "production", + "service.name": "opbeans-ruby", + }, + "target": "opbeans-java", + "targetData": Object { + "agent.name": "java", + "id": "opbeans-java", + "service.environment": "production", + "service.name": "opbeans-java", + "serviceAnomalyStats": Object { + "actualValue": 1707977.2499999995, + "anomalyScore": 0.12232533657975532, + "jobId": "apm-production-229a-high_mean_transaction_duration", + "transactionType": "request", + }, + }, + }, + }, + Object { + "data": Object { + "id": "opbeans-ruby~opbeans-node", + "source": "opbeans-ruby", + "sourceData": Object { + "agent.name": "ruby", + "id": "opbeans-ruby", + "service.environment": "production", + "service.name": "opbeans-ruby", + }, + "target": "opbeans-node", + "targetData": Object { + "agent.name": "nodejs", + "id": "opbeans-node", + "service.environment": "testing", + "service.name": "opbeans-node", + }, + }, + }, + Object { + "data": Object { + "id": "opbeans-ruby~opbeans-python", + "isInverseEdge": true, + "source": "opbeans-ruby", + "sourceData": Object { + "agent.name": "ruby", + "id": "opbeans-ruby", + "service.environment": "production", + "service.name": "opbeans-ruby", + }, + "target": "opbeans-python", + "targetData": Object { + "agent.name": "python", + "id": "opbeans-python", + "service.environment": "production", + "service.name": "opbeans-python", + }, + }, + }, + Object { + "data": Object { + "id": "opbeans-rum~opbeans-go", + "source": "opbeans-rum", + "sourceData": Object { + "agent.name": "rum-js", + "id": "opbeans-rum", + "service.environment": "testing", + "service.name": "opbeans-rum", + }, + "target": "opbeans-go", + "targetData": Object { + "agent.name": "go", + "id": "opbeans-go", + "service.environment": "testing", + "service.name": "opbeans-go", + }, + }, + }, + Object { + "data": Object { + "id": "opbeans-rum~opbeans-java", + "source": "opbeans-rum", + "sourceData": Object { + "agent.name": "rum-js", + "id": "opbeans-rum", + "service.environment": "testing", + "service.name": "opbeans-rum", + }, + "target": "opbeans-java", + "targetData": Object { + "agent.name": "java", + "id": "opbeans-java", + "service.environment": "production", + "service.name": "opbeans-java", + "serviceAnomalyStats": Object { + "actualValue": 1707977.2499999995, + "anomalyScore": 0.12232533657975532, + "jobId": "apm-production-229a-high_mean_transaction_duration", + "transactionType": "request", + }, + }, + }, + }, + Object { + "data": Object { + "id": "opbeans-rum~opbeans-node", + "source": "opbeans-rum", + "sourceData": Object { + "agent.name": "rum-js", + "id": "opbeans-rum", + "service.environment": "testing", + "service.name": "opbeans-rum", + }, + "target": "opbeans-node", + "targetData": Object { + "agent.name": "nodejs", + "id": "opbeans-node", + "service.environment": "testing", + "service.name": "opbeans-node", + }, + }, + }, + Object { + "data": Object { + "id": "opbeans-rum~opbeans-python", + "source": "opbeans-rum", + "sourceData": Object { + "agent.name": "rum-js", + "id": "opbeans-rum", + "service.environment": "testing", + "service.name": "opbeans-rum", + }, + "target": "opbeans-python", + "targetData": Object { + "agent.name": "python", + "id": "opbeans-python", + "service.environment": "production", + "service.name": "opbeans-python", + }, + }, + }, + Object { + "data": Object { + "id": "opbeans-rum~opbeans-ruby", + "source": "opbeans-rum", + "sourceData": Object { + "agent.name": "rum-js", + "id": "opbeans-rum", + "service.environment": "testing", + "service.name": "opbeans-rum", + }, + "target": "opbeans-ruby", + "targetData": Object { + "agent.name": "ruby", + "id": "opbeans-ruby", + "service.environment": "production", + "service.name": "opbeans-ruby", + }, + }, + }, + Object { + "data": Object { + "agent.name": "rum-js", + "id": "opbeans-rum", + "service.environment": "testing", + "service.name": "opbeans-rum", + }, + }, + Object { + "data": Object { + "agent.name": "go", + "id": "opbeans-go", + "service.environment": "testing", + "service.name": "opbeans-go", + }, + }, + Object { + "data": Object { + "agent.name": "nodejs", + "id": "opbeans-node", + "service.environment": "testing", + "service.name": "opbeans-node", + }, + }, + Object { + "data": Object { + "agent.name": "python", + "id": "opbeans-python", + "service.environment": "production", + "service.name": "opbeans-python", + }, + }, + Object { + "data": Object { + "agent.name": "ruby", + "id": "opbeans-ruby", + "service.environment": "production", + "service.name": "opbeans-ruby", + }, + }, + Object { + "data": Object { + "id": ">postgresql", + "label": "postgresql", + "span.destination.service.resource": "postgresql", + "span.subtype": "postgresql", + "span.type": "db", + }, + }, + Object { + "data": Object { + "id": ">elasticsearch", + "label": "elasticsearch", + "span.destination.service.resource": "elasticsearch", + "span.subtype": "elasticsearch", + "span.type": "db", + }, + }, + Object { + "data": Object { + "agent.name": "java", + "id": "opbeans-java", + "service.environment": "production", + "service.name": "opbeans-java", + "serviceAnomalyStats": Object { + "actualValue": 1707977.2499999995, + "anomalyScore": 0.12232533657975532, + "jobId": "apm-production-229a-high_mean_transaction_duration", + "transactionType": "request", + }, + }, + }, + Object { + "data": Object { + "id": ">redis", + "label": "redis", + "span.destination.service.resource": "redis", + "span.subtype": "redis", + "span.type": "db", + }, + }, + Object { + "data": Object { + "agent.name": "dotnet", + "id": "opbeans-dotnet", + "service.environment": null, + "service.name": "opbeans-dotnet", + }, + }, + ], +} +`; diff --git a/x-pack/test/apm_api_integration/trial/tests/service_maps/service_maps.ts b/x-pack/test/apm_api_integration/trial/tests/service_maps/service_maps.ts index f799d80f6ef13..9dc13f58268df 100644 --- a/x-pack/test/apm_api_integration/trial/tests/service_maps/service_maps.ts +++ b/x-pack/test/apm_api_integration/trial/tests/service_maps/service_maps.ts @@ -6,7 +6,9 @@ import querystring from 'querystring'; import expect from '@kbn/expect'; -import { isEmpty } from 'lodash'; +import { isEmpty, uniq } from 'lodash'; +import archives_metadata from '../../../common/archives_metadata'; +import { PromiseReturnType } from '../../../../../plugins/apm/typings/common'; import { expectSnapshot } from '../../../common/match_snapshot'; import { FtrProviderContext } from '../../../common/ftr_provider_context'; @@ -14,13 +16,16 @@ export default function serviceMapsApiTests({ getService }: FtrProviderContext) const supertest = getService('supertest'); const esArchiver = getService('esArchiver'); + const archiveName = 'apm_8.0.0'; + const metadata = archives_metadata[archiveName]; + const start = encodeURIComponent(metadata.start); + const end = encodeURIComponent(metadata.end); + describe('Service Maps with a trial license', () => { describe('/api/apm/service-map', () => { describe('when there is no data', () => { it('returns empty list', async () => { - const response = await supertest.get( - '/api/apm/service-map?start=2020-06-28T10%3A24%3A46.055Z&end=2020-06-29T10%3A24%3A46.055Z' - ); + const response = await supertest.get(`/api/apm/service-map?start=${start}&end=${end}`); expect(response.status).to.be(200); expect(response.body.elements.length).to.be(0); @@ -28,239 +33,56 @@ export default function serviceMapsApiTests({ getService }: FtrProviderContext) }); describe('when there is data', () => { - before(() => esArchiver.load('8.0.0')); - after(() => esArchiver.unload('8.0.0')); + before(() => esArchiver.load(archiveName)); + after(() => esArchiver.unload(archiveName)); - it('returns service map elements', async () => { - const response = await supertest.get( - '/api/apm/service-map?start=2020-06-28T10%3A24%3A46.055Z&end=2020-06-29T10%3A24%3A46.055Z' - ); + let response: PromiseReturnType; + before(async () => { + response = await supertest.get(`/api/apm/service-map?start=${start}&end=${end}`); + }); + + it('returns service map elements', () => { expect(response.status).to.be(200); + expect(response.body.elements.length).to.be.greaterThan(0); + }); - expectSnapshot(response.body).toMatchInline(` - Object { - "elements": Array [ - Object { - "data": Object { - "id": "client~opbeans-node", - "source": "client", - "sourceData": Object { - "agent.name": "rum-js", - "id": "client", - "service.name": "client", - }, - "target": "opbeans-node", - "targetData": Object { - "agent.name": "nodejs", - "id": "opbeans-node", - "service.environment": "production", - "service.name": "opbeans-node", - }, - }, - }, - Object { - "data": Object { - "id": "opbeans-java~>opbeans-java:3000", - "source": "opbeans-java", - "sourceData": Object { - "agent.name": "java", - "id": "opbeans-java", - "service.environment": "production", - "service.name": "opbeans-java", - }, - "target": ">opbeans-java:3000", - "targetData": Object { - "id": ">opbeans-java:3000", - "label": "opbeans-java:3000", - "span.destination.service.resource": "opbeans-java:3000", - "span.subtype": "http", - "span.type": "external", - }, - }, - }, - Object { - "data": Object { - "id": "opbeans-java~>postgresql", - "source": "opbeans-java", - "sourceData": Object { - "agent.name": "java", - "id": "opbeans-java", - "service.environment": "production", - "service.name": "opbeans-java", - }, - "target": ">postgresql", - "targetData": Object { - "id": ">postgresql", - "label": "postgresql", - "span.destination.service.resource": "postgresql", - "span.subtype": "postgresql", - "span.type": "db", - }, - }, - }, - Object { - "data": Object { - "bidirectional": true, - "id": "opbeans-java~opbeans-node", - "source": "opbeans-java", - "sourceData": Object { - "agent.name": "java", - "id": "opbeans-java", - "service.environment": "production", - "service.name": "opbeans-java", - }, - "target": "opbeans-node", - "targetData": Object { - "agent.name": "nodejs", - "id": "opbeans-node", - "service.environment": "production", - "service.name": "opbeans-node", - }, - }, - }, - Object { - "data": Object { - "id": "opbeans-node~>93.184.216.34:80", - "source": "opbeans-node", - "sourceData": Object { - "agent.name": "nodejs", - "id": "opbeans-node", - "service.environment": "production", - "service.name": "opbeans-node", - }, - "target": ">93.184.216.34:80", - "targetData": Object { - "id": ">93.184.216.34:80", - "label": "93.184.216.34:80", - "span.destination.service.resource": "93.184.216.34:80", - "span.subtype": "http", - "span.type": "external", - }, - }, - }, - Object { - "data": Object { - "id": "opbeans-node~>postgresql", - "source": "opbeans-node", - "sourceData": Object { - "agent.name": "nodejs", - "id": "opbeans-node", - "service.environment": "production", - "service.name": "opbeans-node", - }, - "target": ">postgresql", - "targetData": Object { - "id": ">postgresql", - "label": "postgresql", - "span.destination.service.resource": "postgresql", - "span.subtype": "postgresql", - "span.type": "db", - }, - }, - }, - Object { - "data": Object { - "id": "opbeans-node~>redis", - "source": "opbeans-node", - "sourceData": Object { - "agent.name": "nodejs", - "id": "opbeans-node", - "service.environment": "production", - "service.name": "opbeans-node", - }, - "target": ">redis", - "targetData": Object { - "id": ">redis", - "label": "redis", - "span.destination.service.resource": "redis", - "span.subtype": "redis", - "span.type": "cache", - }, - }, - }, - Object { - "data": Object { - "id": "opbeans-node~opbeans-java", - "isInverseEdge": true, - "source": "opbeans-node", - "sourceData": Object { - "agent.name": "nodejs", - "id": "opbeans-node", - "service.environment": "production", - "service.name": "opbeans-node", - }, - "target": "opbeans-java", - "targetData": Object { - "agent.name": "java", - "id": "opbeans-java", - "service.environment": "production", - "service.name": "opbeans-java", - }, - }, - }, - Object { - "data": Object { - "agent.name": "java", - "id": "opbeans-java", - "service.environment": "production", - "service.name": "opbeans-java", - }, - }, - Object { - "data": Object { - "agent.name": "nodejs", - "id": "opbeans-node", - "service.environment": "production", - "service.name": "opbeans-node", - }, - }, - Object { - "data": Object { - "id": ">opbeans-java:3000", - "label": "opbeans-java:3000", - "span.destination.service.resource": "opbeans-java:3000", - "span.subtype": "http", - "span.type": "external", - }, - }, - Object { - "data": Object { - "agent.name": "rum-js", - "id": "client", - "service.name": "client", - }, - }, - Object { - "data": Object { - "id": ">redis", - "label": "redis", - "span.destination.service.resource": "redis", - "span.subtype": "redis", - "span.type": "cache", - }, - }, - Object { - "data": Object { - "id": ">postgresql", - "label": "postgresql", - "span.destination.service.resource": "postgresql", - "span.subtype": "postgresql", - "span.type": "db", - }, - }, - Object { - "data": Object { - "id": ">93.184.216.34:80", - "label": "93.184.216.34:80", - "span.destination.service.resource": "93.184.216.34:80", - "span.subtype": "http", - "span.type": "external", - }, - }, - ], - } + it('returns the correct data', () => { + const elements: Array<{ data: Record }> = response.body.elements; + + const serviceNames = uniq( + elements + .filter((element) => element.data['service.name'] !== undefined) + .map((element) => element.data['service.name']) + ); + + expectSnapshot(serviceNames).toMatchInline(` + Array [ + "opbeans-rum", + "opbeans-go", + "opbeans-node", + "opbeans-python", + "opbeans-ruby", + "opbeans-java", + "opbeans-dotnet", + ] + `); + + const externalDestinations = uniq( + elements + .filter((element) => element.data.target?.startsWith('>')) + .map((element) => element.data.target) + ); + + expectSnapshot(externalDestinations).toMatchInline(` + Array [ + ">postgresql", + ">elasticsearch", + ">redis", + ] `); + + expectSnapshot(elements).toMatch(); }); }); }); @@ -269,48 +91,75 @@ export default function serviceMapsApiTests({ getService }: FtrProviderContext) describe('when there is no data', () => { it('returns an object with nulls', async () => { const q = querystring.stringify({ - start: '2020-06-28T10:24:46.055Z', - end: '2020-06-29T10:24:46.055Z', + start: metadata.start, + end: metadata.end, uiFilters: {}, }); const response = await supertest.get(`/api/apm/service-map/service/opbeans-node?${q}`); expect(response.status).to.be(200); - expect(response.body).to.eql({ - avgCpuUsage: null, - avgErrorRate: null, - avgMemoryUsage: null, - transactionStats: { - avgRequestsPerMinute: null, - avgTransactionDuration: null, - }, - }); + expect(response.body.avgCpuUsage).to.be(null); + expect(response.body.avgErrorRate).to.be(null); + expect(response.body.avgMemoryUsage).to.be(null); + expect(response.body.transactionStats.avgRequestsPerMinute).to.be(null); + expect(response.body.transactionStats.avgTransactionDuration).to.be(null); }); }); }); describe('when there is data with anomalies', () => { - before(() => esArchiver.load('apm_8.0.0')); - after(() => esArchiver.unload('apm_8.0.0')); + before(() => esArchiver.load(archiveName)); + after(() => esArchiver.unload(archiveName)); - it('returns service map elements', async () => { - const start = encodeURIComponent('2020-09-10T06:00:00.000Z'); - const end = encodeURIComponent('2020-09-10T07:00:00.000Z'); + let response: PromiseReturnType; - const response = await supertest.get(`/api/apm/service-map?start=${start}&end=${end}`); + before(async () => { + response = await supertest.get(`/api/apm/service-map?start=${start}&end=${end}`); + }); + it('returns service map elements with anomaly stats', () => { expect(response.status).to.be(200); const dataWithAnomalies = response.body.elements.filter( (el: { data: { serviceAnomalyStats?: {} } }) => !isEmpty(el.data.serviceAnomalyStats) ); + expect(dataWithAnomalies).to.not.empty(); + dataWithAnomalies.forEach(({ data }: any) => { expect( Object.values(data.serviceAnomalyStats).filter((value) => isEmpty(value)) ).to.not.empty(); }); }); + + it('returns the correct anomaly stats', () => { + const dataWithAnomalies = response.body.elements.filter( + (el: { data: { serviceAnomalyStats?: {} } }) => !isEmpty(el.data.serviceAnomalyStats) + ); + + expectSnapshot(dataWithAnomalies.length).toMatchInline(`1`); + expectSnapshot(dataWithAnomalies.slice(0, 3)).toMatchInline(` + Array [ + Object { + "data": Object { + "agent.name": "java", + "id": "opbeans-java", + "service.environment": "production", + "service.name": "opbeans-java", + "serviceAnomalyStats": Object { + "actualValue": 1707977.2499999995, + "anomalyScore": 0.12232533657975532, + "jobId": "apm-production-229a-high_mean_transaction_duration", + "transactionType": "request", + }, + }, + }, + ] + `); + + expectSnapshot(response.body).toMatch(); + }); }); }); } diff --git a/x-pack/test/encrypted_saved_objects_api_integration/fixtures/api_consumer_plugin/server/index.ts b/x-pack/test/encrypted_saved_objects_api_integration/fixtures/api_consumer_plugin/server/index.ts index 87bed7f416019..33ceee68a6013 100644 --- a/x-pack/test/encrypted_saved_objects_api_integration/fixtures/api_consumer_plugin/server/index.ts +++ b/x-pack/test/encrypted_saved_objects_api_integration/fixtures/api_consumer_plugin/server/index.ts @@ -4,8 +4,8 @@ * you may not use this file except in compliance with the Elastic License. */ +import { deepFreeze } from '@kbn/std'; import { - deepFreeze, CoreSetup, PluginInitializer, SavedObjectsNamespaceType, diff --git a/x-pack/test/functional/page_objects/accountsetting_page.js b/x-pack/test/functional/page_objects/account_settings_page.ts similarity index 80% rename from x-pack/test/functional/page_objects/accountsetting_page.js rename to x-pack/test/functional/page_objects/account_settings_page.ts index 283199a76a033..b7351b1e1cf22 100644 --- a/x-pack/test/functional/page_objects/accountsetting_page.js +++ b/x-pack/test/functional/page_objects/account_settings_page.ts @@ -4,15 +4,15 @@ * you may not use this file except in compliance with the Elastic License. */ -//import { map as mapAsync } from 'bluebird'; import expect from '@kbn/expect'; +import { FtrProviderContext } from '../ftr_provider_context'; -export function AccountSettingProvider({ getService }) { +export function AccountSettingProvider({ getService }: FtrProviderContext) { const testSubjects = getService('testSubjects'); const userMenu = getService('userMenu'); class AccountSettingsPage { - async verifyAccountSettings(expectedEmail, expectedUserName) { + async verifyAccountSettings(expectedEmail: string, expectedUserName: string) { await userMenu.clickProvileLink(); const usernameField = await testSubjects.find('username'); @@ -25,7 +25,7 @@ export function AccountSettingProvider({ getService }) { await userMenu.closeMenu(); } - async changePassword(currentPassword, newPassword) { + async changePassword(currentPassword: string, newPassword: string) { await testSubjects.setValue('currentPassword', currentPassword); await testSubjects.setValue('newPassword', newPassword); await testSubjects.setValue('confirmNewPassword', newPassword); diff --git a/x-pack/test/functional/page_objects/gis_page.js b/x-pack/test/functional/page_objects/gis_page.ts similarity index 90% rename from x-pack/test/functional/page_objects/gis_page.js rename to x-pack/test/functional/page_objects/gis_page.ts index 4998635096c39..7be0aa425509e 100644 --- a/x-pack/test/functional/page_objects/gis_page.js +++ b/x-pack/test/functional/page_objects/gis_page.ts @@ -6,8 +6,9 @@ import _ from 'lodash'; import { APP_ID } from '../../../plugins/maps/common/constants'; +import { FtrProviderContext } from '../ftr_provider_context'; -export function GisPageProvider({ getService, getPageObjects }) { +export function GisPageProvider({ getService, getPageObjects }: FtrProviderContext) { const PageObjects = getPageObjects(['common', 'header', 'timePicker']); const log = getService('log'); @@ -19,25 +20,27 @@ export function GisPageProvider({ getService, getPageObjects }) { const comboBox = getService('comboBox'); const renderable = getService('renderable'); - function escapeLayerName(layerName) { + function escapeLayerName(layerName: string) { return layerName.split(' ').join('_'); } class GisPage { + basePath; + constructor() { this.basePath = ''; } - setBasePath(basePath) { + setBasePath(basePath: string) { this.basePath = basePath; } - async setAbsoluteRange(start, end) { + async setAbsoluteRange(start: string, end: string) { await PageObjects.timePicker.setAbsoluteRange(start, end); await this.waitForLayersToLoad(); } - async setAndSubmitQuery(query) { + async setAndSubmitQuery(query: string) { await queryBar.setQuery(query); await queryBar.submitQuery(); await this.waitForLayersToLoad(); @@ -70,7 +73,7 @@ export function GisPageProvider({ getService, getPageObjects }) { // this method waits until the map view has stabilized, signaling that the panning/zooming is complete. // Pass origView parameter when the new map view determinition is async // so method knows when panning/zooming has started. - async waitForMapPanAndZoom(origView) { + async waitForMapPanAndZoom(origView?: { lon: number; lat: number; zoom: number }) { await retry.try(async () => { log.debug('Waiting for map pan and zoom to complete'); const prevView = await this.getView(); @@ -94,7 +97,7 @@ export function GisPageProvider({ getService, getPageObjects }) { }); } - async waitForLayerDeleted(layerName) { + async waitForLayerDeleted(layerName: string) { log.debug('Wait for layer deleted'); await retry.waitFor('Layer to be deleted', async () => { const doesLayerExist = await this.doesLayerExist(layerName); @@ -104,7 +107,7 @@ export function GisPageProvider({ getService, getPageObjects }) { // use the search filter box to narrow the results down to a single // entry, or at least to a single page of results - async loadSavedMap(name) { + async loadSavedMap(name: string) { log.debug(`Load Saved Map ${name}`); await retry.try(async () => { @@ -121,7 +124,7 @@ export function GisPageProvider({ getService, getPageObjects }) { await this.waitForLayersToLoad(); } - async deleteSavedMaps(search) { + async deleteSavedMaps(search: string) { await this.searchForMapWithName(search); await testSubjects.click('checkboxSelectAll'); await testSubjects.click('deleteSelectedItems'); @@ -139,7 +142,7 @@ export function GisPageProvider({ getService, getPageObjects }) { await renderable.waitForRender(); } - async saveMap(name, uncheckReturnToOriginModeSwitch = false) { + async saveMap(name: string, uncheckReturnToOriginModeSwitch = false) { await testSubjects.click('mapSaveButton'); await testSubjects.setValue('savedObjectTitle', name); if (uncheckReturnToOriginModeSwitch) { @@ -180,7 +183,7 @@ export function GisPageProvider({ getService, getPageObjects }) { return exists; } - async searchForMapWithName(name) { + async searchForMapWithName(name: string) { log.debug(`searchForMapWithName: ${name}`); await this.gotoMapListingPage(); @@ -196,7 +199,7 @@ export function GisPageProvider({ getService, getPageObjects }) { await PageObjects.header.waitUntilLoadingHasFinished(); } - async selectMap(name) { + async selectMap(name: string) { await testSubjects.click(`mapListingTitleLink-${name.split(' ').join('-')}`); } @@ -221,7 +224,7 @@ export function GisPageProvider({ getService, getPageObjects }) { } } - async getMapCountWithName(name) { + async getMapCountWithName(name: string) { await this.gotoMapListingPage(); log.debug(`getMapCountWithName: ${name}`); @@ -260,7 +263,7 @@ export function GisPageProvider({ getService, getPageObjects }) { } } - async setView(lat, lon, zoom) { + async setView(lat: number, lon: number, zoom: number) { log.debug( `Set view lat: ${lat.toString()}, lon: ${lon.toString()}, zoom: ${zoom.toString()}` ); @@ -286,7 +289,7 @@ export function GisPageProvider({ getService, getPageObjects }) { }; } - async toggleLayerVisibility(layerName) { + async toggleLayerVisibility(layerName: string) { log.debug(`Toggle layer visibility, layer: ${layerName}`); await this.openLayerTocActionsPanel(layerName); await testSubjects.click('layerVisibilityToggleButton'); @@ -300,7 +303,7 @@ export function GisPageProvider({ getService, getPageObjects }) { } } - async clickFitToBounds(layerName) { + async clickFitToBounds(layerName: string) { log.debug(`Fit to bounds, layer: ${layerName}`); const origView = await this.getView(); await this.openLayerTocActionsPanel(layerName); @@ -308,7 +311,7 @@ export function GisPageProvider({ getService, getPageObjects }) { await this.waitForMapPanAndZoom(origView); } - async openLayerTocActionsPanel(layerName) { + async openLayerTocActionsPanel(layerName: string) { const escapedDisplayName = escapeLayerName(layerName); const isOpen = await testSubjects.exists(`layerTocActionsPanel${escapedDisplayName}`); if (!isOpen) { @@ -316,7 +319,7 @@ export function GisPageProvider({ getService, getPageObjects }) { } } - async openLayerPanel(layerName) { + async openLayerPanel(layerName: string) { log.debug(`Open layer panel, layer: ${layerName}`); await this.openLayerTocActionsPanel(layerName); await testSubjects.click('editLayerButton'); @@ -327,7 +330,7 @@ export function GisPageProvider({ getService, getPageObjects }) { await this.waitForLayersToLoad(); } - async getLayerTOCDetails(layerName) { + async getLayerTOCDetails(layerName: string) { return await testSubjects.getVisibleText(`mapLayerTOCDetails${escapeLayerName(layerName)}`); } @@ -352,13 +355,13 @@ export function GisPageProvider({ getService, getPageObjects }) { } } - async doesLayerExist(layerName) { + async doesLayerExist(layerName: string) { return await testSubjects.exists( `layerTocActionsPanelToggleButton${escapeLayerName(layerName)}` ); } - async hasFilePickerLoadedFile(fileName) { + async hasFilePickerLoadedFile(fileName: string) { log.debug(`Has file picker loaded file ${fileName}`); const filePickerText = await find.byCssSelector('.euiFilePicker__promptText'); const filePickerTextContent = await filePickerText.getVisibleText(); @@ -393,7 +396,7 @@ export function GisPageProvider({ getService, getPageObjects }) { }); } - async cancelLayerAdd(layerName) { + async cancelLayerAdd(layerName: string) { log.debug(`Cancel layer add`); const cancelExists = await testSubjects.exists('layerAddCancelButton'); if (cancelExists) { @@ -405,7 +408,7 @@ export function GisPageProvider({ getService, getPageObjects }) { } } - async closeOrCancelLayer(layerName) { + async closeOrCancelLayer(layerName: string) { log.debug(`Close or cancel layer add`); const cancelExists = await testSubjects.exists('layerAddCancelButton'); const closeExists = await testSubjects.exists('layerPanelCancelButton'); @@ -449,24 +452,24 @@ export function GisPageProvider({ getService, getPageObjects }) { await testSubjects.click('importFileButton'); } - async setIndexName(indexName) { + async setIndexName(indexName: string) { log.debug(`Set index name to: ${indexName}`); await testSubjects.setValue('fileUploadIndexNameInput', indexName); } - async setIndexType(indexType) { + async setIndexType(indexType: string) { log.debug(`Set index type to: ${indexType}`); await testSubjects.selectValue('fileImportIndexSelect', indexType); } - async indexTypeOptionExists(indexType) { + async indexTypeOptionExists(indexType: string) { log.debug(`Check index type "${indexType}" available`); return await find.existsByCssSelector( `select[data-test-subj="fileImportIndexSelect"] > option[value="${indexType}"]` ); } - async getCodeBlockParsedJson(dataTestSubjName) { + async getCodeBlockParsedJson(dataTestSubjName: string) { log.debug(`Get parsed code block for ${dataTestSubjName}`); const indexRespCodeBlock = await testSubjects.find(`${dataTestSubjName}`); const indexRespJson = await indexRespCodeBlock.getAttribute('innerText'); @@ -483,7 +486,7 @@ export function GisPageProvider({ getService, getPageObjects }) { return await this.getCodeBlockParsedJson('indexPatternRespCodeBlock'); } - async setLayerQuery(layerName, query) { + async setLayerQuery(layerName: string, query: string) { await this.openLayerPanel(layerName); await testSubjects.click('mapLayerPanelOpenFilterEditorButton'); const filterEditorContainer = await testSubjects.find('mapFilterEditor'); @@ -505,7 +508,7 @@ export function GisPageProvider({ getService, getPageObjects }) { await this.waitForLayersToLoad(); } - async setJoinWhereQuery(layerName, query) { + async setJoinWhereQuery(layerName: string, query: string) { await this.openLayerPanel(layerName); await testSubjects.click('mapJoinWhereExpressionButton'); const filterEditorContainer = await testSubjects.find('mapJoinWhereFilterEditor'); @@ -531,7 +534,7 @@ export function GisPageProvider({ getService, getPageObjects }) { await testSubjects.click('uploadGeoJson'); } - async uploadJsonFileForIndexing(path) { + async uploadJsonFileForIndexing(path: string) { await PageObjects.common.setFileInputPath(path); log.debug(`File selected`); @@ -540,7 +543,7 @@ export function GisPageProvider({ getService, getPageObjects }) { } // Returns first layer by default - async selectVectorLayer(vectorLayerName) { + async selectVectorLayer(vectorLayerName: string) { log.debug(`Select EMS vector layer ${vectorLayerName}`); if (!vectorLayerName) { throw new Error(`You did not provide the EMS layer to select`); @@ -549,14 +552,14 @@ export function GisPageProvider({ getService, getPageObjects }) { await this.waitForLayersToLoad(); } - async removeLayer(layerName) { + async removeLayer(layerName: string) { log.debug(`Remove layer ${layerName}`); await this.openLayerPanel(layerName); await testSubjects.click(`mapRemoveLayerButton`); await this.waitForLayerDeleted(layerName); } - async getLayerErrorText(layerName) { + async getLayerErrorText(layerName: string) { log.debug(`Remove layer ${layerName}`); await this.openLayerPanel(layerName); return await testSubjects.getVisibleText(`layerErrorMessage`); @@ -589,7 +592,7 @@ export function GisPageProvider({ getService, getPageObjects }) { // Method should only be used when multiple requests are expected // RequestSelector will only display inspectorRequestChooser when there is more than one request - async openInspectorRequest(requestName) { + async openInspectorRequest(requestName: string) { await inspector.open(); await inspector.openInspectorRequestsView(); log.debug(`Open Inspector request ${requestName}`); @@ -620,12 +623,12 @@ export function GisPageProvider({ getService, getPageObjects }) { return mapboxStyle; } - getInspectorStatRowHit(stats, rowName) { + getInspectorStatRowHit(stats: string[][], rowName: string) { const STATS_ROW_NAME_INDEX = 0; const STATS_ROW_VALUE_INDEX = 1; - const statsRow = stats.find((statsRow) => { - return statsRow[STATS_ROW_NAME_INDEX] === rowName; + const statsRow = stats.find((row) => { + return row[STATS_ROW_NAME_INDEX] === rowName; }); if (!statsRow) { throw new Error(`Unable to find value for row ${rowName} in ${stats}`); @@ -634,7 +637,7 @@ export function GisPageProvider({ getService, getPageObjects }) { return statsRow[STATS_ROW_VALUE_INDEX]; } - async triggerSingleRefresh(refreshInterval) { + async triggerSingleRefresh(refreshInterval: number) { log.debug(`triggerSingleRefresh, refreshInterval: ${refreshInterval}`); await PageObjects.timePicker.resumeAutoRefresh(); log.debug('waiting to give time for refresh timer to fire'); @@ -643,7 +646,7 @@ export function GisPageProvider({ getService, getPageObjects }) { await this.waitForLayersToLoad(); } - async lockTooltipAtPosition(xOffset, yOffset) { + async lockTooltipAtPosition(xOffset: number, yOffset: number) { await retry.try(async () => { const mapContainerElement = await testSubjects.find('mapContainer'); await mapContainerElement.moveMouseTo({ xOffset, yOffset }); @@ -656,12 +659,12 @@ export function GisPageProvider({ getService, getPageObjects }) { }); } - async setStyleByValue(styleName, fieldName) { + async setStyleByValue(styleName: string, fieldName: string) { await testSubjects.selectValue(`staticDynamicSelect_${styleName}`, 'DYNAMIC'); await comboBox.set(`styleFieldSelect_${styleName}`, fieldName); } - async selectCustomColorRamp(styleName) { + async selectCustomColorRamp(styleName: string) { // open super select menu await testSubjects.click(`colorMapSelect_${styleName}`); // Click option diff --git a/x-pack/test/functional/page_objects/graph_page.ts b/x-pack/test/functional/page_objects/graph_page.ts index 639add8b0e904..9ce1f87b5bf3d 100644 --- a/x-pack/test/functional/page_objects/graph_page.ts +++ b/x-pack/test/functional/page_objects/graph_page.ts @@ -23,7 +23,7 @@ export function GraphPageProvider({ getService, getPageObjects }: FtrProviderCon const find = getService('find'); const log = getService('log'); const testSubjects = getService('testSubjects'); - const PageObjects = getPageObjects(['common', 'header', 'settings']); + const PageObjects = getPageObjects(['common', 'header']); const retry = getService('retry'); class GraphPage { diff --git a/x-pack/test/functional/page_objects/grok_debugger_page.js b/x-pack/test/functional/page_objects/grok_debugger_page.ts similarity index 86% rename from x-pack/test/functional/page_objects/grok_debugger_page.js rename to x-pack/test/functional/page_objects/grok_debugger_page.ts index fec3e9de3c74b..d3edbe6c27e77 100644 --- a/x-pack/test/functional/page_objects/grok_debugger_page.js +++ b/x-pack/test/functional/page_objects/grok_debugger_page.ts @@ -4,7 +4,9 @@ * you may not use this file except in compliance with the Elastic License. */ -export function GrokDebuggerPageProvider({ getPageObjects, getService }) { +import { FtrProviderContext } from '../ftr_provider_context'; + +export function GrokDebuggerPageProvider({ getPageObjects, getService }: FtrProviderContext) { const PageObjects = getPageObjects(['common']); const grokDebugger = getService('grokDebugger'); diff --git a/x-pack/test/functional/page_objects/index.ts b/x-pack/test/functional/page_objects/index.ts index 833cc452a5d31..7569904fe90fd 100644 --- a/x-pack/test/functional/page_objects/index.ts +++ b/x-pack/test/functional/page_objects/index.ts @@ -7,30 +7,20 @@ import { pageObjects as kibanaFunctionalPageObjects } from '../../../../test/functional/page_objects'; import { CanvasPageProvider } from './canvas_page'; -// @ts-ignore not ts yet import { SecurityPageProvider } from './security_page'; -// @ts-ignore not ts yet import { MonitoringPageProvider } from './monitoring_page'; // @ts-ignore not ts yet import { LogstashPageProvider } from './logstash_page'; -// @ts-ignore not ts yet import { GraphPageProvider } from './graph_page'; -// @ts-ignore not ts yet import { GrokDebuggerPageProvider } from './grok_debugger_page'; -// @ts-ignore not ts yet import { WatcherPageProvider } from './watcher_page'; import { ReportingPageProvider } from './reporting_page'; -// @ts-ignore not ts yet -import { AccountSettingProvider } from './accountsetting_page'; +import { AccountSettingProvider } from './account_settings_page'; import { InfraHomePageProvider } from './infra_home_page'; import { InfraLogsPageProvider } from './infra_logs_page'; -// @ts-ignore not ts yet import { GisPageProvider } from './gis_page'; -// @ts-ignore not ts yet import { StatusPagePageProvider } from './status_page'; -// @ts-ignore not ts yet -import { UpgradeAssistantProvider } from './upgrade_assistant'; -// @ts-ignore not ts yet +import { UpgradeAssistantPageProvider } from './upgrade_assistant_page'; import { RollupPageProvider } from './rollup_page'; import { UptimePageProvider } from './uptime_page'; import { ApiKeysPageProvider } from './api_keys_page'; @@ -66,7 +56,7 @@ export const pageObjects = { infraLogs: InfraLogsPageProvider, maps: GisPageProvider, statusPage: StatusPagePageProvider, - upgradeAssistant: UpgradeAssistantProvider, + upgradeAssistant: UpgradeAssistantPageProvider, uptime: UptimePageProvider, rollup: RollupPageProvider, apiKeys: ApiKeysPageProvider, diff --git a/x-pack/test/functional/page_objects/lens_page.ts b/x-pack/test/functional/page_objects/lens_page.ts index acba3fa472b1a..e3c21085b92d3 100644 --- a/x-pack/test/functional/page_objects/lens_page.ts +++ b/x-pack/test/functional/page_objects/lens_page.ts @@ -13,14 +13,7 @@ export function LensPageProvider({ getService, getPageObjects }: FtrProviderCont const retry = getService('retry'); const find = getService('find'); const comboBox = getService('comboBox'); - const PageObjects = getPageObjects([ - 'header', - 'common', - 'visualize', - 'dashboard', - 'header', - 'timePicker', - ]); + const PageObjects = getPageObjects(['header', 'header', 'timePicker']); return logWrapper('lensPage', log, { /** @@ -105,13 +98,14 @@ export function LensPageProvider({ getService, getPageObjects }: FtrProviderCont const target = await testSubjects.find('indexPattern-dimension-field'); await comboBox.openOptionsList(target); await comboBox.setElement(target, opts.field); + await testSubjects.click('lns-indexPattern-dimensionContainerTitle'); }, /** * Removes the dimension matching a specific test subject */ async removeDimension(dimensionTestSubj: string) { - await testSubjects.click(`${dimensionTestSubj} > indexPattern-dimensionPopover-remove`); + await testSubjects.click(`${dimensionTestSubj} > indexPattern-dimension-remove`); }, /** diff --git a/x-pack/test/functional/page_objects/monitoring_page.js b/x-pack/test/functional/page_objects/monitoring_page.ts similarity index 84% rename from x-pack/test/functional/page_objects/monitoring_page.js rename to x-pack/test/functional/page_objects/monitoring_page.ts index c3b9d20b3ac4a..bbfa884e71cda 100644 --- a/x-pack/test/functional/page_objects/monitoring_page.js +++ b/x-pack/test/functional/page_objects/monitoring_page.ts @@ -4,8 +4,10 @@ * you may not use this file except in compliance with the Elastic License. */ -export function MonitoringPageProvider({ getPageObjects, getService }) { - const PageObjects = getPageObjects(['common', 'header', 'security', 'login', 'spaceSelector']); +import { FtrProviderContext } from '../ftr_provider_context'; + +export function MonitoringPageProvider({ getPageObjects, getService }: FtrProviderContext) { + const PageObjects = getPageObjects(['common', 'header', 'security', 'login']); const testSubjects = getService('testSubjects'); const security = getService('security'); const find = getService('find'); @@ -35,34 +37,34 @@ export function MonitoringPageProvider({ getPageObjects, getService }) { return testSubjects.getVisibleText('accessDeniedTitle'); } - async clickBreadcrumb(subj) { + async clickBreadcrumb(subj: string) { return testSubjects.click(subj); } - async assertTableNoData(subj) { + async assertTableNoData(subj: string) { if (!(await testSubjects.exists(subj))) { throw new Error('Expected to find the no data message'); } } - async tableGetRows(subj) { + async tableGetRows(subj: string) { const table = await testSubjects.find(subj); return table.findAllByTagName('tr'); } - async tableGetRowsFromContainer(subj) { + async tableGetRowsFromContainer(subj: string) { const table = await testSubjects.find(subj); const tbody = await table.findByTagName('tbody'); return tbody.findAllByTagName('tr'); } - async tableSetFilter(subj, text) { + async tableSetFilter(subj: string, text: string) { await testSubjects.setValue(subj, text); await PageObjects.common.pressEnterKey(); await PageObjects.header.waitUntilLoadingHasFinished(); } - async tableClearFilter(subj) { + async tableClearFilter(subj: string) { return await testSubjects.setValue(subj, ' \uE003'); // space and backspace to trigger onChange event } })(); diff --git a/x-pack/test/functional/page_objects/reporting_page.ts b/x-pack/test/functional/page_objects/reporting_page.ts index 7631d0cbce59a..5828871d7c685 100644 --- a/x-pack/test/functional/page_objects/reporting_page.ts +++ b/x-pack/test/functional/page_objects/reporting_page.ts @@ -5,16 +5,15 @@ */ import http, { IncomingMessage } from 'http'; -import { FtrProviderContext } from 'test/functional/ftr_provider_context'; import { parse } from 'url'; +import { FtrProviderContext } from '../ftr_provider_context'; export function ReportingPageProvider({ getService, getPageObjects }: FtrProviderContext) { const browser = getService('browser'); const log = getService('log'); const retry = getService('retry'); const testSubjects = getService('testSubjects'); - - const PageObjects = getPageObjects(['common', 'security' as any, 'share', 'timePicker']); // FIXME: Security PageObject is not Typescript + const PageObjects = getPageObjects(['security', 'share', 'timePicker']); class ReportingPage { async forceSharedItemsContainerSize({ width }: { width: number }) { diff --git a/x-pack/test/functional/page_objects/rollup_page.js b/x-pack/test/functional/page_objects/rollup_page.ts similarity index 85% rename from x-pack/test/functional/page_objects/rollup_page.js rename to x-pack/test/functional/page_objects/rollup_page.ts index f974f60271746..fbeb6acd3ebf2 100644 --- a/x-pack/test/functional/page_objects/rollup_page.js +++ b/x-pack/test/functional/page_objects/rollup_page.ts @@ -6,8 +6,9 @@ import expect from '@kbn/expect'; import { map as mapAsync } from 'bluebird'; +import { FtrProviderContext } from '../ftr_provider_context'; -export function RollupPageProvider({ getService, getPageObjects }) { +export function RollupPageProvider({ getService, getPageObjects }: FtrProviderContext) { const testSubjects = getService('testSubjects'); const log = getService('log'); const find = getService('find'); @@ -15,16 +16,16 @@ export function RollupPageProvider({ getService, getPageObjects }) { class RollupJobPage { async createNewRollUpJob( - jobName, - indexPattern, - indexName, - interval, + jobName: string, + indexPattern: string, + indexName: string, + interval: string, delay = '1d', startImmediately = false, scheduledTime = { time: 'minute', cron: true } ) { let stepNum = 1; - //Step 1 + // Step 1 await testSubjects.click('createRollupJobButton'); await this.verifyStepIsActive(stepNum); await this.addRollupNameandIndexPattern(jobName, indexPattern); @@ -34,47 +35,47 @@ export function RollupPageProvider({ getService, getPageObjects }) { await this.setRollupDelay(delay); stepNum = await this.moveToNextStep(stepNum); - //Step 2: Histogram + // Step 2: Histogram await this.verifyStepIsActive(stepNum); await this.setJobInterval(interval); stepNum = await this.moveToNextStep(stepNum); - //Step 3: Terms (optional) + // Step 3: Terms (optional) await this.verifyStepIsActive(stepNum); stepNum = await this.moveToNextStep(); - //Step 4: Histogram(optional) + // Step 4: Histogram(optional) await this.verifyStepIsActive(stepNum); stepNum = await this.moveToNextStep(); - //Step 5: Metrics(optional) + // Step 5: Metrics(optional) await this.verifyStepIsActive(stepNum); stepNum = await this.moveToNextStep(); - //Step 6: saveJob and verify the name in the list + // Step 6: saveJob and verify the name in the list await this.verifyStepIsActive(stepNum); await this.saveJob(startImmediately); } - async verifyStepIsActive(stepNumber) { + async verifyStepIsActive(stepNumber = 0) { await testSubjects.exists(`createRollupStep${stepNumber}--active`); } - async setScheduleTime(time, cron) { - if (cron) { + async setScheduleTime(time: string, isCron: boolean) { + if (isCron) { await testSubjects.click('rollupShowAdvancedCronLink'); await testSubjects.setValue('rollupAdvancedCron', time); } // TODO: Add handling for if Cron is false to go through clicking options. } - async addRollupNameandIndexPattern(name, indexPattern) { + async addRollupNameandIndexPattern(name: string, indexPattern: string) { log.debug(`Adding name ${name} to form`); await testSubjects.setValue('rollupJobName', name); await testSubjects.setValue('rollupIndexPattern', indexPattern); } - async setRollupDelay(time) { + async setRollupDelay(time: string) { log.debug(`Setting rollup delay to "${time}"`); await testSubjects.setValue('rollupDelay', time); } @@ -86,20 +87,20 @@ export function RollupPageProvider({ getService, getPageObjects }) { expect(text).to.be.equal('Success! Index pattern has matching indices.'); } - async setIndexName(name) { + async setIndexName(name: string) { await testSubjects.setValue('rollupIndexName', name); } - async moveToNextStep(stepNum) { + async moveToNextStep(stepNum = 0) { await testSubjects.click('rollupJobNextButton'); return stepNum + 1; } - async setJobInterval(time) { + async setJobInterval(time: string) { await testSubjects.setValue('rollupJobInterval', time); } - async saveJob(startImmediately) { + async saveJob(startImmediately: boolean) { if (startImmediately) { const checkbox = await find.byCssSelector('.euiCheckbox'); await checkbox.click(); diff --git a/x-pack/test/functional/page_objects/security_page.ts b/x-pack/test/functional/page_objects/security_page.ts index e3efc8731e6b3..3ce8a0e681d69 100644 --- a/x-pack/test/functional/page_objects/security_page.ts +++ b/x-pack/test/functional/page_objects/security_page.ts @@ -17,7 +17,7 @@ export function SecurityPageProvider({ getService, getPageObjects }: FtrProvider const esArchiver = getService('esArchiver'); const userMenu = getService('userMenu'); const comboBox = getService('comboBox'); - const PageObjects = getPageObjects(['common', 'header', 'settings', 'home', 'error']); + const PageObjects = getPageObjects(['common', 'header', 'error']); interface LoginOptions { expectSpaceSelector?: boolean; diff --git a/x-pack/test/functional/page_objects/space_selector_page.ts b/x-pack/test/functional/page_objects/space_selector_page.ts index b272175ff2b21..acf8a65362f01 100644 --- a/x-pack/test/functional/page_objects/space_selector_page.ts +++ b/x-pack/test/functional/page_objects/space_selector_page.ts @@ -13,7 +13,7 @@ export function SpaceSelectorPageProvider({ getService, getPageObjects }: FtrPro const testSubjects = getService('testSubjects'); const browser = getService('browser'); const find = getService('find'); - const PageObjects = getPageObjects(['common', 'header', 'security']); + const PageObjects = getPageObjects(['common']); class SpaceSelectorPage { async initTests() { diff --git a/x-pack/test/functional/page_objects/status_page.js b/x-pack/test/functional/page_objects/status_page.ts similarity index 81% rename from x-pack/test/functional/page_objects/status_page.js rename to x-pack/test/functional/page_objects/status_page.ts index eba5e7dd18496..08726e1320f29 100644 --- a/x-pack/test/functional/page_objects/status_page.js +++ b/x-pack/test/functional/page_objects/status_page.ts @@ -5,13 +5,14 @@ */ import expect from '@kbn/expect'; +import { FtrProviderContext } from '../ftr_provider_context'; -export function StatusPagePageProvider({ getService, getPageObjects }) { +export function StatusPagePageProvider({ getService, getPageObjects }: FtrProviderContext) { const retry = getService('retry'); const log = getService('log'); const browser = getService('browser'); const find = getService('find'); - const PageObjects = getPageObjects(['common', 'home', 'security']); + const { common } = getPageObjects(['common']); class StatusPage { async initTests() { @@ -20,13 +21,13 @@ export function StatusPagePageProvider({ getService, getPageObjects }) { async navigateToPage() { return await retry.try(async () => { - const url = PageObjects.common.getHostPort() + '/status'; + const url = common.getHostPort() + '/status'; log.info(`StatusPage:navigateToPage(): ${url}`); await browser.get(url); }); } - async expectStatusPage() { + async expectStatusPage(): Promise { return await retry.try(async () => { log.debug(`expectStatusPage()`); await find.byCssSelector('[data-test-subj="statusPageRoot"]', 20000); diff --git a/x-pack/test/functional/page_objects/upgrade_assistant.js b/x-pack/test/functional/page_objects/upgrade_assistant_page.ts similarity index 76% rename from x-pack/test/functional/page_objects/upgrade_assistant.js rename to x-pack/test/functional/page_objects/upgrade_assistant_page.ts index 72dbb2175abc9..3fe60747505a7 100644 --- a/x-pack/test/functional/page_objects/upgrade_assistant.js +++ b/x-pack/test/functional/page_objects/upgrade_assistant_page.ts @@ -5,14 +5,15 @@ */ import expect from '@kbn/expect'; +import { FtrProviderContext } from '../ftr_provider_context'; -export function UpgradeAssistantProvider({ getService, getPageObjects }) { +export function UpgradeAssistantPageProvider({ getPageObjects, getService }: FtrProviderContext) { const retry = getService('retry'); const log = getService('log'); const browser = getService('browser'); const find = getService('find'); const testSubjects = getService('testSubjects'); - const PageObjects = getPageObjects(['common', 'settings', 'security']); + const { common } = getPageObjects(['common']); class UpgradeAssistant { async initTests() { @@ -21,7 +22,7 @@ export function UpgradeAssistantProvider({ getService, getPageObjects }) { async navigateToPage() { return await retry.try(async () => { - await PageObjects.common.navigateToApp('settings'); + await common.navigateToApp('settings'); await testSubjects.click('upgrade_assistant'); }); } @@ -29,7 +30,7 @@ export function UpgradeAssistantProvider({ getService, getPageObjects }) { async expectUpgradeAssistant() { return await retry.try(async () => { log.debug(`expectUpgradeAssistant()`); - expect(testSubjects.exists('upgradeAssistantRoot')).to.be.true; + expect(await testSubjects.exists('upgradeAssistantRoot')).to.equal(true); const url = await browser.getCurrentUrl(); expect(url).to.contain(`/upgrade_assistant`); }); @@ -42,7 +43,7 @@ export function UpgradeAssistantProvider({ getService, getPageObjects }) { }); } - async expectDeprecationLoggingLabel(labelText) { + async expectDeprecationLoggingLabel(labelText: string) { return await retry.try(async () => { log.debug('expectDeprecationLoggingLabel()'); const label = await find.byCssSelector( @@ -53,19 +54,17 @@ export function UpgradeAssistantProvider({ getService, getPageObjects }) { }); } - async clickTab(tabId) { + async clickTab(tabId: string) { return await retry.try(async () => { log.debug('clickTab()'); - const tab = await find.byCssSelector(`.euiTabs .euiTab#${tabId}`); - await tab.click(); + await find.clickByCssSelector(`.euiTabs .euiTab#${tabId}`); }); } - async expectIssueSummary(summary) { + async expectIssueSummary(summary: string) { return await retry.try(async () => { log.debug('expectIssueSummary()'); - const summaryEl = await testSubjects.find('upgradeAssistantIssueSummary'); - const summaryElText = await summaryEl.getVisibleText(); + const summaryElText = await testSubjects.getVisibleText('upgradeAssistantIssueSummary'); expect(summaryElText).to.eql(summary); }); } diff --git a/x-pack/test/functional/page_objects/uptime_page.ts b/x-pack/test/functional/page_objects/uptime_page.ts index d0b610ec861b8..fd47478909585 100644 --- a/x-pack/test/functional/page_objects/uptime_page.ts +++ b/x-pack/test/functional/page_objects/uptime_page.ts @@ -8,7 +8,7 @@ import expect from '@kbn/expect'; import { FtrProviderContext } from '../ftr_provider_context'; export function UptimePageProvider({ getPageObjects, getService }: FtrProviderContext) { - const pageObjects = getPageObjects(['common', 'timePicker', 'header']); + const pageObjects = getPageObjects(['timePicker', 'header']); const { common: commonService, monitor, navigation } = getService('uptime'); const retry = getService('retry'); diff --git a/x-pack/test/functional/page_objects/watcher_page.js b/x-pack/test/functional/page_objects/watcher_page.ts similarity index 89% rename from x-pack/test/functional/page_objects/watcher_page.js rename to x-pack/test/functional/page_objects/watcher_page.ts index dfc31a6ad5ed2..ce6d9edcb6cdb 100644 --- a/x-pack/test/functional/page_objects/watcher_page.js +++ b/x-pack/test/functional/page_objects/watcher_page.ts @@ -5,9 +5,10 @@ */ import { map as mapAsync } from 'bluebird'; +import { FtrProviderContext } from '../ftr_provider_context'; -export function WatcherPageProvider({ getPageObjects, getService }) { - const PageObjects = getPageObjects(['common', 'header', 'settings']); +export function WatcherPageProvider({ getPageObjects, getService }: FtrProviderContext) { + const PageObjects = getPageObjects(['header']); const find = getService('find'); const testSubjects = getService('testSubjects'); @@ -22,7 +23,7 @@ export function WatcherPageProvider({ getPageObjects, getService }) { } } - async createWatch(watchName, name) { + async createWatch(watchName: string, name: string) { await testSubjects.click('createWatchButton'); await testSubjects.click('jsonWatchCreateLink'); await find.setValue('#id', watchName); @@ -31,7 +32,7 @@ export function WatcherPageProvider({ getPageObjects, getService }) { await PageObjects.header.waitUntilLoadingHasFinished(); } - async getWatch(watchID) { + async getWatch(watchID: string) { const watchIdColumn = await testSubjects.find(`watchIdColumn-${watchID}`); const watchNameColumn = await testSubjects.find(`watchNameColumn-${watchID}`); const id = await watchIdColumn.getVisibleText(); @@ -47,7 +48,7 @@ export function WatcherPageProvider({ getPageObjects, getService }) { await testSubjects.click('btnDeleteWatches'); } - //get all the watches in the list + // get all the watches in the list async getWatches() { const watches = await find.allByCssSelector('.euiTableRow'); return mapAsync(watches, async (watch) => { diff --git a/x-pack/test/ingest_manager_api_integration/apis/epm/index.js b/x-pack/test/ingest_manager_api_integration/apis/epm/index.js index 8555814245909..28743ee5f43c2 100644 --- a/x-pack/test/ingest_manager_api_integration/apis/epm/index.js +++ b/x-pack/test/ingest_manager_api_integration/apis/epm/index.js @@ -11,6 +11,7 @@ export default function loadTests({ loadTestFile }) { loadTestFile(require.resolve('./file')); //loadTestFile(require.resolve('./template')); loadTestFile(require.resolve('./ilm')); + loadTestFile(require.resolve('./install_by_upload')); loadTestFile(require.resolve('./install_overrides')); loadTestFile(require.resolve('./install_prerelease')); loadTestFile(require.resolve('./install_remove_assets')); diff --git a/x-pack/test/ingest_manager_api_integration/apis/epm/install_by_upload.ts b/x-pack/test/ingest_manager_api_integration/apis/epm/install_by_upload.ts new file mode 100644 index 0000000000000..e6d2affaec0cd --- /dev/null +++ b/x-pack/test/ingest_manager_api_integration/apis/epm/install_by_upload.ts @@ -0,0 +1,55 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import fs from 'fs'; +import path from 'path'; +import expect from '@kbn/expect'; + +import { FtrProviderContext } from '../../../api_integration/ftr_provider_context'; +import { warnAndSkipTest } from '../../helpers'; + +export default function ({ getService }: FtrProviderContext) { + const supertest = getService('supertest'); + const dockerServers = getService('dockerServers'); + const log = getService('log'); + + const testPkgArchiveTgz = path.join( + path.dirname(__filename), + '../fixtures/direct_upload_packages/apache_0.1.4.tar.gz' + ); + const testPkgKey = 'apache-0.14'; + const server = dockerServers.get('registry'); + + const deletePackage = async (pkgkey: string) => { + await supertest.delete(`/api/ingest_manager/epm/packages/${pkgkey}`).set('kbn-xsrf', 'xxxx'); + }; + + describe('installs packages from direct upload', async () => { + after(async () => { + if (server.enabled) { + // remove the package just in case it being installed will affect other tests + await deletePackage(testPkgKey); + } + }); + + it('should install a tar archive correctly', async function () { + if (server.enabled) { + const buf = fs.readFileSync(testPkgArchiveTgz); + const res = await supertest + .post(`/api/ingest_manager/epm/packages`) + .set('kbn-xsrf', 'xxxx') + .type('application/gzip') + .send(buf) + .expect(200); + expect(res.body.response).to.equal( + 'package upload was received ok, but not installed (not implemented yet)' + ); + } else { + warnAndSkipTest(this, log); + } + }); + }); +} diff --git a/x-pack/test/ingest_manager_api_integration/apis/fixtures/direct_upload_packages/apache_0.1.4.tar.gz b/x-pack/test/ingest_manager_api_integration/apis/fixtures/direct_upload_packages/apache_0.1.4.tar.gz new file mode 100644 index 0000000000000..cc983f6ac6d1a Binary files /dev/null and b/x-pack/test/ingest_manager_api_integration/apis/fixtures/direct_upload_packages/apache_0.1.4.tar.gz differ diff --git a/x-pack/test/security_solution_endpoint/apps/endpoint/endpoint_list.ts b/x-pack/test/security_solution_endpoint/apps/endpoint/endpoint_list.ts index b0b8d14108004..7485e5db20478 100644 --- a/x-pack/test/security_solution_endpoint/apps/endpoint/endpoint_list.ts +++ b/x-pack/test/security_solution_endpoint/apps/endpoint/endpoint_list.ts @@ -22,8 +22,8 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { [ 'Hostname', 'Agent Status', - 'Integration', - 'Configuration Status', + 'Integration Policy', + 'Policy Status', 'Operating System', 'IP Address', 'Version', @@ -188,8 +188,8 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { 'OS', 'Last Seen', 'Alerts', - 'Integration', - 'Configuration Status', + 'Integration Policy', + 'Policy Status', 'IP Address', 'Hostname', 'Sensor Version', @@ -236,8 +236,8 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { [ 'Hostname', 'Agent Status', - 'Integration', - 'Configuration Status', + 'Integration Policy', + 'Policy Status', 'Operating System', 'IP Address', 'Version', @@ -267,8 +267,8 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { [ 'Hostname', 'Agent Status', - 'Integration', - 'Configuration Status', + 'Integration Policy', + 'Policy Status', 'Operating System', 'IP Address', 'Version', diff --git a/x-pack/test/security_solution_endpoint/page_objects/ingest_manager_create_package_policy_page.ts b/x-pack/test/security_solution_endpoint/page_objects/ingest_manager_create_package_policy_page.ts index 13b1f8c9d9842..523b327b8de1c 100644 --- a/x-pack/test/security_solution_endpoint/page_objects/ingest_manager_create_package_policy_page.ts +++ b/x-pack/test/security_solution_endpoint/page_objects/ingest_manager_create_package_policy_page.ts @@ -52,13 +52,11 @@ export function IngestManagerCreatePackagePolicy({ async selectAgentPolicy(name?: string) { // if we have a name, then find the button with that `title` set. if (name) { - await ( - await find.byCssSelector(`[data-test-subj="agentPolicyItem"][title="${name}"]`) - ).click(); + await find.clickByCssSelector(`[data-test-subj="agentPolicyItem"][title="${name}"]`); } // Else, just select the first agent policy that is present else { - await (await testSubjects.find('agentPolicyItem')).click(); + await testSubjects.click('agentPolicyItem'); } }, diff --git a/x-pack/test/security_solution_endpoint/page_objects/policy_page.ts b/x-pack/test/security_solution_endpoint/page_objects/policy_page.ts index 9c1fa0c6e86b2..d661b3097bd35 100644 --- a/x-pack/test/security_solution_endpoint/page_objects/policy_page.ts +++ b/x-pack/test/security_solution_endpoint/page_objects/policy_page.ts @@ -27,7 +27,7 @@ export function EndpointPolicyPageProvider({ getService, getPageObjects }: FtrPr */ async findFirstActionsButton() { await this.ensureIsOnPolicyPage(); - return (await testSubjects.findAll('policyActionsButton'))[0]; + return await testSubjects.find('policyActionsButton'); }, /** @@ -36,8 +36,7 @@ export function EndpointPolicyPageProvider({ getService, getPageObjects }: FtrPr async launchAndFindDeleteModal() { const actionsButton = await this.findFirstActionsButton(); await actionsButton.click(); - const deleteAction = await testSubjects.find('policyDeleteButton'); - await deleteAction.click(); + await testSubjects.click('policyDeleteButton'); return await testSubjects.find('policyListDeleteModal'); }, diff --git a/x-pack/test/tsconfig.json b/x-pack/test/tsconfig.json index d0e2ea952e108..e8af79b9e84e0 100644 --- a/x-pack/test/tsconfig.json +++ b/x-pack/test/tsconfig.json @@ -14,5 +14,8 @@ ], "exclude": [ "../typings/jest.d.ts" + ], + "references": [ + { "path": "../../src/core/tsconfig.json" } ] } diff --git a/x-pack/tsconfig.json b/x-pack/tsconfig.json index b5080f83f2eda..38851653898a8 100644 --- a/x-pack/tsconfig.json +++ b/x-pack/tsconfig.json @@ -35,5 +35,8 @@ }, // overhead is too significant "incremental": false, - } + }, + "references": [ + { "path": "../src/core/tsconfig.json" } + ] }