diff --git a/.ci/packer_cache.sh b/.ci/packer_cache.sh
index b697f22c009d1..ab68a60dcfc27 100755
--- a/.ci/packer_cache.sh
+++ b/.ci/packer_cache.sh
@@ -44,6 +44,7 @@ tar -cf "$HOME/.kibana/bootstrap_cache/$branch.tar" \
x-pack/legacy/plugins/*/node_modules \
x-pack/legacy/plugins/reporting/.chromium \
test/plugin_functional/plugins/*/node_modules \
+ examples/*/node_modules \
.es \
.chromedriver \
.geckodriver;
diff --git a/.eslintrc.js b/.eslintrc.js
index 106724c323d30..367ac892107ab 100644
--- a/.eslintrc.js
+++ b/.eslintrc.js
@@ -170,13 +170,6 @@ module.exports = {
'react-hooks/rules-of-hooks': 'off',
},
},
- {
- files: ['x-pack/legacy/plugins/infra/**/*.{js,ts,tsx}'],
- rules: {
- 'react-hooks/exhaustive-deps': 'off',
- 'react-hooks/rules-of-hooks': 'off',
- },
- },
{
files: ['x-pack/legacy/plugins/lens/**/*.{js,ts,tsx}'],
rules: {
@@ -209,13 +202,6 @@ module.exports = {
'react-hooks/rules-of-hooks': 'off',
},
},
- {
- files: ['x-pack/legacy/plugins/watcher/**/*.{js,ts,tsx}'],
- rules: {
- 'react-hooks/rules-of-hooks': 'off',
- 'react-hooks/exhaustive-deps': 'off',
- },
- },
/**
* Prettier
diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS
index c5e6768c17d46..338fbf2e359b7 100644
--- a/.github/CODEOWNERS
+++ b/.github/CODEOWNERS
@@ -5,6 +5,8 @@
# App
/x-pack/legacy/plugins/lens/ @elastic/kibana-app
/x-pack/legacy/plugins/graph/ @elastic/kibana-app
+/src/plugins/share/ @elastic/kibana-app
+/src/legacy/server/url_shortening/ @elastic/kibana-app
/src/legacy/server/sample_data/ @elastic/kibana-app
# App Architecture
@@ -14,7 +16,6 @@
/src/plugins/kibana_react/ @elastic/kibana-app-arch
/src/plugins/kibana_utils/ @elastic/kibana-app-arch
/src/plugins/navigation/ @elastic/kibana-app-arch
-/src/plugins/share/ @elastic/kibana-app-arch
/src/plugins/ui_actions/ @elastic/kibana-app-arch
/src/plugins/visualizations/ @elastic/kibana-app-arch
/x-pack/plugins/advanced_ui_actions/ @elastic/kibana-app-arch
@@ -28,7 +29,6 @@
/src/legacy/core_plugins/kibana/server/routes/api/suggestions/ @elastic/kibana-app-arch
/src/legacy/core_plugins/visualizations/ @elastic/kibana-app-arch
/src/legacy/server/index_patterns/ @elastic/kibana-app-arch
-/src/legacy/server/url_shortening/ @elastic/kibana-app-arch
# APM
/x-pack/legacy/plugins/apm/ @elastic/apm-ui
diff --git a/.i18nrc.json b/.i18nrc.json
index fac9b9ce53184..a1c49ae03f359 100644
--- a/.i18nrc.json
+++ b/.i18nrc.json
@@ -17,6 +17,7 @@
"kbn": "src/legacy/core_plugins/kibana",
"kbnDocViews": "src/legacy/core_plugins/kbn_doc_views",
"kbnVislibVisTypes": "src/legacy/core_plugins/kbn_vislib_vis_types",
+ "management": "src/legacy/core_plugins/management",
"kibana_react": "src/legacy/core_plugins/kibana_react",
"kibana-react": "src/plugins/kibana_react",
"kibana_utils": "src/plugins/kibana_utils",
diff --git a/NOTICE.txt b/NOTICE.txt
index 989bb6f754a09..230e511746022 100644
--- a/NOTICE.txt
+++ b/NOTICE.txt
@@ -186,32 +186,6 @@ LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----
-This product includes code that is based on facebookincubator/idx, which was
-available under a "MIT" license.
-
-MIT License
-
-Copyright (c) 2013-present, Facebook, Inc.
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
-
---
This product includes code that was extracted from angular@1.3.
Original license:
diff --git a/docs/developer/core/development-functional-tests.asciidoc b/docs/developer/core/development-functional-tests.asciidoc
index 350a3c2a997cf..77a2bfe77b4ab 100644
--- a/docs/developer/core/development-functional-tests.asciidoc
+++ b/docs/developer/core/development-functional-tests.asciidoc
@@ -282,7 +282,7 @@ The `FunctionalTestRunner` comes with three built-in services:
* Source: {blob}src/functional_test_runner/lib/lifecycle.ts[src/functional_test_runner/lib/lifecycle.ts]
* Designed primary for use in services
* Exposes lifecycle events for basic coordination. Handlers can return a promise and resolve/fail asynchronously
-* Phases include: `beforeLoadTests`, `beforeTests`, `beforeEachTest`, `cleanup`, `phaseStart`, `phaseEnd`
+* Phases include: `beforeLoadTests`, `beforeTests`, `beforeEachTest`, `cleanup`
[float]
===== Kibana Services
diff --git a/docs/setup/settings.asciidoc b/docs/setup/settings.asciidoc
index 5605ed5c56688..5cda7b2b214f0 100644
--- a/docs/setup/settings.asciidoc
+++ b/docs/setup/settings.asciidoc
@@ -65,6 +65,8 @@ connects to this Kibana instance.
`elasticsearch.requestHeadersWhitelist:`:: *Default: `[ 'authorization' ]`* List
of Kibana client-side headers to send to Elasticsearch. To send *no* client-side
headers, set this value to [] (an empty list).
+Removing the `authorization` header from being whitelisted means that you cannot
+use <> in Kibana.
`elasticsearch.requestTimeout:`:: *Default: 30000* Time in milliseconds to wait
for responses from the back end or Elasticsearch. This value must be a positive
@@ -147,6 +149,36 @@ will default to `true`.
`logging.quiet:`:: *Default: false* Set the value of this setting to `true` to
suppress all logging output other than error messages.
+`logging.rotate:`:: [experimental] Specifies the options for the logging rotate feature.
+When not defined, all the sub options defaults would be applied.
+The following example shows a valid logging rotate configuration:
++
+--
+ logging.rotate:
+ enabled: true
+ everyBytes: 10485760
+ keepFiles: 10
+--
+
+`logging.rotate.enabled:`:: [experimental] *Default: false* Set the value of this setting to `true` to
+enable log rotation. If you do not have a `logging.dest` set that is different from `stdout`
+that feature would not take any effect.
+
+`logging.rotate.everyBytes:`:: [experimental] *Default: 10485760* The maximum size of a log file (that is `not an exact` limit). After the
+limit is reached, a new log file is generated. The default size limit is 10485760 (10 MB) and
+this option should be at least greater than 1024.
+
+`logging.rotate.keepFiles:`:: [experimental] *Default: 7* The number of most recent rotated log files to keep
+on disk. Older files are deleted during log rotation. The default value is 7. The `logging.rotate.keepFiles`
+option has to be in the range of 2 to 1024 files.
+
+`logging.rotate.pollingInterval:`:: [experimental] *Default: 10000* The number of milliseconds for the polling strategy in case
+the `logging.rotate.usePolling` is enabled. That option has to be in the range of 5000 to 3600000 milliseconds.
+
+`logging.rotate.usePolling:`:: [experimental] *Default: false* By default we try to understand the best way to monitoring
+the log file. However, there is some systems where it could not be always accurate. In those cases, if needed,
+the `polling` method could be used enabling that option.
+
`logging.silent:`:: *Default: false* Set the value of this setting to `true` to
suppress all logging output.
diff --git a/examples/README.md b/examples/README.md
new file mode 100644
index 0000000000000..7cade0b35f820
--- /dev/null
+++ b/examples/README.md
@@ -0,0 +1,8 @@
+## Example plugins
+
+This folder contains example plugins. To run the plugins in this folder, use the `--run-examples` flag, via
+
+```
+yarn start --run-examples
+```
+
diff --git a/examples/demo_search/README.md b/examples/demo_search/README.md
new file mode 100644
index 0000000000000..f0b461e3287b4
--- /dev/null
+++ b/examples/demo_search/README.md
@@ -0,0 +1,8 @@
+## Demo search strategy
+
+This example registers a custom search strategy that simply takes a name string in the request and returns the
+string `Hello {name}`
+
+To see the demo search strategy in action, navigate to the `Search explorer` app.
+
+To run these examples, use the command `yarn start --run-examples`.
\ No newline at end of file
diff --git a/test/plugin_functional/plugins/demo_search/common/index.ts b/examples/demo_search/common/index.ts
similarity index 90%
rename from test/plugin_functional/plugins/demo_search/common/index.ts
rename to examples/demo_search/common/index.ts
index 9254412ece291..6587ee96ef61b 100644
--- a/test/plugin_functional/plugins/demo_search/common/index.ts
+++ b/examples/demo_search/common/index.ts
@@ -17,10 +17,7 @@
* under the License.
*/
-import {
- IKibanaSearchRequest,
- IKibanaSearchResponse,
-} from '../../../../../src/plugins/data/public';
+import { IKibanaSearchRequest, IKibanaSearchResponse } from '../../../src/plugins/data/public';
export const DEMO_SEARCH_STRATEGY = 'DEMO_SEARCH_STRATEGY';
diff --git a/test/plugin_functional/plugins/demo_search/kibana.json b/examples/demo_search/kibana.json
similarity index 100%
rename from test/plugin_functional/plugins/demo_search/kibana.json
rename to examples/demo_search/kibana.json
diff --git a/test/plugin_functional/plugins/demo_search/package.json b/examples/demo_search/package.json
similarity index 88%
rename from test/plugin_functional/plugins/demo_search/package.json
rename to examples/demo_search/package.json
index 1f4fa1421906a..404002a50e710 100644
--- a/test/plugin_functional/plugins/demo_search/package.json
+++ b/examples/demo_search/package.json
@@ -8,7 +8,7 @@
},
"license": "Apache-2.0",
"scripts": {
- "kbn": "node ../../../../scripts/kbn.js",
+ "kbn": "node ../../scripts/kbn.js",
"build": "rm -rf './target' && tsc"
},
"devDependencies": {
diff --git a/test/plugin_functional/plugins/demo_search/public/demo_search_strategy.ts b/examples/demo_search/public/demo_search_strategy.ts
similarity index 96%
rename from test/plugin_functional/plugins/demo_search/public/demo_search_strategy.ts
rename to examples/demo_search/public/demo_search_strategy.ts
index 298eaaaf420e0..d2854151e14c8 100644
--- a/test/plugin_functional/plugins/demo_search/public/demo_search_strategy.ts
+++ b/examples/demo_search/public/demo_search_strategy.ts
@@ -22,8 +22,8 @@ import {
ISearchContext,
SYNC_SEARCH_STRATEGY,
ISearchGeneric,
-} from '../../../../../src/plugins/data/public';
-import { TSearchStrategyProvider, ISearchStrategy } from '../../../../../src/plugins/data/public';
+} from '../../../src/plugins/data/public';
+import { TSearchStrategyProvider, ISearchStrategy } from '../../../src/plugins/data/public';
import { DEMO_SEARCH_STRATEGY, IDemoResponse } from '../common';
diff --git a/test/plugin_functional/plugins/demo_search/public/index.ts b/examples/demo_search/public/index.ts
similarity index 100%
rename from test/plugin_functional/plugins/demo_search/public/index.ts
rename to examples/demo_search/public/index.ts
diff --git a/test/plugin_functional/plugins/demo_search/public/plugin.ts b/examples/demo_search/public/plugin.ts
similarity index 92%
rename from test/plugin_functional/plugins/demo_search/public/plugin.ts
rename to examples/demo_search/public/plugin.ts
index 37f8d3955708a..81ba585b99190 100644
--- a/test/plugin_functional/plugins/demo_search/public/plugin.ts
+++ b/examples/demo_search/public/plugin.ts
@@ -17,8 +17,8 @@
* under the License.
*/
-import { DataPublicPluginSetup } from '../../../../../src/plugins/data/public';
-import { Plugin, CoreSetup, PluginInitializerContext } from '../../../../../src/core/public';
+import { DataPublicPluginSetup } from '../../../src/plugins/data/public';
+import { Plugin, CoreSetup, PluginInitializerContext } from '../../../src/core/public';
import { DEMO_SEARCH_STRATEGY } from '../common';
import { demoClientSearchStrategyProvider } from './demo_search_strategy';
import { IDemoRequest, IDemoResponse } from '../common';
@@ -36,7 +36,7 @@ interface DemoDataSearchSetupDependencies {
* If the caller does not pass in the right `request` shape, typescript will
* complain. The caller will also get a typed response.
*/
-declare module '../../../../../src/plugins/data/public' {
+declare module '../../../src/plugins/data/public' {
export interface IRequestTypesMap {
[DEMO_SEARCH_STRATEGY]: IDemoRequest;
}
diff --git a/test/plugin_functional/plugins/demo_search/server/demo_search_strategy.ts b/examples/demo_search/server/demo_search_strategy.ts
similarity index 94%
rename from test/plugin_functional/plugins/demo_search/server/demo_search_strategy.ts
rename to examples/demo_search/server/demo_search_strategy.ts
index d3f2360add6c0..5b0883be1fc51 100644
--- a/test/plugin_functional/plugins/demo_search/server/demo_search_strategy.ts
+++ b/examples/demo_search/server/demo_search_strategy.ts
@@ -17,7 +17,7 @@
* under the License.
*/
-import { TSearchStrategyProvider } from 'src/plugins/data/server';
+import { TSearchStrategyProvider } from '../../../src/plugins/data/server';
import { DEMO_SEARCH_STRATEGY } from '../common';
export const demoSearchStrategyProvider: TSearchStrategyProvider = () => {
diff --git a/test/plugin_functional/plugins/demo_search/server/index.ts b/examples/demo_search/server/index.ts
similarity index 100%
rename from test/plugin_functional/plugins/demo_search/server/index.ts
rename to examples/demo_search/server/index.ts
diff --git a/test/plugin_functional/plugins/demo_search/server/plugin.ts b/examples/demo_search/server/plugin.ts
similarity index 97%
rename from test/plugin_functional/plugins/demo_search/server/plugin.ts
rename to examples/demo_search/server/plugin.ts
index c6628e7c76820..23c82225563c8 100644
--- a/test/plugin_functional/plugins/demo_search/server/plugin.ts
+++ b/examples/demo_search/server/plugin.ts
@@ -35,7 +35,7 @@ interface IDemoSearchExplorerDeps {
* If the caller does not pass in the right `request` shape, typescript will
* complain. The caller will also get a typed response.
*/
-declare module '../../../../../src/plugins/data/server' {
+declare module '../../../src/plugins/data/server' {
export interface IRequestTypesMap {
[DEMO_SEARCH_STRATEGY]: IDemoRequest;
}
diff --git a/test/plugin_functional/plugins/demo_search/tsconfig.json b/examples/demo_search/tsconfig.json
similarity index 75%
rename from test/plugin_functional/plugins/demo_search/tsconfig.json
rename to examples/demo_search/tsconfig.json
index 304ffdc0a299d..7fa03739119b4 100644
--- a/test/plugin_functional/plugins/demo_search/tsconfig.json
+++ b/examples/demo_search/tsconfig.json
@@ -1,5 +1,5 @@
{
- "extends": "../../../../tsconfig.json",
+ "extends": "../../tsconfig.json",
"compilerOptions": {
"outDir": "./target",
"skipLibCheck": true
@@ -10,7 +10,7 @@
"public/**/*.ts",
"public/**/*.tsx",
"server/**/*.ts",
- "../../../../typings/**/*"
+ "../../typings/**/*"
],
"exclude": []
}
diff --git a/examples/search_explorer/README.md b/examples/search_explorer/README.md
new file mode 100644
index 0000000000000..0e5a48cf22dc1
--- /dev/null
+++ b/examples/search_explorer/README.md
@@ -0,0 +1,8 @@
+## Search explorer
+
+This example search explorer app shows how to use different search strategies in order to retrieve data.
+
+One demo uses the built in elasticsearch search strategy, and runs a search against data in elasticsearch. The
+other demo uses the custom demo search strategy, a custom search strategy registerd inside the [demo_search plugin](../demo_search).
+
+To run this example, use the command `yarn start --run-examples`.
\ No newline at end of file
diff --git a/test/plugin_functional/plugins/search_explorer/kibana.json b/examples/search_explorer/kibana.json
similarity index 100%
rename from test/plugin_functional/plugins/search_explorer/kibana.json
rename to examples/search_explorer/kibana.json
diff --git a/test/plugin_functional/plugins/search_explorer/package.json b/examples/search_explorer/package.json
similarity index 87%
rename from test/plugin_functional/plugins/search_explorer/package.json
rename to examples/search_explorer/package.json
index 9a5e0e83a2207..62d0127c30cc6 100644
--- a/test/plugin_functional/plugins/search_explorer/package.json
+++ b/examples/search_explorer/package.json
@@ -8,7 +8,7 @@
},
"license": "Apache-2.0",
"scripts": {
- "kbn": "node ../../../../scripts/kbn.js",
+ "kbn": "node ../../scripts/kbn.js",
"build": "rm -rf './target' && tsc"
},
"devDependencies": {
diff --git a/test/plugin_functional/plugins/search_explorer/public/application.tsx b/examples/search_explorer/public/application.tsx
similarity index 97%
rename from test/plugin_functional/plugins/search_explorer/public/application.tsx
rename to examples/search_explorer/public/application.tsx
index 4762209a548c1..801a3c615ac61 100644
--- a/test/plugin_functional/plugins/search_explorer/public/application.tsx
+++ b/examples/search_explorer/public/application.tsx
@@ -28,7 +28,7 @@ import {
EuiSideNav,
} from '@elastic/eui';
-import { AppMountContext, AppMountParameters } from '../../../../../src/core/public';
+import { AppMountContext, AppMountParameters } from '../../../src/core/public';
import { EsSearchTest } from './es_strategy';
import { Page } from './page';
import { DemoStrategy } from './demo_strategy';
diff --git a/test/plugin_functional/plugins/search_explorer/public/demo_strategy.tsx b/examples/search_explorer/public/demo_strategy.tsx
similarity index 98%
rename from test/plugin_functional/plugins/search_explorer/public/demo_strategy.tsx
rename to examples/search_explorer/public/demo_strategy.tsx
index 8a0dd31e3595f..7c6c21d2b7aed 100644
--- a/test/plugin_functional/plugins/search_explorer/public/demo_strategy.tsx
+++ b/examples/search_explorer/public/demo_strategy.tsx
@@ -25,7 +25,7 @@ import {
EuiFlexGroup,
EuiFieldText,
} from '@elastic/eui';
-import { ISearchGeneric } from '../../../../../src/plugins/data/public';
+import { ISearchGeneric } from '../../../src/plugins/data/public';
import { DoSearch } from './do_search';
import { GuideSection } from './guide_section';
diff --git a/test/plugin_functional/plugins/search_explorer/public/do_search.tsx b/examples/search_explorer/public/do_search.tsx
similarity index 97%
rename from test/plugin_functional/plugins/search_explorer/public/do_search.tsx
rename to examples/search_explorer/public/do_search.tsx
index e039e4ff3f63f..f279b9fcd6e23 100644
--- a/test/plugin_functional/plugins/search_explorer/public/do_search.tsx
+++ b/examples/search_explorer/public/do_search.tsx
@@ -21,10 +21,7 @@ import React from 'react';
import { EuiButton, EuiCodeBlock, EuiFlexItem, EuiFlexGroup, EuiText } from '@elastic/eui';
import { EuiProgress } from '@elastic/eui';
import { Observable } from 'rxjs';
-import {
- IKibanaSearchResponse,
- IKibanaSearchRequest,
-} from '../../../../../src/plugins/data/public';
+import { IKibanaSearchResponse, IKibanaSearchRequest } from '../../../src/plugins/data/public';
interface Props {
request: IKibanaSearchRequest;
diff --git a/test/plugin_functional/plugins/search_explorer/public/documentation.tsx b/examples/search_explorer/public/documentation.tsx
similarity index 100%
rename from test/plugin_functional/plugins/search_explorer/public/documentation.tsx
rename to examples/search_explorer/public/documentation.tsx
diff --git a/test/plugin_functional/plugins/search_explorer/public/es_strategy.tsx b/examples/search_explorer/public/es_strategy.tsx
similarity index 87%
rename from test/plugin_functional/plugins/search_explorer/public/es_strategy.tsx
rename to examples/search_explorer/public/es_strategy.tsx
index d35c67191a1f8..e26c11a646669 100644
--- a/test/plugin_functional/plugins/search_explorer/public/es_strategy.tsx
+++ b/examples/search_explorer/public/es_strategy.tsx
@@ -29,19 +29,19 @@ import {
ISearchGeneric,
IEsSearchResponse,
IEsSearchRequest,
-} from '../../../../../src/plugins/data/public';
+} from '../../../src/plugins/data/public';
import { DoSearch } from './do_search';
import { GuideSection } from './guide_section';
// @ts-ignore
-import serverPlugin from '!!raw-loader!./../../../../../src/plugins/data/server/search/es_search/es_search_service';
+import serverPlugin from '!!raw-loader!./../../../src/plugins/data/server/search/es_search/es_search_service';
// @ts-ignore
-import serverStrategy from '!!raw-loader!./../../../../../src/plugins/data/server/search/es_search/es_search_strategy';
+import serverStrategy from '!!raw-loader!./../../../src/plugins/data/server/search/es_search/es_search_strategy';
// @ts-ignore
-import publicPlugin from '!!raw-loader!./../../../../../src/plugins/data/public/search/es_search/es_search_service';
+import publicPlugin from '!!raw-loader!./../../../src/plugins/data/public/search/es_search/es_search_service';
// @ts-ignore
-import publicStrategy from '!!raw-loader!./../../../../../src/plugins/data/public/search/es_search/es_search_strategy';
+import publicStrategy from '!!raw-loader!./../../../src/plugins/data/public/search/es_search/es_search_strategy';
interface Props {
search: ISearchGeneric;
diff --git a/test/plugin_functional/plugins/search_explorer/public/guide_section.tsx b/examples/search_explorer/public/guide_section.tsx
similarity index 100%
rename from test/plugin_functional/plugins/search_explorer/public/guide_section.tsx
rename to examples/search_explorer/public/guide_section.tsx
diff --git a/test/plugin_functional/plugins/search_explorer/public/index.ts b/examples/search_explorer/public/index.ts
similarity index 100%
rename from test/plugin_functional/plugins/search_explorer/public/index.ts
rename to examples/search_explorer/public/index.ts
diff --git a/test/plugin_functional/plugins/search_explorer/public/page.tsx b/examples/search_explorer/public/page.tsx
similarity index 100%
rename from test/plugin_functional/plugins/search_explorer/public/page.tsx
rename to examples/search_explorer/public/page.tsx
diff --git a/test/plugin_functional/plugins/search_explorer/public/plugin.tsx b/examples/search_explorer/public/plugin.tsx
similarity index 94%
rename from test/plugin_functional/plugins/search_explorer/public/plugin.tsx
rename to examples/search_explorer/public/plugin.tsx
index cbe1073aa186b..a7a6fd11341a4 100644
--- a/test/plugin_functional/plugins/search_explorer/public/plugin.tsx
+++ b/examples/search_explorer/public/plugin.tsx
@@ -18,7 +18,7 @@
*/
import { Plugin, CoreSetup } from 'kibana/public';
-import { ISearchAppMountContext } from '../../../../../src/plugins/data/public';
+import { ISearchAppMountContext } from '../../../src/plugins/data/public';
declare module 'kibana/public' {
interface AppMountContext {
diff --git a/test/plugin_functional/plugins/search_explorer/public/search_api.tsx b/examples/search_explorer/public/search_api.tsx
similarity index 70%
rename from test/plugin_functional/plugins/search_explorer/public/search_api.tsx
rename to examples/search_explorer/public/search_api.tsx
index 8ec6225d1f172..fc68571e4ef68 100644
--- a/test/plugin_functional/plugins/search_explorer/public/search_api.tsx
+++ b/examples/search_explorer/public/search_api.tsx
@@ -20,22 +20,22 @@ import React from 'react';
import { GuideSection } from './guide_section';
// @ts-ignore
-import publicSetupContract from '!!raw-loader!./../../../../../src/plugins/data/public/search/i_search_setup';
+import publicSetupContract from '!!raw-loader!./../../../src/plugins/data/public/search/i_search_setup';
// @ts-ignore
-import publicSearchStrategy from '!!raw-loader!./../../../../../src/plugins/data/public/search/i_search_strategy';
+import publicSearchStrategy from '!!raw-loader!./../../../src/plugins/data/public/search/i_search_strategy';
// @ts-ignore
-import publicSearch from '!!raw-loader!./../../../../../src/plugins/data/public/search/i_search';
+import publicSearch from '!!raw-loader!./../../../src/plugins/data/public/search/i_search';
// @ts-ignore
-import publicPlugin from '!!raw-loader!./../../../../../src/plugins/data/public/search/search_service';
+import publicPlugin from '!!raw-loader!./../../../src/plugins/data/public/search/search_service';
// @ts-ignore
-import serverSetupContract from '!!raw-loader!./../../../../../src/plugins/data/server/search/i_search_setup';
+import serverSetupContract from '!!raw-loader!./../../../src/plugins/data/server/search/i_search_setup';
// @ts-ignore
-import serverSearchStrategy from '!!raw-loader!./../../../../../src/plugins/data/server/search/i_search_strategy';
+import serverSearchStrategy from '!!raw-loader!./../../../src/plugins/data/server/search/i_search_strategy';
// @ts-ignore
-import serverSearch from '!!raw-loader!./../../../../../src/plugins/data/server/search/i_search';
+import serverSearch from '!!raw-loader!./../../../src/plugins/data/server/search/i_search';
// @ts-ignore
-import serverPlugin from '!!raw-loader!./../../../../../src/plugins/data/server/search/search_service';
+import serverPlugin from '!!raw-loader!./../../../src/plugins/data/server/search/search_service';
export const SearchApiPage = () => (
- str.length >= width ? str : `${str}${' '.repeat(width - str.length)}`;
-
-run(
- async ({ log, flags }) => {
- await withProcRunner(log, async proc => {
- log.info('Deleting old output');
- await del(BUILD_DIR);
-
- const cwd = ROOT_DIR;
- const env = { ...process.env };
- if (supportsColor.stdout) {
- env.FORCE_COLOR = 'true';
- }
-
- log.info(`Starting babel and typescript${flags.watch ? ' in watch mode' : ''}`);
- await Promise.all([
- ...['web', 'node'].map(subTask =>
- proc.run(padRight(10, `babel:${subTask}`), {
- cmd: 'babel',
- args: [
- 'src',
- '--config-file',
- require.resolve('../babel.config.js'),
- '--out-dir',
- resolve(BUILD_DIR, subTask),
- '--extensions',
- '.ts,.js,.tsx',
- ...(flags.watch ? ['--watch'] : ['--quiet']),
- ...(flags['source-maps'] ? ['--source-map', 'inline'] : []),
- ],
- wait: true,
- env: {
- ...env,
- BABEL_ENV: subTask,
- },
- cwd,
- })
- ),
-
- proc.run(padRight(10, 'tsc'), {
- cmd: 'tsc',
- args: [
- '--emitDeclarationOnly',
- ...(flags.watch ? ['--watch', '--preserveWatchOutput', 'true'] : []),
- ...(flags['source-maps'] ? ['--declarationMap', 'true'] : []),
- ],
- wait: true,
- env,
- cwd,
- }),
- ]);
-
- log.success('Complete');
- });
- },
- {
- description: 'Simple build tool for @kbn/analytics package',
- flags: {
- boolean: ['watch', 'source-maps'],
- help: `
- --watch Run in watch mode
- --source-maps Include sourcemaps
- `,
- },
- }
-);
+/*
+ * 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.
+ */
+
+const { resolve } = require('path');
+
+const del = require('del');
+const supportsColor = require('supports-color');
+const { run, withProcRunner } = require('@kbn/dev-utils');
+
+const ROOT_DIR = resolve(__dirname, '..');
+const BUILD_DIR = resolve(ROOT_DIR, 'target');
+
+const padRight = (width, str) =>
+ str.length >= width ? str : `${str}${' '.repeat(width - str.length)}`;
+
+run(
+ async ({ log, flags }) => {
+ await withProcRunner(log, async proc => {
+ log.info('Deleting old output');
+ await del(BUILD_DIR);
+
+ const cwd = ROOT_DIR;
+ const env = { ...process.env };
+ if (supportsColor.stdout) {
+ env.FORCE_COLOR = 'true';
+ }
+
+ log.info(`Starting babel and typescript${flags.watch ? ' in watch mode' : ''}`);
+ await Promise.all([
+ ...['web', 'node'].map(subTask =>
+ proc.run(padRight(10, `babel:${subTask}`), {
+ cmd: 'babel',
+ args: [
+ 'src',
+ '--config-file',
+ require.resolve('../babel.config.js'),
+ '--out-dir',
+ resolve(BUILD_DIR, subTask),
+ '--extensions',
+ '.ts,.js,.tsx',
+ ...(flags.watch ? ['--watch'] : ['--quiet']),
+ ...(flags['source-maps'] ? ['--source-maps', 'inline'] : []),
+ ],
+ wait: true,
+ env: {
+ ...env,
+ BABEL_ENV: subTask,
+ },
+ cwd,
+ })
+ ),
+
+ proc.run(padRight(10, 'tsc'), {
+ cmd: 'tsc',
+ args: [
+ '--emitDeclarationOnly',
+ ...(flags.watch ? ['--watch', '--preserveWatchOutput', 'true'] : []),
+ ...(flags['source-maps'] ? ['--declarationMap', 'true'] : []),
+ ],
+ wait: true,
+ env,
+ cwd,
+ }),
+ ]);
+
+ log.success('Complete');
+ });
+ },
+ {
+ description: 'Simple build tool for @kbn/analytics package',
+ flags: {
+ boolean: ['watch', 'source-maps'],
+ help: `
+ --watch Run in watch mode
+ --source-maps Include sourcemaps
+ `,
+ },
+ }
+);
diff --git a/packages/kbn-babel-preset/common_preset.js b/packages/kbn-babel-preset/common_preset.js
index d1b7bc20dd9f9..0de9318ea0c27 100644
--- a/packages/kbn-babel-preset/common_preset.js
+++ b/packages/kbn-babel-preset/common_preset.js
@@ -35,13 +35,6 @@ const plugins = [
// Need this since we are using TypeScript 3.7+
require.resolve('@babel/plugin-proposal-nullish-coalescing-operator'),
];
-const isTestEnv = process.env.BABEL_ENV === 'test' || process.env.NODE_ENV === 'test';
-
-// Only load the idx plugin in non-test environments, since it conflicts with
-// Jest's coverage mapping.
-if (!isTestEnv) {
- plugins.push(require.resolve('@kbn/elastic-idx/babel'));
-}
module.exports = {
presets: [require.resolve('@babel/preset-typescript'), require.resolve('@babel/preset-react')],
diff --git a/packages/kbn-babel-preset/package.json b/packages/kbn-babel-preset/package.json
index 1913301e21a76..e554859928c0b 100644
--- a/packages/kbn-babel-preset/package.json
+++ b/packages/kbn-babel-preset/package.json
@@ -12,7 +12,6 @@
"@babel/preset-env": "^7.5.5",
"@babel/preset-react": "^7.0.0",
"@babel/preset-typescript": "^7.3.3",
- "@kbn/elastic-idx": "1.0.0",
"babel-plugin-add-module-exports": "^1.0.2",
"babel-plugin-filter-imports": "^3.0.0",
"babel-plugin-transform-define": "^1.3.1",
diff --git a/packages/kbn-elastic-idx/.npmignore b/packages/kbn-elastic-idx/.npmignore
deleted file mode 100644
index ece13b72c93ea..0000000000000
--- a/packages/kbn-elastic-idx/.npmignore
+++ /dev/null
@@ -1,3 +0,0 @@
-/tsconfig.json
-/src
-/babel/index.test.js
diff --git a/packages/kbn-elastic-idx/README.md b/packages/kbn-elastic-idx/README.md
deleted file mode 100644
index 81cd5d0f86e9b..0000000000000
--- a/packages/kbn-elastic-idx/README.md
+++ /dev/null
@@ -1,76 +0,0 @@
-Kibana elastic-idx Library
-==========================
-
-The `@kbn/elastic-idx` package provides the `idx` function used for optional
-chaining. Currently, the optional chaining draft is in stage 1, making it too
-uncertain to add syntax support within Kibana. Other optional chaining
-libraries require the Proxy object to be polyfilled for browser support,
-however, this polyfill is not fully supported across all browsers that Kibana
-requires. The facebookincubator `idx` project
-(https://github.com/facebookincubator/idx) provides an answer to this with a
-specific implementation that is understood by TypeScript so that type
-information does not get lost (unlike lodash get) The `@kbn/elastic-idx`
-library makes use the `idx` idiom but differs in the way null values within the
-property chain are handled.
-
-Similar to the facebookincubator `idx` project, `@kbn/elastic-idx` also
-provides the Babel plugin to transform `idx()` function calls into the expanded
-form. This Babel plugin was based off the facebookincubator `idx` Babel
-plugin, since the invocation syntax is almost identical, but the transformed
-code differs to match how the `@kbn/elastic-idx` library treats null values.
-
-App Usage
-----------
-Within Kibana, `@kbn/elastic-idx` can be imported and used in any JavaScript or
-TypeScript project:
-
-```
-import { idx } from '@kbn/elastic-idx';
-
-const obj0 = { a: { b: { c: { d: 'iamdefined' } } } };
-const obj1 = { a: { b: null } };
-
-idx(obj0, _ => _.a.b.c.d); // returns 'iamdefined'
-idx(obj1, _ => _.a.b.c.e); // returns undefined
-idx(obj1, _ => _.a.b); // returns null
-```
-
-Build Optimization
--------------------
-Similar to the facebookincubator `idx` project, it is NOT RECOMMENDED to use
-idx in shipped app code. The implementation details which make
-`@kbn/elastic-idx` possible comes at a non-negligible performance cost. This
-usually isn't noticable during development, but for production builds, it is
-recommended to transform idx calls into native, expanded form JS. Use the
-plugin `@kbn/elastic-idx/babel` within your Babel configuration:
-
-```
-{ "plugins": [ "@kbn/elastic-idx/babel" ] }
-```
-
-The resulting Babel transforms the following:
-
-```
-import { idx } from '@kbn/elastic-idx';
-const obj = { a: { b: { c: { d: 'iamdefined' } } } };
-idx(obj, _ => _.a.b.c.d);
-```
-
-into this:
-
-```
-obj != null &&
-obj.a != null &&
-obj.a.b != null &&
-obj.a.b.c != null ?
-obj.a.b.c.d : undefined
-```
-
-Note that this also removes the import statement from the source code, since it
-no longer needs to be bundled.
-
-Testing
---------
-
-Tests can be run with `npm test`. This includes "functional" tests that
-transform and evaluate idx calls.
diff --git a/packages/kbn-elastic-idx/babel/index.js b/packages/kbn-elastic-idx/babel/index.js
deleted file mode 100644
index 89171e3565530..0000000000000
--- a/packages/kbn-elastic-idx/babel/index.js
+++ /dev/null
@@ -1,304 +0,0 @@
-/* eslint-disable @kbn/eslint/require-license-header */
-
-/* @notice
- * This product includes code that is based on facebookincubator/idx, which was
- * available under a "MIT" license.
- *
- * MIT License
- *
- * Copyright (c) 2013-present, Facebook, Inc.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-/* eslint strict: 0, new-cap: 0 */
-
-'use strict';
-module.exports = context => {
- const t = context.types;
-
- const idxRe = /\bidx\b/;
-
- function checkIdxArguments(file, node) {
- const args = node.arguments;
- if (args.length !== 2) {
- throw file.buildCodeFrameError(node, 'The `idx` function takes exactly two arguments.');
- }
- const arrowFunction = args[1];
- if (!t.isArrowFunctionExpression(arrowFunction)) {
- throw file.buildCodeFrameError(
- arrowFunction,
- 'The second argument supplied to `idx` must be an arrow function.'
- );
- }
- if (!t.isExpression(arrowFunction.body)) {
- throw file.buildCodeFrameError(
- arrowFunction.body,
- 'The body of the arrow function supplied to `idx` must be a single ' +
- 'expression (without curly braces).'
- );
- }
- if (arrowFunction.params.length !== 1) {
- throw file.buildCodeFrameError(
- arrowFunction.params[2] || arrowFunction,
- 'The arrow function supplied to `idx` must take exactly one parameter.'
- );
- }
- const input = arrowFunction.params[0];
- if (!t.isIdentifier(input)) {
- throw file.buildCodeFrameError(
- arrowFunction.params[0],
- 'The parameter supplied to `idx` must be an identifier.'
- );
- }
- }
-
- function checkIdxBindingNode(file, node) {
- if (t.isImportDeclaration(node)) {
- // E.g. `import '...'`
- if (node.specifiers.length === 0) {
- throw file.buildCodeFrameError(node, 'The idx import must have a value.');
- }
- // E.g. `import A, {B} from '...'`
- // `import A, * as B from '...'`
- // `import {A, B} from '...'`
- if (node.specifiers.length > 1) {
- throw file.buildCodeFrameError(
- node.specifiers[1],
- 'The idx import must be a single specifier.'
- );
- }
- // `importKind` is not a property unless flow syntax is enabled.
- // On specifiers, `importKind` is not "value" when it's not a type, it's
- // `null`.
- // E.g. `import type {...} from '...'`
- // `import typeof {...} from '...'`
- // `import {type ...} from '...'`.
- // `import {typeof ...} from '...'`
- if (
- node.importKind === 'type' ||
- node.importKind === 'typeof' ||
- node.specifiers[0].importKind === 'type' ||
- node.specifiers[0].importKind === 'typeof'
- ) {
- throw file.buildCodeFrameError(node, 'The idx import must be a value import.');
- }
- } else if (t.isVariableDeclarator(node)) {
- // E.g. var {idx} or var [idx]
- if (!t.isIdentifier(node.id)) {
- throw file.buildCodeFrameError(
- node.specifiers[0],
- 'The idx declaration must be an identifier.'
- );
- }
- }
- }
-
- class UnsupportedNodeTypeError extends Error {
- constructor(node, ...params) {
- super(`Node type is not supported: ${node.type}`, ...params);
- if (Error.captureStackTrace) {
- Error.captureStackTrace(this, UnsupportedNodeTypeError);
- }
-
- this.name = 'UnsupportedNodeTypeError';
- }
- }
-
- function getDeepProperties(node, properties = [], computedProperties = new Set()) {
- if (t.isMemberExpression(node)) {
- if (node.computed) {
- computedProperties.add(node.property);
- }
- return getDeepProperties(node.object, [node.property, ...properties], computedProperties);
- } else if (t.isIdentifier(node)) {
- return [[node, ...properties], computedProperties];
- }
-
- throw new UnsupportedNodeTypeError(node);
- }
-
- function buildMemberChain(properties, computedProperties) {
- if (properties.length > 1) {
- const lead = properties.slice(0, properties.length - 1);
- const last = properties[properties.length - 1];
- return t.MemberExpression(
- buildMemberChain(lead, computedProperties),
- last,
- computedProperties.has(last)
- );
- } else if (properties.length === 1) {
- return properties[0];
- }
- return t.identifier('undefined');
- }
-
- function buildExpandedMemberNullChecks(
- leadingProperties = [],
- trailingProperties = [],
- computedProperties
- ) {
- const propertyChainNullCheck = t.BinaryExpression(
- '!=',
- buildMemberChain(leadingProperties, computedProperties),
- t.NullLiteral()
- );
-
- if (trailingProperties.length <= 1) {
- return propertyChainNullCheck;
- }
-
- const [headTrailingProperty, ...tailProperties] = trailingProperties;
-
- return t.LogicalExpression(
- '&&',
- propertyChainNullCheck,
- buildExpandedMemberNullChecks(
- [...leadingProperties, headTrailingProperty],
- tailProperties,
- computedProperties
- )
- );
- }
-
- function buildExpandedMemberAccess(node, state) {
- let baseNode;
- let properties;
- let computedProperties;
-
- try {
- [[baseNode, ...properties], computedProperties] = getDeepProperties(node);
- } catch (error) {
- if (error instanceof UnsupportedNodeTypeError) {
- throw state.file.buildCodeFrameError(
- node,
- 'idx callbacks may only access properties on the callback parameter.'
- );
- }
-
- throw error;
- }
-
- if (baseNode.name !== state.base.name) {
- throw state.file.buildCodeFrameError(
- node,
- 'The parameter of the arrow function supplied to `idx` must match ' +
- 'the base of the body expression.'
- );
- }
- return t.ConditionalExpression(
- buildExpandedMemberNullChecks([state.input], properties, computedProperties),
- buildMemberChain([state.input, ...properties], computedProperties),
- t.identifier('undefined')
- );
- }
-
- function visitIdxCallExpression(path, state) {
- const node = path.node;
- checkIdxArguments(state.file, node);
- const replacement = buildExpandedMemberAccess(node.arguments[1].body, {
- file: state.file,
- input: node.arguments[0],
- base: node.arguments[1].params[0],
- });
- path.replaceWith(replacement);
- }
-
- function isIdxImportOrRequire(node, name) {
- if (t.isImportDeclaration(node)) {
- if (name instanceof RegExp) {
- return name.test(node.source.value);
- } else {
- return t.isStringLiteral(node.source, { value: name });
- }
- } else if (t.isVariableDeclarator(node)) {
- return (
- t.isCallExpression(node.init) &&
- t.isIdentifier(node.init.callee, { name: 'require' }) &&
- (name instanceof RegExp
- ? name.test(node.init.arguments[0].value)
- : t.isLiteral(node.init.arguments[0], { value: name }))
- );
- } else {
- return false;
- }
- }
-
- const declareVisitor = {
- 'ImportDeclaration|VariableDeclarator'(path, state) {
- if (!isIdxImportOrRequire(path.node, state.importName)) {
- return;
- }
-
- checkIdxBindingNode(state.file, path.node);
-
- const bindingName = t.isImportDeclaration(path.node)
- ? path.node.specifiers[0].local.name
- : path.node.id.name;
- const idxBinding = path.scope.getOwnBinding(bindingName);
-
- idxBinding.constantViolations.forEach(refPath => {
- throw state.file.buildCodeFrameError(refPath.node, '`idx` cannot be redefined.');
- });
-
- let didTransform = false;
- let didSkip = false;
-
- // Traverse the references backwards to process inner calls before
- // outer calls.
- idxBinding.referencePaths
- .slice()
- .reverse()
- .forEach(refPath => {
- if (refPath.node === idxBinding.node) {
- // Do nothing...
- } else if (refPath.parentPath.isMemberExpression()) {
- visitIdxCallExpression(refPath.parentPath.parentPath, state);
- didTransform = true;
- } else if (refPath.parentPath.isCallExpression()) {
- visitIdxCallExpression(refPath.parentPath, state);
- didTransform = true;
- } else {
- // Should this throw?
- didSkip = true;
- }
- });
- if (didTransform && !didSkip) {
- path.remove();
- }
- },
- };
-
- return {
- visitor: {
- Program(path, state) {
- const importName = state.opts.importName || '@kbn/elastic-idx';
- // If there can't reasonably be an idx call, exit fast.
- if (importName !== '@kbn/elastic-idx' || idxRe.test(state.file.code)) {
- // We're very strict about the shape of idx. Some transforms, like
- // "babel-plugin-transform-async-to-generator", will convert arrow
- // functions inside async functions into regular functions. So we do
- // our transformation before any one else interferes.
- const newState = { file: state.file, importName };
- path.traverse(declareVisitor, newState);
- }
- },
- },
- };
-};
diff --git a/packages/kbn-elastic-idx/babel/index.test.js b/packages/kbn-elastic-idx/babel/index.test.js
deleted file mode 100644
index c4aee5266d6fa..0000000000000
--- a/packages/kbn-elastic-idx/babel/index.test.js
+++ /dev/null
@@ -1,694 +0,0 @@
-/* eslint-disable @kbn/eslint/require-license-header */
-
-/* @notice
- * This product includes code that is based on facebookincubator/idx, which was
- * available under a "MIT" license.
- *
- * MIT License
- *
- * Copyright (c) 2013-present, Facebook, Inc.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-'use strict'; // eslint-disable-line strict
-
-jest.autoMockOff();
-
-const { transformSync: babelTransform } = require('@babel/core');
-const babelPluginIdx = require('./index');
-const transformAsyncToGenerator = require('@babel/plugin-transform-async-to-generator');
-const vm = require('vm');
-
-function transform(source, plugins, options) {
- return babelTransform(source, {
- plugins: plugins || [[babelPluginIdx, options]],
- babelrc: false,
- highlightCode: false,
- }).code;
-}
-
-const asyncToGeneratorHelperCode = `
-function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) {
- try {
- var info = gen[key](arg);
- var value = info.value;
- } catch (error) {
- reject(error);
- return;
- }
- if (info.done) {
- resolve(value);
- } else {
- Promise.resolve(value).then(_next, _throw);
- }
-}
-
-function _asyncToGenerator(fn) {
- return function() {
- var self = this,
- args = arguments;
- return new Promise(function(resolve, reject) {
- var gen = fn.apply(self, args);
-
- function _next(value) {
- asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value);
- }
-
- function _throw(err) {
- asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err);
- }
- _next(undefined);
- });
- };
-}
-`;
-
-function stringByTrimmingSpaces(string) {
- return string.replace(/\s+/g, '');
-}
-
-expect.extend({
- toTransformInto: (input, expected) => {
- const plugins = typeof input === 'string' ? null : input.plugins;
- const options = typeof input === 'string' ? undefined : input.options;
- const code = typeof input === 'string' ? input : input.code;
- const actual = transform(code, plugins, options);
- const pass = stringByTrimmingSpaces(actual) === stringByTrimmingSpaces(expected);
- return {
- pass,
- message: () =>
- 'Expected input to transform into:\n' + expected + '\n' + 'Instead, got:\n' + actual,
- };
- },
- toThrowTransformError: (input, expected) => {
- try {
- const plugins = typeof input === 'string' ? null : input.plugins;
- const options = typeof input === 'string' ? undefined : input.options;
- const code = typeof input === 'string' ? input : input.code;
- transform(code, plugins, options);
- } catch (error) {
- const actual = /^.+:\s*(.*)/.exec(error.message)[1]; // Strip "undefined: " and code snippet
- return {
- pass: actual === expected,
- message: () =>
- 'Expected transform to throw "' + expected + '", but instead ' + 'got "' + actual + '".',
- };
- }
- return {
- pass: false,
- message: () => 'Expected transform to throw "' + expected + '".',
- };
- },
- toReturn: (input, expected) => {
- const code = transform(input, undefined);
- const actual = vm.runInNewContext(code);
- return {
- pass: actual === expected,
- message: () => 'Expected "' + expected + '" but got "' + actual + '".',
- };
- },
-});
-
-describe('kbn-babel-plugin-apm-idx', () => {
- it('transforms member expressions', () => {
- expect(`
- import { idx } from '@kbn/elastic-idx';
- idx(base, _ => _.b.c.d.e);
- `).toTransformInto(`
- base != null && base.b != null && base.b.c != null && base.b.c.d != null
- ? base.b.c.d.e
- : undefined;
- `);
- });
-
- it('throws on call expressions', () => {
- expect(`
- import { idx } from '@kbn/elastic-idx';
- idx(base, _ => _.b.c(...foo)().d(bar, null, [...baz]));
- `).toThrowTransformError('idx callbacks may only access properties on the callback parameter.');
- });
-
- it('transforms bracket notation', () => {
- expect(`
- import { idx } from '@kbn/elastic-idx';
- idx(base, _ => _["b"][0][c + d]);
- `).toTransformInto(`
- base != null && base["b"] != null && base["b"][0] != null ? base["b"][0][c + d] : undefined;
- `);
- });
-
- it('throws on bracket notation call expressions', () => {
- expect(`
- import { idx } from '@kbn/elastic-idx';
- idx(base, _ => _["b"](...foo)()[0][c + d](bar, null, [...baz]));
- `).toThrowTransformError('idx callbacks may only access properties on the callback parameter.');
- });
-
- it('transforms combination of both member access notations', () => {
- expect(`
- import { idx } from '@kbn/elastic-idx';
- idx(base, _ => _.a["b"].c[d[e[f]]].g);
- `).toTransformInto(`
- base != null && base.a != null && base.a["b"] != null && base.a["b"].c != null && base.a["b"].c[d[e[f]]] != null
- ? base.a["b"].c[d[e[f]]].g
- : undefined;
- `);
- });
-
- it('transforms if the base is an expression', () => {
- expect(`
- import { idx } from '@kbn/elastic-idx';
- idx(this.props.base[5], _ => _.property);
- `).toTransformInto(`
- this.props.base[5] != null ? this.props.base[5].property : undefined;
- `);
- });
-
- it('throws if the arrow function has more than one param', () => {
- expect(`
- import { idx } from '@kbn/elastic-idx';
- idx(base, (a, b) => _.property);
- `).toThrowTransformError(
- 'The arrow function supplied to `idx` must take exactly one parameter.'
- );
- });
-
- it('throws if the arrow function has an invalid base', () => {
- expect(`
- import { idx } from '@kbn/elastic-idx';
- idx(base, a => b.property)
- `).toThrowTransformError(
- 'The parameter of the arrow function supplied to `idx` must match the ' +
- 'base of the body expression.'
- );
- });
-
- it('throws if the arrow function expression has non-properties/methods', () => {
- expect(`
- import { idx } from '@kbn/elastic-idx';
- idx(base, _ => (_.a++).b.c);
- `).toThrowTransformError('idx callbacks may only access properties on the callback parameter.');
- });
-
- it('throws if the body of the arrow function is not an expression', () => {
- expect(`
- import { idx } from '@kbn/elastic-idx';
- idx(base, _ => {})
- `).toThrowTransformError(
- 'The body of the arrow function supplied to `idx` must be a single ' +
- 'expression (without curly braces).'
- );
- });
-
- it('ignores non-function call idx', () => {
- expect(`
- import { idx } from '@kbn/elastic-idx';
- result = idx;
- `).toTransformInto(`
- import { idx } from '@kbn/elastic-idx';
- result = idx;
- `);
- });
-
- it('throws if idx is called with zero arguments', () => {
- expect(`
- import { idx } from '@kbn/elastic-idx';
- idx();
- `).toThrowTransformError('The `idx` function takes exactly two arguments.');
- });
-
- it('throws if idx is called with one argument', () => {
- expect(`
- import { idx } from '@kbn/elastic-idx';
- idx(1);
- `).toThrowTransformError('The `idx` function takes exactly two arguments.');
- });
-
- it('throws if idx is called with three arguments', () => {
- expect(`
- import { idx } from '@kbn/elastic-idx';
- idx(1, 2, 3);
- `).toThrowTransformError('The `idx` function takes exactly two arguments.');
- });
-
- it('transforms idx calls as part of another expressions', () => {
- expect(`
- import { idx } from '@kbn/elastic-idx';
- paddingStatement();
- a = idx(base, _ => _.b[c]);
- `).toTransformInto(`
- paddingStatement();
- a = base != null && base.b != null ? base.b[c] : undefined;
- `);
- });
-
- it('transforms nested idx calls', () => {
- expect(`
- import { idx } from '@kbn/elastic-idx';
- idx(
- idx(
- idx(base, _ => _.a.b),
- _ => _.c.d
- ),
- _ => _.e.f
- );
- `).toTransformInto(`
- (
- (base != null && base.a != null ? base.a.b : undefined) != null &&
- (base != null && base.a != null ? base.a.b : undefined).c != null ?
- (base != null && base.a != null ? base.a.b : undefined).c.d :
- undefined
- ) != null
- &&
- (
- (base != null && base.a != null ? base.a.b : undefined) != null &&
- (base != null && base.a != null ? base.a.b : undefined).c != null ?
- (base != null && base.a != null ? base.a.b : undefined).c.d :
- undefined
- ).e != null ?
- (
- (base != null && base.a != null ? base.a.b : undefined) != null &&
- (base != null && base.a != null ? base.a.b : undefined).c != null ?
- (base != null && base.a != null ? base.a.b : undefined).c.d :
- undefined
- ).e.f :
- undefined;
- `);
- });
-
- it('transforms idx calls inside async functions (plugin order #1)', () => {
- expect({
- plugins: [babelPluginIdx, transformAsyncToGenerator],
- code: `
- import { idx } from '@kbn/elastic-idx';
- async function f() {
- idx(base, _ => _.b.c.d.e);
- }
- `,
- }).toTransformInto(`
- ${asyncToGeneratorHelperCode}
- function f() {
- return _f.apply(this, arguments);
- }
-
- function _f() {
- _f = _asyncToGenerator(function* () {
- base != null && base.b != null && base.b.c != null && base.b.c.d != null ? base.b.c.d.e : undefined;
- });
- return _f.apply(this, arguments);
- }
- `);
- });
-
- it('transforms idx calls inside async functions (plugin order #2)', () => {
- expect({
- plugins: [transformAsyncToGenerator, babelPluginIdx],
- code: `
- import { idx } from '@kbn/elastic-idx';
- async function f() {
- idx(base, _ => _.b.c.d.e);
- }
- `,
- }).toTransformInto(`
- ${asyncToGeneratorHelperCode}
-
- function f() {
- return _f.apply(this, arguments);
- }
-
- function _f() {
- _f = _asyncToGenerator(function* () {
- base != null && base.b != null && base.b.c != null && base.b.c.d != null ? base.b.c.d.e : undefined;
- });
- return _f.apply(this, arguments);
- }
- `);
- });
-
- it('transforms idx calls in async methods', () => {
- expect({
- plugins: [transformAsyncToGenerator, babelPluginIdx],
- code: `
- import { idx } from '@kbn/elastic-idx';
- class Foo {
- async bar() {
- idx(base, _ => _.b);
- return this;
- }
- }
- `,
- }).toTransformInto(`
- ${asyncToGeneratorHelperCode}
-
- class Foo {
- bar() {
- var _this = this;
-
- return _asyncToGenerator(function* () {
- base != null ? base.b : undefined;
- return _this;
- })();
- }
- }
- `);
- });
-
- it('transforms idx calls when an idx import binding is in scope', () => {
- expect(`
- import idx from '@kbn/elastic-idx';
- idx(base, _ => _.b);
- `).toTransformInto(`
- base != null ? base.b : undefined;
- `);
- });
-
- it('transforms idx calls when an idx const binding is in scope', () => {
- expect(`
- const idx = require('@kbn/elastic-idx');
- idx(base, _ => _.b);
- `).toTransformInto(`
- base != null ? base.b : undefined;
- `);
- });
-
- it('transforms deep idx calls when an idx import binding is in scope', () => {
- expect(`
- import idx from '@kbn/elastic-idx';
- function f() {
- idx(base, _ => _.b);
- }
- `).toTransformInto(`
- function f() {
- base != null ? base.b : undefined;
- }
- `);
- });
-
- it('transforms deep idx calls when an idx const binding is in scope', () => {
- expect(`
- const idx = require('@kbn/elastic-idx');
- function f() {
- idx(base, _ => _.b);
- }
- `).toTransformInto(`
- function f() {
- base != null ? base.b : undefined;
- }
- `);
- });
-
- it('transforms idx calls when an idx is called as a member function on the binding in scope', () => {
- expect(`
- const elastic_idx = require("@kbn/elastic-idx");
- const result = elastic_idx.idx(base, _ => _.a.b.c.d);
- `).toTransformInto(`
- const result = base != null &&
- base.a != null &&
- base.a.b != null &&
- base.a.b.c != null ?
- base.a.b.c.d :
- undefined;
- `);
- });
-
- it('throws on base call expressions', () => {
- expect(`
- import { idx } from '@kbn/elastic-idx';
- idx(base, _ => _().b.c);
- `).toThrowTransformError('idx callbacks may only access properties on the callback parameter.');
- });
-
- it('transforms when the idx parent is a scope creating expression', () => {
- expect(`
- import { idx } from '@kbn/elastic-idx';
- (() => idx(base, _ => _.b));
- `).toTransformInto(`
- () => base != null ? base.b : undefined;
- `);
- });
-
- it('throws if redefined before use', () => {
- expect(`
- let idx = require('@kbn/elastic-idx');
- idx = null;
- idx(base, _ => _.b);
- `).toThrowTransformError('`idx` cannot be redefined.');
- });
-
- it('throws if redefined after use', () => {
- expect(`
- let idx = require('@kbn/elastic-idx');
- idx(base, _ => _.b);
- idx = null;
- `).toThrowTransformError('`idx` cannot be redefined.');
- });
-
- it('throws if there is a duplicate declaration', () => {
- expect(() =>
- transform(`
- let idx = require('@kbn/elastic-idx');
- idx(base, _ => _.b);
- function idx() {}
- `)
- ).toThrow();
- });
-
- it('handles sibling scopes with unique idx', () => {
- expect(`
- function aaa() {
- const idx = require('@kbn/elastic-idx');
- idx(base, _ => _.b);
- }
- function bbb() {
- const idx = require('@kbn/elastic-idx');
- idx(base, _ => _.b);
- }
- `).toTransformInto(`
- function aaa() {
- base != null ? base.b : undefined;
- }
- function bbb() {
- base != null ? base.b : undefined;
- }
- `);
- });
-
- it('handles sibling scopes with and without idx', () => {
- expect(`
- function aaa() {
- const idx = require('@kbn/elastic-idx');
- idx(base, _ => _.b);
- }
- function bbb() {
- idx(base, _ => _.b);
- }
- `).toTransformInto(`
- function aaa() {
- base != null ? base.b : undefined;
- }
- function bbb() {
- idx(base, _ => _.b);
- }
- `);
- });
-
- it('handles nested scopes with shadowing', () => {
- expect(`
- import { idx } from '@kbn/elastic-idx';
- idx(base, _ => _.b);
- function aaa() {
- idx(base, _ => _.b);
- function bbb(idx) {
- idx(base, _ => _.b);
- }
- }
- `).toTransformInto(`
- base != null ? base.b : undefined;
- function aaa() {
- base != null ? base.b : undefined;
- function bbb(idx) {
- idx(base, _ => _.b);
- }
- }
- `);
- });
-
- it('handles named idx import', () => {
- expect(`
- import { idx } from '@kbn/elastic-idx';
- idx(base, _ => _.b);
- `).toTransformInto(`
- base != null ? base.b : undefined;
- `);
- });
-
- it('throws on default plus named import', () => {
- expect(`
- import idx, {foo} from '@kbn/elastic-idx';
- idx(base, _ => _.b);
- `).toThrowTransformError('The idx import must be a single specifier.');
- });
-
- it('throws on default plus namespace import', () => {
- expect(`
- import idx, * as foo from '@kbn/elastic-idx';
- idx(base, _ => _.b);
- `).toThrowTransformError('The idx import must be a single specifier.');
- });
-
- it('throws on named default plus other import', () => {
- expect(`
- import {default as idx, foo} from '@kbn/elastic-idx';
- idx(base, _ => _.b);
- `).toThrowTransformError('The idx import must be a single specifier.');
- });
-
- it('unused idx import should be left alone', () => {
- expect(`
- import { idx } from '@kbn/elastic-idx';
- `).toTransformInto(`
- import { idx } from '@kbn/elastic-idx';
- `);
- });
-
- it('allows configuration of the import name', () => {
- expect({
- code: `
- import { idx } from 'i_d_x';
- idx(base, _ => _.b);
- `,
- options: { importName: 'i_d_x' },
- }).toTransformInto(`
- base != null ? base.b : undefined;
- `);
- });
-
- it('follows configuration of the import name', () => {
- expect({
- code: `
- import { idx } from '@kbn/elastic-idx';
- import { idx as i_d_x } from 'i_d_x';
- i_d_x(base, _ => _.b);
- idx(base, _ => _.c);
- `,
- options: { importName: 'i_d_x' },
- }).toTransformInto(`
- import { idx } from '@kbn/elastic-idx';
-
- base != null ? base.b : undefined;
- idx(base, _ => _.c);
- `);
- });
-
- it('allows configuration of the require name as a string', () => {
- expect({
- code: `
- import { idx } from 'i_d_x';
- idx(base, _ => _.b);
- `,
- options: { importName: 'i_d_x' },
- }).toTransformInto(`
- base != null ? base.b : undefined;
- `);
- });
-
- it('allows configuration of the require name as a RegExp', () => {
- expect({
- code: `
- import { idx } from '../../common/idx';
- idx(base, _ => _.b);
- `,
- options: { importName: /.*idx$/ },
- }).toTransformInto(`
- base != null ? base.b : undefined;
- `);
- });
-
- it('follows configuration of the require name', () => {
- expect({
- code: `
- const idx = require('@kbn/elastic-idx');
- const i_d_x = require('i_d_x');
- i_d_x(base, _ => _.b);
- idx(base, _ => _.c);
- `,
- options: { importName: 'i_d_x' },
- }).toTransformInto(`
- const idx = require('@kbn/elastic-idx');
-
- base != null ? base.b : undefined;
- idx(base, _ => _.c);
- `);
- });
-
- describe('functional', () => {
- it('works with only properties', () => {
- expect(`
- import { idx } from '@kbn/elastic-idx';
- const base = {a: {b: {c: 2}}};
- idx(base, _ => _.a.b.c);
- `).toReturn(2);
- });
-
- it('works with missing properties', () => {
- expect(`
- import { idx } from '@kbn/elastic-idx';
- const base = {a: {b: {}}};
- idx(base, _ => _.a.b.c);
- `).toReturn(undefined);
- });
-
- it('works with null properties', () => {
- expect(`
- import { idx } from '@kbn/elastic-idx';
- const base = {a: {b: null}};
- idx(base, _ => _.a.b.c);
- `).toReturn(undefined);
- });
-
- it('works with nested idx calls', () => {
- expect(`
- import { idx } from '@kbn/elastic-idx';
- const base = {a: {b: {c: {d: {e: {f: 2}}}}}};
- idx(
- idx(
- idx(base, _ => _.a.b),
- _ => _.c.d
- ),
- _ => _.e.f
- );
- `).toReturn(2);
- });
-
- it('works with nested idx calls with missing properties', () => {
- expect(`
- import { idx } from '@kbn/elastic-idx';
- const base = {a: {b: {c: null}}};
- idx(
- idx(
- idx(base, _ => _.a.b),
- _ => _.c.d
- ),
- _ => _.e.f
- );
- `).toReturn(undefined);
- });
- });
-});
diff --git a/packages/kbn-elastic-idx/package.json b/packages/kbn-elastic-idx/package.json
deleted file mode 100644
index 9532983942d6b..0000000000000
--- a/packages/kbn-elastic-idx/package.json
+++ /dev/null
@@ -1,28 +0,0 @@
-{
- "name": "@kbn/elastic-idx",
- "version": "1.0.0",
- "private": true,
- "license": "Apache-2.0",
- "description": "Library for optional chaining & the Babel plugin to transpile idx calls to plain, optimized JS",
- "main": "target/index.js",
- "types": "target/index.d.js",
- "repository": {
- "type": "git",
- "url": "https://github.com/elastic/kibana/tree/master/packages/kbn-elastic-idx"
- },
- "scripts": {
- "build": "tsc",
- "kbn:bootstrap": "yarn build",
- "kbn:watch": "yarn build --watch",
- "test": "jest"
- },
- "devDependencies": {
- "@babel/core": "^7.5.5",
- "@babel/plugin-transform-async-to-generator": "^7.5.0",
- "jest": "^24.9.0",
- "typescript": "3.7.2"
- },
- "jest": {
- "testEnvironment": "node"
- }
-}
diff --git a/packages/kbn-elastic-idx/src/index.ts b/packages/kbn-elastic-idx/src/index.ts
deleted file mode 100644
index eeb0df2747a14..0000000000000
--- a/packages/kbn-elastic-idx/src/index.ts
+++ /dev/null
@@ -1,65 +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.
- */
-
-/**
- * DeepRequiredArray
- * Nested array condition handler
- */
-// eslint-disable-next-line @typescript-eslint/no-empty-interface
-interface DeepRequiredArray extends Array> {}
-
-/**
- * DeepRequiredObject
- * Nested object condition handler
- */
-type DeepRequiredObject = { [P in keyof T]-?: DeepRequired };
-
-/**
- * Function that has deeply required return type
- */
-type FunctionWithRequiredReturnType any> = T extends (
- ...args: infer A
-) => infer R
- ? (...args: A) => DeepRequired
- : never;
-
-/**
- * DeepRequired
- * Required that works for deeply nested structure
- */
-type DeepRequired = NonNullable extends never
- ? T
- : T extends any[]
- ? DeepRequiredArray
- : T extends (...args: any[]) => any
- ? FunctionWithRequiredReturnType
- : NonNullable extends object
- ? DeepRequiredObject>
- : T;
-
-export function idx(
- input: T1,
- accessor: (input: NonNullable>) => T2
-): T2 | undefined {
- try {
- return accessor(input as NonNullable>);
- } catch (error) {
- return undefined;
- }
-}
diff --git a/packages/kbn-elastic-idx/tsconfig.json b/packages/kbn-elastic-idx/tsconfig.json
deleted file mode 100644
index 27833d7594031..0000000000000
--- a/packages/kbn-elastic-idx/tsconfig.json
+++ /dev/null
@@ -1,8 +0,0 @@
-{
- "extends": "../../tsconfig.json",
- "compilerOptions": {
- "declaration": true,
- "outDir": "./target"
- },
- "include": ["src/**/*"]
-}
diff --git a/packages/kbn-i18n/scripts/build.js b/packages/kbn-i18n/scripts/build.js
index f4260d31d80fb..ccdddc87dbc18 100644
--- a/packages/kbn-i18n/scripts/build.js
+++ b/packages/kbn-i18n/scripts/build.js
@@ -55,7 +55,7 @@ run(
'--extensions',
'.ts,.js,.tsx',
...(flags.watch ? ['--watch'] : ['--quiet']),
- ...(flags['source-maps'] ? ['--source-map', 'inline'] : []),
+ ...(flags['source-maps'] ? ['--source-maps', 'inline'] : []),
],
wait: true,
env: {
diff --git a/packages/kbn-pm/dist/index.js b/packages/kbn-pm/dist/index.js
index bbe12a93c241f..aea85c13d7f32 100644
--- a/packages/kbn-pm/dist/index.js
+++ b/packages/kbn-pm/dist/index.js
@@ -23185,6 +23185,7 @@ function getProjectPaths(rootPath, options = {}) {
projectPaths.push(Object(path__WEBPACK_IMPORTED_MODULE_0__["resolve"])(rootPath, 'test/plugin_functional/plugins/*'));
projectPaths.push(Object(path__WEBPACK_IMPORTED_MODULE_0__["resolve"])(rootPath, 'test/interpreter_functional/plugins/*'));
+ projectPaths.push(Object(path__WEBPACK_IMPORTED_MODULE_0__["resolve"])(rootPath, 'examples/*'));
if (!ossOnly) {
projectPaths.push(Object(path__WEBPACK_IMPORTED_MODULE_0__["resolve"])(rootPath, 'x-pack'));
diff --git a/packages/kbn-pm/src/config.ts b/packages/kbn-pm/src/config.ts
index 4886b0c266a89..2e42a182e7ec3 100644
--- a/packages/kbn-pm/src/config.ts
+++ b/packages/kbn-pm/src/config.ts
@@ -44,6 +44,7 @@ export function getProjectPaths(rootPath: string, options: IProjectPathOptions =
// correct and the expect behavior.
projectPaths.push(resolve(rootPath, 'test/plugin_functional/plugins/*'));
projectPaths.push(resolve(rootPath, 'test/interpreter_functional/plugins/*'));
+ projectPaths.push(resolve(rootPath, 'examples/*'));
if (!ossOnly) {
projectPaths.push(resolve(rootPath, 'x-pack'));
diff --git a/packages/kbn-test/src/functional_test_runner/__tests__/fixtures/failure_hooks/config.js b/packages/kbn-test/src/functional_test_runner/__tests__/fixtures/failure_hooks/config.js
index 3ff674c89682d..37ea49172d2c4 100644
--- a/packages/kbn-test/src/functional_test_runner/__tests__/fixtures/failure_hooks/config.js
+++ b/packages/kbn-test/src/functional_test_runner/__tests__/fixtures/failure_hooks/config.js
@@ -29,18 +29,19 @@ export default function () {
services: {
hookIntoLIfecycle({ getService }) {
const log = getService('log');
+ const lifecycle = getService('lifecycle')
- getService('lifecycle')
- .on('testFailure', async (err, test) => {
- log.info('testFailure %s %s', err.message, test.fullTitle());
- await delay(10);
- log.info('testFailureAfterDelay %s %s', err.message, test.fullTitle());
- })
- .on('testHookFailure', async (err, test) => {
- log.info('testHookFailure %s %s', err.message, test.fullTitle());
- await delay(10);
- log.info('testHookFailureAfterDelay %s %s', err.message, test.fullTitle());
- });
+ lifecycle.testFailure.add(async (err, test) => {
+ log.info('testFailure %s %s', err.message, test.fullTitle());
+ await delay(10);
+ log.info('testFailureAfterDelay %s %s', err.message, test.fullTitle());
+ });
+
+ lifecycle.testHookFailure.add(async (err, test) => {
+ log.info('testHookFailure %s %s', err.message, test.fullTitle());
+ await delay(10);
+ log.info('testHookFailureAfterDelay %s %s', err.message, test.fullTitle());
+ });
}
},
mochaReporter: {
diff --git a/packages/kbn-test/src/functional_test_runner/functional_test_runner.ts b/packages/kbn-test/src/functional_test_runner/functional_test_runner.ts
index 459c52997e229..fcba9691b1772 100644
--- a/packages/kbn-test/src/functional_test_runner/functional_test_runner.ts
+++ b/packages/kbn-test/src/functional_test_runner/functional_test_runner.ts
@@ -18,10 +18,11 @@
*/
import { ToolingLog } from '@kbn/dev-utils';
-import { Suite, Test } from './fake_mocha_types';
+import { Suite, Test } from './fake_mocha_types';
import {
- createLifecycle,
+ Lifecycle,
+ LifecyclePhase,
readConfigFile,
ProviderCollection,
readProviderSpec,
@@ -31,7 +32,7 @@ import {
} from './lib';
export class FunctionalTestRunner {
- public readonly lifecycle = createLifecycle();
+ public readonly lifecycle = new Lifecycle();
private closed = false;
constructor(
@@ -39,13 +40,12 @@ export class FunctionalTestRunner {
private readonly configFile: string,
private readonly configOverrides: any
) {
- this.lifecycle.on('phaseStart', name => {
- log.verbose('starting %j lifecycle phase', name);
- });
-
- this.lifecycle.on('phaseEnd', name => {
- log.verbose('ending %j lifecycle phase', name);
- });
+ for (const [key, value] of Object.entries(this.lifecycle)) {
+ if (value instanceof LifecyclePhase) {
+ value.before$.subscribe(() => log.verbose('starting %j lifecycle phase', key));
+ value.after$.subscribe(() => log.verbose('starting %j lifecycle phase', key));
+ }
+ }
}
async run() {
@@ -59,7 +59,7 @@ export class FunctionalTestRunner {
await providers.loadAll();
const mocha = await setupMocha(this.lifecycle, this.log, config, providers);
- await this.lifecycle.trigger('beforeTests');
+ await this.lifecycle.beforeTests.trigger();
this.log.info('Starting tests');
return await runTests(this.lifecycle, mocha);
@@ -140,6 +140,6 @@ export class FunctionalTestRunner {
if (this.closed) return;
this.closed = true;
- await this.lifecycle.trigger('cleanup');
+ await this.lifecycle.cleanup.trigger();
}
}
diff --git a/packages/kbn-test/src/functional_test_runner/lib/index.ts b/packages/kbn-test/src/functional_test_runner/lib/index.ts
index 88995e9acc5fe..2d354938d7648 100644
--- a/packages/kbn-test/src/functional_test_runner/lib/index.ts
+++ b/packages/kbn-test/src/functional_test_runner/lib/index.ts
@@ -17,7 +17,8 @@
* under the License.
*/
-export { createLifecycle, Lifecycle } from './lifecycle';
+export { Lifecycle } from './lifecycle';
+export { LifecyclePhase } from './lifecycle_phase';
export { readConfigFile, Config } from './config';
export { readProviderSpec, ProviderCollection, Provider } from './providers';
export { runTests, setupMocha } from './mocha';
diff --git a/packages/kbn-test/src/functional_test_runner/lib/lifecycle.ts b/packages/kbn-test/src/functional_test_runner/lib/lifecycle.ts
index 2d9629a436b3a..7f78bc28c6d3d 100644
--- a/packages/kbn-test/src/functional_test_runner/lib/lifecycle.ts
+++ b/packages/kbn-test/src/functional_test_runner/lib/lifecycle.ts
@@ -17,64 +17,22 @@
* under the License.
*/
-import * as Rx from 'rxjs';
-
-type Listener = (...args: any[]) => Promise | void;
-export type Lifecycle = ReturnType;
-
-export function createLifecycle() {
- const listeners = {
- beforeLoadTests: [] as Listener[],
- beforeTests: [] as Listener[],
- beforeTestSuite: [] as Listener[],
- beforeEachTest: [] as Listener[],
- afterTestSuite: [] as Listener[],
- testFailure: [] as Listener[],
- testHookFailure: [] as Listener[],
- cleanup: [] as Listener[],
- phaseStart: [] as Listener[],
- phaseEnd: [] as Listener[],
- };
-
- const cleanup$ = new Rx.ReplaySubject(1);
-
- return {
- cleanup$: cleanup$.asObservable(),
-
- on(name: keyof typeof listeners, fn: Listener) {
- if (!listeners[name]) {
- throw new TypeError(`invalid lifecycle event "${name}"`);
- }
-
- listeners[name].push(fn);
- return this;
- },
-
- async trigger(name: keyof typeof listeners, ...args: any[]) {
- if (!listeners[name]) {
- throw new TypeError(`invalid lifecycle event "${name}"`);
- }
-
- if (name === 'cleanup') {
- if (cleanup$.closed) {
- return;
- }
-
- cleanup$.next();
- cleanup$.complete();
- }
-
- try {
- if (name !== 'phaseStart' && name !== 'phaseEnd') {
- await this.trigger('phaseStart', name);
- }
-
- await Promise.all(listeners[name].map(async fn => await fn(...args)));
- } finally {
- if (name !== 'phaseStart' && name !== 'phaseEnd') {
- await this.trigger('phaseEnd', name);
- }
- }
- },
- };
+import { LifecyclePhase } from './lifecycle_phase';
+
+// mocha's global types mean we can't import Mocha or it will override the global jest types..............
+type ItsASuite = any;
+type ItsATest = any;
+
+export class Lifecycle {
+ public readonly beforeTests = new LifecyclePhase<[]>({
+ singular: true,
+ });
+ public readonly beforeTestSuite = new LifecyclePhase<[ItsASuite]>();
+ public readonly beforeEachTest = new LifecyclePhase<[ItsATest]>();
+ public readonly afterTestSuite = new LifecyclePhase<[ItsASuite]>();
+ public readonly testFailure = new LifecyclePhase<[Error, ItsATest]>();
+ public readonly testHookFailure = new LifecyclePhase<[Error, ItsATest]>();
+ public readonly cleanup = new LifecyclePhase<[]>({
+ singular: true,
+ });
}
diff --git a/packages/kbn-test/src/functional_test_runner/lib/lifecycle_phase.test.ts b/packages/kbn-test/src/functional_test_runner/lib/lifecycle_phase.test.ts
new file mode 100644
index 0000000000000..94dd76884f2ca
--- /dev/null
+++ b/packages/kbn-test/src/functional_test_runner/lib/lifecycle_phase.test.ts
@@ -0,0 +1,206 @@
+/*
+ * 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 * as Rx from 'rxjs';
+import { materialize, toArray } from 'rxjs/operators';
+
+import { LifecyclePhase } from './lifecycle_phase';
+
+describe('with randomness', () => {
+ beforeEach(() => {
+ const randomOrder = [0, 0.75, 0.5, 0.25, 1];
+ jest.spyOn(Math, 'random').mockImplementation(() => {
+ const n = randomOrder.shift()!;
+ randomOrder.push(n);
+ return n;
+ });
+ });
+
+ afterEach(() => {
+ jest.restoreAllMocks();
+ });
+
+ it('calls handlers in random order', async () => {
+ const phase = new LifecyclePhase();
+ const order: string[] = [];
+
+ phase.add(
+ jest.fn(() => {
+ order.push('one');
+ })
+ );
+
+ phase.add(
+ jest.fn(() => {
+ order.push('two');
+ })
+ );
+
+ phase.add(
+ jest.fn(() => {
+ order.push('three');
+ })
+ );
+
+ await phase.trigger();
+ expect(order).toMatchInlineSnapshot(`
+ Array [
+ "one",
+ "three",
+ "two",
+ ]
+ `);
+ });
+});
+
+describe('without randomness', () => {
+ beforeEach(() => jest.spyOn(Math, 'random').mockImplementation(() => 0));
+ afterEach(() => jest.restoreAllMocks());
+
+ it('calls all handlers and throws first error', async () => {
+ const phase = new LifecyclePhase();
+ const fn1 = jest.fn();
+ phase.add(fn1);
+
+ const fn2 = jest.fn(() => {
+ throw new Error('foo');
+ });
+ phase.add(fn2);
+
+ const fn3 = jest.fn();
+ phase.add(fn3);
+
+ await expect(phase.trigger()).rejects.toThrowErrorMatchingInlineSnapshot(`"foo"`);
+ expect(fn1).toHaveBeenCalled();
+ expect(fn2).toHaveBeenCalled();
+ expect(fn3).toHaveBeenCalled();
+ });
+
+ it('triggers before$ just before calling handler and after$ once it resolves', async () => {
+ const phase = new LifecyclePhase();
+ const order: string[] = [];
+
+ const beforeSub = jest.fn(() => order.push('before'));
+ phase.before$.subscribe(beforeSub);
+
+ const afterSub = jest.fn(() => order.push('after'));
+ phase.after$.subscribe(afterSub);
+
+ const handler = jest.fn(async () => {
+ order.push('handler start');
+ await new Promise(resolve => setTimeout(resolve, 100));
+ order.push('handler done');
+ });
+ phase.add(handler);
+
+ await phase.trigger();
+ expect(order).toMatchInlineSnapshot(`
+ Array [
+ "before",
+ "handler start",
+ "handler done",
+ "after",
+ ]
+ `);
+ });
+
+ it('completes before$ and after$ if phase is singular', async () => {
+ const phase = new LifecyclePhase({ singular: true });
+
+ const beforeNotifs: Array> = [];
+ phase.before$.pipe(materialize()).subscribe(n => beforeNotifs.push(n));
+
+ const afterNotifs: Array> = [];
+ phase.after$.pipe(materialize()).subscribe(n => afterNotifs.push(n));
+
+ await phase.trigger();
+ expect(beforeNotifs).toMatchInlineSnapshot(`
+ Array [
+ Notification {
+ "error": undefined,
+ "hasValue": true,
+ "kind": "N",
+ "value": undefined,
+ },
+ Notification {
+ "error": undefined,
+ "hasValue": false,
+ "kind": "C",
+ "value": undefined,
+ },
+ ]
+ `);
+ expect(afterNotifs).toMatchInlineSnapshot(`
+ Array [
+ Notification {
+ "error": undefined,
+ "hasValue": true,
+ "kind": "N",
+ "value": undefined,
+ },
+ Notification {
+ "error": undefined,
+ "hasValue": false,
+ "kind": "C",
+ "value": undefined,
+ },
+ ]
+ `);
+ });
+
+ it('completes before$ subscribers after trigger of singular phase', async () => {
+ const phase = new LifecyclePhase({ singular: true });
+ await phase.trigger();
+
+ await expect(phase.before$.pipe(materialize(), toArray()).toPromise()).resolves
+ .toMatchInlineSnapshot(`
+ Array [
+ Notification {
+ "error": undefined,
+ "hasValue": false,
+ "kind": "C",
+ "value": undefined,
+ },
+ ]
+ `);
+ });
+
+ it('replays after$ event subscribers after trigger of singular phase', async () => {
+ const phase = new LifecyclePhase({ singular: true });
+ await phase.trigger();
+
+ await expect(phase.after$.pipe(materialize(), toArray()).toPromise()).resolves
+ .toMatchInlineSnapshot(`
+ Array [
+ Notification {
+ "error": undefined,
+ "hasValue": true,
+ "kind": "N",
+ "value": undefined,
+ },
+ Notification {
+ "error": undefined,
+ "hasValue": false,
+ "kind": "C",
+ "value": undefined,
+ },
+ ]
+ `);
+ });
+});
diff --git a/packages/kbn-test/src/functional_test_runner/lib/lifecycle_phase.ts b/packages/kbn-test/src/functional_test_runner/lib/lifecycle_phase.ts
new file mode 100644
index 0000000000000..5c7fdb532faa1
--- /dev/null
+++ b/packages/kbn-test/src/functional_test_runner/lib/lifecycle_phase.ts
@@ -0,0 +1,82 @@
+/*
+ * 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 * as Rx from 'rxjs';
+
+const shuffle = (arr: T[]) => arr.slice().sort(() => (Math.random() > 0.5 ? 1 : -1));
+
+export type GetArgsType> = T extends LifecyclePhase
+ ? X
+ : never;
+
+export class LifecyclePhase {
+ private readonly handlers: Array<(...args: Args) => Promise | void> = [];
+
+ private readonly beforeSubj = new Rx.Subject();
+ public readonly before$ = this.beforeSubj.asObservable();
+
+ private readonly afterSubj = this.options.singular
+ ? new Rx.ReplaySubject(1)
+ : new Rx.Subject();
+ public readonly after$ = this.afterSubj.asObservable();
+
+ constructor(
+ private readonly options: {
+ singular?: boolean;
+ } = {}
+ ) {}
+
+ public add(fn: (...args: Args) => Promise | void) {
+ this.handlers.push(fn);
+ }
+
+ public async trigger(...args: Args) {
+ if (this.beforeSubj.isStopped) {
+ throw new Error(`singular lifecycle event can only be triggered once`);
+ }
+
+ this.beforeSubj.next(undefined);
+ if (this.options.singular) {
+ this.beforeSubj.complete();
+ }
+
+ // catch the first error but still execute all handlers
+ let error;
+
+ // shuffle the handlers to prevent relying on their order
+ for (const fn of shuffle(this.handlers)) {
+ try {
+ await fn(...args);
+ } catch (_error) {
+ if (!error) {
+ error = _error;
+ }
+ }
+ }
+
+ this.afterSubj.next(undefined);
+ if (this.options.singular) {
+ this.afterSubj.complete();
+ }
+
+ if (error) {
+ throw error;
+ }
+ }
+}
diff --git a/packages/kbn-test/src/functional_test_runner/lib/mocha/decorate_mocha_ui.js b/packages/kbn-test/src/functional_test_runner/lib/mocha/decorate_mocha_ui.js
index e65eb2f27d063..4eb45229c2234 100644
--- a/packages/kbn-test/src/functional_test_runner/lib/mocha/decorate_mocha_ui.js
+++ b/packages/kbn-test/src/functional_test_runner/lib/mocha/decorate_mocha_ui.js
@@ -58,7 +58,7 @@ export function decorateMochaUi(lifecycle, context) {
argumentsList[1] = function() {
before(async () => {
- await lifecycle.trigger('beforeTestSuite', this);
+ await lifecycle.beforeTestSuite.trigger(this);
});
this.tags = tags => {
@@ -68,7 +68,7 @@ export function decorateMochaUi(lifecycle, context) {
provider.call(this);
after(async () => {
- await lifecycle.trigger('afterTestSuite', this);
+ await lifecycle.afterTestSuite.trigger(this);
});
};
@@ -94,7 +94,7 @@ export function decorateMochaUi(lifecycle, context) {
return wrapNonSuiteFunction(
name,
wrapRunnableArgsWithErrorHandler(fn, async (err, test) => {
- await lifecycle.trigger('testFailure', err, test);
+ await lifecycle.testFailure.trigger(err, test);
})
);
}
@@ -112,7 +112,7 @@ export function decorateMochaUi(lifecycle, context) {
return wrapNonSuiteFunction(
name,
wrapRunnableArgsWithErrorHandler(fn, async (err, test) => {
- await lifecycle.trigger('testHookFailure', err, test);
+ await lifecycle.testHookFailure.trigger(err, test);
})
);
}
diff --git a/packages/kbn-test/src/functional_test_runner/lib/mocha/run_tests.ts b/packages/kbn-test/src/functional_test_runner/lib/mocha/run_tests.ts
index 2d98052b1062a..654f588fda858 100644
--- a/packages/kbn-test/src/functional_test_runner/lib/mocha/run_tests.ts
+++ b/packages/kbn-test/src/functional_test_runner/lib/mocha/run_tests.ts
@@ -35,7 +35,7 @@ export async function runTests(lifecycle: Lifecycle, mocha: Mocha) {
runComplete = true;
});
- lifecycle.on('cleanup', () => {
+ lifecycle.cleanup.add(() => {
if (!runComplete) runner.abort();
});
diff --git a/packages/kbn-test/src/functional_test_runner/lib/mocha/setup_mocha.js b/packages/kbn-test/src/functional_test_runner/lib/mocha/setup_mocha.js
index a425251a29f36..326877919d985 100644
--- a/packages/kbn-test/src/functional_test_runner/lib/mocha/setup_mocha.js
+++ b/packages/kbn-test/src/functional_test_runner/lib/mocha/setup_mocha.js
@@ -41,7 +41,7 @@ export async function setupMocha(lifecycle, log, config, providers) {
// global beforeEach hook in root suite triggers before all others
mocha.suite.beforeEach('global before each', async function() {
- await lifecycle.trigger('beforeEachTest', this.currentTest);
+ await lifecycle.beforeEachTest.trigger(this.currentTest);
});
loadTestFiles({
diff --git a/packages/kbn-ui-framework/dist/kui_dark.css b/packages/kbn-ui-framework/dist/kui_dark.css
index dcbd65fbca520..aa16bcdb34d36 100644
--- a/packages/kbn-ui-framework/dist/kui_dark.css
+++ b/packages/kbn-ui-framework/dist/kui_dark.css
@@ -1,10 +1,24 @@
+/* 1 */
+/* 1 */
+/**
+ * 1. Extend beta badges to at least 40% of the container's width
+ * 2. Fix for IE to ensure badges are visible outside of a
+
);
};
const addVisualizationParagraph = (
@@ -70,6 +84,7 @@ export function DashboardEmptyScreen({ showLinkToVisualize, onLinkClick }: Props
constants.addVisualizationLinkAriaLabel,
'emptyDashboardAddPanelButton'
)}
+
{linkToVisualizeParagraph}
);
@@ -81,11 +96,19 @@ export function DashboardEmptyScreen({ showLinkToVisualize, onLinkClick }: Props
);
return (
-
-
- {constants.fillDashboardTitle}
- {showLinkToVisualize ? addVisualizationParagraph : enterEditModeParagraph}
-
+
+
+
+
+
+
+ {constants.fillDashboardTitle}
+
+
+ {showLinkToVisualize ? addVisualizationParagraph : enterEditModeParagraph}
+
+
+
);
}
diff --git a/src/legacy/core_plugins/kibana/public/dashboard/legacy_imports.ts b/src/legacy/core_plugins/kibana/public/dashboard/legacy_imports.ts
index b0f09f0cf9745..af0a833399a52 100644
--- a/src/legacy/core_plugins/kibana/public/dashboard/legacy_imports.ts
+++ b/src/legacy/core_plugins/kibana/public/dashboard/legacy_imports.ts
@@ -65,4 +65,3 @@ export { stateMonitorFactory, StateMonitor } from 'ui/state_management/state_mon
export { ensureDefaultIndexPattern } from 'ui/legacy_compat';
export { unhashUrl } from '../../../../../plugins/kibana_utils/public';
export { IInjector } from 'ui/chrome';
-export { SavedObjectFinder } from 'ui/saved_objects/components/saved_object_finder';
diff --git a/src/legacy/core_plugins/kibana/public/dashboard/top_nav/top_nav_ids.ts b/src/legacy/core_plugins/kibana/public/dashboard/top_nav/top_nav_ids.ts
index 9df86f2ca3cce..c67d6891c18e7 100644
--- a/src/legacy/core_plugins/kibana/public/dashboard/top_nav/top_nav_ids.ts
+++ b/src/legacy/core_plugins/kibana/public/dashboard/top_nav/top_nav_ids.ts
@@ -26,4 +26,5 @@ export const TopNavIds = {
ENTER_EDIT_MODE: 'enterEditMode',
CLONE: 'clone',
FULL_SCREEN: 'fullScreenMode',
+ VISUALIZE: 'visualize',
};
diff --git a/src/legacy/core_plugins/kibana/public/discover/_discover.scss b/src/legacy/core_plugins/kibana/public/discover/_discover.scss
index 12cac1c89275b..0da28e41579ae 100644
--- a/src/legacy/core_plugins/kibana/public/discover/_discover.scss
+++ b/src/legacy/core_plugins/kibana/public/discover/_discover.scss
@@ -1,5 +1,3 @@
-@import 'node_modules/@elastic/eui/src/components/panel/mixins';
-
discover-app {
flex-grow: 1;
@@ -37,7 +35,7 @@ discover-app {
z-index: 1;
}
-@include euiPanel('dscWrapper__content');
+@include euiPanel('.dscWrapper__content');
.dscWrapper__content {
padding-top: $euiSizeXS;
@@ -213,7 +211,6 @@ discover-app {
}
.dscResults {
-
h3 {
margin: -20px 0 10px 0;
text-align: center;
diff --git a/src/legacy/core_plugins/kibana/public/discover/angular/discover.js b/src/legacy/core_plugins/kibana/public/discover/angular/discover.js
index ed233c08e8d49..ce1419cd637b9 100644
--- a/src/legacy/core_plugins/kibana/public/discover/angular/discover.js
+++ b/src/legacy/core_plugins/kibana/public/discover/angular/discover.js
@@ -65,7 +65,6 @@ const {
data,
docTitle,
filterManager,
- State,
share,
timefilter,
toastNotifications,
@@ -121,7 +120,7 @@ app.config($routeProvider => {
template: indexTemplate,
reloadOnSearch: false,
resolve: {
- savedObjects: function (redirectWhenMissing, $route, kbnUrl, Promise, $rootScope) {
+ savedObjects: function (redirectWhenMissing, $route, kbnUrl, Promise, $rootScope, State) {
const indexPatterns = getServices().indexPatterns;
const savedSearchId = $route.current.params.id;
return ensureDefaultIndexPattern(core, getServices().data, $rootScope, kbnUrl).then(() => {
@@ -137,7 +136,6 @@ app.config($routeProvider => {
* @type {State}
*/
const state = new State('_a', {});
-
const id = getIndexPatternId(state.index, indexPatternList, uiSettings.get('defaultIndex'));
state.destroy();
return Promise.props({
diff --git a/src/legacy/core_plugins/kibana/public/discover/components/top_nav/__snapshots__/open_search_panel.test.js.snap b/src/legacy/core_plugins/kibana/public/discover/components/top_nav/__snapshots__/open_search_panel.test.js.snap
index cc53e4bdcdcf9..2878b11040cf3 100644
--- a/src/legacy/core_plugins/kibana/public/discover/components/top_nav/__snapshots__/open_search_panel.test.js.snap
+++ b/src/legacy/core_plugins/kibana/public/discover/components/top_nav/__snapshots__/open_search_panel.test.js.snap
@@ -26,7 +26,7 @@ exports[`render 1`] = `
-
diff --git a/src/legacy/core_plugins/kibana/public/discover/components/top_nav/open_search_panel.js b/src/legacy/core_plugins/kibana/public/discover/components/top_nav/open_search_panel.js
index 0c3b52fbf0640..ec1763f44f25f 100644
--- a/src/legacy/core_plugins/kibana/public/discover/components/top_nav/open_search_panel.js
+++ b/src/legacy/core_plugins/kibana/public/discover/components/top_nav/open_search_panel.js
@@ -32,11 +32,16 @@ import {
EuiFlyoutBody,
EuiTitle,
} from '@elastic/eui';
-import { SavedObjectFinder } from 'ui/saved_objects/components/saved_object_finder';
+import { SavedObjectFinderUi } from '../../../../../../../plugins/kibana_react/public';
+import { getServices } from '../../kibana_services';
const SEARCH_OBJECT_TYPE = 'search';
export function OpenSearchPanel(props) {
+ const {
+ core: { uiSettings, savedObjects },
+ } = getServices();
+
return (
@@ -50,7 +55,7 @@ export function OpenSearchPanel(props) {
-
diff --git a/src/legacy/core_plugins/kibana/public/discover/components/top_nav/open_search_panel.test.js b/src/legacy/core_plugins/kibana/public/discover/components/top_nav/open_search_panel.test.js
index ea5c0ef39604d..0c82aeea95294 100644
--- a/src/legacy/core_plugins/kibana/public/discover/components/top_nav/open_search_panel.test.js
+++ b/src/legacy/core_plugins/kibana/public/discover/components/top_nav/open_search_panel.test.js
@@ -23,7 +23,7 @@ import { shallow } from 'enzyme';
jest.mock('../../kibana_services', () => {
return {
getServices: () => ({
- SavedObjectFinder: jest.fn()
+ core: { uiSettings: {}, savedObjects: {} },
}),
};
});
diff --git a/src/legacy/core_plugins/kibana/public/discover/get_inner_angular.ts b/src/legacy/core_plugins/kibana/public/discover/get_inner_angular.ts
index 275dfa073fecd..f6982e13d7d03 100644
--- a/src/legacy/core_plugins/kibana/public/discover/get_inner_angular.ts
+++ b/src/legacy/core_plugins/kibana/public/discover/get_inner_angular.ts
@@ -25,6 +25,8 @@ import 'ui/angular-bootstrap';
import { IPrivate } from 'ui/private';
import { EuiIcon } from '@elastic/eui';
// @ts-ignore
+import { StateProvider } from 'ui/state_management/state';
+// @ts-ignore
import { EventsProvider } from 'ui/events';
import { PersistedState } from 'ui/persisted_state';
// @ts-ignore
@@ -277,6 +279,9 @@ function createLocalAppStateModule() {
})
.service('getAppState', function(Private: any) {
return Private(AppStateProvider).getAppState;
+ })
+ .service('State', function(Private: any) {
+ return Private(StateProvider);
});
}
diff --git a/src/legacy/core_plugins/kibana/public/discover/helpers/build_services.ts b/src/legacy/core_plugins/kibana/public/discover/helpers/build_services.ts
index a7f849704b5b2..b72bd27a31cf9 100644
--- a/src/legacy/core_plugins/kibana/public/discover/helpers/build_services.ts
+++ b/src/legacy/core_plugins/kibana/public/discover/helpers/build_services.ts
@@ -29,8 +29,6 @@ import chromeLegacy from 'ui/chrome';
import { IPrivate } from 'ui/private';
import { FilterManager, TimefilterContract, IndexPatternsContract } from 'src/plugins/data/public';
// @ts-ignore
-import { StateProvider } from 'ui/state_management/state';
-// @ts-ignore
import { createSavedSearchesService } from '../saved_searches/saved_searches';
// @ts-ignore
import { createSavedSearchFactory } from '../saved_searches/_saved_search';
@@ -57,7 +55,6 @@ export interface DiscoverServices {
// legacy
getSavedSearchById: (id: string) => Promise;
getSavedSearchUrlById: (id: string) => Promise;
- State: unknown;
uiSettings: IUiSettingsClient;
}
@@ -65,13 +62,11 @@ export async function buildGlobalAngularServices() {
const injector = await chromeLegacy.dangerouslyGetActiveInjector();
const Private = injector.get('Private');
const kbnUrl = injector.get('kbnUrl');
- const State = Private(StateProvider);
const SavedSearchFactory = createSavedSearchFactory(Private);
const service = createSavedSearchesService(Private, SavedSearchFactory, kbnUrl, chromeLegacy);
return {
getSavedSearchById: async (id: string) => service.get(id),
getSavedSearchUrlById: async (id: string) => service.urlFor(id),
- State,
};
}
diff --git a/src/legacy/core_plugins/kibana/public/index.scss b/src/legacy/core_plugins/kibana/public/index.scss
index 7a6a3ca1d01d0..611fe613ad99c 100644
--- a/src/legacy/core_plugins/kibana/public/index.scss
+++ b/src/legacy/core_plugins/kibana/public/index.scss
@@ -1,8 +1,6 @@
@import 'src/legacy/ui/public/styles/styling_constants';
// Elastic charts
-@import '@elastic/eui/src/components/tool_tip/variables';
-@import '@elastic/eui/src/components/tool_tip/mixins';
@import '@elastic/charts/dist/theme';
@import '@elastic/eui/src/themes/charts/theme';
diff --git a/src/legacy/core_plugins/kibana/public/kibana.js b/src/legacy/core_plugins/kibana/public/kibana.js
index cc438d338c7d5..0045819257018 100644
--- a/src/legacy/core_plugins/kibana/public/kibana.js
+++ b/src/legacy/core_plugins/kibana/public/kibana.js
@@ -29,7 +29,6 @@ import { npSetup } from 'ui/new_platform';
import 'uiExports/home';
import 'uiExports/visTypes';
-import 'uiExports/visEditorTypes';
import 'uiExports/visualize';
import 'uiExports/savedObjectTypes';
import 'uiExports/fieldFormatEditors';
diff --git a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/create_index_pattern_wizard/components/step_time_field/step_time_field.js b/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/create_index_pattern_wizard/components/step_time_field/step_time_field.js
index 5cb93a36cdd18..1e894664c2bf1 100644
--- a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/create_index_pattern_wizard/components/step_time_field/step_time_field.js
+++ b/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/create_index_pattern_wizard/components/step_time_field/step_time_field.js
@@ -50,8 +50,6 @@ export class StepTimeField extends Component {
constructor(props) {
super(props);
- const { getIndexPatternType, getIndexPatternName } = props.indexPatternCreationType;
-
this.state = {
error: '',
timeFields: [],
@@ -61,8 +59,8 @@ export class StepTimeField extends Component {
isFetchingTimeFields: false,
isCreating: false,
indexPatternId: '',
- indexPatternType: getIndexPatternType(),
- indexPatternName: getIndexPatternName(),
+ indexPatternType: props.indexPatternCreationType.getIndexPatternType(),
+ indexPatternName: props.indexPatternCreationType.getIndexPatternName(),
};
}
diff --git a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/create_index_pattern_wizard/index.js b/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/create_index_pattern_wizard/index.js
index b500f5c79e98b..833ca8467292e 100644
--- a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/create_index_pattern_wizard/index.js
+++ b/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/create_index_pattern_wizard/index.js
@@ -21,7 +21,7 @@ import { SavedObjectsClientProvider } from 'ui/saved_objects';
import uiRoutes from 'ui/routes';
import angularTemplate from './angular_template.html';
import 'ui/index_patterns';
-import { IndexPatternCreationFactory } from 'ui/management/index_pattern_creation';
+import { setup as managementSetup } from '../../../../../../management/public/legacy';
import { getCreateBreadcrumbs } from '../breadcrumbs';
import { renderCreateIndexPatternWizard, destroyCreateIndexPatternWizard } from './render';
@@ -35,8 +35,9 @@ uiRoutes.when('/management/kibana/index_pattern', {
const Private = $injector.get('Private');
$scope.$$postDigest(() => {
const $routeParams = $injector.get('$routeParams');
- const indexPatternCreationProvider = Private(IndexPatternCreationFactory)($routeParams.type);
- const indexPatternCreationType = indexPatternCreationProvider.getType();
+ const indexPatternCreationType = managementSetup.indexPattern.creation.getType(
+ $routeParams.type
+ );
const services = {
config: $injector.get('config'),
es: $injector.get('es'),
@@ -52,12 +53,9 @@ uiRoutes.when('/management/kibana/index_pattern', {
const initialQuery = $routeParams.id ? decodeURIComponent($routeParams.id) : undefined;
- renderCreateIndexPatternWizard(
- initialQuery,
- services
- );
+ renderCreateIndexPatternWizard(initialQuery, services);
});
$scope.$on('$destroy', destroyCreateIndexPatternWizard);
- }
+ },
});
diff --git a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/edit_index_pattern.js b/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/edit_index_pattern.js
index 6ae84b9c641c2..150fae6e87dde 100644
--- a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/edit_index_pattern.js
+++ b/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/edit_index_pattern.js
@@ -28,7 +28,7 @@ import uiRoutes from 'ui/routes';
import { uiModules } from 'ui/modules';
import template from './edit_index_pattern.html';
import { fieldWildcardMatcher } from 'ui/field_wildcard';
-import { IndexPatternListFactory } from 'ui/management/index_pattern_list';
+import { setup as managementSetup } from '../../../../../../management/public/legacy';
import React from 'react';
import { render, unmountComponentAtNode } from 'react-dom';
import { SourceFiltersTable } from './source_filters_table';
@@ -58,13 +58,17 @@ function updateSourceFiltersTable($scope, $state) {
filterFilter={$scope.fieldFilter}
fieldWildcardMatcher={$scope.fieldWildcardMatcher}
onAddOrRemoveFilter={() => {
- $scope.editSections = $scope.editSectionsProvider($scope.indexPattern, $scope.fieldFilter, $scope.indexPatternListProvider);
+ $scope.editSections = $scope.editSectionsProvider(
+ $scope.indexPattern,
+ $scope.fieldFilter,
+ $scope.indexPatternListProvider
+ );
$scope.refreshFilters();
$scope.$apply();
}}
/>
,
- node,
+ node
);
});
} else {
@@ -77,7 +81,6 @@ function destroySourceFiltersTable() {
node && unmountComponentAtNode(node);
}
-
function updateScriptedFieldsTable($scope, $state) {
if ($state.tab === 'scriptedFields') {
$scope.$$postDigest(() => {
@@ -100,13 +103,17 @@ function updateScriptedFieldsTable($scope, $state) {
getRouteHref: (obj, route) => $scope.kbnUrl.getRouteHref(obj, route),
}}
onRemoveField={() => {
- $scope.editSections = $scope.editSectionsProvider($scope.indexPattern, $scope.fieldFilter, $scope.indexPatternListProvider);
+ $scope.editSections = $scope.editSectionsProvider(
+ $scope.indexPattern,
+ $scope.fieldFilter,
+ $scope.indexPatternListProvider
+ );
$scope.refreshFilters();
$scope.$apply();
}}
/>
,
- node,
+ node
);
});
} else {
@@ -144,7 +151,7 @@ function updateIndexedFieldsTable($scope, $state) {
}}
/>
,
- node,
+ node
);
});
} else {
@@ -157,34 +164,36 @@ function destroyIndexedFieldsTable() {
node && unmountComponentAtNode(node);
}
-uiRoutes
- .when('/management/kibana/index_patterns/:indexPatternId', {
- template,
- k7Breadcrumbs: getEditBreadcrumbs,
- resolve: {
- indexPattern: function ($route, Promise, redirectWhenMissing, indexPatterns) {
- return Promise.resolve(indexPatterns.get($route.current.params.indexPatternId))
- .catch(redirectWhenMissing('/management/kibana/index_patterns'));
- }
+uiRoutes.when('/management/kibana/index_patterns/:indexPatternId', {
+ template,
+ k7Breadcrumbs: getEditBreadcrumbs,
+ resolve: {
+ indexPattern: function ($route, Promise, redirectWhenMissing, indexPatterns) {
+ return Promise.resolve(indexPatterns.get($route.current.params.indexPatternId)).catch(
+ redirectWhenMissing('/management/kibana/index_patterns')
+ );
},
- });
+ },
+});
-uiModules.get('apps/management')
+uiModules
+ .get('apps/management')
.controller('managementIndexPatternsEdit', function (
$scope, $location, $route, Promise, config, indexPatterns, Private, AppState, confirmModal) {
const $state = $scope.state = new AppState();
- const indexPatternListProvider = Private(IndexPatternListFactory)();
$scope.fieldWildcardMatcher = (...args) => fieldWildcardMatcher(...args, config.get('metaFields'));
$scope.editSectionsProvider = Private(IndicesEditSectionsProvider);
$scope.kbnUrl = Private(KbnUrlProvider);
$scope.indexPattern = $route.current.locals.indexPattern;
- $scope.indexPatternListProvider = indexPatternListProvider;
- $scope.indexPattern.tags = indexPatternListProvider.getIndexPatternTags(
+ $scope.indexPatternListProvider = managementSetup.indexPattern.list;
+ $scope.indexPattern.tags = managementSetup.indexPattern.list.getIndexPatternTags(
$scope.indexPattern,
$scope.indexPattern.id === config.get('defaultIndex')
);
- $scope.getFieldInfo = indexPatternListProvider.getFieldInfo;
+ $scope.getFieldInfo = managementSetup.indexPattern.list.getFieldInfo.bind(
+ managementSetup.indexPattern.list
+ );
docTitle.change($scope.indexPattern.title);
const otherPatterns = _.filter($route.current.locals.indexPatterns, pattern => {
@@ -192,7 +201,11 @@ uiModules.get('apps/management')
});
$scope.$watch('indexPattern.fields', function () {
- $scope.editSections = $scope.editSectionsProvider($scope.indexPattern, $scope.fieldFilter, indexPatternListProvider);
+ $scope.editSections = $scope.editSectionsProvider(
+ $scope.indexPattern,
+ $scope.fieldFilter,
+ managementSetup.indexPattern.list
+ );
$scope.refreshFilters();
$scope.fields = $scope.indexPattern.getNonScriptedFields();
updateIndexedFieldsTable($scope, $state);
@@ -231,26 +244,26 @@ uiModules.get('apps/management')
});
$scope.$watchCollection('indexPattern.fields', function () {
- $scope.conflictFields = $scope.indexPattern.fields
- .filter(field => field.type === 'conflict');
+ $scope.conflictFields = $scope.indexPattern.fields.filter(field => field.type === 'conflict');
});
$scope.refreshFields = function () {
const confirmMessage = i18n.translate('kbn.management.editIndexPattern.refreshLabel', {
- defaultMessage: 'This action resets the popularity counter of each field.'
+ defaultMessage: 'This action resets the popularity counter of each field.',
});
const confirmModalOptions = {
- confirmButtonText: i18n.translate('kbn.management.editIndexPattern.refreshButton', { defaultMessage: 'Refresh' }),
+ confirmButtonText: i18n.translate('kbn.management.editIndexPattern.refreshButton', {
+ defaultMessage: 'Refresh',
+ }),
onConfirm: async () => {
await $scope.indexPattern.init(true);
$scope.fields = $scope.indexPattern.getNonScriptedFields();
},
- title: i18n.translate('kbn.management.editIndexPattern.refreshHeader', { defaultMessage: 'Refresh field list?' })
+ title: i18n.translate('kbn.management.editIndexPattern.refreshHeader', {
+ defaultMessage: 'Refresh field list?',
+ }),
};
- confirmModal(
- confirmMessage,
- confirmModalOptions
- );
+ confirmModal(confirmMessage, confirmModalOptions);
};
$scope.removePattern = function () {
@@ -271,9 +284,13 @@ uiModules.get('apps/management')
}
const confirmModalOptions = {
- confirmButtonText: i18n.translate('kbn.management.editIndexPattern.deleteButton', { defaultMessage: 'Delete' }),
+ confirmButtonText: i18n.translate('kbn.management.editIndexPattern.deleteButton', {
+ defaultMessage: 'Delete',
+ }),
onConfirm: doRemove,
- title: i18n.translate('kbn.management.editIndexPattern.deleteHeader', { defaultMessage: 'Delete index pattern?' })
+ title: i18n.translate('kbn.management.editIndexPattern.deleteHeader', {
+ defaultMessage: 'Delete index pattern?',
+ }),
};
confirmModal('', confirmModalOptions);
};
@@ -285,7 +302,8 @@ uiModules.get('apps/management')
$scope.setIndexPatternsTimeField = function (field) {
if (field.type !== 'date') {
const errorMessage = i18n.translate('kbn.management.editIndexPattern.notDateErrorMessage', {
- defaultMessage: 'That field is a {fieldType} not a date.', values: { fieldType: field.type }
+ defaultMessage: 'That field is a {fieldType} not a date.',
+ values: { fieldType: field.type },
});
toastNotifications.addDanger(errorMessage);
return;
@@ -295,12 +313,16 @@ uiModules.get('apps/management')
};
$scope.$watch('fieldFilter', () => {
- $scope.editSections = $scope.editSectionsProvider($scope.indexPattern, $scope.fieldFilter, indexPatternListProvider);
+ $scope.editSections = $scope.editSectionsProvider(
+ $scope.indexPattern,
+ $scope.fieldFilter,
+ managementSetup.indexPattern.list
+ );
if ($scope.fieldFilter === undefined) {
return;
}
- switch($state.tab) {
+ switch ($state.tab) {
case 'indexedFields':
updateIndexedFieldsTable($scope, $state);
case 'scriptedFields':
diff --git a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/index.js b/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/index.js
index 272544fa036cc..5935afec1dd70 100644
--- a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/index.js
+++ b/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/index.js
@@ -18,8 +18,7 @@
*/
import { management } from 'ui/management';
-import { IndexPatternListFactory } from 'ui/management/index_pattern_list';
-import { IndexPatternCreationFactory } from 'ui/management/index_pattern_creation';
+import { setup as managementSetup } from '../../../../../management/public/legacy';
import './create_index_pattern_wizard';
import './edit_index_pattern';
import uiRoutes from 'ui/routes';
@@ -28,7 +27,10 @@ import indexTemplate from './index.html';
import indexPatternListTemplate from './list.html';
import { IndexPatternTable } from './index_pattern_table';
import { SavedObjectsClientProvider } from 'ui/saved_objects';
-import { FeatureCatalogueRegistryProvider, FeatureCatalogueCategory } from 'ui/registry/feature_catalogue';
+import {
+ FeatureCatalogueRegistryProvider,
+ FeatureCatalogueCategory,
+} from 'ui/registry/feature_catalogue';
import { i18n } from '@kbn/i18n';
import { I18nContext } from 'ui/i18n';
import { UICapabilitiesProvider } from 'ui/capabilities/react';
@@ -39,11 +41,7 @@ import { render, unmountComponentAtNode } from 'react-dom';
const INDEX_PATTERN_LIST_DOM_ELEMENT_ID = 'indexPatternListReact';
-export function updateIndexPatternList(
- indexPatterns,
- kbnUrl,
- indexPatternCreationOptions,
-) {
+export function updateIndexPatternList(indexPatterns, kbnUrl, indexPatternCreationOptions) {
const node = document.getElementById(INDEX_PATTERN_LIST_DOM_ELEMENT_ID);
if (!node) {
return;
@@ -59,7 +57,7 @@ export function updateIndexPatternList(
/>
,
- node,
+ node
);
}
@@ -72,55 +70,56 @@ const indexPatternsResolutions = {
indexPatterns: function (Private) {
const savedObjectsClient = Private(SavedObjectsClientProvider);
- return savedObjectsClient.find({
- type: 'index-pattern',
- fields: ['title', 'type'],
- perPage: 10000
- }).then(response => response.savedObjects);
- }
+ return savedObjectsClient
+ .find({
+ type: 'index-pattern',
+ fields: ['title', 'type'],
+ perPage: 10000,
+ })
+ .then(response => response.savedObjects);
+ },
};
// add a dependency to all of the subsection routes
-uiRoutes
- .defaults(/management\/kibana\/(index_patterns|index_pattern)/, {
- resolve: indexPatternsResolutions,
- requireUICapability: 'management.kibana.index_patterns',
- badge: uiCapabilities => {
- if (uiCapabilities.indexPatterns.save) {
- return undefined;
- }
-
- return {
- text: i18n.translate('kbn.management.indexPatterns.badge.readOnly.text', {
- defaultMessage: 'Read only',
- }),
- tooltip: i18n.translate('kbn.management.indexPatterns.badge.readOnly.tooltip', {
- defaultMessage: 'Unable to save index patterns',
- }),
- iconType: 'glasses'
- };
+uiRoutes.defaults(/management\/kibana\/(index_patterns|index_pattern)/, {
+ resolve: indexPatternsResolutions,
+ requireUICapability: 'management.kibana.index_patterns',
+ badge: uiCapabilities => {
+ if (uiCapabilities.indexPatterns.save) {
+ return undefined;
}
- });
-uiRoutes
- .when('/management/kibana/index_patterns', {
- template: indexPatternListTemplate,
- k7Breadcrumbs: getListBreadcrumbs
- });
+ return {
+ text: i18n.translate('kbn.management.indexPatterns.badge.readOnly.text', {
+ defaultMessage: 'Read only',
+ }),
+ tooltip: i18n.translate('kbn.management.indexPatterns.badge.readOnly.tooltip', {
+ defaultMessage: 'Unable to save index patterns',
+ }),
+ iconType: 'glasses',
+ };
+ },
+});
+
+uiRoutes.when('/management/kibana/index_patterns', {
+ template: indexPatternListTemplate,
+ k7Breadcrumbs: getListBreadcrumbs,
+});
// wrapper directive, which sets some global stuff up like the left nav
-uiModules.get('apps/management')
- .directive('kbnManagementIndexPatterns', function ($route, config, kbnUrl, Private) {
+uiModules
+ .get('apps/management')
+ .directive('kbnManagementIndexPatterns', function ($route, config, kbnUrl) {
return {
restrict: 'E',
transclude: true,
template: indexTemplate,
link: async function ($scope) {
- const indexPatternListProvider = Private(IndexPatternListFactory)();
- const indexPatternCreationProvider = Private(IndexPatternCreationFactory)();
- const indexPatternCreationOptions = await indexPatternCreationProvider.getIndexPatternCreationOptions((url) => {
- $scope.$evalAsync(() => kbnUrl.change(url));
- });
+ const indexPatternCreationOptions = await managementSetup.indexPattern.creation.getIndexPatternCreationOptions(
+ url => {
+ $scope.$evalAsync(() => kbnUrl.change(url));
+ }
+ );
const renderList = () => {
$scope.indexPatternList =
@@ -129,7 +128,7 @@ uiModules.get('apps/management')
const id = pattern.id;
const title = pattern.get('title');
const isDefault = $scope.defaultIndex === id;
- const tags = indexPatternListProvider.getIndexPatternTags(
+ const tags = managementSetup.indexPattern.list.getIndexPatternTags(
pattern,
isDefault
);
@@ -165,25 +164,30 @@ uiModules.get('apps/management')
$scope.$watch('defaultIndex', () => renderList());
config.bindToScope($scope, 'defaultIndex');
$scope.$apply();
- }
+ },
};
});
management.getSection('kibana').register('index_patterns', {
- display: i18n.translate('kbn.management.indexPattern.sectionsHeader', { defaultMessage: 'Index Patterns' }),
+ display: i18n.translate('kbn.management.indexPattern.sectionsHeader', {
+ defaultMessage: 'Index Patterns',
+ }),
order: 0,
- url: '#/management/kibana/index_patterns/'
+ url: '#/management/kibana/index_patterns/',
});
FeatureCatalogueRegistryProvider.register(() => {
return {
id: 'index_patterns',
- title: i18n.translate('kbn.management.indexPatternHeader', { defaultMessage: 'Index Patterns' }),
- description: i18n.translate('kbn.management.indexPatternLabel',
- { defaultMessage: 'Manage the index patterns that help retrieve your data from Elasticsearch.' }),
+ title: i18n.translate('kbn.management.indexPatternHeader', {
+ defaultMessage: 'Index Patterns',
+ }),
+ description: i18n.translate('kbn.management.indexPatternLabel', {
+ defaultMessage: 'Manage the index patterns that help retrieve your data from Elasticsearch.',
+ }),
icon: 'indexPatternApp',
path: '/app/kibana#/management/kibana/index_patterns',
showOnHomePage: true,
- category: FeatureCatalogueCategory.ADMIN
+ category: FeatureCatalogueCategory.ADMIN,
};
});
diff --git a/src/legacy/core_plugins/kibana/public/management/sections/objects/components/objects_table/__jest__/objects_table.test.js b/src/legacy/core_plugins/kibana/public/management/sections/objects/components/objects_table/__jest__/objects_table.test.js
index 5956b6c306b0e..1c3666ac0980c 100644
--- a/src/legacy/core_plugins/kibana/public/management/sections/objects/components/objects_table/__jest__/objects_table.test.js
+++ b/src/legacy/core_plugins/kibana/public/management/sections/objects/components/objects_table/__jest__/objects_table.test.js
@@ -19,6 +19,7 @@
import React from 'react';
import { shallowWithI18nProvider } from 'test_utils/enzyme_helpers';
+import { mockManagementPlugin } from '../../../../../../../../management/public/np_ready/mocks';
import { Query } from '@elastic/eui';
import { ObjectsTable, POSSIBLE_TYPES } from '../objects_table';
@@ -29,6 +30,11 @@ import { extractExportDetails } from '../../../lib/extract_export_details';
jest.mock('ui/kfetch', () => ({ kfetch: jest.fn() }));
+jest.mock('../../../../../../../../management/public/legacy', () => ({
+ setup: mockManagementPlugin.createSetupContract(),
+ start: mockManagementPlugin.createStartContract(),
+}));
+
jest.mock('../../../lib/find_objects', () => ({
findObjects: jest.fn(),
}));
diff --git a/src/legacy/core_plugins/kibana/public/management/sections/objects/components/objects_table/components/flyout/__jest__/flyout.test.js b/src/legacy/core_plugins/kibana/public/management/sections/objects/components/objects_table/components/flyout/__jest__/flyout.test.js
index e465149b301dc..97c0d5b89d657 100644
--- a/src/legacy/core_plugins/kibana/public/management/sections/objects/components/objects_table/components/flyout/__jest__/flyout.test.js
+++ b/src/legacy/core_plugins/kibana/public/management/sections/objects/components/objects_table/components/flyout/__jest__/flyout.test.js
@@ -19,7 +19,7 @@
import React from 'react';
import { shallowWithI18nProvider } from 'test_utils/enzyme_helpers';
-
+import { mockManagementPlugin } from '../../../../../../../../../../management/public/np_ready/mocks';
import { Flyout } from '../flyout';
jest.mock('ui/kfetch', () => ({ kfetch: jest.fn() }));
@@ -48,6 +48,11 @@ jest.mock('../../../../../lib/resolve_saved_objects', () => ({
saveObjects: jest.fn(),
}));
+jest.mock('../../../../../../../../../../management/public/legacy', () => ({
+ setup: mockManagementPlugin.createSetupContract(),
+ start: mockManagementPlugin.createStartContract(),
+}));
+
jest.mock('ui/notify', () => ({}));
const defaultProps = {
diff --git a/src/legacy/core_plugins/kibana/public/management/sections/objects/components/objects_table/components/table/__jest__/table.test.js b/src/legacy/core_plugins/kibana/public/management/sections/objects/components/objects_table/components/table/__jest__/table.test.js
index d3f5fb1945254..fba249670ce60 100644
--- a/src/legacy/core_plugins/kibana/public/management/sections/objects/components/objects_table/components/table/__jest__/table.test.js
+++ b/src/legacy/core_plugins/kibana/public/management/sections/objects/components/objects_table/components/table/__jest__/table.test.js
@@ -21,6 +21,7 @@ import React from 'react';
import { shallowWithI18nProvider, mountWithI18nProvider } from 'test_utils/enzyme_helpers';
import { findTestSubject } from '@elastic/eui/lib/test';
import { keyCodes } from '@elastic/eui/lib/services';
+import { mockManagementPlugin } from '../../../../../../../../../../management/public/np_ready/mocks';
jest.mock('ui/kfetch', () => ({ kfetch: jest.fn() }));
@@ -28,6 +29,11 @@ jest.mock('ui/chrome', () => ({
addBasePath: () => '',
}));
+jest.mock('../../../../../../../../../../management/public/legacy', () => ({
+ setup: mockManagementPlugin.createSetupContract(),
+ start: mockManagementPlugin.createStartContract(),
+}));
+
import { Table } from '../table';
const defaultProps = {
diff --git a/src/legacy/core_plugins/kibana/public/management/sections/objects/components/objects_table/components/table/table.js b/src/legacy/core_plugins/kibana/public/management/sections/objects/components/objects_table/components/table/table.js
index 43cf8c2a23286..eeddc390037a6 100644
--- a/src/legacy/core_plugins/kibana/public/management/sections/objects/components/objects_table/components/table/table.js
+++ b/src/legacy/core_plugins/kibana/public/management/sections/objects/components/objects_table/components/table/table.js
@@ -18,7 +18,7 @@
*/
import chrome from 'ui/chrome';
-import { SavedObjectsManagementActionRegistry } from 'ui/management/saved_objects_management';
+import { setup as managementSetup } from '../../../../../../../../../management/public/legacy';
import React, { PureComponent, Fragment } from 'react';
import PropTypes from 'prop-types';
@@ -79,7 +79,7 @@ export class Table extends PureComponent {
constructor(props) {
super(props);
- this.extraActions = SavedObjectsManagementActionRegistry.get();
+ this.extraActions = managementSetup.savedObjects.registry.get();
}
onChange = ({ query, error }) => {
diff --git a/src/legacy/core_plugins/kibana/public/visualize/application.ts b/src/legacy/core_plugins/kibana/public/visualize/application.ts
new file mode 100644
index 0000000000000..7684f982de7e0
--- /dev/null
+++ b/src/legacy/core_plugins/kibana/public/visualize/application.ts
@@ -0,0 +1,193 @@
+/*
+ * 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 angular, { IModule } from 'angular';
+import { EuiConfirmModal } from '@elastic/eui';
+import { i18nDirective, i18nFilter, I18nProvider } from '@kbn/i18n/angular';
+
+import { AppMountContext, LegacyCoreStart } from 'kibana/public';
+import {
+ AppStateProvider,
+ AppState,
+ configureAppAngularModule,
+ confirmModalFactory,
+ createTopNavDirective,
+ createTopNavHelper,
+ EventsProvider,
+ GlobalStateProvider,
+ KbnUrlProvider,
+ RedirectWhenMissingProvider,
+ IPrivate,
+ PersistedState,
+ PrivateProvider,
+ PromiseServiceCreator,
+ StateManagementConfigProvider,
+} from './legacy_imports';
+import { NavigationStart } from '../../../navigation/public';
+
+// @ts-ignore
+import { initVisualizeApp } from './legacy_app';
+import { VisualizeKibanaServices } from './kibana_services';
+
+let angularModuleInstance: IModule | null = null;
+
+export const renderApp = async (
+ element: HTMLElement,
+ appBasePath: string,
+ deps: VisualizeKibanaServices
+) => {
+ if (!angularModuleInstance) {
+ angularModuleInstance = createLocalAngularModule(deps.core, deps.navigation);
+ // global routing stuff
+ configureAppAngularModule(angularModuleInstance, deps.core as LegacyCoreStart, true);
+ // custom routing stuff
+ initVisualizeApp(angularModuleInstance, deps);
+ }
+ const $injector = mountVisualizeApp(appBasePath, element);
+ return () => $injector.get('$rootScope').$destroy();
+};
+
+const mainTemplate = (basePath: string) => `
+`;
+
+const moduleName = 'app/visualize';
+
+const thirdPartyAngularDependencies = ['ngSanitize', 'ngRoute', 'react'];
+
+function mountVisualizeApp(appBasePath: string, element: HTMLElement) {
+ const mountpoint = document.createElement('div');
+ mountpoint.setAttribute('style', 'height: 100%');
+ mountpoint.innerHTML = mainTemplate(appBasePath);
+ // bootstrap angular into detached element and attach it later to
+ // make angular-within-angular possible
+ const $injector = angular.bootstrap(mountpoint, [moduleName]);
+ // initialize global state handler
+ element.appendChild(mountpoint);
+ return $injector;
+}
+
+function createLocalAngularModule(core: AppMountContext['core'], navigation: NavigationStart) {
+ createLocalI18nModule();
+ createLocalPrivateModule();
+ createLocalPromiseModule();
+ createLocalConfigModule(core);
+ createLocalKbnUrlModule();
+ createLocalStateModule();
+ createLocalPersistedStateModule();
+ createLocalTopNavModule(navigation);
+ createLocalConfirmModalModule();
+
+ const visualizeAngularModule: IModule = angular.module(moduleName, [
+ ...thirdPartyAngularDependencies,
+ 'app/visualize/Config',
+ 'app/visualize/I18n',
+ 'app/visualize/Private',
+ 'app/visualize/PersistedState',
+ 'app/visualize/TopNav',
+ 'app/visualize/State',
+ 'app/visualize/ConfirmModal',
+ ]);
+ return visualizeAngularModule;
+}
+
+function createLocalConfirmModalModule() {
+ angular
+ .module('app/visualize/ConfirmModal', ['react'])
+ .factory('confirmModal', confirmModalFactory)
+ .directive('confirmModal', reactDirective => reactDirective(EuiConfirmModal));
+}
+
+function createLocalStateModule() {
+ angular
+ .module('app/visualize/State', [
+ 'app/visualize/Private',
+ 'app/visualize/Config',
+ 'app/visualize/KbnUrl',
+ 'app/visualize/Promise',
+ 'app/visualize/PersistedState',
+ ])
+ .factory('AppState', function(Private: IPrivate) {
+ return Private(AppStateProvider);
+ })
+ .service('getAppState', function(Private: IPrivate) {
+ return Private(AppStateProvider).getAppState;
+ })
+ .service('globalState', function(Private: IPrivate) {
+ return Private(GlobalStateProvider);
+ });
+}
+
+function createLocalPersistedStateModule() {
+ angular
+ .module('app/visualize/PersistedState', ['app/visualize/Private', 'app/visualize/Promise'])
+ .factory('PersistedState', (Private: IPrivate) => {
+ const Events = Private(EventsProvider);
+ return class AngularPersistedState extends PersistedState {
+ constructor(value: any, path: any) {
+ super(value, path, Events);
+ }
+ };
+ });
+}
+
+function createLocalKbnUrlModule() {
+ angular
+ .module('app/visualize/KbnUrl', ['app/visualize/Private', 'ngRoute'])
+ .service('kbnUrl', (Private: IPrivate) => Private(KbnUrlProvider))
+ .service('redirectWhenMissing', (Private: IPrivate) => Private(RedirectWhenMissingProvider));
+}
+
+function createLocalConfigModule(core: AppMountContext['core']) {
+ angular
+ .module('app/visualize/Config', ['app/visualize/Private'])
+ .provider('stateManagementConfig', StateManagementConfigProvider)
+ .provider('config', () => {
+ return {
+ $get: () => ({
+ get: core.uiSettings.get.bind(core.uiSettings),
+ }),
+ };
+ });
+}
+
+function createLocalPromiseModule() {
+ angular.module('app/visualize/Promise', []).service('Promise', PromiseServiceCreator);
+}
+
+function createLocalPrivateModule() {
+ angular.module('app/visualize/Private', []).provider('Private', PrivateProvider);
+}
+
+function createLocalTopNavModule(navigation: NavigationStart) {
+ angular
+ .module('app/visualize/TopNav', ['react'])
+ .directive('kbnTopNav', createTopNavDirective)
+ .directive('kbnTopNavHelper', createTopNavHelper(navigation.ui));
+}
+
+function createLocalI18nModule() {
+ angular
+ .module('app/visualize/I18n', [])
+ .provider('i18n', I18nProvider)
+ .filter('i18n', i18nFilter)
+ .directive('i18nId', i18nDirective);
+}
diff --git a/src/legacy/core_plugins/kibana/public/visualize/editor/editor.html b/src/legacy/core_plugins/kibana/public/visualize/editor/editor.html
index bf9ac9b9bbe36..6190b92c9be3e 100644
--- a/src/legacy/core_plugins/kibana/public/visualize/editor/editor.html
+++ b/src/legacy/core_plugins/kibana/public/visualize/editor/editor.html
@@ -39,7 +39,7 @@
show-search-bar="true"
show-query-bar="true"
show-query-input="showQueryInput()"
- show-filter-bar="showFilterBar() && chrome.getVisible()"
+ show-filter-bar="showFilterBar() && isVisible"
show-date-picker="showQueryBarTimePicker()"
show-auto-refresh-only="!showQueryBarTimePicker()"
query="state.query"
@@ -67,7 +67,7 @@
-->
savedVisualizations.get($route.current.params))
- .then(savedVis => {
- if (savedVis.vis.type.setup) {
- return savedVis.vis.type.setup(savedVis)
- .catch(() => savedVis);
- }
- return savedVis;
- })
- .catch(redirectWhenMissing({
- '*': '/visualize'
- }));
- }
- }
- })
- .when(`${VisualizeConstants.EDIT_PATH}/:id`, {
- template: editorTemplate,
- k7Breadcrumbs: getEditBreadcrumbs,
- resolve: {
- savedVis: function (savedVisualizations, redirectWhenMissing, $route, $rootScope, kbnUrl) {
- return ensureDefaultIndexPattern(core, npData, $rootScope, kbnUrl)
- .then(() => savedVisualizations.get($route.current.params.id))
- .then((savedVis) => {
- chrome.recentlyAccessed.add(
- savedVis.getFullPath(),
- savedVis.title,
- savedVis.id
- );
- return savedVis;
- })
- .then(savedVis => {
- if (savedVis.vis.type.setup) {
- return savedVis.vis.type.setup(savedVis).catch(() => savedVis);
- }
- return savedVis;
- })
- .catch(
- redirectWhenMissing({
- visualization: '/visualize',
- search: '/management/kibana/objects/savedVisualizations/' + $route.current.params.id,
- 'index-pattern':
- '/management/kibana/objects/savedVisualizations/' + $route.current.params.id,
- 'index-pattern-field':
- '/management/kibana/objects/savedVisualizations/' + $route.current.params.id,
- })
- );
- }
- }
- });
+import { getServices } from '../kibana_services';
-uiModules
- .get('app/visualize', [
- 'kibana/url'
- ])
- .directive('visualizeApp', function () {
+export function initEditorDirective(app, deps) {
+ app.directive('visualizeApp', function () {
return {
restrict: 'E',
controllerAs: 'visualizeApp',
- controller: VisEditor,
+ controller: VisualizeAppController,
};
});
-function VisEditor(
+ initVisEditorDirective(app, deps);
+ initVisualizationDirective(app, deps);
+}
+
+function VisualizeAppController(
$scope,
$element,
$route,
@@ -154,19 +70,42 @@ function VisEditor(
$window,
$injector,
$timeout,
- indexPatterns,
kbnUrl,
redirectWhenMissing,
- Private,
Promise,
- config,
kbnBaseUrl,
- localStorage,
+ getAppState,
+ globalState,
) {
- const queryFilter = Private(FilterBarQueryFilterProvider);
-
+ const {
+ indexPatterns,
+ localStorage,
+ visualizeCapabilities,
+ share,
+ data: {
+ query: {
+ filterManager,
+ timefilter: { timefilter },
+ },
+ },
+ toastNotifications,
+ legacyChrome,
+ chrome,
+ getBasePath,
+ core: { docLinks },
+ savedQueryService,
+ uiSettings,
+ } = getServices();
+
+ const filterStateManager = new FilterStateManager(globalState, getAppState, filterManager);
+ const queryFilter = filterManager;
// Retrieve the resolved SavedVis instance.
const savedVis = $route.current.locals.savedVis;
+ const _applyVis = () => {
+ $scope.$apply();
+ };
+ // This will trigger a digest cycle. This is needed when vis is updated from a global angular like in visualize_embeddable.js.
+ savedVis.vis.on('apply', _applyVis);
// vis is instance of src/legacy/ui/public/vis/vis.js.
// SearchSource is a promise-based stream of search results that can inherit from other search sources.
const { vis, searchSource } = savedVis;
@@ -177,7 +116,7 @@ function VisEditor(
dirty: !savedVis.id
};
- $scope.topNavMenu = [...(capabilities.visualize.save ? [{
+ $scope.topNavMenu = [...(visualizeCapabilities.save ? [{
id: 'save',
label: i18n.translate('kbn.topNavMenu.saveVisualizationButtonLabel', { defaultMessage: 'save' }),
description: i18n.translate('kbn.visualize.topNavMenu.saveVisualizationButtonAriaLabel', {
@@ -246,7 +185,7 @@ function VisEditor(
share.toggleShareContextMenu({
anchorElement,
allowEmbed: true,
- allowShortUrl: capabilities.visualize.createShortUrl,
+ allowShortUrl: visualizeCapabilities.createShortUrl,
shareableUrl: unhashUrl(window.location.href),
objectId: savedVis.id,
objectType: 'visualization',
@@ -295,7 +234,7 @@ function VisEditor(
let stateMonitor;
if (savedVis.id) {
- docTitle.change(savedVis.title);
+ chrome.docTitle.change(savedVis.title);
}
// Extract visualization state with filtered aggs. You can see these filtered aggs in the URL.
@@ -306,7 +245,7 @@ function VisEditor(
linked: !!savedVis.savedSearchId,
query: searchSource.getOwnField('query') || {
query: '',
- language: localStorage.get('kibana.userQueryLanguage') || config.get('search:queryLanguage')
+ language: localStorage.get('kibana.userQueryLanguage') || uiSettings.get('search:queryLanguage')
},
filters: searchSource.getOwnField('filter') || [],
vis: savedVisState
@@ -345,9 +284,9 @@ function VisEditor(
queryFilter.setFilters(filters);
};
- $scope.showSaveQuery = capabilities.visualize.saveQuery;
+ $scope.showSaveQuery = visualizeCapabilities.saveQuery;
- $scope.$watch(() => capabilities.visualize.saveQuery, (newCapability) => {
+ $scope.$watch(() => visualizeCapabilities.saveQuery, (newCapability) => {
$scope.showSaveQuery = newCapability;
});
@@ -455,13 +394,15 @@ function VisEditor(
}
}));
- $scope.$on('$destroy', function () {
+ $scope.$on('$destroy', () => {
if ($scope._handler) {
$scope._handler.destroy();
}
savedVis.destroy();
stateMonitor.destroy();
+ filterStateManager.destroy();
subscriptions.unsubscribe();
+ $scope.vis.off('apply', _applyVis);
});
@@ -503,7 +444,7 @@ function VisEditor(
delete $state.savedQuery;
$state.query = {
query: '',
- language: localStorage.get('kibana.userQueryLanguage') || config.get('search:queryLanguage')
+ language: localStorage.get('kibana.userQueryLanguage') || uiSettings.get('search:queryLanguage')
};
queryFilter.removeAll();
$state.save();
@@ -589,14 +530,14 @@ function VisEditor(
// Since we aren't reloading the page, only inserting a new browser history item, we need to manually update
// the last url for this app, so directly clicking on the Visualize tab will also bring the user to the saved
// url, not the unsaved one.
- chromeLegacy.trackSubUrlForApp('kibana:visualize', savedVisualizationParsedUrl);
+ legacyChrome.trackSubUrlForApp('kibana:visualize', savedVisualizationParsedUrl);
const lastDashboardAbsoluteUrl = chrome.navLinks.get('kibana:dashboard').url;
const dashboardParsedUrl = absoluteToParsedUrl(lastDashboardAbsoluteUrl, getBasePath());
dashboardParsedUrl.addQueryParameter(DashboardConstants.NEW_VISUALIZATION_ID_PARAM, savedVis.id);
kbnUrl.change(dashboardParsedUrl.appPath);
} else if (savedVis.id === $route.current.params.id) {
- docTitle.change(savedVis.lastSavedTitle);
+ chrome.docTitle.change(savedVis.lastSavedTitle);
chrome.setBreadcrumbs($injector.invoke(getEditBreadcrumbs));
savedVis.vis.title = savedVis.title;
savedVis.vis.description = savedVis.description;
@@ -661,7 +602,7 @@ function VisEditor(
vis.type.feedbackMessage;
};
- addHelpMenuToAppChrome(chrome);
+ addHelpMenuToAppChrome(chrome, docLinks);
init();
}
diff --git a/src/legacy/core_plugins/kibana/public/visualize/editor/visualization.js b/src/legacy/core_plugins/kibana/public/visualize/editor/visualization.js
index 198fbe19a0b7a..d3651735c1a1d 100644
--- a/src/legacy/core_plugins/kibana/public/visualize/editor/visualization.js
+++ b/src/legacy/core_plugins/kibana/public/visualize/editor/visualization.js
@@ -17,13 +17,8 @@
* under the License.
*/
-import { getServices } from '../kibana_services';
-
-const { embeddables, uiModules } = getServices();
-
-uiModules
- .get('kibana/directive', ['ngSanitize'])
- .directive('visualizationEmbedded', function (Private, $timeout, getAppState) {
+export function initVisualizationDirective(app, deps) {
+ app.directive('visualizationEmbedded', function ($timeout, getAppState) {
return {
restrict: 'E',
@@ -37,7 +32,7 @@ uiModules
link: function ($scope, element) {
$scope.renderFunction = async () => {
if (!$scope._handler) {
- $scope._handler = await embeddables.getEmbeddableFactory('visualization').createFromObject($scope.savedObj, {
+ $scope._handler = await deps.embeddables.getEmbeddableFactory('visualization').createFromObject($scope.savedObj, {
timeRange: $scope.timeRange,
filters: $scope.filters || [],
query: $scope.query,
@@ -66,3 +61,4 @@ uiModules
}
};
});
+}
diff --git a/src/legacy/core_plugins/kibana/public/visualize/editor/visualization_editor.js b/src/legacy/core_plugins/kibana/public/visualize/editor/visualization_editor.js
index ead77e6bc41d5..bc6d4d4c48466 100644
--- a/src/legacy/core_plugins/kibana/public/visualize/editor/visualization_editor.js
+++ b/src/legacy/core_plugins/kibana/public/visualize/editor/visualization_editor.js
@@ -17,15 +17,8 @@
* under the License.
*/
-import { getServices, VisEditorTypesRegistryProvider } from '../kibana_services';
-
-const { uiModules } = getServices();
-
-uiModules
- .get('kibana/directive', ['ngSanitize'])
- .directive('visualizationEditor', function (Private, $timeout, getAppState) {
- const editorTypes = Private(VisEditorTypesRegistryProvider);
-
+export function initVisEditorDirective(app, deps) {
+ app.directive('visualizationEditor', function ($timeout, getAppState) {
return {
restrict: 'E',
scope: {
@@ -38,7 +31,8 @@ uiModules
link: function ($scope, element) {
const editorType = $scope.savedObj.vis.type.editor;
const Editor = typeof editorType === 'function' ? editorType :
- editorTypes.find(editor => editor.key === editorType);
+ deps.editorTypes.find(editor => editor.key === editorType);
+
const editor = new Editor(element[0], $scope.savedObj);
$scope.renderFunction = () => {
@@ -62,3 +56,4 @@ uiModules
}
};
});
+}
diff --git a/src/legacy/core_plugins/kibana/public/visualize/embeddable/disabled_lab_embeddable.tsx b/src/legacy/core_plugins/kibana/public/visualize/embeddable/disabled_lab_embeddable.tsx
index 065feae045597..d8792a761b186 100644
--- a/src/legacy/core_plugins/kibana/public/visualize/embeddable/disabled_lab_embeddable.tsx
+++ b/src/legacy/core_plugins/kibana/public/visualize/embeddable/disabled_lab_embeddable.tsx
@@ -19,8 +19,8 @@
import React from 'react';
import ReactDOM from 'react-dom';
+import { Embeddable, EmbeddableOutput } from '../../../../../../plugins/embeddable/public';
-import { Embeddable, EmbeddableOutput } from '../kibana_services';
import { DisabledLabVisualization } from './disabled_lab_visualization';
import { VisualizeInput } from './visualize_embeddable';
import { VISUALIZE_EMBEDDABLE_TYPE } from './constants';
diff --git a/src/legacy/core_plugins/kibana/public/visualize/embeddable/get_index_pattern.ts b/src/legacy/core_plugins/kibana/public/visualize/embeddable/get_index_pattern.ts
index 9bc9ab99c4aff..7fe3678bb1f77 100644
--- a/src/legacy/core_plugins/kibana/public/visualize/embeddable/get_index_pattern.ts
+++ b/src/legacy/core_plugins/kibana/public/visualize/embeddable/get_index_pattern.ts
@@ -17,11 +17,10 @@
* under the License.
*/
-import { getServices, getFromSavedObject, VisSavedObject } from '../kibana_services';
+import { npStart } from 'ui/new_platform';
-import { IIndexPattern } from '../../../../../../plugins/data/public';
-
-const { savedObjectsClient, uiSettings } = getServices();
+import { VisSavedObject } from './visualize_embeddable';
+import { indexPatterns, IIndexPattern } from '../../../../../../plugins/data/public';
export async function getIndexPattern(
savedVis: VisSavedObject
@@ -30,7 +29,8 @@ export async function getIndexPattern(
return savedVis.vis.indexPattern;
}
- const defaultIndex = uiSettings.get('defaultIndex');
+ const savedObjectsClient = npStart.core.savedObjects.client;
+ const defaultIndex = npStart.core.uiSettings.get('defaultIndex');
if (savedVis.vis.params.index_pattern) {
const indexPatternObjects = await savedObjectsClient.find({
@@ -39,10 +39,10 @@ export async function getIndexPattern(
search: `"${savedVis.vis.params.index_pattern}"`,
searchFields: ['title'],
});
- const [indexPattern] = indexPatternObjects.savedObjects.map(getFromSavedObject);
+ const [indexPattern] = indexPatternObjects.savedObjects.map(indexPatterns.getFromSavedObject);
return indexPattern;
}
const savedObject = await savedObjectsClient.get('index-pattern', defaultIndex);
- return getFromSavedObject(savedObject);
+ return indexPatterns.getFromSavedObject(savedObject);
}
diff --git a/src/legacy/core_plugins/kibana/public/visualize/embeddable/visualize_embeddable.ts b/src/legacy/core_plugins/kibana/public/visualize/embeddable/visualize_embeddable.ts
index e5a723a99eafd..7ab60f8867c38 100644
--- a/src/legacy/core_plugins/kibana/public/visualize/embeddable/visualize_embeddable.ts
+++ b/src/legacy/core_plugins/kibana/public/visualize/embeddable/visualize_embeddable.ts
@@ -375,6 +375,8 @@ export class VisualizeEmbeddable extends Embeddable {
diff --git a/src/legacy/core_plugins/kibana/public/visualize/embeddable/visualize_embeddable_factory.tsx b/src/legacy/core_plugins/kibana/public/visualize/embeddable/visualize_embeddable_factory.tsx
index 15ad9a33232ef..a377dafe9e512 100644
--- a/src/legacy/core_plugins/kibana/public/visualize/embeddable/visualize_embeddable_factory.tsx
+++ b/src/legacy/core_plugins/kibana/public/visualize/embeddable/visualize_embeddable_factory.tsx
@@ -17,36 +17,48 @@
* under the License.
*/
+import 'uiExports/contextMenuActions';
+import 'uiExports/devTools';
+import 'uiExports/docViews';
+import 'uiExports/embeddableActions';
+import 'uiExports/fieldFormatEditors';
+import 'uiExports/fieldFormats';
+import 'uiExports/home';
+import 'uiExports/indexManagement';
+import 'uiExports/inspectorViews';
+import 'uiExports/savedObjectTypes';
+import 'uiExports/search';
+import 'uiExports/shareContextMenuExtensions';
+import 'uiExports/visTypes';
+import 'uiExports/visualize';
+
import { i18n } from '@kbn/i18n';
+import chrome from 'ui/chrome';
+import { npStart } from 'ui/new_platform';
+
import { Legacy } from 'kibana';
import { SavedObjectAttributes } from 'kibana/server';
+import {
+ EmbeddableFactory,
+ ErrorEmbeddable,
+ Container,
+ EmbeddableOutput,
+} from '../../../../../../plugins/embeddable/public';
+import { start as visualizations } from '../../../../visualizations/public/np_ready/public/legacy';
import { showNewVisModal } from '../wizard';
import { SavedVisualizations } from '../types';
import { DisabledLabEmbeddable } from './disabled_lab_embeddable';
import { getIndexPattern } from './get_index_pattern';
-import { VisualizeEmbeddable, VisualizeInput, VisualizeOutput } from './visualize_embeddable';
-import { VISUALIZE_EMBEDDABLE_TYPE } from './constants';
-import { TypesStart } from '../../../../visualizations/public/np_ready/public/types';
-
import {
- getServices,
- Container,
- EmbeddableFactory,
- EmbeddableOutput,
- ErrorEmbeddable,
+ VisualizeEmbeddable,
+ VisualizeInput,
+ VisualizeOutput,
VisSavedObject,
-} from '../kibana_services';
-
-const {
- addBasePath,
- capabilities,
- embeddable,
- getInjector,
- uiSettings,
- visualizations,
-} = getServices();
+} from './visualize_embeddable';
+import { VISUALIZE_EMBEDDABLE_TYPE } from './constants';
+import { TypesStart } from '../../../../visualizations/public/np_ready/public/types';
interface VisualizationAttributes extends SavedObjectAttributes {
visState: string;
@@ -96,7 +108,7 @@ export class VisualizeEmbeddableFactory extends EmbeddableFactory<
if (!visType) {
return false;
}
- if (uiSettings.get('visualize:enableLabs')) {
+ if (npStart.core.uiSettings.get('visualize:enableLabs')) {
return true;
}
return visType.stage !== 'experimental';
@@ -108,7 +120,7 @@ export class VisualizeEmbeddableFactory extends EmbeddableFactory<
}
public isEditable() {
- return capabilities.visualize.save as boolean;
+ return npStart.core.application.capabilities.visualize.save as boolean;
}
public getDisplayName() {
@@ -122,14 +134,16 @@ export class VisualizeEmbeddableFactory extends EmbeddableFactory<
input: Partial & { id: string },
parent?: Container
): Promise {
- const $injector = await getInjector();
+ const $injector = await chrome.dangerouslyGetActiveInjector();
const config = $injector.get('config');
const savedVisualizations = $injector.get('savedVisualizations');
try {
const visId = savedObject.id as string;
- const editUrl = visId ? addBasePath(`/app/kibana${savedVisualizations.urlFor(visId)}`) : '';
+ const editUrl = visId
+ ? npStart.core.http.basePath.prepend(`/app/kibana${savedVisualizations.urlFor(visId)}`)
+ : '';
const isLabsEnabled = config.get('visualize:enableLabs');
if (!isLabsEnabled && savedObject.vis.type.stage === 'experimental') {
@@ -161,7 +175,7 @@ export class VisualizeEmbeddableFactory extends EmbeddableFactory<
input: Partial & { id: string },
parent?: Container
): Promise {
- const $injector = await getInjector();
+ const $injector = await chrome.dangerouslyGetActiveInjector();
const savedVisualizations = $injector.get('savedVisualizations');
try {
@@ -179,14 +193,16 @@ export class VisualizeEmbeddableFactory extends EmbeddableFactory<
// TODO: This is a bit of a hack to preserve the original functionality. Ideally we will clean this up
// to allow for in place creation of visualizations without having to navigate away to a new URL.
if (this.visTypes) {
- showNewVisModal(this.visTypes, {
- editorParams: ['addToDashboard'],
- });
+ showNewVisModal(
+ this.visTypes,
+ {
+ editorParams: ['addToDashboard'],
+ },
+ npStart.core.http.basePath.prepend,
+ npStart.core.uiSettings,
+ npStart.core.savedObjects
+ );
}
return undefined;
}
}
-
-VisualizeEmbeddableFactory.createVisualizeEmbeddableFactory().then(embeddableFactory => {
- embeddable.registerEmbeddableFactory(VISUALIZE_EMBEDDABLE_TYPE, embeddableFactory);
-});
diff --git a/src/legacy/core_plugins/kibana/public/visualize/global_state_sync.ts b/src/legacy/core_plugins/kibana/public/visualize/global_state_sync.ts
new file mode 100644
index 0000000000000..71156bc38d498
--- /dev/null
+++ b/src/legacy/core_plugins/kibana/public/visualize/global_state_sync.ts
@@ -0,0 +1,67 @@
+/*
+ * 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 { State } from './legacy_imports';
+import { DataPublicPluginStart as DataStart } from '../../../../../plugins/data/public';
+
+/**
+ * Helper function to sync the global state with the various state providers
+ * when a local angular application mounts. There are three different ways
+ * global state can be passed into the application:
+ * * parameter in the URL hash - e.g. shared link
+ * * in-memory state in the data plugin exports (timefilter and filterManager) - e.g. default values
+ *
+ * This function looks up the three sources (earlier in the list means it takes precedence),
+ * puts it into the globalState object and syncs it with the url.
+ *
+ * Currently the legacy chrome takes care of restoring the global state when navigating from
+ * one app to another - to migrate away from that it will become necessary to also write the current
+ * state to local storage
+ */
+export function syncOnMount(
+ globalState: State,
+ {
+ query: {
+ filterManager,
+ timefilter: { timefilter },
+ },
+ }: DataStart
+) {
+ // pull in global state information from the URL
+ globalState.fetch();
+ // remember whether there were info in the URL
+ const hasGlobalURLState = Boolean(Object.keys(globalState.toObject()).length);
+
+ // sync kibana platform state with the angular global state
+ if (!globalState.time) {
+ globalState.time = timefilter.getTime();
+ }
+ if (!globalState.refreshInterval) {
+ globalState.refreshInterval = timefilter.getRefreshInterval();
+ }
+ if (!globalState.filters && filterManager.getGlobalFilters().length > 0) {
+ globalState.filters = filterManager.getGlobalFilters();
+ }
+ // only inject cross app global state if there is none in the url itself (that takes precedence)
+ if (hasGlobalURLState) {
+ // set flag the global state is set from the URL
+ globalState.$inheritedGlobalState = true;
+ }
+ globalState.save();
+}
diff --git a/src/legacy/core_plugins/kibana/public/visualize/help_menu/help_menu_util.js b/src/legacy/core_plugins/kibana/public/visualize/help_menu/help_menu_util.js
index d27003f39d4c0..9c00947d7663c 100644
--- a/src/legacy/core_plugins/kibana/public/visualize/help_menu/help_menu_util.js
+++ b/src/legacy/core_plugins/kibana/public/visualize/help_menu/help_menu_util.js
@@ -18,10 +18,8 @@
*/
import { i18n } from '@kbn/i18n';
-import { getServices } from '../kibana_services';
-const { docLinks } = getServices();
-export function addHelpMenuToAppChrome(chrome) {
+export function addHelpMenuToAppChrome(chrome, docLinks) {
chrome.setHelpExtension({
appName: i18n.translate('kbn.visualize.helpMenu.appName', {
defaultMessage: 'Visualize',
diff --git a/src/legacy/core_plugins/kibana/public/visualize/index.js b/src/legacy/core_plugins/kibana/public/visualize/index.js
deleted file mode 100644
index d42c72f67f815..0000000000000
--- a/src/legacy/core_plugins/kibana/public/visualize/index.js
+++ /dev/null
@@ -1,89 +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 { ensureDefaultIndexPattern } from 'ui/legacy_compat';
-import './editor/editor';
-import { i18n } from '@kbn/i18n';
-import './saved_visualizations/_saved_vis';
-import './saved_visualizations/saved_visualizations';
-import visualizeListingTemplate from './listing/visualize_listing.html';
-import { VisualizeListingController } from './listing/visualize_listing';
-import { VisualizeConstants } from './visualize_constants';
-import { getLandingBreadcrumbs, getWizardStep1Breadcrumbs } from './breadcrumbs';
-
-import { getServices, FeatureCatalogueCategory } from './kibana_services';
-
-const { FeatureCatalogueRegistryProvider, uiRoutes } = getServices();
-
-uiRoutes
- .defaults(/visualize/, {
- requireUICapability: 'visualize.show',
- badge: uiCapabilities => {
- if (uiCapabilities.visualize.save) {
- return undefined;
- }
-
- return {
- text: i18n.translate('kbn.visualize.badge.readOnly.text', {
- defaultMessage: 'Read only',
- }),
- tooltip: i18n.translate('kbn.visualize.badge.readOnly.tooltip', {
- defaultMessage: 'Unable to save visualizations',
- }),
- iconType: 'glasses'
- };
- }
- })
- .when(VisualizeConstants.LANDING_PAGE_PATH, {
- template: visualizeListingTemplate,
- k7Breadcrumbs: getLandingBreadcrumbs,
- controller: VisualizeListingController,
- controllerAs: 'listingController',
- resolve: {
- createNewVis: () => false,
- hasDefaultIndex: ($rootScope, kbnUrl) => ensureDefaultIndexPattern(getServices().core, getServices().npData, $rootScope, kbnUrl)
- },
- })
- .when(VisualizeConstants.WIZARD_STEP_1_PAGE_PATH, {
- template: visualizeListingTemplate,
- k7Breadcrumbs: getWizardStep1Breadcrumbs,
- controller: VisualizeListingController,
- controllerAs: 'listingController',
- resolve: {
- createNewVis: () => true,
- hasDefaultIndex: ($rootScope, kbnUrl) => ensureDefaultIndexPattern(getServices().core, getServices().npData, $rootScope, kbnUrl)
- },
- });
-
-FeatureCatalogueRegistryProvider.register(() => {
- return {
- id: 'visualize',
- title: 'Visualize',
- description: i18n.translate(
- 'kbn.visualize.visualizeDescription',
- {
- defaultMessage: 'Create visualizations and aggregate data stores in your Elasticsearch indices.',
- }
- ),
- icon: 'visualizeApp',
- path: `/app/kibana#${VisualizeConstants.LANDING_PAGE_PATH}`,
- showOnHomePage: true,
- category: FeatureCatalogueCategory.DATA
- };
-});
diff --git a/src/legacy/core_plugins/kibana/public/visualize/index.ts b/src/legacy/core_plugins/kibana/public/visualize/index.ts
new file mode 100644
index 0000000000000..5e9f2fdeb8999
--- /dev/null
+++ b/src/legacy/core_plugins/kibana/public/visualize/index.ts
@@ -0,0 +1,70 @@
+/*
+ * 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 'ui/collapsible_sidebar'; // used in default editor
+import 'ui/vis/editors/default/sidebar';
+
+import {
+ IPrivate,
+ legacyChrome,
+ npSetup,
+ npStart,
+ SavedObjectRegistryProvider,
+ VisEditorTypesRegistryProvider,
+} from './legacy_imports';
+import { VisualizePlugin, LegacyAngularInjectedDependencies } from './plugin';
+import { start as embeddables } from '../../../embeddable_api/public/np_ready/public/legacy';
+import { start as navigation } from '../../../navigation/public/legacy';
+import { start as visualizations } from '../../../visualizations/public/np_ready/public/legacy';
+
+/**
+ * Get dependencies relying on the global angular context.
+ * They also have to get resolved together with the legacy imports above
+ */
+async function getAngularDependencies(): Promise {
+ const injector = await legacyChrome.dangerouslyGetActiveInjector();
+
+ const Private = injector.get('Private');
+
+ const editorTypes = Private(VisEditorTypesRegistryProvider);
+ const savedObjectRegistry = Private(SavedObjectRegistryProvider);
+
+ return {
+ legacyChrome,
+ editorTypes,
+ savedObjectRegistry,
+ savedVisualizations: injector.get('savedVisualizations'),
+ };
+}
+
+(() => {
+ const instance = new VisualizePlugin();
+ instance.setup(npSetup.core, {
+ ...npSetup.plugins,
+ __LEGACY: {
+ getAngularDependencies,
+ },
+ });
+ instance.start(npStart.core, {
+ ...npStart.plugins,
+ embeddables,
+ navigation,
+ visualizations,
+ });
+})();
diff --git a/src/legacy/core_plugins/kibana/public/visualize/kibana_services.ts b/src/legacy/core_plugins/kibana/public/visualize/kibana_services.ts
index 40d36dab227fa..36a9ecf3fcf8c 100644
--- a/src/legacy/core_plugins/kibana/public/visualize/kibana_services.ts
+++ b/src/legacy/core_plugins/kibana/public/visualize/kibana_services.ts
@@ -17,108 +17,59 @@
* under the License.
*/
-import 'angular-sanitize'; // used in visualization_editor.js and visualization.js
-import 'ui/collapsible_sidebar'; // used in default editor
-import 'ui/vis/editors/default/sidebar';
-// load directives
-import '../../../data/public';
+import {
+ ChromeStart,
+ LegacyCoreStart,
+ SavedObjectsClientContract,
+ ToastsStart,
+ IUiSettingsClient,
+} from 'kibana/public';
-import { npStart } from 'ui/new_platform';
-import angular from 'angular'; // just used in editor.js
-import chromeLegacy from 'ui/chrome';
+import { NavigationStart } from '../../../navigation/public';
+import { Storage } from '../../../../../plugins/kibana_utils/public';
+import { IEmbeddableStart } from '../../../../../plugins/embeddable/public';
+import { SharePluginStart } from '../../../../../plugins/share/public';
+import { DataPublicPluginStart, IndexPatternsContract } from '../../../../../plugins/data/public';
+import { VisualizationsStart } from '../../../visualizations/public';
+import { SavedVisualizations } from './types';
-import uiRoutes from 'ui/routes';
-
-// @ts-ignore
-import { docTitle } from 'ui/doc_title';
-import { FilterBarQueryFilterProvider } from 'ui/filter_manager/query_filter';
-import { wrapInI18nContext } from 'ui/i18n';
-// @ts-ignore
-import { uiModules } from 'ui/modules';
-import { FeatureCatalogueRegistryProvider } from 'ui/registry/feature_catalogue';
-
-// Saved objects
-import { SavedObjectsClientProvider } from 'ui/saved_objects';
-// @ts-ignore
-import { SavedObject, SavedObjectProvider } from 'ui/saved_objects/saved_object';
-import { SavedObjectRegistryProvider } from 'ui/saved_objects/saved_object_registry';
-
-import { createUiStatsReporter, METRIC_TYPE } from '../../../ui_metric/public';
-import { start as visualizations } from '../../../visualizations/public/np_ready/public/legacy';
-import { start as embeddables } from '../../../../core_plugins/embeddable_api/public/np_ready/public/legacy';
-import { start as data } from '../../../data/public/legacy';
-
-const services = {
- // new platform
- addBasePath: npStart.core.http.basePath.prepend,
- capabilities: npStart.core.application.capabilities,
- chrome: npStart.core.chrome,
- docLinks: npStart.core.docLinks,
- embeddable: npStart.plugins.embeddable,
- getBasePath: npStart.core.http.basePath.get,
- savedObjectsClient: npStart.core.savedObjects.client,
- toastNotifications: npStart.core.notifications.toasts,
- uiSettings: npStart.core.uiSettings,
- core: npStart.core,
-
- share: npStart.plugins.share,
- npData: npStart.plugins.data,
- data,
- embeddables,
- visualizations,
-
- // legacy
- chromeLegacy,
- docTitle,
- FeatureCatalogueRegistryProvider,
- FilterBarQueryFilterProvider,
- getInjector: () => {
- return chromeLegacy.dangerouslyGetActiveInjector();
- },
- SavedObjectProvider,
- SavedObjectRegistryProvider,
- SavedObjectsClientProvider,
- timefilter: npStart.plugins.data.query.timefilter.timefilter,
- uiModules,
- uiRoutes,
- wrapInI18nContext,
+export interface VisualizeKibanaServices {
+ addBasePath: (url: string) => string;
+ chrome: ChromeStart;
+ core: LegacyCoreStart;
+ data: DataPublicPluginStart;
+ editorTypes: any;
+ embeddables: IEmbeddableStart;
+ getBasePath: () => string;
+ indexPatterns: IndexPatternsContract;
+ legacyChrome: any;
+ localStorage: Storage;
+ navigation: NavigationStart;
+ toastNotifications: ToastsStart;
+ savedObjectsClient: SavedObjectsClientContract;
+ savedObjectRegistry: any;
+ savedQueryService: DataPublicPluginStart['query']['savedQueries'];
+ savedVisualizations: SavedVisualizations;
+ share: SharePluginStart;
+ uiSettings: IUiSettingsClient;
+ visualizeCapabilities: any;
+ visualizations: VisualizationsStart;
+}
- createUiStatsReporter,
-};
+let services: VisualizeKibanaServices | null = null;
+export function setServices(newServices: VisualizeKibanaServices) {
+ services = newServices;
+}
export function getServices() {
+ if (!services) {
+ throw new Error(
+ 'Kibana services not set - are you trying to import this module from outside of the visualize app?'
+ );
+ }
return services;
}
-// export legacy static dependencies
-export { angular };
-export { getFromSavedObject } from 'ui/index_patterns';
-export { PersistedState } from 'ui/persisted_state';
-// @ts-ignore
-export { VisEditorTypesRegistryProvider } from 'ui/registry/vis_editor_types';
-export { showSaveModal } from 'ui/saved_objects/show_saved_object_save_modal';
-export { stateMonitorFactory } from 'ui/state_management/state_monitor_factory';
-export { absoluteToParsedUrl } from 'ui/url/absolute_to_parsed_url';
-export { KibanaParsedUrl } from 'ui/url/kibana_parsed_url';
-export { migrateLegacyQuery } from 'ui/utils/migrate_legacy_query';
-export { subscribeWithScope } from 'ui/utils/subscribe_with_scope';
-export { SavedObjectSaveModal } from 'ui/saved_objects/components/saved_object_save_modal';
-export { unhashUrl } from '../../../../../plugins/kibana_utils/public';
-export {
- Container,
- Embeddable,
- EmbeddableFactory,
- EmbeddableInput,
- EmbeddableOutput,
- ErrorEmbeddable,
-} from '../../../../../plugins/embeddable/public';
-
-// export types
-export { METRIC_TYPE };
-export { AppState } from 'ui/state_management/app_state';
-export { VisType } from 'ui/vis';
-
-// export const
-export { FeatureCatalogueCategory } from 'ui/registry/feature_catalogue';
-
-export { VisSavedObject } from './embeddable/visualize_embeddable';
+export function clearServices() {
+ services = null;
+}
diff --git a/src/legacy/core_plugins/kibana/public/visualize/legacy_app.js b/src/legacy/core_plugins/kibana/public/visualize/legacy_app.js
new file mode 100644
index 0000000000000..f47552e99a5c7
--- /dev/null
+++ b/src/legacy/core_plugins/kibana/public/visualize/legacy_app.js
@@ -0,0 +1,169 @@
+/*
+ * 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 { find } from 'lodash';
+import { i18n } from '@kbn/i18n';
+
+import editorTemplate from './editor/editor.html';
+import visualizeListingTemplate from './listing/visualize_listing.html';
+
+import { initVisualizeAppDirective } from './visualize_app';
+import { VisualizeConstants } from './visualize_constants';
+import { VisualizeListingController } from './listing/visualize_listing';
+import { ensureDefaultIndexPattern, registerTimefilterWithGlobalStateFactory } from './legacy_imports';
+import { syncOnMount } from './global_state_sync';
+
+import {
+ getLandingBreadcrumbs,
+ getWizardStep1Breadcrumbs,
+ getCreateBreadcrumbs,
+ getEditBreadcrumbs
+} from './breadcrumbs';
+
+export function initVisualizeApp(app, deps) {
+ initVisualizeAppDirective(app, deps);
+
+ app.run(globalState => {
+ syncOnMount(globalState, deps.data);
+ });
+
+ app.run((globalState, $rootScope) => {
+ registerTimefilterWithGlobalStateFactory(
+ deps.data.query.timefilter.timefilter,
+ globalState,
+ $rootScope
+ );
+ });
+
+ app.config(function ($routeProvider) {
+ const defaults = {
+ reloadOnSearch: false,
+ requireUICapability: 'visualize.show',
+ badge: () => {
+ if (deps.visualizeCapabilities.save) {
+ return undefined;
+ }
+
+ return {
+ text: i18n.translate('kbn.visualize.badge.readOnly.text', {
+ defaultMessage: 'Read only',
+ }),
+ tooltip: i18n.translate('kbn.visualize.badge.readOnly.tooltip', {
+ defaultMessage: 'Unable to save visualizations',
+ }),
+ iconType: 'glasses',
+ };
+ },
+ };
+
+ $routeProvider
+ .when(VisualizeConstants.LANDING_PAGE_PATH, {
+ ...defaults,
+ template: visualizeListingTemplate,
+ k7Breadcrumbs: getLandingBreadcrumbs,
+ controller: VisualizeListingController,
+ controllerAs: 'listingController',
+ resolve: {
+ createNewVis: () => false,
+ hasDefaultIndex: ($rootScope, kbnUrl) => ensureDefaultIndexPattern(deps.core, deps.data, $rootScope, kbnUrl),
+ },
+ })
+ .when(VisualizeConstants.WIZARD_STEP_1_PAGE_PATH, {
+ ...defaults,
+ template: visualizeListingTemplate,
+ k7Breadcrumbs: getWizardStep1Breadcrumbs,
+ controller: VisualizeListingController,
+ controllerAs: 'listingController',
+ resolve: {
+ createNewVis: () => true,
+ hasDefaultIndex: ($rootScope, kbnUrl) => ensureDefaultIndexPattern(deps.core, deps.data, $rootScope, kbnUrl),
+ },
+ })
+ .when(VisualizeConstants.CREATE_PATH, {
+ ...defaults,
+ template: editorTemplate,
+ k7Breadcrumbs: getCreateBreadcrumbs,
+ resolve: {
+ savedVis: function (redirectWhenMissing, $route, $rootScope, kbnUrl) {
+ const { core, data, savedVisualizations, visualizations } = deps;
+ const visTypes = visualizations.types.all();
+ const visType = find(visTypes, { name: $route.current.params.type });
+ const shouldHaveIndex = visType.requiresSearch && visType.options.showIndexSelection;
+ const hasIndex = $route.current.params.indexPattern || $route.current.params.savedSearchId;
+ if (shouldHaveIndex && !hasIndex) {
+ throw new Error(
+ i18n.translate('kbn.visualize.createVisualization.noIndexPatternOrSavedSearchIdErrorMessage', {
+ defaultMessage: 'You must provide either an indexPattern or a savedSearchId',
+ })
+ );
+ }
+
+ return ensureDefaultIndexPattern(core, data, $rootScope, kbnUrl).then(() => savedVisualizations.get($route.current.params))
+ .then(savedVis => {
+ if (savedVis.vis.type.setup) {
+ return savedVis.vis.type.setup(savedVis)
+ .catch(() => savedVis);
+ }
+ return savedVis;
+ })
+ .catch(redirectWhenMissing({
+ '*': '/visualize'
+ }));
+ }
+ }
+ })
+ .when(`${VisualizeConstants.EDIT_PATH}/:id`, {
+ ...defaults,
+ template: editorTemplate,
+ k7Breadcrumbs: getEditBreadcrumbs,
+ resolve: {
+ savedVis: function (redirectWhenMissing, $route, $rootScope, kbnUrl) {
+ const { chrome, core, data, savedVisualizations } = deps;
+ return ensureDefaultIndexPattern(core, data, $rootScope, kbnUrl)
+ .then(() => savedVisualizations.get($route.current.params.id))
+ .then(savedVis => {
+ chrome.recentlyAccessed.add(
+ savedVis.getFullPath(),
+ savedVis.title,
+ savedVis.id
+ );
+ return savedVis;
+ })
+ .then(savedVis => {
+ if (savedVis.vis.type.setup) {
+ return savedVis.vis.type.setup(savedVis).catch(() => savedVis);
+ }
+ return savedVis;
+ })
+ .catch(
+ redirectWhenMissing({
+ 'visualization': '/visualize',
+ 'search': '/management/kibana/objects/savedVisualizations/' + $route.current.params.id,
+ 'index-pattern': '/management/kibana/objects/savedVisualizations/' + $route.current.params.id,
+ 'index-pattern-field': '/management/kibana/objects/savedVisualizations/' + $route.current.params.id
+ })
+ );
+ }
+ }
+ })
+ .when(`visualize/:tail*?`, {
+ redirectTo: `/${deps.core.injectedMetadata.getInjectedVar('kbnDefaultAppId')}`,
+ });
+ });
+}
diff --git a/src/legacy/core_plugins/kibana/public/visualize/legacy_imports.ts b/src/legacy/core_plugins/kibana/public/visualize/legacy_imports.ts
new file mode 100644
index 0000000000000..b9909e522b571
--- /dev/null
+++ b/src/legacy/core_plugins/kibana/public/visualize/legacy_imports.ts
@@ -0,0 +1,75 @@
+/*
+ * 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.
+ */
+
+/**
+ * The imports in this file are static functions and types which still live in legacy folders and are used
+ * within dashboard. To consolidate them all in one place, they are re-exported from this file. Eventually
+ * this list should become empty. Imports from the top level of shimmed or moved plugins can be imported
+ * directly where they are needed.
+ */
+
+import chrome from 'ui/chrome';
+
+export const legacyChrome = chrome;
+
+// @ts-ignore
+export { AppState, AppStateProvider } from 'ui/state_management/app_state';
+export { State } from 'ui/state_management/state';
+// @ts-ignore
+export { GlobalStateProvider } from 'ui/state_management/global_state';
+// @ts-ignore
+export { StateManagementConfigProvider } from 'ui/state_management/config_provider';
+export { stateMonitorFactory } from 'ui/state_management/state_monitor_factory';
+export { PersistedState } from 'ui/persisted_state';
+
+export { npSetup, npStart } from 'ui/new_platform';
+export { IPrivate } from 'ui/private';
+// @ts-ignore
+export { PrivateProvider } from 'ui/private/private';
+
+export { SavedObjectRegistryProvider } from 'ui/saved_objects';
+export { SavedObjectSaveModal } from 'ui/saved_objects/components/saved_object_save_modal';
+export { showSaveModal } from 'ui/saved_objects/show_saved_object_save_modal';
+
+export { subscribeWithScope } from 'ui/utils/subscribe_with_scope';
+export { migrateLegacyQuery } from 'ui/utils/migrate_legacy_query';
+// @ts-ignore
+export { EventsProvider } from 'ui/events';
+// @ts-ignore
+export { createTopNavDirective, createTopNavHelper } from 'ui/kbn_top_nav/kbn_top_nav';
+// @ts-ignore
+export { PromiseServiceCreator } from 'ui/promises/promises';
+// @ts-ignore
+export { confirmModalFactory } from 'ui/modals/confirm_modal';
+export { configureAppAngularModule, ensureDefaultIndexPattern } from 'ui/legacy_compat';
+export { registerTimefilterWithGlobalStateFactory } from 'ui/timefilter/setup_router';
+// @ts-ignore
+export { VisEditorTypesRegistryProvider } from 'ui/registry/vis_editor_types';
+
+// @ts-ignore
+export { KbnUrlProvider, RedirectWhenMissingProvider } from 'ui/url';
+export { absoluteToParsedUrl } from 'ui/url/absolute_to_parsed_url';
+export { KibanaParsedUrl } from 'ui/url/kibana_parsed_url';
+
+// @ts-ignore
+export { defaultEditor } from 'ui/vis/editors/default/default';
+export { VisType } from 'ui/vis';
+export { wrapInI18nContext } from 'ui/i18n';
+
+export { VisSavedObject } from './embeddable/visualize_embeddable';
diff --git a/src/legacy/core_plugins/kibana/public/visualize/listing/visualize_listing.html b/src/legacy/core_plugins/kibana/public/visualize/listing/visualize_listing.html
index edb7cccbd46a2..4ee8809fab228 100644
--- a/src/legacy/core_plugins/kibana/public/visualize/listing/visualize_listing.html
+++ b/src/legacy/core_plugins/kibana/public/visualize/listing/visualize_listing.html
@@ -14,6 +14,9 @@
is-open="listingController.showNewVisModal"
on-close="listingController.closeNewVisModal"
vis-types-registry="listingController.visTypeRegistry"
+ add-base-path="listingController.addBasePath"
+ ui-settings="listingController.uiSettings"
+ saved-objects="listingController.savedObjects"
>
diff --git a/src/legacy/core_plugins/kibana/public/visualize/listing/visualize_listing.js b/src/legacy/core_plugins/kibana/public/visualize/listing/visualize_listing.js
index f9e3a1a90115a..b1ed5ce81d6ee 100644
--- a/src/legacy/core_plugins/kibana/public/visualize/listing/visualize_listing.js
+++ b/src/legacy/core_plugins/kibana/public/visualize/listing/visualize_listing.js
@@ -24,36 +24,48 @@ import { VisualizeConstants } from '../visualize_constants';
import { i18n } from '@kbn/i18n';
import { getServices } from '../kibana_services';
-
-const {
- addBasePath,
- chrome,
- chromeLegacy,
- SavedObjectRegistryProvider,
- SavedObjectsClientProvider,
- timefilter,
- toastNotifications,
- uiModules,
- wrapInI18nContext,
- visualizations,
-} = getServices();
-
-const app = uiModules.get('app/visualize', ['ngRoute', 'react']);
-app.directive('visualizeListingTable', reactDirective =>
- reactDirective(wrapInI18nContext(VisualizeListingTable))
-);
-app.directive('newVisModal', reactDirective => reactDirective(wrapInI18nContext(NewVisModal)));
+import { wrapInI18nContext } from '../legacy_imports';
+
+export function initListingDirective(app) {
+ app.directive('visualizeListingTable', reactDirective => reactDirective(wrapInI18nContext(VisualizeListingTable)));
+ app.directive('newVisModal', reactDirective =>
+ reactDirective(wrapInI18nContext(NewVisModal), [
+ ['visTypesRegistry', { watchDepth: 'collection' }],
+ ['onClose', { watchDepth: 'reference' }],
+ ['addBasePath', { watchDepth: 'reference' }],
+ ['uiSettings', { watchDepth: 'reference' }],
+ ['savedObjects', { watchDepth: 'reference' }],
+ 'isOpen',
+ ])
+ );
+}
export function VisualizeListingController($injector, createNewVis) {
- const Private = $injector.get('Private');
- const config = $injector.get('config');
+ const {
+ addBasePath,
+ chrome,
+ legacyChrome,
+ savedObjectRegistry,
+ savedObjectsClient,
+ data: {
+ query: {
+ timefilter: { timefilter },
+ },
+ },
+ toastNotifications,
+ uiSettings,
+ visualizations,
+ core: { docLinks, savedObjects },
+ } = getServices();
const kbnUrl = $injector.get('kbnUrl');
- const savedObjectClient = Private(SavedObjectsClientProvider);
timefilter.disableAutoRefreshSelector();
timefilter.disableTimeRangeSelector();
this.showNewVisModal = false;
+ this.addBasePath = addBasePath;
+ this.uiSettings = uiSettings;
+ this.savedObjects = savedObjects;
this.createNewVis = () => {
this.showNewVisModal = true;
@@ -82,14 +94,14 @@ export function VisualizeListingController($injector, createNewVis) {
}
// TODO: Extract this into an external service.
- const services = Private(SavedObjectRegistryProvider).byLoaderPropertiesName;
+ const services = savedObjectRegistry.byLoaderPropertiesName;
const visualizationService = services.visualizations;
this.visTypeRegistry = visualizations.types;
this.fetchItems = filter => {
- const isLabsEnabled = config.get('visualize:enableLabs');
+ const isLabsEnabled = uiSettings.get('visualize:enableLabs');
return visualizationService
- .findListItems(filter, config.get('savedObjects:listingLimit'))
+ .findListItems(filter, uiSettings.get('savedObjects:listingLimit'))
.then(result => {
this.totalItems = result.total;
@@ -103,11 +115,11 @@ export function VisualizeListingController($injector, createNewVis) {
this.deleteSelectedItems = function deleteSelectedItems(selectedItems) {
return Promise.all(
selectedItems.map(item => {
- return savedObjectClient.delete(item.savedObjectType, item.id);
+ return savedObjectsClient.delete(item.savedObjectType, item.id);
})
)
.then(() => {
- chromeLegacy.untrackNavLinksForDeletedSavedObjects(selectedItems.map(item => item.id));
+ legacyChrome.untrackNavLinksForDeletedSavedObjects(selectedItems.map(item => item.id));
})
.catch(error => {
toastNotifications.addError(error, {
@@ -126,7 +138,7 @@ export function VisualizeListingController($injector, createNewVis) {
},
]);
- this.listingLimit = config.get('savedObjects:listingLimit');
+ this.listingLimit = uiSettings.get('savedObjects:listingLimit');
- addHelpMenuToAppChrome(chrome);
+ addHelpMenuToAppChrome(chrome, docLinks);
}
diff --git a/src/legacy/core_plugins/kibana/public/visualize/listing/visualize_listing_table.js b/src/legacy/core_plugins/kibana/public/visualize/listing/visualize_listing_table.js
index efab03303aa80..890fa64af9693 100644
--- a/src/legacy/core_plugins/kibana/public/visualize/listing/visualize_listing_table.js
+++ b/src/legacy/core_plugins/kibana/public/visualize/listing/visualize_listing_table.js
@@ -27,22 +27,21 @@ import { EuiIcon, EuiBetaBadge, EuiLink, EuiButton, EuiEmptyPrompt } from '@elas
import { getServices } from '../kibana_services';
-const { capabilities, toastNotifications, uiSettings } = getServices();
-
class VisualizeListingTable extends Component {
constructor(props) {
super(props);
}
render() {
+ const { visualizeCapabilities, uiSettings, toastNotifications } = getServices();
return (
item.canDelete}
diff --git a/src/legacy/core_plugins/kibana/public/visualize/plugin.ts b/src/legacy/core_plugins/kibana/public/visualize/plugin.ts
new file mode 100644
index 0000000000000..1aa2d70dabea6
--- /dev/null
+++ b/src/legacy/core_plugins/kibana/public/visualize/plugin.ts
@@ -0,0 +1,161 @@
+/*
+ * 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 { i18n } from '@kbn/i18n';
+
+import {
+ CoreSetup,
+ CoreStart,
+ LegacyCoreStart,
+ Plugin,
+ SavedObjectsClientContract,
+} from 'kibana/public';
+
+import { Storage } from '../../../../../plugins/kibana_utils/public';
+import { DataPublicPluginStart } from '../../../../../plugins/data/public';
+import { IEmbeddableStart } from '../../../../../plugins/embeddable/public';
+import { NavigationStart } from '../../../navigation/public';
+import { SharePluginStart } from '../../../../../plugins/share/public';
+import { KibanaLegacySetup } from '../../../../../plugins/kibana_legacy/public';
+import { VisualizationsStart } from '../../../visualizations/public';
+import { VisualizeEmbeddableFactory } from './embeddable/visualize_embeddable_factory';
+import { VISUALIZE_EMBEDDABLE_TYPE } from './embeddable/constants';
+import { VisualizeConstants } from './visualize_constants';
+import { setServices, VisualizeKibanaServices } from './kibana_services';
+import {
+ FeatureCatalogueCategory,
+ HomePublicPluginSetup,
+} from '../../../../../plugins/home/public';
+import { defaultEditor, VisEditorTypesRegistryProvider } from './legacy_imports';
+import { SavedVisualizations } from './types';
+
+export interface LegacyAngularInjectedDependencies {
+ legacyChrome: any;
+ editorTypes: any;
+ savedObjectRegistry: any;
+ savedVisualizations: SavedVisualizations;
+}
+
+export interface VisualizePluginStartDependencies {
+ data: DataPublicPluginStart;
+ embeddables: IEmbeddableStart;
+ navigation: NavigationStart;
+ share: SharePluginStart;
+ visualizations: VisualizationsStart;
+}
+
+export interface VisualizePluginSetupDependencies {
+ __LEGACY: {
+ getAngularDependencies: () => Promise;
+ };
+ home: HomePublicPluginSetup;
+ kibana_legacy: KibanaLegacySetup;
+}
+
+export class VisualizePlugin implements Plugin {
+ private startDependencies: {
+ data: DataPublicPluginStart;
+ embeddables: IEmbeddableStart;
+ navigation: NavigationStart;
+ savedObjectsClient: SavedObjectsClientContract;
+ share: SharePluginStart;
+ visualizations: VisualizationsStart;
+ } | null = null;
+
+ public async setup(
+ core: CoreSetup,
+ { home, kibana_legacy, __LEGACY: { getAngularDependencies } }: VisualizePluginSetupDependencies
+ ) {
+ kibana_legacy.registerLegacyApp({
+ id: 'visualize',
+ title: 'Visualize',
+ mount: async ({ core: contextCore }, params) => {
+ if (this.startDependencies === null) {
+ throw new Error('not started yet');
+ }
+
+ const {
+ savedObjectsClient,
+ embeddables,
+ navigation,
+ visualizations,
+ data,
+ share,
+ } = this.startDependencies;
+
+ const angularDependencies = await getAngularDependencies();
+ const deps: VisualizeKibanaServices = {
+ ...angularDependencies,
+ addBasePath: contextCore.http.basePath.prepend,
+ core: contextCore as LegacyCoreStart,
+ chrome: contextCore.chrome,
+ data,
+ embeddables,
+ getBasePath: core.http.basePath.get,
+ indexPatterns: data.indexPatterns,
+ localStorage: new Storage(localStorage),
+ navigation,
+ savedObjectsClient,
+ savedQueryService: data.query.savedQueries,
+ share,
+ toastNotifications: contextCore.notifications.toasts,
+ uiSettings: contextCore.uiSettings,
+ visualizeCapabilities: contextCore.application.capabilities.visualize,
+ visualizations,
+ };
+ setServices(deps);
+
+ const { renderApp } = await import('./application');
+ return renderApp(params.element, params.appBasePath, deps);
+ },
+ });
+
+ home.featureCatalogue.register({
+ id: 'visualize',
+ title: 'Visualize',
+ description: i18n.translate('kbn.visualize.visualizeDescription', {
+ defaultMessage:
+ 'Create visualizations and aggregate data stores in your Elasticsearch indices.',
+ }),
+ icon: 'visualizeApp',
+ path: `/app/kibana#${VisualizeConstants.LANDING_PAGE_PATH}`,
+ showOnHomePage: true,
+ category: FeatureCatalogueCategory.DATA,
+ });
+
+ VisEditorTypesRegistryProvider.register(defaultEditor);
+ }
+
+ public start(
+ { savedObjects: { client: savedObjectsClient } }: CoreStart,
+ { embeddables, navigation, data, share, visualizations }: VisualizePluginStartDependencies
+ ) {
+ this.startDependencies = {
+ data,
+ embeddables,
+ navigation,
+ savedObjectsClient,
+ share,
+ visualizations,
+ };
+
+ const embeddableFactory = new VisualizeEmbeddableFactory(visualizations.types);
+ embeddables.registerEmbeddableFactory(VISUALIZE_EMBEDDABLE_TYPE, embeddableFactory);
+ }
+}
diff --git a/src/legacy/core_plugins/kibana/public/visualize/types.d.ts b/src/legacy/core_plugins/kibana/public/visualize/types.d.ts
index c83f7f5a5da8b..b6a3981215384 100644
--- a/src/legacy/core_plugins/kibana/public/visualize/types.d.ts
+++ b/src/legacy/core_plugins/kibana/public/visualize/types.d.ts
@@ -17,7 +17,7 @@
* under the License.
*/
-import { VisSavedObject } from './kibana_services';
+import { VisSavedObject } from './legacy_imports';
export interface SavedVisualizations {
urlFor: (id: string) => string;
diff --git a/src/legacy/core_plugins/kibana/public/dashboard/dashboard_empty_screen_directive.ts b/src/legacy/core_plugins/kibana/public/visualize/visualize_app.ts
similarity index 67%
rename from src/legacy/core_plugins/kibana/public/dashboard/dashboard_empty_screen_directive.ts
rename to src/legacy/core_plugins/kibana/public/visualize/visualize_app.ts
index 5ebefd817ca4a..c64287a0e63b8 100644
--- a/src/legacy/core_plugins/kibana/public/dashboard/dashboard_empty_screen_directive.ts
+++ b/src/legacy/core_plugins/kibana/public/visualize/visualize_app.ts
@@ -16,15 +16,16 @@
* specific language governing permissions and limitations
* under the License.
*/
+
+import { IModule } from 'angular';
+import { VisualizeKibanaServices } from './kibana_services';
+
+// @ts-ignore
+import { initEditorDirective } from './editor/editor';
// @ts-ignore
-import angular from 'angular';
-import { DashboardEmptyScreen } from './dashboard_empty_screen';
+import { initListingDirective } from './listing/visualize_listing';
-angular
- .module('app/dashboard/emptyScreen', ['react'])
- .directive('dashboardEmptyScreen', function(reactDirective: any) {
- return reactDirective(DashboardEmptyScreen, [
- ['showLinkToVisualize', { watchDepth: 'value' }],
- ['onLinkClick', { watchDepth: 'reference' }],
- ]);
- });
+export function initVisualizeAppDirective(app: IModule, deps: VisualizeKibanaServices) {
+ initEditorDirective(app, deps);
+ initListingDirective(app);
+}
diff --git a/src/legacy/core_plugins/kibana/public/visualize/wizard/__snapshots__/new_vis_modal.test.tsx.snap b/src/legacy/core_plugins/kibana/public/visualize/wizard/__snapshots__/new_vis_modal.test.tsx.snap
index 4aa614b68ea23..04b7cddc75289 100644
--- a/src/legacy/core_plugins/kibana/public/visualize/wizard/__snapshots__/new_vis_modal.test.tsx.snap
+++ b/src/legacy/core_plugins/kibana/public/visualize/wizard/__snapshots__/new_vis_modal.test.tsx.snap
@@ -2,6 +2,7 @@
exports[`NewVisModal filter for visualization types should render as expected 1`] = `
@@ -1287,6 +1308,7 @@ exports[`NewVisModal filter for visualization types should render as expected 1`
exports[`NewVisModal should render as expected 1`] = `
diff --git a/src/legacy/core_plugins/kibana/public/visualize/wizard/new_vis_modal.test.tsx b/src/legacy/core_plugins/kibana/public/visualize/wizard/new_vis_modal.test.tsx
index 99d9590e750fd..4eafd06c7bb20 100644
--- a/src/legacy/core_plugins/kibana/public/visualize/wizard/new_vis_modal.test.tsx
+++ b/src/legacy/core_plugins/kibana/public/visualize/wizard/new_vis_modal.test.tsx
@@ -20,33 +20,18 @@
import React from 'react';
import { mountWithIntl } from 'test_utils/enzyme_helpers';
-import { NewVisModal } from './new_vis_modal';
-import { VisType } from '../kibana_services';
+import { VisType } from '../legacy_imports';
import { TypesStart } from '../../../../visualizations/public/np_ready/public/types';
-jest.mock('../kibana_services', () => {
- const mock = {
- addBasePath: jest.fn(path => `root${path}`),
- uiSettings: { get: jest.fn() },
- createUiStatsReporter: () => jest.fn(),
- };
-
- return {
- getServices: () => mock,
- VisType: {},
- METRIC_TYPE: 'metricType',
- };
-});
-
-import { getServices } from '../kibana_services';
+jest.mock('../legacy_imports', () => ({
+ State: () => null,
+ AppState: () => null,
+}));
-beforeEach(() => {
- jest.clearAllMocks();
-});
+import { NewVisModal } from './new_vis_modal';
+import { SavedObjectsStart } from 'kibana/public';
describe('NewVisModal', () => {
- const settingsGet = getServices().uiSettings.get as jest.Mock;
-
const defaultVisTypeParams = {
hidden: false,
visualization: class Controller {
@@ -76,17 +61,38 @@ describe('NewVisModal', () => {
},
getAliases: () => [],
};
+ const addBasePath = (url: string) => `testbasepath${url}`;
+ const settingsGet = jest.fn();
+ const uiSettings: any = { get: settingsGet };
+
+ beforeEach(() => {
+ jest.clearAllMocks();
+ });
it('should render as expected', () => {
const wrapper = mountWithIntl(
- null} visTypesRegistry={visTypes} />
+ null}
+ visTypesRegistry={visTypes}
+ addBasePath={addBasePath}
+ uiSettings={uiSettings}
+ savedObjects={{} as SavedObjectsStart}
+ />
);
expect(wrapper).toMatchSnapshot();
});
it('should show a button for regular visualizations', () => {
const wrapper = mountWithIntl(
- null} visTypesRegistry={visTypes} />
+ null}
+ visTypesRegistry={visTypes}
+ addBasePath={addBasePath}
+ uiSettings={uiSettings}
+ savedObjects={{} as SavedObjectsStart}
+ />
);
expect(wrapper.find('[data-test-subj="visType-vis"]').exists()).toBe(true);
});
@@ -95,7 +101,14 @@ describe('NewVisModal', () => {
it('should open the editor for visualizations without search', () => {
window.location.assign = jest.fn();
const wrapper = mountWithIntl(
- null} visTypesRegistry={visTypes} />
+ null}
+ visTypesRegistry={visTypes}
+ addBasePath={addBasePath}
+ uiSettings={uiSettings}
+ savedObjects={{} as SavedObjectsStart}
+ />
);
const visButton = wrapper.find('button[data-test-subj="visType-vis"]');
visButton.simulate('click');
@@ -110,6 +123,9 @@ describe('NewVisModal', () => {
onClose={() => null}
visTypesRegistry={visTypes}
editorParams={['foo=true', 'bar=42']}
+ addBasePath={addBasePath}
+ uiSettings={uiSettings}
+ savedObjects={{} as SavedObjectsStart}
/>
);
const visButton = wrapper.find('button[data-test-subj="visType-vis"]');
@@ -121,7 +137,14 @@ describe('NewVisModal', () => {
describe('filter for visualization types', () => {
it('should render as expected', () => {
const wrapper = mountWithIntl(
- null} visTypesRegistry={visTypes} />
+ null}
+ visTypesRegistry={visTypes}
+ addBasePath={addBasePath}
+ uiSettings={uiSettings}
+ savedObjects={{} as SavedObjectsStart}
+ />
);
const searchBox = wrapper.find('input[data-test-subj="filterVisType"]');
searchBox.simulate('change', { target: { value: 'with' } });
@@ -133,7 +156,14 @@ describe('NewVisModal', () => {
it('should not show experimental visualizations if visualize:enableLabs is false', () => {
settingsGet.mockReturnValue(false);
const wrapper = mountWithIntl(
- null} visTypesRegistry={visTypes} />
+ null}
+ visTypesRegistry={visTypes}
+ addBasePath={addBasePath}
+ uiSettings={uiSettings}
+ savedObjects={{} as SavedObjectsStart}
+ />
);
expect(wrapper.find('[data-test-subj="visType-visExp"]').exists()).toBe(false);
});
@@ -141,7 +171,14 @@ describe('NewVisModal', () => {
it('should show experimental visualizations if visualize:enableLabs is true', () => {
settingsGet.mockReturnValue(true);
const wrapper = mountWithIntl(
- null} visTypesRegistry={visTypes} />
+ null}
+ visTypesRegistry={visTypes}
+ addBasePath={addBasePath}
+ uiSettings={uiSettings}
+ savedObjects={{} as SavedObjectsStart}
+ />
);
expect(wrapper.find('[data-test-subj="visType-visExp"]').exists()).toBe(true);
});
diff --git a/src/legacy/core_plugins/kibana/public/visualize/wizard/new_vis_modal.tsx b/src/legacy/core_plugins/kibana/public/visualize/wizard/new_vis_modal.tsx
index 420f0e5198056..0402265610fb1 100644
--- a/src/legacy/core_plugins/kibana/public/visualize/wizard/new_vis_modal.tsx
+++ b/src/legacy/core_plugins/kibana/public/visualize/wizard/new_vis_modal.tsx
@@ -22,20 +22,22 @@ import React from 'react';
import { EuiModal, EuiOverlayMask } from '@elastic/eui';
import { i18n } from '@kbn/i18n';
+import { IUiSettingsClient, SavedObjectsStart } from 'kibana/public';
+import { VisType } from '../legacy_imports';
import { VisualizeConstants } from '../visualize_constants';
+import { createUiStatsReporter, METRIC_TYPE } from '../../../../ui_metric/public';
import { SearchSelection } from './search_selection';
import { TypeSelection } from './type_selection';
import { TypesStart, VisTypeAlias } from '../../../../visualizations/public/np_ready/public/types';
-import { getServices, METRIC_TYPE, VisType } from '../kibana_services';
-
-const { addBasePath, createUiStatsReporter, uiSettings } = getServices();
-
interface TypeSelectionProps {
isOpen: boolean;
onClose: () => void;
visTypesRegistry: TypesStart;
editorParams?: string[];
+ addBasePath: (path: string) => string;
+ uiSettings: IUiSettingsClient;
+ savedObjects: SavedObjectsStart;
}
interface TypeSelectionState {
@@ -55,7 +57,7 @@ class NewVisModal extends React.Component
-
+
) : (
);
@@ -124,7 +132,7 @@ class NewVisModal extends React.Component void;
visType: VisType;
+ uiSettings: IUiSettingsClient;
+ savedObjects: SavedObjectsStart;
}
export class SearchSelection extends React.Component {
@@ -52,7 +54,7 @@ export class SearchSelection extends React.Component {
- {
},
]}
fixedPageSize={this.fixedPageSize}
+ uiSettings={this.props.uiSettings}
+ savedObjects={this.props.savedObjects}
/>
diff --git a/src/legacy/core_plugins/kibana/public/visualize/wizard/show_new_vis.tsx b/src/legacy/core_plugins/kibana/public/visualize/wizard/show_new_vis.tsx
index fa2ca6747bc40..88838e16c40e2 100644
--- a/src/legacy/core_plugins/kibana/public/visualize/wizard/show_new_vis.tsx
+++ b/src/legacy/core_plugins/kibana/public/visualize/wizard/show_new_vis.tsx
@@ -20,7 +20,8 @@
import React from 'react';
import ReactDOM from 'react-dom';
-import { I18nContext } from 'ui/i18n';
+import { I18nProvider } from '@kbn/i18n/react';
+import { IUiSettingsClient, SavedObjectsStart } from 'kibana/public';
import { NewVisModal } from './new_vis_modal';
import { TypesStart } from '../../../../visualizations/public/np_ready/public/types';
@@ -30,7 +31,10 @@ interface ShowNewVisModalParams {
export function showNewVisModal(
visTypeRegistry: TypesStart,
- { editorParams = [] }: ShowNewVisModalParams = {}
+ { editorParams = [] }: ShowNewVisModalParams = {},
+ addBasePath: (path: string) => string,
+ uiSettings: IUiSettingsClient,
+ savedObjects: SavedObjectsStart
) {
const container = document.createElement('div');
const onClose = () => {
@@ -40,14 +44,17 @@ export function showNewVisModal(
document.body.appendChild(container);
const element = (
-
+
-
+
);
ReactDOM.render(element, container);
}
diff --git a/src/legacy/core_plugins/kibana/public/visualize/wizard/type_selection/new_vis_help.test.tsx b/src/legacy/core_plugins/kibana/public/visualize/wizard/type_selection/new_vis_help.test.tsx
index 382f475669f5d..3093499a030c8 100644
--- a/src/legacy/core_plugins/kibana/public/visualize/wizard/type_selection/new_vis_help.test.tsx
+++ b/src/legacy/core_plugins/kibana/public/visualize/wizard/type_selection/new_vis_help.test.tsx
@@ -21,18 +21,6 @@ import React from 'react';
import { shallowWithIntl } from 'test_utils/enzyme_helpers';
import { NewVisHelp } from './new_vis_help';
-jest.mock('../../kibana_services', () => {
- return {
- getServices: () => ({
- addBasePath: jest.fn((url: string) => `testbasepath${url}`),
- }),
- };
-});
-
-beforeEach(() => {
- jest.clearAllMocks();
-});
-
describe('NewVisHelp', () => {
it('should render as expected', () => {
expect(
@@ -53,6 +41,7 @@ describe('NewVisHelp', () => {
stage: 'production',
},
]}
+ addBasePath={(url: string) => `testbasepath${url}`}
/>
)
).toMatchInlineSnapshot(`
diff --git a/src/legacy/core_plugins/kibana/public/visualize/wizard/type_selection/new_vis_help.tsx b/src/legacy/core_plugins/kibana/public/visualize/wizard/type_selection/new_vis_help.tsx
index 44c36f7d17d55..107cbc0e754b5 100644
--- a/src/legacy/core_plugins/kibana/public/visualize/wizard/type_selection/new_vis_help.tsx
+++ b/src/legacy/core_plugins/kibana/public/visualize/wizard/type_selection/new_vis_help.tsx
@@ -22,10 +22,9 @@ import React, { Fragment } from 'react';
import { EuiText, EuiButton } from '@elastic/eui';
import { VisTypeAliasListEntry } from './type_selection';
-import { getServices } from '../../kibana_services';
-
interface Props {
promotedTypes: VisTypeAliasListEntry[];
+ addBasePath: (path: string) => string;
}
export function NewVisHelp(props: Props) {
@@ -43,7 +42,7 @@ export function NewVisHelp(props: Props) {
{t.promotion!.description}
string;
onVisTypeSelected: (visType: VisType | VisTypeAlias) => void;
visTypesRegistry: TypesStart;
showExperimental: boolean;
@@ -153,6 +154,7 @@ class TypeSelection extends React.Component
t.promotion)}
+ addBasePath={this.props.addBasePath}
/>
)}
diff --git a/src/legacy/core_plugins/kibana/server/routes/api/suggestions/register_value_suggestions.js b/src/legacy/core_plugins/kibana/server/routes/api/suggestions/register_value_suggestions.js
index 4ffe790bd51a1..1f5ed443fee80 100644
--- a/src/legacy/core_plugins/kibana/server/routes/api/suggestions/register_value_suggestions.js
+++ b/src/legacy/core_plugins/kibana/server/routes/api/suggestions/register_value_suggestions.js
@@ -18,6 +18,7 @@
*/
import { get, map } from 'lodash';
+import { abortableRequestHandler } from '../../../../../elasticsearch/lib/abortable_request_handler';
export function registerValueSuggestions(server) {
const serverConfig = server.config();
@@ -26,7 +27,7 @@ export function registerValueSuggestions(server) {
server.route({
path: '/api/kibana/suggestions/values/{index}',
method: ['POST'],
- handler: async function (req) {
+ handler: abortableRequestHandler(async function (signal, req) {
const { index } = req.params;
const { field: fieldName, query, boolFilter } = req.payload;
const { callWithRequest } = server.plugins.elasticsearch.getCluster('data');
@@ -46,7 +47,7 @@ export function registerValueSuggestions(server) {
);
try {
- const response = await callWithRequest(req, 'search', { index, body });
+ const response = await callWithRequest(req, 'search', { index, body }, { signal });
const buckets = get(response, 'aggregations.suggestions.buckets')
|| get(response, 'aggregations.nestedSuggestions.suggestions.buckets')
|| [];
@@ -55,7 +56,7 @@ export function registerValueSuggestions(server) {
} catch (error) {
throw server.plugins.elasticsearch.handleESError(error);
}
- },
+ }),
});
}
diff --git a/src/legacy/core_plugins/kibana/server/tutorials/apm/index_pattern.json b/src/legacy/core_plugins/kibana/server/tutorials/apm/index_pattern.json
index 69a165c09c2f9..9001613623ccb 100644
--- a/src/legacy/core_plugins/kibana/server/tutorials/apm/index_pattern.json
+++ b/src/legacy/core_plugins/kibana/server/tutorials/apm/index_pattern.json
@@ -1,7 +1,7 @@
{
"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.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\":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\":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\":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\":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\":\"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\":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\":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\":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\":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.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.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\":\"file.accessed\",\"scripted\":false,\"searchable\":true,\"type\":\"date\"},{\"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.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.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\":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\":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.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\":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\":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\":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\":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\":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\":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\":\"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.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\":\"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.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\":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\":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\":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\":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\":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.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.size\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"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\":\"process.args\",\"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\":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\":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\":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\":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\":\"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\":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\":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\":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\":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\":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\":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\":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\":\"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\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"url.original\",\"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\":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\":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\":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\":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\":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\":\"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\":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\":\"experimental\",\"scripted\":false,\"searchable\":true},{\"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\":\"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\":\"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\":\"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\":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\"}]",
+ "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\":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\":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\":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\":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\":\"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\":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\":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\":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\":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.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.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\":\"file.accessed\",\"scripted\":false,\"searchable\":true,\"type\":\"date\"},{\"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.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.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\":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\":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.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\":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\":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\":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\":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\":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\":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\":\"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.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\":\"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.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\":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\":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\":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\":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\":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.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.size\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"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\":\"process.args\",\"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\":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\":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\":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\":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\":\"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\":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\":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\":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\":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\":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\":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\":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\":\"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\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"url.original\",\"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\":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\":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\":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\":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\":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\":\"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\":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\":\"experimental\",\"scripted\":false,\"searchable\":true},{\"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\":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\":\"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\":\"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\":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"
},
diff --git a/src/legacy/core_plugins/management/index.ts b/src/legacy/core_plugins/management/index.ts
new file mode 100644
index 0000000000000..65601b5371815
--- /dev/null
+++ b/src/legacy/core_plugins/management/index.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 { resolve } from 'path';
+import { Legacy } from '../../../../kibana';
+
+// eslint-disable-next-line import/no-default-export
+export default function ManagementPlugin(kibana: any) {
+ const config: Legacy.PluginSpecOptions = {
+ id: 'management',
+ publicDir: resolve(__dirname, 'public'),
+ config: (Joi: any) => {
+ return Joi.object({
+ enabled: Joi.boolean().default(true),
+ }).default();
+ },
+ init: (server: Legacy.Server) => ({}),
+ };
+
+ return new kibana.Plugin(config);
+}
diff --git a/src/legacy/core_plugins/management/package.json b/src/legacy/core_plugins/management/package.json
new file mode 100644
index 0000000000000..77d33a7bce3b6
--- /dev/null
+++ b/src/legacy/core_plugins/management/package.json
@@ -0,0 +1,5 @@
+{
+ "name": "management",
+ "version": "kibana"
+}
+
\ No newline at end of file
diff --git a/src/legacy/ui/public/management/saved_objects_management/index.ts b/src/legacy/core_plugins/management/public/index.ts
similarity index 72%
rename from src/legacy/ui/public/management/saved_objects_management/index.ts
rename to src/legacy/core_plugins/management/public/index.ts
index c7223a859ee37..3d64b6d2aa2bb 100644
--- a/src/legacy/ui/public/management/saved_objects_management/index.ts
+++ b/src/legacy/core_plugins/management/public/index.ts
@@ -17,13 +17,24 @@
* under the License.
*/
-export { SavedObjectsManagementActionRegistry } from './saved_objects_management_action_registry';
+/**
+ * Static np-ready code, re-exported here so consumers can import from
+ * `src/legacy/core_plugins/management/public`
+ *
+ * @public
+ */
+
export {
+ ManagementSetup,
+ ManagementStart,
+ plugin,
+ IndexPatternCreationConfig,
+ IndexPatternListConfig,
SavedObjectsManagementAction,
SavedObjectsManagementRecord,
- SavedObjectsManagementRecordReference,
-} from './saved_objects_management_action';
+} from './np_ready';
+
export {
processImportResponse,
ProcessedImportResponse,
-} from '../../../../core_plugins/kibana/public/management/sections/objects/lib/process_import_response';
+} from '../../kibana/public/management/sections/objects/lib/process_import_response';
diff --git a/src/legacy/core_plugins/management/public/legacy.ts b/src/legacy/core_plugins/management/public/legacy.ts
new file mode 100644
index 0000000000000..7c17f0c6bddc0
--- /dev/null
+++ b/src/legacy/core_plugins/management/public/legacy.ts
@@ -0,0 +1,45 @@
+/*
+ * 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.
+ */
+
+/**
+ * New Platform Shim
+ *
+ * In this file, we import any legacy dependencies we have, and shim them into
+ * our plugin by manually constructing the values that the new platform will
+ * eventually be passing to the `setup/start` method of our plugin definition.
+ *
+ * The idea is that our `plugin.ts` can stay "pure" and not contain any legacy
+ * world code. Then when it comes time to migrate to the new platform, we can
+ * simply delete this shim file.
+ *
+ * We are also calling `setup/start` here and exporting our public contract so that
+ * other legacy plugins are able to import from '../core_plugins/visualizations/legacy'
+ * and receive the response value of the `setup/start` contract, mimicking the
+ * data that will eventually be injected by the new platform.
+ */
+
+import { PluginInitializerContext } from 'src/core/public';
+import { npSetup, npStart } from 'ui/new_platform';
+
+import { plugin } from '.';
+
+const pluginInstance = plugin({} as PluginInitializerContext);
+
+export const setup = pluginInstance.setup(npSetup.core, {});
+export const start = pluginInstance.start(npStart.core, {});
diff --git a/src/legacy/core_plugins/management/public/np_ready/index.ts b/src/legacy/core_plugins/management/public/np_ready/index.ts
new file mode 100644
index 0000000000000..ec93516df8349
--- /dev/null
+++ b/src/legacy/core_plugins/management/public/np_ready/index.ts
@@ -0,0 +1,47 @@
+/*
+ * 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.
+ */
+
+/**
+ * Management Plugin - public
+ *
+ * This is the entry point for the entire client-side public contract of the plugin.
+ * If something is not explicitly exported here, you can safely assume it is private
+ * to the plugin and not considered stable.
+ *
+ * All stateful contracts will be injected by the platform at runtime, and are defined
+ * in the setup/start interfaces in `plugin.ts`. The remaining items exported here are
+ * either types, or static code.
+ */
+import { PluginInitializerContext } from 'src/core/public';
+import { ManagementPlugin } from './plugin';
+export { ManagementSetup, ManagementStart } from './plugin';
+
+export function plugin(initializerContext: PluginInitializerContext) {
+ return new ManagementPlugin(initializerContext);
+}
+
+export {
+ IndexPatternCreationConfig,
+ IndexPatternListConfig,
+} from './services/index_pattern_management';
+
+export {
+ SavedObjectsManagementAction,
+ SavedObjectsManagementRecord,
+} from './services/saved_objects_management';
diff --git a/src/legacy/core_plugins/management/public/np_ready/mocks.ts b/src/legacy/core_plugins/management/public/np_ready/mocks.ts
new file mode 100644
index 0000000000000..13a0cf4c891a3
--- /dev/null
+++ b/src/legacy/core_plugins/management/public/np_ready/mocks.ts
@@ -0,0 +1,66 @@
+/*
+ * 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 { PluginInitializerContext } from 'src/core/public';
+import { coreMock } from '../../../../../core/public/mocks';
+import { ManagementSetup, ManagementStart, ManagementPlugin } from './plugin';
+
+const createSetupContract = (): ManagementSetup => ({
+ indexPattern: {
+ creation: {
+ add: jest.fn(),
+ getType: jest.fn(),
+ getIndexPatternCreationOptions: jest.fn(),
+ } as any,
+ list: {
+ add: jest.fn(),
+ getIndexPatternTags: jest.fn(),
+ getFieldInfo: jest.fn(),
+ areScriptedFieldsEnabled: jest.fn(),
+ } as any,
+ },
+ savedObjects: {
+ registry: {
+ register: jest.fn(),
+ has: jest.fn(),
+ get: jest.fn(() => []),
+ },
+ },
+});
+
+const createStartContract = (): ManagementStart => ({});
+
+const createInstance = async () => {
+ const plugin = new ManagementPlugin({} as PluginInitializerContext);
+
+ const setup = plugin.setup(coreMock.createSetup(), {});
+ const doStart = () => plugin.start(coreMock.createStart(), {});
+
+ return {
+ plugin,
+ setup,
+ doStart,
+ };
+};
+
+export const mockManagementPlugin = {
+ createSetupContract,
+ createStartContract,
+ createInstance,
+};
diff --git a/src/legacy/core_plugins/management/public/np_ready/plugin.ts b/src/legacy/core_plugins/management/public/np_ready/plugin.ts
new file mode 100644
index 0000000000000..032a46439ba55
--- /dev/null
+++ b/src/legacy/core_plugins/management/public/np_ready/plugin.ts
@@ -0,0 +1,67 @@
+/*
+ * 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 { PluginInitializerContext, CoreSetup, CoreStart, Plugin } from 'src/core/public';
+import { IndexPatternManagementService, IndexPatternManagementSetup } from './services';
+import {
+ SavedObjectsManagementService,
+ SavedObjectsManagementServiceSetup,
+} from './services/saved_objects_management';
+
+// eslint-disable-next-line @typescript-eslint/no-empty-interface
+interface ManagementPluginSetupDependencies {}
+
+// eslint-disable-next-line @typescript-eslint/no-empty-interface
+interface ManagementPluginStartDependencies {}
+
+export interface ManagementSetup {
+ indexPattern: IndexPatternManagementSetup;
+ savedObjects: SavedObjectsManagementServiceSetup;
+}
+
+// eslint-disable-next-line @typescript-eslint/no-empty-interface
+export interface ManagementStart {}
+
+export class ManagementPlugin
+ implements
+ Plugin<
+ ManagementSetup,
+ ManagementStart,
+ ManagementPluginSetupDependencies,
+ ManagementPluginStartDependencies
+ > {
+ private readonly indexPattern = new IndexPatternManagementService();
+ private readonly savedObjects = new SavedObjectsManagementService();
+
+ constructor(initializerContext: PluginInitializerContext) {}
+
+ public setup(core: CoreSetup, deps: ManagementPluginSetupDependencies) {
+ return {
+ indexPattern: this.indexPattern.setup({ httpClient: core.http }),
+ savedObjects: this.savedObjects.setup(),
+ };
+ }
+
+ public start(core: CoreStart, plugins: ManagementPluginStartDependencies) {
+ return {};
+ }
+
+ public stop() {
+ this.indexPattern.stop();
+ }
+}
diff --git a/src/legacy/core_plugins/management/public/np_ready/services/index.ts b/src/legacy/core_plugins/management/public/np_ready/services/index.ts
new file mode 100644
index 0000000000000..4d55fce3d8a7d
--- /dev/null
+++ b/src/legacy/core_plugins/management/public/np_ready/services/index.ts
@@ -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.
+ */
+
+export * from './index_pattern_management';
+export * from './saved_objects_management';
diff --git a/src/legacy/ui/public/management/index_pattern_creation/index_pattern_creation_config.js b/src/legacy/core_plugins/management/public/np_ready/services/index_pattern_management/creation/config.ts
similarity index 55%
rename from src/legacy/ui/public/management/index_pattern_creation/index_pattern_creation_config.js
rename to src/legacy/core_plugins/management/public/np_ready/services/index_pattern_management/creation/config.ts
index 9cf1e6c4ed373..0598c88c80ba7 100644
--- a/src/legacy/ui/public/management/index_pattern_creation/index_pattern_creation_config.js
+++ b/src/legacy/core_plugins/management/public/np_ready/services/index_pattern_management/creation/config.ts
@@ -19,17 +19,39 @@
import { i18n } from '@kbn/i18n';
-const indexPatternTypeName = i18n.translate('common.ui.management.editIndexPattern.createIndex.defaultTypeName',
- { defaultMessage: 'index pattern' });
-
-const indexPatternButtonText = i18n.translate('common.ui.management.editIndexPattern.createIndex.defaultButtonText',
- { defaultMessage: 'Standard index pattern' });
-
-const indexPatternButtonDescription = i18n.translate('common.ui.management.editIndexPattern.createIndex.defaultButtonDescription',
- { defaultMessage: 'Perform full aggregations against any data' });
+const indexPatternTypeName = i18n.translate(
+ 'management.editIndexPattern.createIndex.defaultTypeName',
+ { defaultMessage: 'index pattern' }
+);
+
+const indexPatternButtonText = i18n.translate(
+ 'management.editIndexPattern.createIndex.defaultButtonText',
+ { defaultMessage: 'Standard index pattern' }
+);
+
+const indexPatternButtonDescription = i18n.translate(
+ 'management.editIndexPattern.createIndex.defaultButtonDescription',
+ { defaultMessage: 'Perform full aggregations against any data' }
+);
+
+export type UrlHandler = (url: string) => void;
+
+export interface IndexPatternCreationOption {
+ text: string;
+ description: string;
+ testSubj: string;
+ onClick: () => void;
+ isBeta?: boolean;
+}
export class IndexPatternCreationConfig {
- static key = 'default';
+ public readonly key = 'default';
+
+ protected type?: string;
+ protected name: string;
+ protected showSystemIndices: boolean;
+ protected httpClient: object | null;
+ protected isBeta: boolean;
constructor({
type = undefined,
@@ -37,6 +59,12 @@ export class IndexPatternCreationConfig {
showSystemIndices = true,
httpClient = null,
isBeta = false,
+ }: {
+ type?: string;
+ name?: string;
+ showSystemIndices?: boolean;
+ httpClient?: object | null;
+ isBeta?: boolean;
}) {
this.type = type;
this.name = name;
@@ -45,7 +73,9 @@ export class IndexPatternCreationConfig {
this.isBeta = isBeta;
}
- async getIndexPatternCreationOption(urlHandler) {
+ public async getIndexPatternCreationOption(
+ urlHandler: UrlHandler
+ ): Promise {
return {
text: indexPatternButtonText,
description: indexPatternButtonDescription,
@@ -56,39 +86,39 @@ export class IndexPatternCreationConfig {
};
}
- getIndexPatternType = () => {
+ public getIndexPatternType() {
return this.type;
}
- getIndexPatternName = () => {
+ public getIndexPatternName() {
return this.name;
}
- getIsBeta = () => {
+ public getIsBeta() {
return this.isBeta;
}
- getShowSystemIndices = () => {
+ public getShowSystemIndices() {
return this.showSystemIndices;
}
- getIndexTags() {
+ public getIndexTags() {
return [];
}
- checkIndicesForErrors = () => {
+ public checkIndicesForErrors() {
return undefined;
}
- getIndexPatternMappings = () => {
+ public getIndexPatternMappings() {
return {};
}
- renderPrompt = () => {
+ public renderPrompt() {
return null;
}
- getFetchForWildcardOptions = () => {
+ public getFetchForWildcardOptions() {
return {};
}
}
diff --git a/src/legacy/core_plugins/management/public/np_ready/services/index_pattern_management/creation/index.ts b/src/legacy/core_plugins/management/public/np_ready/services/index_pattern_management/creation/index.ts
new file mode 100644
index 0000000000000..84c4c28aa2260
--- /dev/null
+++ b/src/legacy/core_plugins/management/public/np_ready/services/index_pattern_management/creation/index.ts
@@ -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.
+ */
+
+export { IndexPatternCreationConfig } from './config';
+export { IndexPatternCreationManager } from './manager';
diff --git a/src/legacy/core_plugins/management/public/np_ready/services/index_pattern_management/creation/manager.ts b/src/legacy/core_plugins/management/public/np_ready/services/index_pattern_management/creation/manager.ts
new file mode 100644
index 0000000000000..605ffdd6f2134
--- /dev/null
+++ b/src/legacy/core_plugins/management/public/np_ready/services/index_pattern_management/creation/manager.ts
@@ -0,0 +1,61 @@
+/*
+ * 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 { HttpServiceBase } from '../../../../../../../../core/public';
+import { IndexPatternCreationConfig, UrlHandler, IndexPatternCreationOption } from './config';
+
+export class IndexPatternCreationManager {
+ private configs: IndexPatternCreationConfig[];
+
+ constructor(private readonly httpClient: HttpServiceBase) {
+ this.configs = [];
+ }
+
+ public add(Config: typeof IndexPatternCreationConfig) {
+ const config = new Config({ httpClient: this.httpClient });
+ if (this.configs.findIndex(c => c.key === config.key) !== -1) {
+ throw new Error(`${config.key} exists in IndexPatternCreationManager.`);
+ }
+ this.configs.push(config);
+ }
+
+ public getType(key: string | undefined): IndexPatternCreationConfig | null {
+ if (key) {
+ const index = this.configs.findIndex(config => config.key === key);
+ return this.configs[index] || null;
+ } else {
+ return this.getType('default');
+ }
+ }
+
+ public async getIndexPatternCreationOptions(urlHandler: UrlHandler) {
+ const options: IndexPatternCreationOption[] = [];
+ await Promise.all(
+ this.configs.map(async config => {
+ const option = config.getIndexPatternCreationOption
+ ? await config.getIndexPatternCreationOption(urlHandler)
+ : null;
+ if (option) {
+ options.push(option);
+ }
+ })
+ );
+ return options;
+ }
+}
diff --git a/src/legacy/core_plugins/management/public/np_ready/services/index_pattern_management/index.ts b/src/legacy/core_plugins/management/public/np_ready/services/index_pattern_management/index.ts
new file mode 100644
index 0000000000000..2abe13eb0e292
--- /dev/null
+++ b/src/legacy/core_plugins/management/public/np_ready/services/index_pattern_management/index.ts
@@ -0,0 +1,22 @@
+/*
+ * 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 * from './index_pattern_management_service';
+export { IndexPatternCreationConfig } from './creation';
+export { IndexPatternListConfig } from './list';
diff --git a/src/legacy/core_plugins/management/public/np_ready/services/index_pattern_management/index_pattern_management_service.ts b/src/legacy/core_plugins/management/public/np_ready/services/index_pattern_management/index_pattern_management_service.ts
new file mode 100644
index 0000000000000..b9e07564a324c
--- /dev/null
+++ b/src/legacy/core_plugins/management/public/np_ready/services/index_pattern_management/index_pattern_management_service.ts
@@ -0,0 +1,53 @@
+/*
+ * 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 { HttpServiceBase } from '../../../../../../../core/public';
+import { IndexPatternCreationManager, IndexPatternCreationConfig } from './creation';
+import { IndexPatternListManager, IndexPatternListConfig } from './list';
+
+interface SetupDependencies {
+ httpClient: HttpServiceBase;
+}
+
+/**
+ * Index patterns management service
+ *
+ * @internal
+ */
+export class IndexPatternManagementService {
+ public setup({ httpClient }: SetupDependencies) {
+ const creation = new IndexPatternCreationManager(httpClient);
+ const list = new IndexPatternListManager();
+
+ creation.add(IndexPatternCreationConfig);
+ list.add(IndexPatternListConfig);
+
+ return {
+ creation,
+ list,
+ };
+ }
+
+ public stop() {
+ // nothing to do here yet.
+ }
+}
+
+/** @internal */
+export type IndexPatternManagementSetup = ReturnType;
diff --git a/src/legacy/ui/public/utils/base_object.ts b/src/legacy/core_plugins/management/public/np_ready/services/index_pattern_management/list/config.ts
similarity index 50%
rename from src/legacy/ui/public/utils/base_object.ts
rename to src/legacy/core_plugins/management/public/np_ready/services/index_pattern_management/list/config.ts
index 63c7ebf6de5bb..dd4d77a681171 100644
--- a/src/legacy/ui/public/utils/base_object.ts
+++ b/src/legacy/core_plugins/management/public/np_ready/services/index_pattern_management/list/config.ts
@@ -17,31 +17,35 @@
* under the License.
*/
-import angular from 'angular';
-import _ from 'lodash';
-// @ts-ignore -- awaiting https://github.com/w33ble/rison-node/issues/1
-import rison from 'rison-node';
+import { i18n } from '@kbn/i18n';
+import { IIndexPattern, IFieldType } from 'src/plugins/data/public';
-export class BaseObject {
- // Set the attributes or default to an empty object
- constructor(attributes: Record = {}) {
- // Set the attributes or default to an empty object
- _.assign(this, attributes);
- }
+export interface IndexPatternTag {
+ key: string;
+ name: string;
+}
+
+export class IndexPatternListConfig {
+ public readonly key = 'default';
- public toObject() {
- // return just the data.
- return _.omit(this, (value: any, key: string) => {
- return key.charAt(0) === '$' || key.charAt(0) === '_' || _.isFunction(value);
- });
+ public getIndexPatternTags(indexPattern: IIndexPattern, isDefault: boolean): IndexPatternTag[] {
+ return isDefault
+ ? [
+ {
+ key: 'default',
+ name: i18n.translate('management.editIndexPattern.list.defaultIndexPatternListName', {
+ defaultMessage: 'Default',
+ }),
+ },
+ ]
+ : [];
}
- public toRISON() {
- // Use Angular to remove the private vars, and JSON.stringify to serialize
- return rison.encode(JSON.parse(angular.toJson(this)));
+ public getFieldInfo(indexPattern: IIndexPattern, field: IFieldType): string[] {
+ return [];
}
- public toJSON() {
- return this.toObject();
+ public areScriptedFieldsEnabled(indexPattern: IIndexPattern): boolean {
+ return true;
}
}
diff --git a/src/legacy/core_plugins/management/public/np_ready/services/index_pattern_management/list/index.ts b/src/legacy/core_plugins/management/public/np_ready/services/index_pattern_management/list/index.ts
new file mode 100644
index 0000000000000..114226b3a4570
--- /dev/null
+++ b/src/legacy/core_plugins/management/public/np_ready/services/index_pattern_management/list/index.ts
@@ -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.
+ */
+
+export { IndexPatternListConfig } from './config';
+export { IndexPatternListManager } from './manager';
diff --git a/src/legacy/core_plugins/management/public/np_ready/services/index_pattern_management/list/manager.ts b/src/legacy/core_plugins/management/public/np_ready/services/index_pattern_management/list/manager.ts
new file mode 100644
index 0000000000000..73ca33ae914a9
--- /dev/null
+++ b/src/legacy/core_plugins/management/public/np_ready/services/index_pattern_management/list/manager.ts
@@ -0,0 +1,57 @@
+/*
+ * 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 { IIndexPattern, IFieldType } from 'src/plugins/data/public';
+import { IndexPatternListConfig, IndexPatternTag } from './config';
+
+export class IndexPatternListManager {
+ private configs: IndexPatternListConfig[];
+
+ constructor() {
+ this.configs = [];
+ }
+
+ public add(Config: typeof IndexPatternListConfig) {
+ const config = new Config();
+ if (this.configs.findIndex(c => c.key === config.key) !== -1) {
+ throw new Error(`${config.key} exists in IndexPatternListManager.`);
+ }
+ this.configs.push(config);
+ }
+
+ public getIndexPatternTags(indexPattern: IIndexPattern, isDefault: boolean) {
+ return this.configs.reduce((tags: IndexPatternTag[], config) => {
+ return config.getIndexPatternTags
+ ? tags.concat(config.getIndexPatternTags(indexPattern, isDefault))
+ : tags;
+ }, []);
+ }
+
+ public getFieldInfo(indexPattern: IIndexPattern, field: IFieldType): string[] {
+ return this.configs.reduce((info: string[], config) => {
+ return config.getFieldInfo ? info.concat(config.getFieldInfo(indexPattern, field)) : info;
+ }, []);
+ }
+
+ public areScriptedFieldsEnabled(indexPattern: IIndexPattern): boolean {
+ return this.configs.every(config => {
+ return config.areScriptedFieldsEnabled ? config.areScriptedFieldsEnabled(indexPattern) : true;
+ });
+ }
+}
diff --git a/src/legacy/core_plugins/management/public/np_ready/services/saved_objects_management/index.ts b/src/legacy/core_plugins/management/public/np_ready/services/saved_objects_management/index.ts
new file mode 100644
index 0000000000000..bad3b3ac36ef7
--- /dev/null
+++ b/src/legacy/core_plugins/management/public/np_ready/services/saved_objects_management/index.ts
@@ -0,0 +1,22 @@
+/*
+ * 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 * from './saved_objects_management_action_registry';
+export * from './saved_objects_management_action';
+export * from './saved_objects_management_service';
diff --git a/src/legacy/ui/public/management/saved_objects_management/saved_objects_management_action.ts b/src/legacy/core_plugins/management/public/np_ready/services/saved_objects_management/saved_objects_management_action.ts
similarity index 96%
rename from src/legacy/ui/public/management/saved_objects_management/saved_objects_management_action.ts
rename to src/legacy/core_plugins/management/public/np_ready/services/saved_objects_management/saved_objects_management_action.ts
index a09f842e36713..d83afb195a492 100644
--- a/src/legacy/ui/public/management/saved_objects_management/saved_objects_management_action.ts
+++ b/src/legacy/core_plugins/management/public/np_ready/services/saved_objects_management/saved_objects_management_action.ts
@@ -17,7 +17,7 @@
* under the License.
*/
-import { ReactNode } from '@elastic/eui/node_modules/@types/react';
+import { ReactNode } from 'react';
export interface SavedObjectsManagementRecordReference {
type: string;
diff --git a/src/legacy/ui/public/management/saved_objects_management/saved_objects_management_action_registry.test.ts b/src/legacy/core_plugins/management/public/np_ready/services/saved_objects_management/saved_objects_management_action_registry.test.ts
similarity index 100%
rename from src/legacy/ui/public/management/saved_objects_management/saved_objects_management_action_registry.test.ts
rename to src/legacy/core_plugins/management/public/np_ready/services/saved_objects_management/saved_objects_management_action_registry.test.ts
diff --git a/src/legacy/ui/public/management/saved_objects_management/saved_objects_management_action_registry.ts b/src/legacy/core_plugins/management/public/np_ready/services/saved_objects_management/saved_objects_management_action_registry.ts
similarity index 100%
rename from src/legacy/ui/public/management/saved_objects_management/saved_objects_management_action_registry.ts
rename to src/legacy/core_plugins/management/public/np_ready/services/saved_objects_management/saved_objects_management_action_registry.ts
diff --git a/src/legacy/core_plugins/management/public/np_ready/services/saved_objects_management/saved_objects_management_service.ts b/src/legacy/core_plugins/management/public/np_ready/services/saved_objects_management/saved_objects_management_service.ts
new file mode 100644
index 0000000000000..d5e90d12cccc9
--- /dev/null
+++ b/src/legacy/core_plugins/management/public/np_ready/services/saved_objects_management/saved_objects_management_service.ts
@@ -0,0 +1,32 @@
+/*
+ * 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 { SavedObjectsManagementActionRegistry } from './saved_objects_management_action_registry';
+
+export class SavedObjectsManagementService {
+ public setup() {
+ return {
+ registry: SavedObjectsManagementActionRegistry,
+ };
+ }
+
+ public stop() {}
+}
+
+/** @internal */
+export type SavedObjectsManagementServiceSetup = ReturnType;
diff --git a/src/legacy/core_plugins/telemetry/public/components/__snapshots__/telemetry_form.test.js.snap b/src/legacy/core_plugins/telemetry/public/components/__snapshots__/telemetry_form.test.js.snap
index a7f8d72e016f8..079a43e77616d 100644
--- a/src/legacy/core_plugins/telemetry/public/components/__snapshots__/telemetry_form.test.js.snap
+++ b/src/legacy/core_plugins/telemetry/public/components/__snapshots__/telemetry_form.test.js.snap
@@ -38,7 +38,24 @@ exports[`TelemetryForm renders as expected when allows to change optIn status 1`
"defVal": true,
"description":
- Help us improve the Elastic Stack by providing usage statistics for basic features. We will not share this data outside of Elastic.
+
+
+ ,
+ }
+ }
+ />
-
-
-
-
-
,
"type": "boolean",
"value": false,
diff --git a/src/legacy/core_plugins/telemetry/public/components/telemetry_form.js b/src/legacy/core_plugins/telemetry/public/components/telemetry_form.js
index d4bbe1029b40d..f6012a271cde5 100644
--- a/src/legacy/core_plugins/telemetry/public/components/telemetry_form.js
+++ b/src/legacy/core_plugins/telemetry/public/components/telemetry_form.js
@@ -29,7 +29,7 @@ import {
EuiSpacer,
EuiText,
} from '@elastic/eui';
-import { getConfigTelemetryDesc, PRIVACY_STATEMENT_URL } from '../../common/constants';
+import { PRIVACY_STATEMENT_URL } from '../../common/constants';
import { OptInExampleFlyout } from './opt_in_details_component';
import { Field } from 'ui/management';
import { FormattedMessage } from '@kbn/i18n/react';
@@ -162,7 +162,23 @@ export class TelemetryForm extends Component {
renderDescription = () => (
- {getConfigTelemetryDesc()}
+
+
+
+
+ )
+ }}
+ />
+
-
-
-
-
-
)
diff --git a/src/legacy/core_plugins/vis_type_timeseries/public/_mixins.scss b/src/legacy/core_plugins/vis_type_timeseries/public/_mixins.scss
index aefebe8117bbf..8d3aea2a3ae54 100644
--- a/src/legacy/core_plugins/vis_type_timeseries/public/_mixins.scss
+++ b/src/legacy/core_plugins/vis_type_timeseries/public/_mixins.scss
@@ -1,6 +1,3 @@
-@import 'node_modules/@elastic/eui/src/components/form/variables';
-@import 'node_modules/@elastic/eui/src/components/form/mixins';
-
@mixin tvbEditorRepeatingRow {
background-color: $euiColorLightestShade;
padding: $euiSizeS;
diff --git a/src/legacy/core_plugins/vis_type_timeseries/public/components/_annotations_editor.scss b/src/legacy/core_plugins/vis_type_timeseries/public/components/_annotations_editor.scss
index 3372367be273d..99e024c9c5193 100644
--- a/src/legacy/core_plugins/vis_type_timeseries/public/components/_annotations_editor.scss
+++ b/src/legacy/core_plugins/vis_type_timeseries/public/components/_annotations_editor.scss
@@ -1,11 +1,9 @@
-@import 'node_modules/@elastic/eui/src/components/panel/mixins';
-
.tvbAnnotationsEditor__container {
padding: $euiSize;
background-color: $euiColorLightestShade;
}
-@include euiPanel('tvbAnnotationsEditor');
+@include euiPanel('.tvbAnnotationsEditor');
.tvbAnnotationsEditor {
margin-bottom: $euiSize;
diff --git a/src/legacy/core_plugins/vis_type_timeseries/public/components/_series_editor.scss b/src/legacy/core_plugins/vis_type_timeseries/public/components/_series_editor.scss
index 0cfe5fef010d3..82d1f4ea62676 100644
--- a/src/legacy/core_plugins/vis_type_timeseries/public/components/_series_editor.scss
+++ b/src/legacy/core_plugins/vis_type_timeseries/public/components/_series_editor.scss
@@ -1,10 +1,8 @@
-@import 'node_modules/@elastic/eui/src/components/panel/mixins';
-
.tvbSeriesEditor__container {
padding: $euiSize;
}
-@include euiPanel('tvbSeriesEditor');
+@include euiPanel('.tvbSeriesEditor');
.tvbSeriesEditor {
margin-bottom: $euiSize;
diff --git a/src/legacy/server/config/schema.js b/src/legacy/server/config/schema.js
index 24fe4e1a4d986..a19a39da0f6dd 100644
--- a/src/legacy/server/config/schema.js
+++ b/src/legacy/server/config/schema.js
@@ -135,7 +135,14 @@ export default () => Joi.object({
then: Joi.default(!process.stdout.isTTY),
otherwise: Joi.default(true)
}),
- timezone: Joi.string()
+ timezone: Joi.string(),
+ rotate: Joi.object().keys({
+ enabled: Joi.boolean().default(false),
+ everyBytes: Joi.number().greater(1024).default(10485760),
+ keepFiles: Joi.number().greater(2).less(1024).default(7),
+ pollingInterval: Joi.number().greater(5000).less(3600000).default(10000),
+ usePolling: Joi.boolean().default(false)
+ }).default()
}).default(),
ops: Joi.object({
diff --git a/src/legacy/server/logging/index.js b/src/legacy/server/logging/index.js
index 6e07757abf7bc..defbcd3331df4 100644
--- a/src/legacy/server/logging/index.js
+++ b/src/legacy/server/logging/index.js
@@ -20,6 +20,7 @@
import good from '@elastic/good';
import loggingConfiguration from './configuration';
import { logWithMetadata } from './log_with_metadata';
+import { setupLoggingRotate } from './rotate';
export async function setupLogging(server, config) {
return await server.register({
@@ -30,5 +31,7 @@ export async function setupLogging(server, config) {
export async function loggingMixin(kbnServer, server, config) {
logWithMetadata.decorateServer(server);
- return await setupLogging(server, config);
+
+ await setupLogging(server, config);
+ await setupLoggingRotate(server, config);
}
diff --git a/src/legacy/server/logging/rotate/index.ts b/src/legacy/server/logging/rotate/index.ts
new file mode 100644
index 0000000000000..646c89efe8e20
--- /dev/null
+++ b/src/legacy/server/logging/rotate/index.ts
@@ -0,0 +1,59 @@
+/*
+ * 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 { isMaster, isWorker } from 'cluster';
+import { Server } from 'hapi';
+import { LogRotator } from './log_rotator';
+import { KibanaConfig } from '../../kbn_server';
+
+let logRotator: LogRotator;
+
+export async function setupLoggingRotate(server: Server, config: KibanaConfig) {
+ // If log rotate is not enabled we skip
+ if (!config.get('logging.rotate.enabled')) {
+ return;
+ }
+
+ // We just want to start the logging rotate service once
+ // and we choose to use the master (prod) or the worker server (dev)
+ if (!isMaster && isWorker && process.env.kbnWorkerType !== 'server') {
+ return;
+ }
+
+ // We don't want to run logging rotate server if
+ // we are not logging to a file
+ if (config.get('logging.dest') === 'stdout') {
+ server.log(
+ ['warning', 'logging:rotate'],
+ 'Log rotation is enabled but logging.dest is configured for stdout. Set logging.dest to a file for this setting to take effect.'
+ );
+ return;
+ }
+
+ // Enable Logging Rotate Service
+ // We need the master process and it can
+ // try to setupLoggingRotate more than once,
+ // so we'll need to assure it only loads once.
+ if (!logRotator) {
+ logRotator = new LogRotator(config, server);
+ await logRotator.start();
+ }
+
+ return logRotator;
+}
diff --git a/src/legacy/server/logging/rotate/log_rotator.test.ts b/src/legacy/server/logging/rotate/log_rotator.test.ts
new file mode 100644
index 0000000000000..c2100546364d4
--- /dev/null
+++ b/src/legacy/server/logging/rotate/log_rotator.test.ts
@@ -0,0 +1,265 @@
+/*
+ * 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 del from 'del';
+import fs, { existsSync, mkdirSync, statSync, writeFileSync } from 'fs';
+import { LogRotator } from './log_rotator';
+import { tmpdir } from 'os';
+import { dirname, join } from 'path';
+
+const mockOn = jest.fn();
+jest.mock('chokidar', () => ({
+ watch: jest.fn(() => ({
+ on: mockOn,
+ close: jest.fn(),
+ })),
+}));
+
+jest.mock('lodash', () => ({
+ ...require.requireActual('lodash'),
+ throttle: (fn: any) => fn,
+}));
+
+const tempDir = join(tmpdir(), 'kbn_log_rotator_test');
+const testFilePath = join(tempDir, 'log_rotator_test_log_file.log');
+
+const createLogRotatorConfig: any = (logFilePath: string) => {
+ return new Map([
+ ['logging.dest', logFilePath],
+ ['logging.rotate.everyBytes', 2],
+ ['logging.rotate.keepFiles', 2],
+ ['logging.rotate.usePolling', false],
+ ['logging.rotate.pollingInterval', 10000],
+ ] as any);
+};
+
+const mockServer: any = {
+ log: jest.fn(),
+};
+
+const writeBytesToFile = (filePath: string, numberOfBytes: number) => {
+ writeFileSync(filePath, 'a'.repeat(numberOfBytes), { flag: 'a' });
+};
+
+describe('LogRotator', () => {
+ beforeEach(() => {
+ mkdirSync(tempDir, { recursive: true });
+ writeFileSync(testFilePath, '');
+ });
+
+ afterEach(() => {
+ del.sync(dirname(testFilePath), { force: true });
+ mockOn.mockClear();
+ });
+
+ it('rotates log file when bigger than set limit on start', async () => {
+ writeBytesToFile(testFilePath, 3);
+
+ const logRotator = new LogRotator(createLogRotatorConfig(testFilePath), mockServer);
+ jest.spyOn(logRotator, '_sendReloadLogConfigSignal').mockImplementation(() => {});
+ await logRotator.start();
+
+ expect(logRotator.running).toBe(true);
+
+ await logRotator.stop();
+ const testLogFileDir = dirname(testFilePath);
+
+ expect(existsSync(join(testLogFileDir, 'log_rotator_test_log_file.log.0'))).toBeTruthy();
+ });
+
+ it('rotates log file when equal than set limit over time', async () => {
+ writeBytesToFile(testFilePath, 1);
+
+ const logRotator = new LogRotator(createLogRotatorConfig(testFilePath), mockServer);
+ jest.spyOn(logRotator, '_sendReloadLogConfigSignal').mockImplementation(() => {});
+ await logRotator.start();
+
+ expect(logRotator.running).toBe(true);
+
+ const testLogFileDir = dirname(testFilePath);
+ expect(existsSync(join(testLogFileDir, 'log_rotator_test_log_file.log.0'))).toBeFalsy();
+
+ writeBytesToFile(testFilePath, 1);
+
+ // ['change', [asyncFunction]]
+ const onChangeCb = mockOn.mock.calls[0][1];
+ await onChangeCb(testLogFileDir, { size: 2 });
+
+ await logRotator.stop();
+ expect(existsSync(join(testLogFileDir, 'log_rotator_test_log_file.log.0'))).toBeTruthy();
+ });
+
+ it('rotates log file when file size is bigger than limit', async () => {
+ writeBytesToFile(testFilePath, 1);
+
+ const logRotator = new LogRotator(createLogRotatorConfig(testFilePath), mockServer);
+ jest.spyOn(logRotator, '_sendReloadLogConfigSignal').mockImplementation(() => {});
+ await logRotator.start();
+
+ expect(logRotator.running).toBe(true);
+
+ const testLogFileDir = dirname(testFilePath);
+ expect(existsSync(join(testLogFileDir, 'log_rotator_test_log_file.log.0'))).toBeFalsy();
+
+ writeBytesToFile(testFilePath, 2);
+
+ // ['change', [asyncFunction]]
+ const onChangeCb = mockOn.mock.calls[0][1];
+ await onChangeCb(testLogFileDir, { size: 3 });
+
+ await logRotator.stop();
+ expect(existsSync(join(testLogFileDir, 'log_rotator_test_log_file.log.0'))).toBeTruthy();
+ });
+
+ it('rotates log file service correctly keeps number of files', async () => {
+ writeBytesToFile(testFilePath, 3);
+
+ const logRotator = new LogRotator(createLogRotatorConfig(testFilePath), mockServer);
+ jest.spyOn(logRotator, '_sendReloadLogConfigSignal').mockImplementation(() => {});
+ await logRotator.start();
+
+ expect(logRotator.running).toBe(true);
+
+ const testLogFileDir = dirname(testFilePath);
+ expect(existsSync(join(testLogFileDir, 'log_rotator_test_log_file.log.0'))).toBeTruthy();
+
+ writeBytesToFile(testFilePath, 2);
+
+ // ['change', [asyncFunction]]
+ const onChangeCb = mockOn.mock.calls[0][1];
+ await onChangeCb(testLogFileDir, { size: 2 });
+
+ writeBytesToFile(testFilePath, 5);
+ await onChangeCb(testLogFileDir, { size: 5 });
+
+ await logRotator.stop();
+ expect(existsSync(join(testLogFileDir, 'log_rotator_test_log_file.log.0'))).toBeTruthy();
+ expect(existsSync(join(testLogFileDir, 'log_rotator_test_log_file.log.1'))).toBeTruthy();
+ expect(existsSync(join(testLogFileDir, 'log_rotator_test_log_file.log.2'))).toBeFalsy();
+ expect(statSync(join(testLogFileDir, 'log_rotator_test_log_file.log.0')).size).toBe(5);
+ });
+
+ it('rotates log file service correctly keeps number of files even when number setting changes', async () => {
+ writeBytesToFile(testFilePath, 3);
+
+ const logRotator = new LogRotator(createLogRotatorConfig(testFilePath), mockServer);
+ jest.spyOn(logRotator, '_sendReloadLogConfigSignal').mockImplementation(() => {});
+ await logRotator.start();
+
+ expect(logRotator.running).toBe(true);
+
+ const testLogFileDir = dirname(testFilePath);
+ expect(existsSync(join(testLogFileDir, 'log_rotator_test_log_file.log.0'))).toBeTruthy();
+
+ writeBytesToFile(testFilePath, 2);
+
+ // ['change', [asyncFunction]]
+ const onChangeCb = mockOn.mock.calls[0][1];
+ await onChangeCb(testLogFileDir, { size: 2 });
+
+ writeBytesToFile(testFilePath, 5);
+ await onChangeCb(testLogFileDir, { size: 5 });
+
+ await logRotator.stop();
+ expect(existsSync(join(testLogFileDir, 'log_rotator_test_log_file.log.0'))).toBeTruthy();
+ expect(existsSync(join(testLogFileDir, 'log_rotator_test_log_file.log.1'))).toBeTruthy();
+ expect(existsSync(join(testLogFileDir, 'log_rotator_test_log_file.log.2'))).toBeFalsy();
+ expect(statSync(join(testLogFileDir, 'log_rotator_test_log_file.log.0')).size).toBe(5);
+
+ logRotator.keepFiles = 1;
+ await logRotator.start();
+
+ writeBytesToFile(testFilePath, 5);
+ await onChangeCb(testLogFileDir, { size: 5 });
+
+ await logRotator.stop();
+ expect(existsSync(join(testLogFileDir, 'log_rotator_test_log_file.log.0'))).toBeTruthy();
+ expect(existsSync(join(testLogFileDir, 'log_rotator_test_log_file.log.1'))).toBeFalsy();
+ expect(statSync(join(testLogFileDir, 'log_rotator_test_log_file.log.0')).size).toBe(5);
+ });
+
+ it('rotates log file service correctly detects usePolling when it should be false', async () => {
+ writeBytesToFile(testFilePath, 1);
+
+ const logRotator = new LogRotator(createLogRotatorConfig(testFilePath), mockServer);
+ jest.spyOn(logRotator, '_sendReloadLogConfigSignal').mockImplementation(() => {});
+ await logRotator.start();
+
+ expect(logRotator.running).toBe(true);
+ expect(logRotator.usePolling).toBe(false);
+
+ const usePolling = await logRotator._shouldUsePolling();
+ expect(usePolling).toBe(false);
+
+ await logRotator.stop();
+ });
+
+ it('rotates log file service correctly detects usePolling when it should be true', async () => {
+ writeBytesToFile(testFilePath, 1);
+
+ const logRotator = new LogRotator(createLogRotatorConfig(testFilePath), mockServer);
+ jest.spyOn(logRotator, '_sendReloadLogConfigSignal').mockImplementation(() => {});
+
+ jest.spyOn(fs, 'watch').mockImplementation(
+ () =>
+ ({
+ on: jest.fn((eventType, cb) => {
+ if (eventType === 'error') {
+ cb();
+ }
+ }),
+ close: jest.fn(),
+ } as any)
+ );
+
+ await logRotator.start();
+
+ expect(logRotator.running).toBe(true);
+ expect(logRotator.usePolling).toBe(true);
+
+ await logRotator.stop();
+ });
+
+ it('rotates log file service correctly fallback to usePolling true after defined timeout', async () => {
+ jest.useFakeTimers();
+ writeBytesToFile(testFilePath, 1);
+
+ const logRotator = new LogRotator(createLogRotatorConfig(testFilePath), mockServer);
+ jest.spyOn(logRotator, '_sendReloadLogConfigSignal').mockImplementation(() => {});
+ jest.spyOn(fs, 'watch').mockImplementation(
+ () =>
+ ({
+ on: jest.fn((ev: string) => {
+ if (ev === 'error') {
+ jest.runTimersToTime(15000);
+ }
+ }),
+ close: jest.fn(),
+ } as any)
+ );
+
+ await logRotator.start();
+
+ expect(logRotator.running).toBe(true);
+ expect(logRotator.usePolling).toBe(true);
+
+ await logRotator.stop();
+ jest.useRealTimers();
+ });
+});
diff --git a/src/legacy/server/logging/rotate/log_rotator.ts b/src/legacy/server/logging/rotate/log_rotator.ts
new file mode 100644
index 0000000000000..3662910ca5a7b
--- /dev/null
+++ b/src/legacy/server/logging/rotate/log_rotator.ts
@@ -0,0 +1,359 @@
+/*
+ * 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 * as chokidar from 'chokidar';
+import { isMaster } from 'cluster';
+import fs from 'fs';
+import { Server } from 'hapi';
+import { throttle } from 'lodash';
+import { tmpdir } from 'os';
+import { basename, dirname, join, sep } from 'path';
+import { Observable } from 'rxjs';
+import { first } from 'rxjs/operators';
+import { promisify } from 'util';
+import { KibanaConfig } from '../../kbn_server';
+
+const mkdirAsync = promisify(fs.mkdir);
+const readdirAsync = promisify(fs.readdir);
+const renameAsync = promisify(fs.rename);
+const statAsync = promisify(fs.stat);
+const unlinkAsync = promisify(fs.unlink);
+const writeFileAsync = promisify(fs.writeFile);
+
+export class LogRotator {
+ private readonly config: KibanaConfig;
+ private readonly log: Server['log'];
+ public logFilePath: string;
+ public everyBytes: number;
+ public keepFiles: number;
+ public running: boolean;
+ private logFileSize: number;
+ public isRotating: boolean;
+ public throttledRotate: () => void;
+ public stalker: chokidar.FSWatcher | null;
+ public usePolling: boolean;
+ public pollingInterval: number;
+ private stalkerUsePollingPolicyTestTimeout: NodeJS.Timeout | null;
+
+ constructor(config: KibanaConfig, server: Server) {
+ this.config = config;
+ this.log = server.log.bind(server);
+ this.logFilePath = config.get('logging.dest');
+ this.everyBytes = config.get('logging.rotate.everyBytes');
+ this.keepFiles = config.get('logging.rotate.keepFiles');
+ this.running = false;
+ this.logFileSize = 0;
+ this.isRotating = false;
+ this.throttledRotate = throttle(async () => await this._rotate(), 5000);
+ this.stalker = null;
+ this.usePolling = config.get('logging.rotate.usePolling');
+ this.pollingInterval = config.get('logging.rotate.pollingInterval');
+ this.stalkerUsePollingPolicyTestTimeout = null;
+ }
+
+ async start() {
+ if (this.running) {
+ return;
+ }
+
+ this.running = true;
+
+ // create exit listener for cleanup purposes
+ this._createExitListener();
+
+ // call rotate on startup
+ await this._callRotateOnStartup();
+
+ // init log file size monitor
+ await this._startLogFileSizeMonitor();
+ }
+
+ stop = () => {
+ if (!this.running) {
+ return;
+ }
+
+ // cleanup exit listener
+ this._deleteExitListener();
+
+ // stop log file size monitor
+ this._stopLogFileSizeMonitor();
+
+ this.running = false;
+ };
+
+ async _shouldUsePolling() {
+ try {
+ // Setup a test file in order to try the fs env
+ // and understand if we need to usePolling or not
+ const tempFileDir = tmpdir();
+ const tempFile = join(tempFileDir, 'kbn_log_rotation_use_polling_test_file.log');
+
+ await mkdirAsync(tempFileDir, { recursive: true });
+ await writeFileAsync(tempFile, '');
+
+ // setup fs.watch for the temp test file
+ const testWatcher = fs.watch(tempFile, { persistent: false });
+
+ // await writeFileAsync(tempFile, 'test');
+
+ const usePollingTest$ = new Observable(observer => {
+ // observable complete function
+ const completeFn = (completeStatus: boolean) => {
+ if (this.stalkerUsePollingPolicyTestTimeout) {
+ clearTimeout(this.stalkerUsePollingPolicyTestTimeout);
+ }
+ testWatcher.close();
+
+ observer.next(completeStatus);
+ observer.complete();
+ };
+
+ // setup conditions that would fire the observable
+ this.stalkerUsePollingPolicyTestTimeout = setTimeout(() => completeFn(true), 15000);
+ testWatcher.on('change', () => completeFn(false));
+ testWatcher.on('error', () => completeFn(true));
+
+ // fire test watcher events
+ setTimeout(() => {
+ fs.writeFileSync(tempFile, 'test');
+ }, 0);
+ });
+
+ // wait for the first observable result and consider it as the result
+ // for our use polling test
+ const usePollingTestResult = await usePollingTest$.pipe(first()).toPromise();
+
+ // delete the temp file used for the test
+ await unlinkAsync(tempFile);
+
+ return usePollingTestResult;
+ } catch {
+ return true;
+ }
+ }
+
+ async _startLogFileSizeMonitor() {
+ this.usePolling = await this._shouldUsePolling();
+
+ if (this.usePolling && this.usePolling !== this.config.get('logging.rotate.usePolling')) {
+ this.log(
+ ['warning', 'logging:rotate'],
+ 'The current environment does not support `fs.watch`. Falling back to polling using `fs.watchFile`'
+ );
+ }
+
+ this.stalker = chokidar.watch(this.logFilePath, {
+ ignoreInitial: true,
+ awaitWriteFinish: false,
+ useFsEvents: false,
+ usePolling: this.usePolling,
+ interval: this.pollingInterval,
+ binaryInterval: this.pollingInterval,
+ alwaysStat: true,
+ atomic: false,
+ });
+ this.stalker.on('change', this._logFileSizeMonitorHandler);
+ }
+
+ _logFileSizeMonitorHandler = async (filename: string, stats: fs.Stats) => {
+ if (!filename || !stats) {
+ return;
+ }
+
+ this.logFileSize = stats.size || 0;
+ await this.throttledRotate();
+ };
+
+ _stopLogFileSizeMonitor() {
+ if (!this.stalker) {
+ return;
+ }
+
+ this.stalker.close();
+
+ if (this.stalkerUsePollingPolicyTestTimeout) {
+ clearTimeout(this.stalkerUsePollingPolicyTestTimeout);
+ }
+ }
+
+ _createExitListener() {
+ process.on('exit', this.stop);
+ }
+
+ _deleteExitListener() {
+ process.removeListener('exit', this.stop);
+ }
+
+ async _getLogFileSizeAndCreateIfNeeded() {
+ try {
+ const logFileStats = await statAsync(this.logFilePath);
+ return logFileStats.size;
+ } catch {
+ // touch the file to make the watcher being able to register
+ // change events
+ await writeFileAsync(this.logFilePath, '');
+ return 0;
+ }
+ }
+
+ async _callRotateOnStartup() {
+ this.logFileSize = await this._getLogFileSizeAndCreateIfNeeded();
+ await this._rotate();
+ }
+
+ _shouldRotate() {
+ // should rotate evaluation
+ // 1. should rotate if current log size exceeds
+ // the defined one on everyBytes
+ // 2. should not rotate if is already rotating or if any
+ // of the conditions on 1. do not apply
+ if (this.isRotating) {
+ return false;
+ }
+
+ return this.logFileSize >= this.everyBytes;
+ }
+
+ async _rotate() {
+ if (!this._shouldRotate()) {
+ return;
+ }
+
+ await this._rotateNow();
+ }
+
+ async _rotateNow() {
+ // rotate process
+ // 1. get rotated files metadata (list of log rotated files present on the log folder, numerical sorted)
+ // 2. delete last file
+ // 3. rename all files to the correct index +1
+ // 4. rename + compress current log into 1
+ // 5. send SIGHUP to reload log config
+
+ // rotate process is starting
+ this.isRotating = true;
+
+ // get rotated files metadata
+ const foundRotatedFiles = await this._readRotatedFilesMetadata();
+
+ // delete number of rotated files exceeding the keepFiles limit setting
+ const rotatedFiles: string[] = await this._deleteFoundRotatedFilesAboveKeepFilesLimit(
+ foundRotatedFiles
+ );
+
+ // delete last file
+ await this._deleteLastRotatedFile(rotatedFiles);
+
+ // rename all files to correct index + 1
+ // and normalize numbering if by some reason
+ // (for example log file deletion) that numbering
+ // was interrupted
+ await this._renameRotatedFilesByOne(rotatedFiles);
+
+ // rename current log into 0
+ await this._rotateCurrentLogFile();
+
+ // send SIGHUP to reload log configuration
+ this._sendReloadLogConfigSignal();
+
+ // Reset log file size
+ this.logFileSize = 0;
+
+ // rotate process is finished
+ this.isRotating = false;
+ }
+
+ async _readRotatedFilesMetadata() {
+ const logFileBaseName = basename(this.logFilePath);
+ const logFilesFolder = dirname(this.logFilePath);
+ const foundLogFiles: string[] = await readdirAsync(logFilesFolder);
+
+ return (
+ foundLogFiles
+ .filter(file => new RegExp(`${logFileBaseName}\\.\\d`).test(file))
+ // we use .slice(-1) here in order to retrieve the last number match in the read filenames
+ .sort((a, b) => Number(a.match(/(\d+)/g)!.slice(-1)) - Number(b.match(/(\d+)/g)!.slice(-1)))
+ .map(filename => `${logFilesFolder}${sep}${filename}`)
+ );
+ }
+
+ async _deleteFoundRotatedFilesAboveKeepFilesLimit(foundRotatedFiles: string[]) {
+ if (foundRotatedFiles.length <= this.keepFiles) {
+ return foundRotatedFiles;
+ }
+
+ const finalRotatedFiles = foundRotatedFiles.slice(0, this.keepFiles);
+ const rotatedFilesToDelete = foundRotatedFiles.slice(
+ finalRotatedFiles.length,
+ foundRotatedFiles.length
+ );
+
+ await Promise.all(
+ rotatedFilesToDelete.map((rotatedFilePath: string) => unlinkAsync(rotatedFilePath))
+ );
+
+ return finalRotatedFiles;
+ }
+
+ async _deleteLastRotatedFile(rotatedFiles: string[]) {
+ if (rotatedFiles.length < this.keepFiles) {
+ return;
+ }
+
+ const lastFilePath: string = rotatedFiles.pop() as string;
+ await unlinkAsync(lastFilePath);
+ }
+
+ async _renameRotatedFilesByOne(rotatedFiles: string[]) {
+ const logFileBaseName = basename(this.logFilePath);
+ const logFilesFolder = dirname(this.logFilePath);
+
+ for (let i = rotatedFiles.length - 1; i >= 0; i--) {
+ const oldFilePath = rotatedFiles[i];
+ const newFilePath = `${logFilesFolder}${sep}${logFileBaseName}.${i + 1}`;
+ await renameAsync(oldFilePath, newFilePath);
+ }
+ }
+
+ async _rotateCurrentLogFile() {
+ const newFilePath = `${this.logFilePath}.0`;
+ await renameAsync(this.logFilePath, newFilePath);
+ }
+
+ _sendReloadLogConfigSignal() {
+ if (isMaster) {
+ (process as NodeJS.EventEmitter).emit('SIGHUP');
+ return;
+ }
+
+ // Send a special message to the cluster manager
+ // so it can forward it correctly
+ // It will only run when we are under cluster mode (not under a production environment)
+ if (!process.send) {
+ this.log(
+ ['error', 'logging:rotate'],
+ 'For some unknown reason process.send is not defined, the rotation was not successful'
+ );
+ return;
+ }
+
+ process.send(['RELOAD_LOGGING_CONFIG_FROM_SERVER_WORKER']);
+ }
+}
diff --git a/src/legacy/server/sass/build.test.js b/src/legacy/server/sass/build.test.js
index 810b7cb44b917..bde552e9df00f 100644
--- a/src/legacy/server/sass/build.test.js
+++ b/src/legacy/server/sass/build.test.js
@@ -47,14 +47,35 @@ it('builds light themed SASS', async () => {
expect(readFileSync(targetPath, 'utf8').replace(/(\/\*# sourceMappingURL=).*( \*\/)/, '$1...$2'))
.toMatchInlineSnapshot(`
-"foo bar {
- display: -webkit-box;
- display: -webkit-flex;
- display: -ms-flexbox;
- display: flex;
- background: #e6f0f8 url(./images/img.png) url(ui/assets/favicons/favicon.ico); }
-/*# sourceMappingURL=... */"
-`);
+ "/* 1 */
+ /* 1 */
+ /**
+ * 1. Extend beta badges to at least 40% of the container's width
+ * 2. Fix for IE to ensure badges are visible outside of a tag
+ */
+ /**
+ * 1. Apply margin to all but last item in the flex.
+ * 2. Margin gets flipped because of the row-reverse.
+ */
+ /**
+ * 3. Must supply both values to background-size or some browsers apply the single value to both directions
+ */
+ /**
+ * 4. Override invalid state with focus state.
+ */
+ /**
+ * Mixin for use in:
+ * - EuiCard
+ * - EuiPageContent
+ */
+ foo bar {
+ display: -webkit-box;
+ display: -webkit-flex;
+ display: -ms-flexbox;
+ display: flex;
+ background: #e6f0f8 url(./images/img.png) url(ui/assets/favicons/favicon.ico); }
+ /*# sourceMappingURL=... */"
+ `);
});
it('builds dark themed SASS', async () => {
@@ -72,14 +93,35 @@ it('builds dark themed SASS', async () => {
expect(readFileSync(targetPath, 'utf8').replace(/(\/\*# sourceMappingURL=).*( \*\/)/, '$1...$2'))
.toMatchInlineSnapshot(`
-"foo bar {
- display: -webkit-box;
- display: -webkit-flex;
- display: -ms-flexbox;
- display: flex;
- background: #232635 url(./images/img.png) url(ui/assets/favicons/favicon.ico); }
-/*# sourceMappingURL=... */"
-`);
+ "/* 1 */
+ /* 1 */
+ /**
+ * 1. Extend beta badges to at least 40% of the container's width
+ * 2. Fix for IE to ensure badges are visible outside of a tag
+ */
+ /**
+ * 1. Apply margin to all but last item in the flex.
+ * 2. Margin gets flipped because of the row-reverse.
+ */
+ /**
+ * 3. Must supply both values to background-size or some browsers apply the single value to both directions
+ */
+ /**
+ * 4. Override invalid state with focus state.
+ */
+ /**
+ * Mixin for use in:
+ * - EuiCard
+ * - EuiPageContent
+ */
+ foo bar {
+ display: -webkit-box;
+ display: -webkit-flex;
+ display: -ms-flexbox;
+ display: flex;
+ background: #232635 url(./images/img.png) url(ui/assets/favicons/favicon.ico); }
+ /*# sourceMappingURL=... */"
+ `);
});
it('rewrites url imports', async () => {
@@ -99,16 +141,38 @@ it('rewrites url imports', async () => {
},
}).build();
+ /* eslint-disable max-len */
expect(readFileSync(targetPath, 'utf8').replace(/(\/\*# sourceMappingURL=).*( \*\/)/, '$1...$2'))
.toMatchInlineSnapshot(`
-"foo bar {
- display: -webkit-box;
- display: -webkit-flex;
- display: -ms-flexbox;
- display: flex;
- background: #232635 url(__REPLACE_WITH_PUBLIC_PATH__foo/bar/images/img.png) url(__REPLACE_WITH_PUBLIC_PATH__ui/favicons/favicon.ico); }
-/*# sourceMappingURL=... */"
-`);
+ "/* 1 */
+ /* 1 */
+ /**
+ * 1. Extend beta badges to at least 40% of the container's width
+ * 2. Fix for IE to ensure badges are visible outside of a tag
+ */
+ /**
+ * 1. Apply margin to all but last item in the flex.
+ * 2. Margin gets flipped because of the row-reverse.
+ */
+ /**
+ * 3. Must supply both values to background-size or some browsers apply the single value to both directions
+ */
+ /**
+ * 4. Override invalid state with focus state.
+ */
+ /**
+ * Mixin for use in:
+ * - EuiCard
+ * - EuiPageContent
+ */
+ foo bar {
+ display: -webkit-box;
+ display: -webkit-flex;
+ display: -ms-flexbox;
+ display: flex;
+ background: #232635 url(__REPLACE_WITH_PUBLIC_PATH__foo/bar/images/img.png) url(__REPLACE_WITH_PUBLIC_PATH__ui/favicons/favicon.ico); }
+ /*# sourceMappingURL=... */"
+ `);
expect(
Buffer.compare(
@@ -118,9 +182,9 @@ it('rewrites url imports', async () => {
).toBe(0);
expect(await globby('**/*', { cwd: TMP })).toMatchInlineSnapshot(`
-Array [
- "style.css",
- "images/img.png",
-]
-`);
+ Array [
+ "style.css",
+ "images/img.png",
+ ]
+ `);
});
diff --git a/src/legacy/server/url_shortening/routes/create_routes.js b/src/legacy/server/url_shortening/routes/create_routes.js
index 091eabcf47c1f..c6347ace873f7 100644
--- a/src/legacy/server/url_shortening/routes/create_routes.js
+++ b/src/legacy/server/url_shortening/routes/create_routes.js
@@ -19,12 +19,10 @@
import { shortUrlLookupProvider } from './lib/short_url_lookup';
import { createGotoRoute } from './goto';
-import { createShortenUrlRoute } from './shorten_url';
export function createRoutes(server) {
const shortUrlLookup = shortUrlLookupProvider(server);
server.route(createGotoRoute({ server, shortUrlLookup }));
- server.route(createShortenUrlRoute({ shortUrlLookup }));
}
diff --git a/src/legacy/server/url_shortening/routes/goto.js b/src/legacy/server/url_shortening/routes/goto.js
index 675bc5df50670..60a34499dd2d5 100644
--- a/src/legacy/server/url_shortening/routes/goto.js
+++ b/src/legacy/server/url_shortening/routes/goto.js
@@ -22,18 +22,12 @@ import { shortUrlAssertValid } from './lib/short_url_assert_valid';
export const createGotoRoute = ({ server, shortUrlLookup }) => ({
method: 'GET',
- path: '/goto/{urlId}',
+ path: '/goto_LP/{urlId}',
handler: async function (request, h) {
try {
const url = await shortUrlLookup.getUrl(request.params.urlId, request);
shortUrlAssertValid(url);
- const uiSettings = request.getUiSettingsService();
- const stateStoreInSessionStorage = await uiSettings.get('state:storeInSessionStorage');
- if (!stateStoreInSessionStorage) {
- return h.redirect(request.getBasePath() + url);
- }
-
const app = server.getHiddenUiAppById('stateSessionStorageRedirect');
return h.renderApp(app, {
redirectUrl: url,
diff --git a/src/legacy/server/url_shortening/routes/lib/short_url_lookup.js b/src/legacy/server/url_shortening/routes/lib/short_url_lookup.js
index c4f6af03d7d93..3a4b96c802c58 100644
--- a/src/legacy/server/url_shortening/routes/lib/short_url_lookup.js
+++ b/src/legacy/server/url_shortening/routes/lib/short_url_lookup.js
@@ -17,7 +17,6 @@
* under the License.
*/
-import crypto from 'crypto';
import { get } from 'lodash';
export function shortUrlLookupProvider(server) {
@@ -34,29 +33,6 @@ export function shortUrlLookupProvider(server) {
}
return {
- async generateUrlId(url, req) {
- const id = crypto.createHash('md5').update(url).digest('hex');
- const savedObjectsClient = req.getSavedObjectsClient();
- const { isConflictError } = savedObjectsClient.errors;
-
- try {
- const doc = await savedObjectsClient.create('url', {
- url,
- accessCount: 0,
- createDate: new Date(),
- accessDate: new Date()
- }, { id });
-
- return doc.id;
- } catch (error) {
- if (isConflictError(error)) {
- return id;
- }
-
- throw error;
- }
- },
-
async getUrl(id, req) {
const doc = await req.getSavedObjectsClient().get('url', id);
updateMetadata(doc, req);
diff --git a/src/legacy/server/url_shortening/routes/lib/short_url_lookup.test.js b/src/legacy/server/url_shortening/routes/lib/short_url_lookup.test.js
index 033aeb92926a5..7303682c63e0b 100644
--- a/src/legacy/server/url_shortening/routes/lib/short_url_lookup.test.js
+++ b/src/legacy/server/url_shortening/routes/lib/short_url_lookup.test.js
@@ -48,43 +48,6 @@ describe('shortUrlLookupProvider', () => {
sandbox.restore();
});
- describe('generateUrlId', () => {
- it('returns the document id', async () => {
- const id = await shortUrl.generateUrlId(URL, req);
- expect(id).toEqual(ID);
- });
-
- it('provides correct arguments to savedObjectsClient', async () => {
- await shortUrl.generateUrlId(URL, req);
-
- sinon.assert.calledOnce(savedObjectsClient.create);
- const [type, attributes, options] = savedObjectsClient.create.getCall(0).args;
-
- expect(type).toEqual(TYPE);
- expect(Object.keys(attributes).sort()).toEqual(['accessCount', 'accessDate', 'createDate', 'url']);
- expect(attributes.url).toEqual(URL);
- expect(options.id).toEqual(ID);
- });
-
- it('passes persists attributes', async () => {
- await shortUrl.generateUrlId(URL, req);
-
- sinon.assert.calledOnce(savedObjectsClient.create);
- const [type, attributes] = savedObjectsClient.create.getCall(0).args;
-
- expect(type).toEqual(TYPE);
- expect(Object.keys(attributes).sort()).toEqual(['accessCount', 'accessDate', 'createDate', 'url']);
- expect(attributes.url).toEqual(URL);
- });
-
- it('gracefully handles version conflict', async () => {
- const error = savedObjectsClient.errors.decorateConflictError(new Error());
- savedObjectsClient.create.throws(error);
- const id = await shortUrl.generateUrlId(URL, req);
- expect(id).toEqual(ID);
- });
- });
-
describe('getUrl', () => {
beforeEach(() => {
const attributes = { accessCount: 2, url: URL };
diff --git a/src/legacy/ui/public/agg_types/buckets/geo_hash.ts b/src/legacy/ui/public/agg_types/buckets/geo_hash.ts
index 700f5a048fce2..0acbaf4aa02a2 100644
--- a/src/legacy/ui/public/agg_types/buckets/geo_hash.ts
+++ b/src/legacy/ui/public/agg_types/buckets/geo_hash.ts
@@ -18,13 +18,13 @@
*/
import { i18n } from '@kbn/i18n';
+import { geohashColumns } from 'ui/vis/map/decode_geo_hash';
import chrome from '../../chrome';
import { BucketAggType, IBucketAggConfig } from './_bucket_agg_type';
import { AutoPrecisionParamEditor } from '../../vis/editors/default/controls/auto_precision';
import { UseGeocentroidParamEditor } from '../../vis/editors/default/controls/use_geocentroid';
import { IsFilteredByCollarParamEditor } from '../../vis/editors/default/controls/is_filtered_by_collar';
import { PrecisionParamEditor } from '../../vis/editors/default/controls/precision';
-import { geohashColumns } from '../../utils/decode_geo_hash';
import { AggGroupNames } from '../../vis/editors/default/agg_groups';
import { KBN_FIELD_TYPES } from '../../../../../plugins/data/public';
diff --git a/src/legacy/ui/public/management/index_pattern_creation/index.js b/src/legacy/ui/public/management/index_pattern_creation/index.js
deleted file mode 100644
index 0b677cbfd1f64..0000000000000
--- a/src/legacy/ui/public/management/index_pattern_creation/index.js
+++ /dev/null
@@ -1,23 +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 './register';
-export { IndexPatternCreationFactory } from './index_pattern_creation';
-export { IndexPatternCreationConfig } from './index_pattern_creation_config';
-export { indexPatternTypes, addIndexPatternType } from './index_pattern_types';
diff --git a/src/legacy/ui/public/management/index_pattern_creation/index_pattern_creation.js b/src/legacy/ui/public/management/index_pattern_creation/index_pattern_creation.js
deleted file mode 100644
index 12cecc956ab68..0000000000000
--- a/src/legacy/ui/public/management/index_pattern_creation/index_pattern_creation.js
+++ /dev/null
@@ -1,54 +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 { indexPatternTypes } from './index_pattern_types';
-
-class IndexPatternCreation {
- constructor(httpClient, type) {
- this._allTypes = indexPatternTypes.map(Plugin => new Plugin({ httpClient }));
- this._setCurrentType(type);
- }
-
- _setCurrentType = (type) => {
- const index = type ? indexPatternTypes.findIndex(Plugin => Plugin.key === type) : -1;
- this._currentType = index > -1 && this._allTypes[index] ? this._allTypes[index] : null;
- }
-
- getType = () => {
- return this._currentType || null;
- }
-
- getIndexPatternCreationOptions = async (urlHandler) => {
- const options = [];
- await Promise.all(this._allTypes.map(async type => {
- const option = type.getIndexPatternCreationOption ? await type.getIndexPatternCreationOption(urlHandler) : null;
- if(option) {
- options.push(option);
- }
- }));
- return options;
- }
-}
-
-export const IndexPatternCreationFactory = (Private, $http) => {
- return (type = 'default') => {
- const indexPatternCreationProvider = new IndexPatternCreation($http, type);
- return indexPatternCreationProvider;
- };
-};
diff --git a/src/legacy/ui/public/management/index_pattern_list/index.js b/src/legacy/ui/public/management/index_pattern_list/index.js
deleted file mode 100644
index a77a3f1f61f2c..0000000000000
--- a/src/legacy/ui/public/management/index_pattern_list/index.js
+++ /dev/null
@@ -1,23 +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 './register';
-export { IndexPatternListFactory } from './index_pattern_list';
-export { IndexPatternListConfig } from './index_pattern_list_config';
-export { IndexPatternListConfigRegistry } from './index_pattern_list_config_registry';
diff --git a/src/legacy/ui/public/management/index_pattern_list/index_pattern_list.js b/src/legacy/ui/public/management/index_pattern_list/index_pattern_list.js
deleted file mode 100644
index 9ff82db27fefc..0000000000000
--- a/src/legacy/ui/public/management/index_pattern_list/index_pattern_list.js
+++ /dev/null
@@ -1,52 +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 { IndexPatternListConfigRegistry } from './index_pattern_list_config_registry';
-
-class IndexPatternList {
- constructor(registry) {
- this._plugins = registry.inOrder.map(Plugin => new Plugin());
- }
-
- getIndexPatternTags = (indexPattern, isDefault) => {
- return this._plugins.reduce((tags, plugin) => {
- return plugin.getIndexPatternTags ? tags.concat(plugin.getIndexPatternTags(indexPattern, isDefault)) : tags;
- }, []);
- }
-
- getFieldInfo = (indexPattern, field) => {
- return this._plugins.reduce((info, plugin) => {
- return plugin.getFieldInfo ? info.concat(plugin.getFieldInfo(indexPattern, field)) : info;
- }, []);
- }
-
- areScriptedFieldsEnabled = (indexPattern) => {
- return this._plugins.every((plugin) => {
- return plugin.areScriptedFieldsEnabled ? plugin.areScriptedFieldsEnabled(indexPattern) : true;
- });
- }
-}
-
-export const IndexPatternListFactory = (Private) => {
- return function () {
- const indexPatternListRegistry = Private(IndexPatternListConfigRegistry);
- const indexPatternListProvider = new IndexPatternList(indexPatternListRegistry);
- return indexPatternListProvider;
- };
-};
diff --git a/src/legacy/ui/public/management/section.js b/src/legacy/ui/public/management/section.js
index d5e70c03d4259..b6952695cd910 100644
--- a/src/legacy/ui/public/management/section.js
+++ b/src/legacy/ui/public/management/section.js
@@ -42,7 +42,7 @@ export class ManagementSection {
this.id = id;
this.items = new IndexedArray({
index: ['id'],
- order: ['order']
+ order: ['order'],
});
this.visible = true;
this.disabled = false;
@@ -51,13 +51,14 @@ export class ManagementSection {
this.url = '';
assign(this, options);
-
}
get visibleItems() {
return this.items.inOrder.filter(item => {
const capabilityManagementSection = capabilities.get().management[this.id];
- const itemCapability = capabilityManagementSection ? capabilityManagementSection[item.id] : null;
+ const itemCapability = capabilityManagementSection
+ ? capabilityManagementSection[item.id]
+ : null;
return item.visible && itemCapability !== false;
});
@@ -95,10 +96,10 @@ export class ManagementSection {
}
/**
- * Deregisters a section
- *
- * @param {string} id
- */
+ * Deregisters a section
+ *
+ * @param {string} id
+ */
deregister(id) {
this.items.remove(item => item.id === id);
listeners.forEach(fn => fn(this.items));
diff --git a/src/legacy/ui/public/management/section.test.js b/src/legacy/ui/public/management/section.test.js
index a45fca426e2b4..e6363f2e164b4 100644
--- a/src/legacy/ui/public/management/section.test.js
+++ b/src/legacy/ui/public/management/section.test.js
@@ -24,10 +24,10 @@ jest.mock('ui/capabilities', () => ({
kibana: {
sampleFeature1: true,
sampleFeature2: false,
- }
- }
- })
- }
+ },
+ },
+ }),
+ },
}));
import { ManagementSection } from './section';
@@ -115,7 +115,9 @@ describe('ManagementSection', () => {
it('calls listener when item added', () => {
let listerCalled = false;
- const listenerFn = () => { listerCalled = true; };
+ const listenerFn = () => {
+ listerCalled = true;
+ };
section.addListener(listenerFn);
section.register('about');
@@ -131,12 +133,12 @@ describe('ManagementSection', () => {
section.register('about');
});
- it ('deregisters an existing section', () => {
+ it('deregisters an existing section', () => {
section.deregister('about');
expect(section.items).toHaveLength(0);
});
- it ('allows deregistering a section more than once', () => {
+ it('allows deregistering a section more than once', () => {
section.deregister('about');
section.deregister('about');
expect(section.items).toHaveLength(0);
@@ -144,7 +146,9 @@ describe('ManagementSection', () => {
it('calls listener when item added', () => {
let listerCalled = false;
- const listenerFn = () => { listerCalled = true; };
+ const listenerFn = () => {
+ listerCalled = true;
+ };
section.addListener(listenerFn);
section.deregister('about');
@@ -202,7 +206,9 @@ describe('ManagementSection', () => {
});
it('can be ordered', () => {
- const ids = section.items.inOrder.map((i) => { return i.id; });
+ const ids = section.items.inOrder.map(i => {
+ return i.id;
+ });
expect(ids).toEqual(['one', 'two', 'three']);
});
});
@@ -256,20 +262,26 @@ describe('ManagementSection', () => {
});
it('maintains the order', () => {
- const ids = section.visibleItems.map((i) => { return i.id; });
+ const ids = section.visibleItems.map(i => {
+ return i.id;
+ });
expect(ids).toEqual(['one', 'two', 'three']);
});
it('does not include hidden items', () => {
section.getSection('two').hide();
- const ids = section.visibleItems.map((i) => { return i.id; });
+ const ids = section.visibleItems.map(i => {
+ return i.id;
+ });
expect(ids).toEqual(['one', 'three']);
});
it('does not include visible items hidden via uiCapabilities', () => {
section.register('sampleFeature2', { order: 4, visible: true });
- const ids = section.visibleItems.map((i) => { return i.id; });
+ const ids = section.visibleItems.map(i => {
+ return i.id;
+ });
expect(ids).toEqual(['one', 'two', 'three']);
});
});
diff --git a/src/legacy/ui/public/management/sections_register.js b/src/legacy/ui/public/management/sections_register.js
index b25b381eef67b..a63fd390ea3ca 100644
--- a/src/legacy/ui/public/management/sections_register.js
+++ b/src/legacy/ui/public/management/sections_register.js
@@ -22,15 +22,15 @@ import { i18n } from '@kbn/i18n';
export const management = new ManagementSection('management', {
display: i18n.translate('common.ui.management.displayName', {
- defaultMessage: 'Management'
- })
+ defaultMessage: 'Management',
+ }),
});
management.register('data', {
display: i18n.translate('common.ui.management.connectDataDisplayName', {
- defaultMessage: 'Connect Data'
+ defaultMessage: 'Connect Data',
}),
- order: 0
+ order: 0,
});
management.register('elasticsearch', {
diff --git a/src/legacy/ui/public/saved_objects/components/saved_object_finder.tsx b/src/legacy/ui/public/saved_objects/components/saved_object_finder.tsx
deleted file mode 100644
index 5b787eb265509..0000000000000
--- a/src/legacy/ui/public/saved_objects/components/saved_object_finder.tsx
+++ /dev/null
@@ -1,108 +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 React from 'react';
-import { npStart } from 'ui/new_platform';
-import { IconType } from '@elastic/eui';
-import { SavedObjectAttributes } from 'src/core/server';
-import { SimpleSavedObject } from 'src/core/public';
-import { SavedObjectFinder as SavedObjectFinderNP } from '../../../../../plugins/kibana_react/public';
-
-/**
- * DO NOT USE THIS COMPONENT, IT IS DEPRECATED.
- * Use the one in `src/plugins/kibana_react` instead.
- */
-
-export interface SavedObjectMetaData {
- type: string;
- name: string;
- getIconForSavedObject(savedObject: SimpleSavedObject): IconType;
- getTooltipForSavedObject?(savedObject: SimpleSavedObject): string;
- showSavedObject?(savedObject: SimpleSavedObject): boolean;
-}
-
-interface BaseSavedObjectFinder {
- /**
- * @deprecated
- *
- * Use component in `src/plugins/kibana_react` instead.
- */
- onChoose?: (
- id: SimpleSavedObject['id'],
- type: SimpleSavedObject['type'],
- name: string
- ) => void;
- /**
- * @deprecated
- *
- * Use component in `src/plugins/kibana_react` instead.
- */
- noItemsMessage?: React.ReactNode;
- /**
- * @deprecated
- *
- * Use component in `src/plugins/kibana_react` instead.
- */
- savedObjectMetaData: Array>;
- /**
- * @deprecated
- *
- * Use component in `src/plugins/kibana_react` instead.
- */
- showFilter?: boolean;
-}
-
-interface SavedObjectFinderFixedPage extends BaseSavedObjectFinder {
- /**
- * @deprecated
- *
- * Use component in `src/plugins/kibana_react` instead.
- */
- initialPageSize?: undefined;
- /**
- * @deprecated
- *
- * Use component in `src/plugins/kibana_react` instead.
- */
- fixedPageSize: number;
-}
-
-interface SavedObjectFinderInitialPageSize extends BaseSavedObjectFinder {
- /**
- * @deprecated
- *
- * Use component in `src/plugins/kibana_react` instead.
- */
- initialPageSize?: 5 | 10 | 15 | 25;
- /**
- * @deprecated
- *
- * Use component in `src/plugins/kibana_react` instead.
- */
- fixedPageSize?: undefined;
-}
-type SavedObjectFinderProps = SavedObjectFinderFixedPage | SavedObjectFinderInitialPageSize;
-
-export const SavedObjectFinder: React.FC = props => (
-
-);
diff --git a/src/legacy/ui/public/state_management/state.js b/src/legacy/ui/public/state_management/state.js
index 27186b4249978..e868abb98c852 100644
--- a/src/legacy/ui/public/state_management/state.js
+++ b/src/legacy/ui/public/state_management/state.js
@@ -316,6 +316,27 @@ export function StateProvider(Private, $rootScope, $location, stateManagementCon
return this._urlParam;
};
+ /**
+ * Returns an object with each property name and value corresponding to the entries in this collection
+ * excluding fields started from '$', '_' and all methods
+ *
+ * @return {object}
+ */
+ State.prototype.toObject = function () {
+ return _.omit(this, (value, key) => {
+ return key.charAt(0) === '$' || key.charAt(0) === '_' || _.isFunction(value);
+ });
+ };
+
+ /** Alias for method 'toObject'
+ *
+ * @obsolete Please use 'toObject' method instead
+ * @return {object}
+ */
+ State.prototype.toJSON = function () {
+ return this.toObject();
+ };
+
return State;
}
diff --git a/src/legacy/ui/public/styles/_legacy/_mixins.scss b/src/legacy/ui/public/styles/_legacy/_mixins.scss
index b063aa763838b..2834f60555070 100644
--- a/src/legacy/ui/public/styles/_legacy/_mixins.scss
+++ b/src/legacy/ui/public/styles/_legacy/_mixins.scss
@@ -3,8 +3,6 @@
// DO NOT CONTINUE TO USE THESE MIXINS
-@import '@elastic/eui/src/components/form/variables';
-
@mixin __legacyInputStyles__bad {
&:not([type='range']) {
appearance: none;
diff --git a/src/legacy/ui/public/styles/_legacy/components/_ui_select.scss b/src/legacy/ui/public/styles/_legacy/components/_ui_select.scss
index 50ec20f016194..691ec17b5b967 100644
--- a/src/legacy/ui/public/styles/_legacy/components/_ui_select.scss
+++ b/src/legacy/ui/public/styles/_legacy/components/_ui_select.scss
@@ -1,6 +1,3 @@
-@import '@elastic/eui/src/components/button/variables';
-@import '@elastic/eui/src/components/form/variables';
-
/*!
* ui-select
* http://github.com/angular-ui/ui-select
@@ -8,7 +5,6 @@
* License: MIT
*/
-
/* Style when highlighting a search. */
.ui-select-highlight {
font-weight: bold;
@@ -43,12 +39,12 @@
padding-left: 0;
}
-.select2-locked > .select2-search-choice-close{
- display:none;
+.select2-locked > .select2-search-choice-close {
+ display: none;
}
-.select-locked > .ui-select-match-close{
- display:none;
+.select-locked > .ui-select-match-close {
+ display: none;
}
body > .select2-container.open {
@@ -56,42 +52,42 @@ body > .select2-container.open {
}
/* Handle up direction Select2 */
-.ui-select-container[theme="select2"].direction-up .ui-select-match,
+.ui-select-container[theme='select2'].direction-up .ui-select-match,
.ui-select-container.select2.direction-up .ui-select-match {
- border-radius: 4px; /* FIXME hardcoded value :-/ */
- border-top-left-radius: 0;
- border-top-right-radius: 0;
+ border-radius: 4px; /* FIXME hardcoded value :-/ */
+ border-top-left-radius: 0;
+ border-top-right-radius: 0;
}
-.ui-select-container[theme="select2"].direction-up .ui-select-dropdown,
+.ui-select-container[theme='select2'].direction-up .ui-select-dropdown,
.ui-select-container.select2.direction-up .ui-select-dropdown {
- border-radius: 4px; /* FIXME hardcoded value :-/ */
- border-bottom-left-radius: 0;
- border-bottom-right-radius: 0;
+ border-radius: 4px; /* FIXME hardcoded value :-/ */
+ border-bottom-left-radius: 0;
+ border-bottom-right-radius: 0;
- border-top-width: 1px; /* FIXME hardcoded value :-/ */
- border-top-style: solid;
+ border-top-width: 1px; /* FIXME hardcoded value :-/ */
+ border-top-style: solid;
- box-shadow: 0 -4px 8px rgba(0, 0, 0, 0.25);
+ box-shadow: 0 -4px 8px rgba(0, 0, 0, 0.25);
- margin-top: -4px; /* FIXME hardcoded value :-/ */
+ margin-top: -4px; /* FIXME hardcoded value :-/ */
}
-.ui-select-container[theme="select2"].direction-up .ui-select-dropdown .select2-search,
+.ui-select-container[theme='select2'].direction-up .ui-select-dropdown .select2-search,
.ui-select-container.select2.direction-up .ui-select-dropdown .select2-search {
- margin-top: 4px; /* FIXME hardcoded value :-/ */
+ margin-top: 4px; /* FIXME hardcoded value :-/ */
}
-.ui-select-container[theme="select2"].direction-up.select2-dropdown-open .ui-select-match,
+.ui-select-container[theme='select2'].direction-up.select2-dropdown-open .ui-select-match,
.ui-select-container.select2.direction-up.select2-dropdown-open .ui-select-match {
- border-bottom-color: $euiColorPrimary;
+ border-bottom-color: $euiColorPrimary;
}
-.ui-select-container[theme="select2"] .ui-select-dropdown .ui-select-search-hidden,
-.ui-select-container[theme="select2"] .ui-select-dropdown .ui-select-search-hidden input{
- opacity: 0;
- height: 0;
- min-height: 0;
- padding: 0;
- margin: 0;
- border:0;
+.ui-select-container[theme='select2'] .ui-select-dropdown .ui-select-search-hidden,
+.ui-select-container[theme='select2'] .ui-select-dropdown .ui-select-search-hidden input {
+ opacity: 0;
+ height: 0;
+ min-height: 0;
+ padding: 0;
+ margin: 0;
+ border: 0;
}
/* Bootstrap theme */
@@ -133,12 +129,12 @@ body > .select2-container.open {
}
.ui-select-bootstrap .ui-select-search-hidden {
- opacity: 0;
- height: 0;
- min-height: 0;
- padding: 0;
- margin: 0;
- border:0;
+ opacity: 0;
+ height: 0;
+ min-height: 0;
+ padding: 0;
+ margin: 0;
+ border: 0;
}
.ui-select-bootstrap > .ui-select-match > .btn {
@@ -213,7 +209,7 @@ body > .ui-select-bootstrap.open {
}
.ui-select-multiple:hover .ui-select-match-item.dropping-before:before {
- content: "";
+ content: '';
position: absolute;
top: 0;
right: 100%;
@@ -223,7 +219,7 @@ body > .ui-select-bootstrap.open {
}
.ui-select-multiple:hover .ui-select-match-item.dropping-after:after {
- content: "";
+ content: '';
position: absolute;
top: 0;
left: 100%;
@@ -232,7 +228,7 @@ body > .ui-select-bootstrap.open {
border-right: 1px solid $euiColorPrimary;
}
-.ui-select-bootstrap .ui-select-choices-row>span {
+.ui-select-bootstrap .ui-select-choices-row > span {
@include euiFontSizeS;
@include euiTextTruncate;
font-weight: inherit;
@@ -251,45 +247,44 @@ body > .ui-select-bootstrap.open {
}
}
-
-.ui-select-bootstrap .ui-select-choices-row.active>span {
- color: $euiTextColor;
- text-decoration: none;
- outline: 0;
- background-color: $euiFocusBackgroundColor;
+.ui-select-bootstrap .ui-select-choices-row.active > span {
+ color: $euiTextColor;
+ text-decoration: none;
+ outline: 0;
+ background-color: $euiFocusBackgroundColor;
}
-.ui-select-bootstrap .ui-select-choices-row.disabled>span,
-.ui-select-bootstrap .ui-select-choices-row.active.disabled>span {
- color: $euiButtonColorDisabled;
- cursor: not-allowed;
- background-color: transparent;
+.ui-select-bootstrap .ui-select-choices-row.disabled > span,
+.ui-select-bootstrap .ui-select-choices-row.active.disabled > span {
+ color: $euiButtonColorDisabled;
+ cursor: not-allowed;
+ background-color: transparent;
}
/* fix hide/show angular animation */
.ui-select-match.ng-hide-add,
.ui-select-search.ng-hide-add {
- display: none !important;
+ display: none !important;
}
/* Mark invalid Bootstrap */
.ui-select-bootstrap.ng-dirty.ng-invalid > button.btn.ui-select-match {
- border-color: $euiColorDanger;
+ border-color: $euiColorDanger;
}
/* Handle up direction Bootstrap */
-.ui-select-container[theme="bootstrap"].direction-up .ui-select-dropdown {
+.ui-select-container[theme='bootstrap'].direction-up .ui-select-dropdown {
@include euiBottomShadowMedium;
}
.ui-select-bootstrap .ui-select-match-text {
- width: 100%;
- padding-right: 1em;
+ width: 100%;
+ padding-right: 1em;
}
.ui-select-bootstrap .ui-select-match-text span {
- display: inline-block;
- width: 100%;
- overflow: hidden;
+ display: inline-block;
+ width: 100%;
+ overflow: hidden;
}
.ui-select-bootstrap .ui-select-toggle > a.btn {
position: absolute;
@@ -300,17 +295,17 @@ body > .ui-select-bootstrap.open {
/* Spinner */
.ui-select-refreshing {
- position: absolute;
- right: 0;
- padding: 8px 27px;
- top: 1px;
- display: inline-block;
- font-family: 'Glyphicons Halflings';
- font-style: normal;
- font-weight: normal;
- line-height: 1;
- -webkit-font-smoothing:antialiased;
- }
+ position: absolute;
+ right: 0;
+ padding: 8px 27px;
+ top: 1px;
+ display: inline-block;
+ font-family: 'Glyphicons Halflings';
+ font-style: normal;
+ font-weight: normal;
+ line-height: 1;
+ -webkit-font-smoothing: antialiased;
+}
@-webkit-keyframes ui-select-spin {
0% {
@@ -342,7 +337,6 @@ body > .ui-select-bootstrap.open {
-webkit-animation: none 0s;
}
-
// Other Custom
/**
diff --git a/src/legacy/ui/public/utils/range.d.ts b/src/legacy/ui/public/time_buckets/index.d.ts
similarity index 81%
rename from src/legacy/ui/public/utils/range.d.ts
rename to src/legacy/ui/public/time_buckets/index.d.ts
index c484c6f43eebb..70b9495b81f0e 100644
--- a/src/legacy/ui/public/utils/range.d.ts
+++ b/src/legacy/ui/public/time_buckets/index.d.ts
@@ -17,12 +17,6 @@
* under the License.
*/
-export function parseRange(input: string): Range;
-
-export interface Range {
- min: number;
- max: number;
- minInclusive: boolean;
- maxInclusive: boolean;
- within(n: number): boolean;
+declare module 'ui/time_buckets' {
+ export const TimeBuckets: any;
}
diff --git a/src/legacy/ui/public/utils/__tests__/base_object.js b/src/legacy/ui/public/utils/__tests__/base_object.js
deleted file mode 100644
index dfc5688c7b2f4..0000000000000
--- a/src/legacy/ui/public/utils/__tests__/base_object.js
+++ /dev/null
@@ -1,57 +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 expect from '@kbn/expect';
-import ngMock from 'ng_mock';
-import '../../private';
-
-import { BaseObject } from '../base_object';
-
-describe('Base Object', function () {
- beforeEach(ngMock.module('kibana'));
-
- it('should take an inital set of values', function () {
- const baseObject = new BaseObject({ message: 'test' });
- expect(baseObject).to.have.property('message', 'test');
- });
-
- it('should serialize attributes to RISON', function () {
- const baseObject = new BaseObject();
- baseObject.message = 'Testing... 1234';
- const rison = baseObject.toRISON();
- expect(rison).to.equal('(message:\'Testing... 1234\')');
- });
-
- it('should not serialize $$attributes to RISON', function () {
- const baseObject = new BaseObject();
- baseObject.$$attributes = { foo: 'bar' };
- baseObject.message = 'Testing... 1234';
- const rison = baseObject.toRISON();
- expect(rison).to.equal('(message:\'Testing... 1234\')');
- });
-
- it('should serialize attributes for JSON', function () {
- const baseObject = new BaseObject();
- baseObject.message = 'Testing... 1234';
- baseObject._private = 'foo';
- baseObject.$private = 'stuff';
- const json = JSON.stringify(baseObject);
- expect(json).to.equal('{"message":"Testing... 1234"}');
- });
-});
diff --git a/src/legacy/ui/public/utils/__tests__/simple_emitter.js b/src/legacy/ui/public/utils/__tests__/simple_emitter.js
deleted file mode 100644
index 25224a409f8f4..0000000000000
--- a/src/legacy/ui/public/utils/__tests__/simple_emitter.js
+++ /dev/null
@@ -1,175 +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 { SimpleEmitter } from '../simple_emitter';
-import expect from '@kbn/expect';
-import sinon from 'sinon';
-
-describe('SimpleEmitter class', function () {
- let emitter;
-
- beforeEach(function () {
- emitter = new SimpleEmitter();
- });
-
- it('constructs an event emitter', function () {
- expect(emitter).to.have.property('on');
- expect(emitter).to.have.property('off');
- expect(emitter).to.have.property('emit');
- expect(emitter).to.have.property('listenerCount');
- expect(emitter).to.have.property('removeAllListeners');
- });
-
- describe('#listenerCount', function () {
- it('counts all event listeners without any arg', function () {
- expect(emitter.listenerCount()).to.be(0);
- emitter.on('a', function () {});
- expect(emitter.listenerCount()).to.be(1);
- emitter.on('b', function () {});
- expect(emitter.listenerCount()).to.be(2);
- });
-
- it('limits to the event that is passed in', function () {
- expect(emitter.listenerCount()).to.be(0);
- emitter.on('a', function () {});
- expect(emitter.listenerCount('a')).to.be(1);
- emitter.on('a', function () {});
- expect(emitter.listenerCount('a')).to.be(2);
- emitter.on('b', function () {});
- expect(emitter.listenerCount('a')).to.be(2);
- expect(emitter.listenerCount('b')).to.be(1);
- expect(emitter.listenerCount()).to.be(3);
- });
- });
-
- describe('#on', function () {
- it('registers a handler', function () {
- const handler = sinon.stub();
- emitter.on('a', handler);
- expect(emitter.listenerCount('a')).to.be(1);
-
- expect(handler.callCount).to.be(0);
- emitter.emit('a');
- expect(handler.callCount).to.be(1);
- });
-
- it('allows multiple event handlers for the same event', function () {
- emitter.on('a', function () {});
- emitter.on('a', function () {});
- expect(emitter.listenerCount('a')).to.be(2);
- });
-
- it('allows the same function to be registered multiple times', function () {
- const handler = function () {};
- emitter.on('a', handler);
- expect(emitter.listenerCount()).to.be(1);
- emitter.on('a', handler);
- expect(emitter.listenerCount()).to.be(2);
- });
- });
-
- describe('#off', function () {
- it('removes a listener if it was registered', function () {
- const handler = sinon.stub();
- expect(emitter.listenerCount()).to.be(0);
- emitter.on('a', handler);
- expect(emitter.listenerCount('a')).to.be(1);
- emitter.off('a', handler);
- expect(emitter.listenerCount('a')).to.be(0);
- });
-
- it('clears all listeners if no handler is passed', function () {
- emitter.on('a', function () {});
- emitter.on('a', function () {});
- expect(emitter.listenerCount()).to.be(2);
- emitter.off('a');
- expect(emitter.listenerCount()).to.be(0);
- });
-
- it('does not mind if the listener is not registered', function () {
- emitter.off('a', function () {});
- });
-
- it('does not mind if the event has no listeners', function () {
- emitter.off('a');
- });
- });
-
- describe('#emit', function () {
- it('calls the handlers in the order they were defined', function () {
- let i = 0;
- const incr = function () { return ++i; };
- const one = sinon.spy(incr);
- const two = sinon.spy(incr);
- const three = sinon.spy(incr);
- const four = sinon.spy(incr);
-
- emitter
- .on('a', one)
- .on('a', two)
- .on('a', three)
- .on('a', four)
- .emit('a');
-
- expect(one).to.have.property('callCount', 1);
- expect(one.returned(1)).to.be.ok();
-
- expect(two).to.have.property('callCount', 1);
- expect(two.returned(2)).to.be.ok();
-
- expect(three).to.have.property('callCount', 1);
- expect(three.returned(3)).to.be.ok();
-
- expect(four).to.have.property('callCount', 1);
- expect(four.returned(4)).to.be.ok();
- });
-
- it('always emits the handlers that were initially registered', function () {
-
- const destructive = sinon.spy(function () {
- emitter.removeAllListeners();
- expect(emitter.listenerCount()).to.be(0);
- });
- const stub = sinon.stub();
-
- emitter.on('run', destructive).on('run', stub).emit('run');
-
- expect(destructive).to.have.property('callCount', 1);
- expect(stub).to.have.property('callCount', 1);
- });
-
- it('applies all arguments except the first', function () {
- emitter
- .on('a', function (a, b, c) {
- expect(a).to.be('foo');
- expect(b).to.be('bar');
- expect(c).to.be('baz');
- })
- .emit('a', 'foo', 'bar', 'baz');
- });
-
- it('uses the SimpleEmitter as the this context', function () {
- emitter
- .on('a', function () {
- expect(this).to.be(emitter);
- })
- .emit('a');
- });
- });
-});
diff --git a/src/legacy/ui/public/utils/simple_emitter.js b/src/legacy/ui/public/utils/simple_emitter.js
index 84397962c286b..503798ba160db 100644
--- a/src/legacy/ui/public/utils/simple_emitter.js
+++ b/src/legacy/ui/public/utils/simple_emitter.js
@@ -18,8 +18,6 @@
*/
import _ from 'lodash';
-import { BaseObject } from './base_object';
-import { createLegacyClass } from './legacy_class';
/**
* Simple event emitter class used in the vislib. Calls
@@ -27,7 +25,6 @@ import { createLegacyClass } from './legacy_class';
*
* @class
*/
-createLegacyClass(SimpleEmitter).inherits(BaseObject);
export function SimpleEmitter() {
this._listeners = {};
}
@@ -134,4 +131,3 @@ SimpleEmitter.prototype.listenerCount = function (name) {
return count + _.size(handlers);
}, 0);
};
-
diff --git a/src/legacy/ui/public/utils/simple_emitter.test.js b/src/legacy/ui/public/utils/simple_emitter.test.js
new file mode 100644
index 0000000000000..ff884a12be7ee
--- /dev/null
+++ b/src/legacy/ui/public/utils/simple_emitter.test.js
@@ -0,0 +1,173 @@
+/*
+ * 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 { SimpleEmitter } from './simple_emitter';
+import sinon from 'sinon';
+
+describe('SimpleEmitter class', () => {
+ let emitter;
+
+ beforeEach(() => {
+ emitter = new SimpleEmitter();
+ });
+
+ it('constructs an event emitter', () => {
+ expect(emitter).toHaveProperty('on');
+ expect(emitter).toHaveProperty('off');
+ expect(emitter).toHaveProperty('emit');
+ expect(emitter).toHaveProperty('listenerCount');
+ expect(emitter).toHaveProperty('removeAllListeners');
+ });
+
+ describe('#listenerCount', () => {
+ it('counts all event listeners without any arg', () => {
+ expect(emitter.listenerCount()).toBe(0);
+ emitter.on('a', () => {});
+ expect(emitter.listenerCount()).toBe(1);
+ emitter.on('b', () => {});
+ expect(emitter.listenerCount()).toBe(2);
+ });
+
+ it('limits to the event that is passed in', () => {
+ expect(emitter.listenerCount()).toBe(0);
+ emitter.on('a', () => {});
+ expect(emitter.listenerCount('a')).toBe(1);
+ emitter.on('a', () => {});
+ expect(emitter.listenerCount('a')).toBe(2);
+ emitter.on('b', () => {});
+ expect(emitter.listenerCount('a')).toBe(2);
+ expect(emitter.listenerCount('b')).toBe(1);
+ expect(emitter.listenerCount()).toBe(3);
+ });
+ });
+
+ describe('#on', () => {
+ it('registers a handler', () => {
+ const handler = sinon.stub();
+ emitter.on('a', handler);
+ expect(emitter.listenerCount('a')).toBe(1);
+
+ expect(handler.callCount).toBe(0);
+ emitter.emit('a');
+ expect(handler.callCount).toBe(1);
+ });
+
+ it('allows multiple event handlers for the same event', () => {
+ emitter.on('a', () => {});
+ emitter.on('a', () => {});
+ expect(emitter.listenerCount('a')).toBe(2);
+ });
+
+ it('allows the same function to be registered multiple times', () => {
+ const handler = () => {};
+ emitter.on('a', handler);
+ expect(emitter.listenerCount()).toBe(1);
+ emitter.on('a', handler);
+ expect(emitter.listenerCount()).toBe(2);
+ });
+ });
+
+ describe('#off', () => {
+ it('removes a listener if it was registered', () => {
+ const handler = sinon.stub();
+ expect(emitter.listenerCount()).toBe(0);
+ emitter.on('a', handler);
+ expect(emitter.listenerCount('a')).toBe(1);
+ emitter.off('a', handler);
+ expect(emitter.listenerCount('a')).toBe(0);
+ });
+
+ it('clears all listeners if no handler is passed', () => {
+ emitter.on('a', () => {});
+ emitter.on('a', () => {});
+ expect(emitter.listenerCount()).toBe(2);
+ emitter.off('a');
+ expect(emitter.listenerCount()).toBe(0);
+ });
+
+ it('does not mind if the listener is not registered', () => {
+ emitter.off('a', () => {});
+ });
+
+ it('does not mind if the event has no listeners', () => {
+ emitter.off('a');
+ });
+ });
+
+ describe('#emit', () => {
+ it('calls the handlers in the order they were defined', () => {
+ let i = 0;
+ const incr = () => ++i;
+ const one = sinon.spy(incr);
+ const two = sinon.spy(incr);
+ const three = sinon.spy(incr);
+ const four = sinon.spy(incr);
+
+ emitter
+ .on('a', one)
+ .on('a', two)
+ .on('a', three)
+ .on('a', four)
+ .emit('a');
+
+ expect(one).toHaveProperty('callCount', 1);
+ expect(one.returned(1)).toBeDefined();
+
+ expect(two).toHaveProperty('callCount', 1);
+ expect(two.returned(2)).toBeDefined();
+
+ expect(three).toHaveProperty('callCount', 1);
+ expect(three.returned(3)).toBeDefined();
+
+ expect(four).toHaveProperty('callCount', 1);
+ expect(four.returned(4)).toBeDefined();
+ });
+
+ it('always emits the handlers that were initially registered', () => {
+ const destructive = sinon.spy(() => {
+ emitter.removeAllListeners();
+ expect(emitter.listenerCount()).toBe(0);
+ });
+ const stub = sinon.stub();
+
+ emitter.on('run', destructive).on('run', stub).emit('run');
+
+ expect(destructive).toHaveProperty('callCount', 1);
+ expect(stub).toHaveProperty('callCount', 1);
+ });
+
+ it('applies all arguments except the first', () => {
+ emitter
+ .on('a', (a, b, c) => {
+ expect(a).toBe('foo');
+ expect(b).toBe('bar');
+ expect(c).toBe('baz');
+ })
+ .emit('a', 'foo', 'bar', 'baz');
+ });
+
+ it('uses the SimpleEmitter as the this context', () => {
+ emitter
+ .on('a', function () {
+ expect(this).toBe(emitter);
+ })
+ .emit('a');
+ });
+ });
+});
diff --git a/src/legacy/ui/public/vis/components/tooltip/_tooltip.scss b/src/legacy/ui/public/vis/components/tooltip/_tooltip.scss
index 451ecc80844dd..5a30ded7c2e5b 100644
--- a/src/legacy/ui/public/vis/components/tooltip/_tooltip.scss
+++ b/src/legacy/ui/public/vis/components/tooltip/_tooltip.scss
@@ -1,6 +1,3 @@
-@import '@elastic/eui/src/components/tool_tip/variables';
-@import '@elastic/eui/src/components/tool_tip/mixins';
-
.visTooltip,
.visTooltip__sizingClone {
@include euiToolTipStyle('s');
diff --git a/src/legacy/ui/public/vis/editors/default/_sidebar.scss b/src/legacy/ui/public/vis/editors/default/_sidebar.scss
index 5a8a0aabad565..e6b75b1a1f783 100644
--- a/src/legacy/ui/public/vis/editors/default/_sidebar.scss
+++ b/src/legacy/ui/public/vis/editors/default/_sidebar.scss
@@ -1,5 +1,3 @@
-@import '@elastic/eui/src/components/form/variables';
-
//
// LAYOUT
//
@@ -44,7 +42,6 @@
}
}
-
/**
* 1. TODO: Override bootstrap styles. Remove !important once we're rid of bootstrap.
*/
@@ -97,7 +94,7 @@
margin-top: $euiSizeS;
}
- label:not([class^="eui"]) {
+ label:not([class^='eui']) {
@include __legacyLabelStyles__bad;
display: block;
}
@@ -169,7 +166,7 @@
.visEditorSidebar__aggGroupAccordionButtonContent {
font-size: $euiFontSizeS;
- span {
+ span {
color: $euiColorDarkShade;
}
}
diff --git a/src/legacy/ui/public/vis/editors/default/controls/components/number_list/__snapshots__/number_list.test.tsx.snap b/src/legacy/ui/public/vis/editors/default/controls/components/number_list/__snapshots__/number_list.test.tsx.snap
index ab192e6fd3cbb..4004f8627a898 100644
--- a/src/legacy/ui/public/vis/editors/default/controls/components/number_list/__snapshots__/number_list.test.tsx.snap
+++ b/src/legacy/ui/public/vis/editors/default/controls/components/number_list/__snapshots__/number_list.test.tsx.snap
@@ -18,7 +18,7 @@ exports[`NumberList should be rendered with default set of props 1`] = `
onChange={[Function]}
onDelete={[Function]}
range={
- Range {
+ NumberListRange {
"max": 10,
"maxInclusive": true,
"min": 1,
@@ -45,7 +45,7 @@ exports[`NumberList should be rendered with default set of props 1`] = `
onChange={[Function]}
onDelete={[Function]}
range={
- Range {
+ NumberListRange {
"max": 10,
"maxInclusive": true,
"min": 1,
diff --git a/src/legacy/ui/public/vis/editors/default/controls/components/number_list/number_row.tsx b/src/legacy/ui/public/vis/editors/default/controls/components/number_list/number_row.tsx
index 23e671180e980..777b0a94f0f3d 100644
--- a/src/legacy/ui/public/vis/editors/default/controls/components/number_list/number_row.tsx
+++ b/src/legacy/ui/public/vis/editors/default/controls/components/number_list/number_row.tsx
@@ -21,7 +21,7 @@ import React, { useCallback } from 'react';
import { EuiFieldNumber, EuiFlexGroup, EuiFlexItem, EuiButtonIcon } from '@elastic/eui';
import { i18n } from '@kbn/i18n';
-import { Range } from '../../../../../../utils/range';
+import { NumberListRange } from './range';
export interface NumberRowProps {
autoFocus: boolean;
@@ -29,7 +29,7 @@ export interface NumberRowProps {
isInvalid: boolean;
labelledbyId: string;
model: NumberRowModel;
- range: Range;
+ range: NumberListRange;
onBlur(): void;
onChange({ id, value }: { id: string; value: string }): void;
onDelete(index: string): void;
diff --git a/src/legacy/ui/public/utils/__tests__/range.js b/src/legacy/ui/public/vis/editors/default/controls/components/number_list/range.test.ts
similarity index 66%
rename from src/legacy/ui/public/utils/__tests__/range.js
rename to src/legacy/ui/public/vis/editors/default/controls/components/number_list/range.test.ts
index e7947894d3e22..e9090e5b38ef7 100644
--- a/src/legacy/ui/public/utils/__tests__/range.js
+++ b/src/legacy/ui/public/vis/editors/default/controls/components/number_list/range.test.ts
@@ -17,32 +17,30 @@
* under the License.
*/
-import _ from 'lodash';
-import expect from '@kbn/expect';
-import { parseRange } from '../range';
+import { forOwn } from 'lodash';
+import { parseRange } from './range';
-describe('Range parsing utility', function () {
-
- it('throws an error for inputs that are not formatted properly', function () {
- expect(function () {
+describe('Range parsing utility', () => {
+ test('throws an error for inputs that are not formatted properly', () => {
+ expect(() => {
parseRange('');
- }).to.throwException(TypeError);
+ }).toThrowError(TypeError);
- expect(function () {
+ expect(function() {
parseRange('p10202');
- }).to.throwException(TypeError);
+ }).toThrowError(TypeError);
- expect(function () {
+ expect(function() {
parseRange('{0,100}');
- }).to.throwException(TypeError);
+ }).toThrowError(TypeError);
- expect(function () {
+ expect(function() {
parseRange('[0,100');
- }).to.throwException(TypeError);
+ }).toThrowError(TypeError);
- expect(function () {
+ expect(function() {
parseRange(')0,100(');
- }).to.throwException(TypeError);
+ }).toThrowError(TypeError);
});
const tests = {
@@ -51,52 +49,52 @@ describe('Range parsing utility', function () {
min: 0,
max: 100,
minInclusive: true,
- maxInclusive: true
+ maxInclusive: true,
},
within: [
[0, true],
[0.0000001, true],
[1, true],
[99.99999, true],
- [100, true]
- ]
+ [100, true],
+ ],
},
'(26.3 , 42]': {
props: {
min: 26.3,
max: 42,
minInclusive: false,
- maxInclusive: true
+ maxInclusive: true,
},
within: [
[26.2999999, false],
[26.3000001, true],
[30, true],
[41, true],
- [42, true]
- ]
+ [42, true],
+ ],
},
'(-50,50)': {
props: {
min: -50,
max: 50,
minInclusive: false,
- maxInclusive: false
+ maxInclusive: false,
},
within: [
[-50, false],
[-49.99999, true],
[0, true],
[49.99999, true],
- [50, false]
- ]
+ [50, false],
+ ],
},
'(Infinity, -Infinity)': {
props: {
min: -Infinity,
max: Infinity,
minInclusive: false,
- maxInclusive: false
+ maxInclusive: false,
},
within: [
[0, true],
@@ -105,25 +103,24 @@ describe('Range parsing utility', function () {
[-10000000000, true],
[-Infinity, false],
[Infinity, false],
- ]
- }
+ ],
+ },
};
- _.forOwn(tests, function (spec, str) {
-
- describe(str, function () {
+ forOwn(tests, (spec, str: any) => {
+ // eslint-disable-next-line jest/valid-describe
+ describe(str, () => {
const range = parseRange(str);
- it('creation', function () {
- expect(range).to.eql(spec.props);
+ it('creation', () => {
+ expect(range).toEqual(spec.props);
});
- spec.within.forEach(function (tup) {
- it('#within(' + tup[0] + ')', function () {
- expect(range.within(tup[0])).to.be(tup[1]);
+ spec.within.forEach((tup: any[]) => {
+ it('#within(' + tup[0] + ')', () => {
+ expect(range.within(tup[0])).toBe(tup[1]);
});
});
});
-
});
});
diff --git a/src/legacy/ui/public/utils/range.js b/src/legacy/ui/public/vis/editors/default/controls/components/number_list/range.ts
similarity index 59%
rename from src/legacy/ui/public/utils/range.js
rename to src/legacy/ui/public/vis/editors/default/controls/components/number_list/range.ts
index 54bd1b1903346..da3b7a61aea9d 100644
--- a/src/legacy/ui/public/utils/range.js
+++ b/src/legacy/ui/public/vis/editors/default/controls/components/number_list/range.ts
@@ -17,8 +17,6 @@
* under the License.
*/
-import _ from 'lodash';
-
/**
* Regexp portion that matches our number
*
@@ -44,41 +42,44 @@ const _RE_NUMBER = '(\\-?(?:\\d+(?:\\.\\d+)?|Infinity))';
*
* @type {RegExp}
*/
-const RANGE_RE = new RegExp('^\\s*([\\[|\\(])\\s*' + _RE_NUMBER + '\\s*,\\s*' + _RE_NUMBER + '\\s*([\\]|\\)])\\s*$');
+const RANGE_RE = new RegExp(
+ '^\\s*([\\[|\\(])\\s*' + _RE_NUMBER + '\\s*,\\s*' + _RE_NUMBER + '\\s*([\\]|\\)])\\s*$'
+);
+
+export class NumberListRange {
+ constructor(
+ public minInclusive: boolean,
+ public min: number,
+ public max: number,
+ public maxInclusive: boolean
+ ) {}
-export function parseRange(input) {
+ within(n: number): boolean {
+ if ((this.min === n && !this.minInclusive) || this.min > n) return false;
+ if ((this.max === n && !this.maxInclusive) || this.max < n) return false;
+
+ return true;
+ }
+}
+export function parseRange(input: string): NumberListRange {
const match = String(input).match(RANGE_RE);
if (!match) {
throw new TypeError('expected input to be in interval notation e.g., (100, 200]');
}
- return new Range(
- match[1] === '[',
- parseFloat(match[2]),
- parseFloat(match[3]),
- match[4] === ']'
- );
-}
-
-function Range(/* minIncl, min, max, maxIncl */) {
- const args = _.toArray(arguments);
- if (args[1] > args[2]) args.reverse();
+ const args = [match[1] === '[', parseFloat(match[2]), parseFloat(match[3]), match[4] === ']'];
- this.minInclusive = args[0];
- this.min = args[1];
- this.max = args[2];
- this.maxInclusive = args[3];
-}
-
-Range.prototype.within = function (n) {
- if (this.min === n && !this.minInclusive) return false;
- if (this.min > n) return false;
-
- if (this.max === n && !this.maxInclusive) return false;
- if (this.max < n) return false;
-
- return true;
-};
+ if (args[1] > args[2]) {
+ args.reverse();
+ }
+ const [minInclusive, min, max, maxInclusive] = args;
+ return new NumberListRange(
+ minInclusive as boolean,
+ min as number,
+ max as number,
+ maxInclusive as boolean
+ );
+}
diff --git a/src/legacy/ui/public/vis/editors/default/controls/components/number_list/utils.test.ts b/src/legacy/ui/public/vis/editors/default/controls/components/number_list/utils.test.ts
index c6772cc108762..89fb5738db379 100644
--- a/src/legacy/ui/public/vis/editors/default/controls/components/number_list/utils.test.ts
+++ b/src/legacy/ui/public/vis/editors/default/controls/components/number_list/utils.test.ts
@@ -27,12 +27,12 @@ import {
getNextModel,
getRange,
} from './utils';
-import { Range } from '../../../../../../utils/range';
+import { NumberListRange } from './range';
import { NumberRowModel } from './number_row';
describe('NumberList utils', () => {
let modelList: NumberRowModel[];
- let range: Range;
+ let range: NumberListRange;
beforeEach(() => {
modelList = [
diff --git a/src/legacy/ui/public/vis/editors/default/controls/components/number_list/utils.ts b/src/legacy/ui/public/vis/editors/default/controls/components/number_list/utils.ts
index 563e8f0a6a9b7..399253f27445c 100644
--- a/src/legacy/ui/public/vis/editors/default/controls/components/number_list/utils.ts
+++ b/src/legacy/ui/public/vis/editors/default/controls/components/number_list/utils.ts
@@ -21,7 +21,7 @@ import { last } from 'lodash';
import { i18n } from '@kbn/i18n';
import { htmlIdGenerator } from '@elastic/eui';
-import { parseRange, Range } from '../../../../../../utils/range';
+import { parseRange, NumberListRange } from './range';
import { NumberRowModel } from './number_row';
const EMPTY_STRING = '';
@@ -34,7 +34,7 @@ function parse(value: string) {
return isNaN(parsedValue) ? EMPTY_STRING : parsedValue;
}
-function getRange(range?: string): Range {
+function getRange(range?: string): NumberListRange {
try {
return range ? parseRange(range) : defaultRange;
} catch (e) {
@@ -42,7 +42,7 @@ function getRange(range?: string): Range {
}
}
-function validateValue(value: number | '', numberRange: Range) {
+function validateValue(value: number | '', numberRange: NumberListRange) {
const result: { isInvalid: boolean; error?: string } = {
isInvalid: false,
};
@@ -76,7 +76,7 @@ function validateOrder(list: Array) {
return result;
}
-function getNextModel(list: NumberRowModel[], range: Range): NumberRowModel {
+function getNextModel(list: NumberRowModel[], range: NumberListRange): NumberRowModel {
const lastValue = last(list).value;
let next = Number(lastValue) ? Number(lastValue) + 1 : 1;
@@ -104,7 +104,7 @@ function getInitModelList(list: Array): NumberRowModel[] {
function getUpdatedModels(
numberList: Array,
modelList: NumberRowModel[],
- numberRange: Range,
+ numberRange: NumberListRange,
invalidOrderModelIndex?: number
): NumberRowModel[] {
if (!numberList.length) {
diff --git a/src/legacy/ui/public/vis/editors/default/default.js b/src/legacy/ui/public/vis/editors/default/default.js
index 43d2962df0a1e..9df866d29a8a2 100644
--- a/src/legacy/ui/public/vis/editors/default/default.js
+++ b/src/legacy/ui/public/vis/editors/default/default.js
@@ -33,12 +33,11 @@ import { keyCodes } from '@elastic/eui';
import { parentPipelineAggHelper } from 'ui/agg_types/metrics/lib/parent_pipeline_agg_helper';
import { DefaultEditorSize } from '../../editor_size';
-import { VisEditorTypesRegistryProvider } from '../../../registry/vis_editor_types';
import { AggGroupNames } from './agg_groups';
import { start as embeddables } from '../../../../../core_plugins/embeddable_api/public/np_ready/public/legacy';
-const defaultEditor = function ($rootScope, $compile, getAppState) {
+const defaultEditor = function ($rootScope, $compile) {
return class DefaultEditor {
static key = 'default';
@@ -58,7 +57,7 @@ const defaultEditor = function ($rootScope, $compile, getAppState) {
}
}
- render({ uiState, timeRange, filters, query }) {
+ render({ uiState, timeRange, filters, query, appState }) {
let $scope;
const updateScope = () => {
@@ -161,7 +160,7 @@ const defaultEditor = function ($rootScope, $compile, getAppState) {
this._handler = await embeddables.getEmbeddableFactory('visualization').createFromObject(this.savedObj, {
uiState: uiState,
- appState: getAppState(),
+ appState,
timeRange: timeRange,
filters: filters || [],
query: query,
@@ -195,6 +194,4 @@ const defaultEditor = function ($rootScope, $compile, getAppState) {
};
};
-VisEditorTypesRegistryProvider.register(defaultEditor);
-
export { defaultEditor };
diff --git a/src/legacy/ui/public/vis/map/convert_to_geojson.js b/src/legacy/ui/public/vis/map/convert_to_geojson.js
index 77896490678ff..14c282b58beda 100644
--- a/src/legacy/ui/public/vis/map/convert_to_geojson.js
+++ b/src/legacy/ui/public/vis/map/convert_to_geojson.js
@@ -17,10 +17,9 @@
* under the License.
*/
-import { decodeGeoHash } from 'ui/utils/decode_geo_hash';
+import { decodeGeoHash } from './decode_geo_hash';
import { gridDimensions } from './grid_dimensions';
-
export function convertToGeoJson(tabifiedResponse, { geohash, geocentroid, metric }) {
let features;
diff --git a/src/legacy/ui/public/utils/__tests__/decode_geo_hash.test.js b/src/legacy/ui/public/vis/map/decode_geo_hash.test.ts
similarity index 75%
rename from src/legacy/ui/public/utils/__tests__/decode_geo_hash.test.js
rename to src/legacy/ui/public/vis/map/decode_geo_hash.test.ts
index 1ffe9ca7b4df2..c1ca7e4c80383 100644
--- a/src/legacy/ui/public/utils/__tests__/decode_geo_hash.test.js
+++ b/src/legacy/ui/public/vis/map/decode_geo_hash.test.ts
@@ -17,27 +17,18 @@
* under the License.
*/
-import { geohashColumns, decodeGeoHash } from '../decode_geo_hash';
+import { geohashColumns, decodeGeoHash } from './decode_geo_hash';
-test('geohashColumns', function () {
+test('geohashColumns', () => {
expect(geohashColumns(1)).toBe(8);
expect(geohashColumns(2)).toBe(8 * 4);
expect(geohashColumns(3)).toBe(8 * 4 * 8);
expect(geohashColumns(4)).toBe(8 * 4 * 8 * 4);
});
-test('decodeGeoHash', function () {
+test('decodeGeoHash', () => {
expect(decodeGeoHash('drm3btev3e86')).toEqual({
- latitude: [
- 41.119999922811985,
- 41.12000009045005,
- 41.12000000663102,
- ],
- longitude: [
- -71.34000029414892,
- -71.3399999588728,
- -71.34000012651086,
- ],
+ latitude: [41.119999922811985, 41.12000009045005, 41.12000000663102],
+ longitude: [-71.34000029414892, -71.3399999588728, -71.34000012651086],
});
});
-
diff --git a/src/legacy/ui/public/utils/decode_geo_hash.ts b/src/legacy/ui/public/vis/map/decode_geo_hash.ts
similarity index 100%
rename from src/legacy/ui/public/utils/decode_geo_hash.ts
rename to src/legacy/ui/public/vis/map/decode_geo_hash.ts
diff --git a/src/legacy/ui/public/vis/map/kibana_map.js b/src/legacy/ui/public/vis/map/kibana_map.js
index dc57809b6570f..cb618444af7ce 100644
--- a/src/legacy/ui/public/vis/map/kibana_map.js
+++ b/src/legacy/ui/public/vis/map/kibana_map.js
@@ -22,7 +22,7 @@ import { createZoomWarningMsg } from './map_messages';
import L from 'leaflet';
import $ from 'jquery';
import _ from 'lodash';
-import { zoomToPrecision } from '../../utils/zoom_to_precision';
+import { zoomToPrecision } from './zoom_to_precision';
import { i18n } from '@kbn/i18n';
import { ORIGIN } from '../../../../core_plugins/tile_map/common/origin';
diff --git a/src/legacy/ui/public/utils/zoom_to_precision.js b/src/legacy/ui/public/vis/map/zoom_to_precision.ts
similarity index 52%
rename from src/legacy/ui/public/utils/zoom_to_precision.js
rename to src/legacy/ui/public/vis/map/zoom_to_precision.ts
index f5c16b640d127..552c509590286 100644
--- a/src/legacy/ui/public/utils/zoom_to_precision.js
+++ b/src/legacy/ui/public/vis/map/zoom_to_precision.ts
@@ -19,39 +19,42 @@
import { geohashColumns } from './decode_geo_hash';
-const maxPrecision = 12;
-/**
- * Map Leaflet zoom levels to geohash precision levels.
- * The size of a geohash column-width on the map should be at least `minGeohashPixels` pixels wide.
- */
-
-
+const defaultMaxPrecision = 12;
+const minGeoHashPixels = 16;
-
-const zoomPrecisionMap = {};
-const minGeohashPixels = 16;
-
-function calculateZoomToPrecisionMap(maxZoom) {
+const calculateZoomToPrecisionMap = (maxZoom: number): Map => {
+ /**
+ * Map Leaflet zoom levels to geohash precision levels.
+ * The size of a geohash column-width on the map should be at least `minGeohashPixels` pixels wide.
+ */
+ const zoomPrecisionMap = new Map();
for (let zoom = 0; zoom <= maxZoom; zoom += 1) {
- if (typeof zoomPrecisionMap[zoom] === 'number') {
+ if (typeof zoomPrecisionMap.get(zoom) === 'number') {
continue;
}
+
const worldPixels = 256 * Math.pow(2, zoom);
- zoomPrecisionMap[zoom] = 1;
- for (let precision = 2; precision <= maxPrecision; precision += 1) {
+
+ zoomPrecisionMap.set(zoom, 1);
+
+ for (let precision = 2; precision <= defaultMaxPrecision; precision += 1) {
const columns = geohashColumns(precision);
- if ((worldPixels / columns) >= minGeohashPixels) {
- zoomPrecisionMap[zoom] = precision;
+
+ if (worldPixels / columns >= minGeoHashPixels) {
+ zoomPrecisionMap.set(zoom, precision);
} else {
break;
}
}
}
-}
+ return zoomPrecisionMap;
+};
+
+export function zoomToPrecision(mapZoom: number, maxPrecision: number, maxZoom: number) {
+ const zoomPrecisionMap = calculateZoomToPrecisionMap(typeof maxZoom === 'number' ? maxZoom : 21);
+ const precision = zoomPrecisionMap.get(mapZoom);
-export function zoomToPrecision(mapZoom, maxPrecision, maxZoom) {
- calculateZoomToPrecisionMap(typeof maxZoom === 'number' ? maxZoom : 21);
- return Math.min(zoomPrecisionMap[mapZoom], maxPrecision);
+ return precision ? Math.min(precision, maxPrecision) : maxPrecision;
}
diff --git a/src/legacy/ui/ui_exports/ui_export_defaults.js b/src/legacy/ui/ui_exports/ui_export_defaults.js
index 291d9feea3c40..80bee41175771 100644
--- a/src/legacy/ui/ui_exports/ui_export_defaults.js
+++ b/src/legacy/ui/ui_exports/ui_export_defaults.js
@@ -50,12 +50,6 @@ export const UI_EXPORT_DEFAULTS = {
fieldFormatEditors: [
'ui/field_editor/components/field_format_editor/register'
],
- visEditorTypes: [
- 'ui/vis/editors/default/default',
- ],
- embeddableFactories: [
- 'plugins/kibana/visualize/embeddable/visualize_embeddable_factory',
- ],
search: [
'ui/courier/search_strategy/default_search_strategy',
],
diff --git a/src/plugins/dashboard_embeddable_container/public/embeddable/dashboard_container.tsx b/src/plugins/dashboard_embeddable_container/public/embeddable/dashboard_container.tsx
index 684aa93779bc1..021a1a9d1e64a 100644
--- a/src/plugins/dashboard_embeddable_container/public/embeddable/dashboard_container.tsx
+++ b/src/plugins/dashboard_embeddable_container/public/embeddable/dashboard_container.tsx
@@ -90,6 +90,8 @@ export type DashboardReactContext = KibanaReactContext {
public readonly type = DASHBOARD_CONTAINER_TYPE;
+ public renderEmpty?: undefined | (() => React.ReactNode);
+
constructor(
initialInput: DashboardContainerInput,
private readonly options: DashboardContainerOptions,
@@ -124,7 +126,7 @@ export class DashboardContainer extends Container
-
+
,
dom
diff --git a/src/plugins/dashboard_embeddable_container/public/embeddable/grid/_dashboard_grid.scss b/src/plugins/dashboard_embeddable_container/public/embeddable/grid/_dashboard_grid.scss
index 24b813ec58964..0bd356522c7fa 100644
--- a/src/plugins/dashboard_embeddable_container/public/embeddable/grid/_dashboard_grid.scss
+++ b/src/plugins/dashboard_embeddable_container/public/embeddable/grid/_dashboard_grid.scss
@@ -34,7 +34,7 @@
.dshLayout-isMaximizedPanel {
height: 100% !important; /* 1. */
width: 100%;
- position: absolute;
+ position: absolute !important;
}
/**
diff --git a/src/plugins/dashboard_embeddable_container/public/embeddable/viewport/dashboard_viewport.test.tsx b/src/plugins/dashboard_embeddable_container/public/embeddable/viewport/dashboard_viewport.test.tsx
index a2f7b8dc28fb0..e3d9b8552f060 100644
--- a/src/plugins/dashboard_embeddable_container/public/embeddable/viewport/dashboard_viewport.test.tsx
+++ b/src/plugins/dashboard_embeddable_container/public/embeddable/viewport/dashboard_viewport.test.tsx
@@ -121,6 +121,24 @@ test('renders DashboardViewport with no visualizations', () => {
component.unmount();
});
+test('renders DashboardEmptyScreen', () => {
+ const renderEmptyScreen = jest.fn();
+ const { props, options } = getProps({ renderEmpty: renderEmptyScreen });
+ props.container.updateInput({ isEmptyState: true });
+ const component = mount(
+
+
+
+
+
+ );
+ const dashboardEmptyScreenDiv = component.find('.dshDashboardEmptyScreen');
+ expect(dashboardEmptyScreenDiv.length).toBe(1);
+ expect(renderEmptyScreen).toHaveBeenCalled();
+
+ component.unmount();
+});
+
test('renders exit full screen button when in full screen mode', async () => {
const { props, options } = getProps();
props.container.updateInput({ isFullScreenMode: true });
@@ -153,6 +171,39 @@ test('renders exit full screen button when in full screen mode', async () => {
component.unmount();
});
+test('renders exit full screen button when in full screen mode and empty screen', async () => {
+ const renderEmptyScreen = jest.fn();
+ renderEmptyScreen.mockReturnValue(React.createElement('div'));
+ const { props, options } = getProps({ renderEmpty: renderEmptyScreen });
+ props.container.updateInput({ isEmptyState: true, isFullScreenMode: true });
+ const component = mount(
+
+
+
+
+
+ );
+ expect(
+ (component
+ .find('.dshDashboardEmptyScreen')
+ .childAt(0)
+ .type() as any).name
+ ).toBe('ExitFullScreenButton');
+
+ props.container.updateInput({ isFullScreenMode: false });
+ component.update();
+ await nextTick();
+
+ expect(
+ (component
+ .find('.dshDashboardEmptyScreen')
+ .childAt(0)
+ .type() as any).name
+ ).not.toBe('ExitFullScreenButton');
+
+ component.unmount();
+});
+
test('DashboardViewport unmount unsubscribes', async done => {
const { props, options } = getProps();
const component = mount(
diff --git a/src/plugins/dashboard_embeddable_container/public/embeddable/viewport/dashboard_viewport.tsx b/src/plugins/dashboard_embeddable_container/public/embeddable/viewport/dashboard_viewport.tsx
index 13407e5e33725..e7fd379898dd1 100644
--- a/src/plugins/dashboard_embeddable_container/public/embeddable/viewport/dashboard_viewport.tsx
+++ b/src/plugins/dashboard_embeddable_container/public/embeddable/viewport/dashboard_viewport.tsx
@@ -26,6 +26,7 @@ import { context } from '../../../../kibana_react/public';
export interface DashboardViewportProps {
container: DashboardContainer;
+ renderEmpty?: () => React.ReactNode;
}
interface State {
@@ -34,6 +35,7 @@ interface State {
title: string;
description?: string;
panels: { [key: string]: PanelState };
+ isEmptyState?: boolean;
}
export class DashboardViewport extends React.Component {
@@ -44,26 +46,40 @@ export class DashboardViewport extends React.Component {
- const { isFullScreenMode, useMargins, title, description } = this.props.container.getInput();
+ const {
+ isFullScreenMode,
+ useMargins,
+ title,
+ description,
+ isEmptyState,
+ } = this.props.container.getInput();
if (this.mounted) {
this.setState({
isFullScreenMode,
description,
useMargins,
title,
+ isEmptyState,
});
}
});
@@ -82,19 +98,33 @@ export class DashboardViewport extends React.Component
+ {isFullScreenMode && (
+
+ )}
+ {renderEmpty && renderEmpty()}
+
+ );
+ }
+
+ private renderContainerScreen() {
const { container } = this.props;
+ const { isFullScreenMode, panels, title, description, useMargins } = this.state;
return (
- {this.state.isFullScreenMode && (
+ {isFullScreenMode && (
@@ -103,4 +133,13 @@ export class DashboardViewport extends React.Component
);
}
+
+ public render() {
+ return (
+
+ {this.state.isEmptyState ? this.renderEmptyScreen() : null}
+ {this.renderContainerScreen()}
+
+ );
+ }
}
diff --git a/src/plugins/dashboard_embeddable_container/public/plugin.tsx b/src/plugins/dashboard_embeddable_container/public/plugin.tsx
index 79cc9b6980545..d18fbba239ec0 100644
--- a/src/plugins/dashboard_embeddable_container/public/plugin.tsx
+++ b/src/plugins/dashboard_embeddable_container/public/plugin.tsx
@@ -27,7 +27,7 @@ import { ExpandPanelAction, ReplacePanelAction } from '.';
import { DashboardContainerFactory } from './embeddable/dashboard_container_factory';
import { Start as InspectorStartContract } from '../../../plugins/inspector/public';
import {
- SavedObjectFinder as SavedObjectFinderUi,
+ SavedObjectFinderUi,
SavedObjectFinderProps,
ExitFullScreenButton as ExitFullScreenButtonUi,
ExitFullScreenButtonProps,
diff --git a/src/plugins/data/common/es_query/__fixtures__/index_pattern_response.ts b/src/plugins/data/common/es_query/__fixtures__/index_pattern_response.ts
new file mode 100644
index 0000000000000..1784a2650a95a
--- /dev/null
+++ b/src/plugins/data/common/es_query/__fixtures__/index_pattern_response.ts
@@ -0,0 +1,322 @@
+/*
+ * 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 const indexPatternResponse = {
+ id: 'logstash-*',
+ title: 'logstash-*',
+ fields: [
+ {
+ name: 'bytes',
+ type: 'number',
+ esTypes: ['long'],
+ count: 10,
+ scripted: false,
+ searchable: true,
+ aggregatable: true,
+ readFromDocValues: true,
+ },
+ {
+ name: 'ssl',
+ type: 'boolean',
+ esTypes: ['boolean'],
+ count: 20,
+ scripted: false,
+ searchable: true,
+ aggregatable: true,
+ readFromDocValues: true,
+ },
+ {
+ name: '@timestamp',
+ type: 'date',
+ esTypes: ['date'],
+ count: 30,
+ scripted: false,
+ searchable: true,
+ aggregatable: true,
+ readFromDocValues: true,
+ },
+ {
+ name: 'time',
+ type: 'date',
+ esTypes: ['date'],
+ count: 30,
+ scripted: false,
+ searchable: true,
+ aggregatable: true,
+ readFromDocValues: true,
+ },
+ {
+ name: '@tags',
+ type: 'string',
+ esTypes: ['keyword'],
+ count: 0,
+ scripted: false,
+ searchable: true,
+ aggregatable: true,
+ readFromDocValues: true,
+ },
+ {
+ name: 'utc_time',
+ type: 'date',
+ esTypes: ['date'],
+ count: 0,
+ scripted: false,
+ searchable: true,
+ aggregatable: true,
+ readFromDocValues: true,
+ },
+ {
+ name: 'phpmemory',
+ type: 'number',
+ esTypes: ['integer'],
+ count: 0,
+ scripted: false,
+ searchable: true,
+ aggregatable: true,
+ readFromDocValues: true,
+ },
+ {
+ name: 'ip',
+ type: 'ip',
+ esTypes: ['ip'],
+ count: 0,
+ scripted: false,
+ searchable: true,
+ aggregatable: true,
+ readFromDocValues: true,
+ },
+ {
+ name: 'request_body',
+ type: 'attachment',
+ esTypes: ['attachment'],
+ count: 0,
+ scripted: false,
+ searchable: true,
+ aggregatable: true,
+ readFromDocValues: true,
+ },
+ {
+ name: 'point',
+ type: 'geo_point',
+ esTypes: ['geo_point'],
+ count: 0,
+ scripted: false,
+ searchable: true,
+ aggregatable: true,
+ readFromDocValues: true,
+ },
+ {
+ name: 'area',
+ type: 'geo_shape',
+ esTypes: ['geo_shape'],
+ count: 0,
+ scripted: false,
+ searchable: true,
+ aggregatable: true,
+ readFromDocValues: true,
+ },
+ {
+ name: 'hashed',
+ type: 'murmur3',
+ esTypes: ['murmur3'],
+ count: 0,
+ scripted: false,
+ searchable: true,
+ aggregatable: false,
+ readFromDocValues: false,
+ },
+ {
+ name: 'geo.coordinates',
+ type: 'geo_point',
+ esTypes: ['geo_point'],
+ count: 0,
+ scripted: false,
+ searchable: true,
+ aggregatable: true,
+ readFromDocValues: true,
+ },
+ {
+ name: 'extension',
+ type: 'string',
+ esTypes: ['keyword'],
+ count: 0,
+ scripted: false,
+ searchable: true,
+ aggregatable: true,
+ readFromDocValues: true,
+ },
+ {
+ name: 'machine.os',
+ type: 'string',
+ esTypes: ['text'],
+ count: 0,
+ scripted: false,
+ searchable: true,
+ aggregatable: true,
+ readFromDocValues: false,
+ },
+ {
+ name: 'machine.os.raw',
+ type: 'string',
+ esTypes: ['keyword'],
+ count: 0,
+ scripted: false,
+ searchable: true,
+ aggregatable: true,
+ readFromDocValues: true,
+ subType: { multi: { parent: 'machine.os' } },
+ },
+ {
+ name: 'geo.src',
+ type: 'string',
+ esTypes: ['keyword'],
+ count: 0,
+ scripted: false,
+ searchable: true,
+ aggregatable: true,
+ readFromDocValues: true,
+ },
+ {
+ name: '_id',
+ type: 'string',
+ esTypes: ['_id'],
+ count: 0,
+ scripted: false,
+ searchable: true,
+ aggregatable: true,
+ readFromDocValues: false,
+ },
+ {
+ name: '_type',
+ type: 'string',
+ esTypes: ['_type'],
+ count: 0,
+ scripted: false,
+ searchable: true,
+ aggregatable: true,
+ readFromDocValues: false,
+ },
+ {
+ name: '_source',
+ type: '_source',
+ esTypes: ['_source'],
+ count: 0,
+ scripted: false,
+ searchable: true,
+ aggregatable: true,
+ readFromDocValues: false,
+ },
+ {
+ name: 'non-filterable',
+ type: 'string',
+ esTypes: ['text'],
+ count: 0,
+ scripted: false,
+ searchable: false,
+ aggregatable: true,
+ readFromDocValues: false,
+ },
+ {
+ name: 'non-sortable',
+ type: 'string',
+ esTypes: ['text'],
+ count: 0,
+ scripted: false,
+ searchable: false,
+ aggregatable: false,
+ readFromDocValues: false,
+ },
+ {
+ name: 'custom_user_field',
+ type: 'conflict',
+ esTypes: ['long', 'text'],
+ count: 0,
+ scripted: false,
+ searchable: true,
+ aggregatable: true,
+ readFromDocValues: true,
+ },
+ {
+ name: 'script string',
+ type: 'string',
+ count: 0,
+ scripted: true,
+ script: "'i am a string'",
+ lang: 'expression',
+ searchable: true,
+ aggregatable: true,
+ readFromDocValues: false,
+ },
+ {
+ name: 'script number',
+ type: 'number',
+ count: 0,
+ scripted: true,
+ script: '1234',
+ lang: 'expression',
+ searchable: true,
+ aggregatable: true,
+ readFromDocValues: false,
+ },
+ {
+ name: 'script date',
+ type: 'date',
+ count: 0,
+ scripted: true,
+ script: '1234',
+ lang: 'painless',
+ searchable: true,
+ aggregatable: true,
+ readFromDocValues: false,
+ },
+ {
+ name: 'script murmur3',
+ type: 'murmur3',
+ count: 0,
+ scripted: true,
+ script: '1234',
+ lang: 'expression',
+ searchable: true,
+ aggregatable: true,
+ readFromDocValues: false,
+ },
+ {
+ name: 'nestedField.child',
+ type: 'string',
+ esTypes: ['text'],
+ count: 0,
+ scripted: false,
+ searchable: true,
+ aggregatable: false,
+ readFromDocValues: false,
+ subType: { nested: { path: 'nestedField' } },
+ },
+ {
+ name: 'nestedField.nestedChild.doublyNestedChild',
+ type: 'string',
+ esTypes: ['text'],
+ count: 0,
+ scripted: false,
+ searchable: true,
+ aggregatable: false,
+ readFromDocValues: false,
+ subType: { nested: { path: 'nestedField.nestedChild' } },
+ },
+ ],
+};
diff --git a/src/plugins/data/common/es_query/es_query/from_filters.test.ts b/src/plugins/data/common/es_query/es_query/from_filters.test.ts
index 8c1d990c389b8..a93a91a42dbf3 100644
--- a/src/plugins/data/common/es_query/es_query/from_filters.test.ts
+++ b/src/plugins/data/common/es_query/es_query/from_filters.test.ts
@@ -144,5 +144,30 @@ describe('build query', () => {
expect(result.filter).toEqual(expectedESQueries);
});
+
+ test('should wrap filters targeting nested fields in a nested query', () => {
+ const filters = [
+ {
+ exists: { field: 'nestedField.child' },
+ meta: { type: 'exists', alias: '', disabled: false, negate: false },
+ },
+ ];
+
+ const expectedESQueries = [
+ {
+ nested: {
+ path: 'nestedField',
+ query: {
+ exists: {
+ field: 'nestedField.child',
+ },
+ },
+ },
+ },
+ ];
+
+ const result = buildQueryFromFilters(filters, indexPattern);
+ expect(result.filter).toEqual(expectedESQueries);
+ });
});
});
diff --git a/src/plugins/data/common/es_query/es_query/from_filters.ts b/src/plugins/data/common/es_query/es_query/from_filters.ts
index e33040485bf47..ed91d391fc1fd 100644
--- a/src/plugins/data/common/es_query/es_query/from_filters.ts
+++ b/src/plugins/data/common/es_query/es_query/from_filters.ts
@@ -21,6 +21,7 @@ import { migrateFilter } from './migrate_filter';
import { filterMatchesIndex } from './filter_matches_index';
import { Filter, cleanFilter, isFilterDisabled } from '../filters';
import { IIndexPattern } from '../../index_patterns';
+import { handleNestedFilter } from './handle_nested_filter';
/**
* Create a filter that can be reversed for filters with negate set
@@ -59,20 +60,22 @@ export const buildQueryFromFilters = (
) => {
filters = filters.filter(filter => filter && !isFilterDisabled(filter));
- return {
- must: [],
- filter: filters
- .filter(filterNegate(false))
+ const filtersToESQueries = (negate: boolean) => {
+ return filters
+ .filter(filterNegate(negate))
.filter(filter => !ignoreFilterIfFieldNotInIndex || filterMatchesIndex(filter, indexPattern))
+ .map(filter => {
+ return migrateFilter(filter, indexPattern);
+ })
+ .map(filter => handleNestedFilter(filter, indexPattern))
.map(translateToQuery)
- .map(cleanFilter)
- .map(filter => migrateFilter(filter, indexPattern)),
+ .map(cleanFilter);
+ };
+
+ return {
+ must: [],
+ filter: filtersToESQueries(false),
should: [],
- must_not: filters
- .filter(filterNegate(true))
- .filter(filter => !ignoreFilterIfFieldNotInIndex || filterMatchesIndex(filter, indexPattern))
- .map(translateToQuery)
- .map(cleanFilter)
- .map(filter => migrateFilter(filter, indexPattern)),
+ must_not: filtersToESQueries(true),
};
};
diff --git a/src/plugins/data/common/es_query/es_query/handle_nested_filter.test.ts b/src/plugins/data/common/es_query/es_query/handle_nested_filter.test.ts
new file mode 100644
index 0000000000000..594b2641c39be
--- /dev/null
+++ b/src/plugins/data/common/es_query/es_query/handle_nested_filter.test.ts
@@ -0,0 +1,91 @@
+/*
+ * 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 { handleNestedFilter } from './handle_nested_filter';
+import { fields } from '../../index_patterns/mocks';
+import { buildPhraseFilter, buildQueryFilter } from '../filters';
+import { IFieldType, IIndexPattern } from '../../index_patterns';
+
+describe('handleNestedFilter', function() {
+ const indexPattern: IIndexPattern = ({
+ id: 'logstash-*',
+ fields,
+ } as unknown) as IIndexPattern;
+
+ it("should return the filter's query wrapped in nested query if the target field is nested", () => {
+ const field = getField('nestedField.child');
+ const filter = buildPhraseFilter(field!, 'foo', indexPattern);
+ const result = handleNestedFilter(filter, indexPattern);
+ expect(result).toEqual({
+ meta: {
+ index: 'logstash-*',
+ },
+ nested: {
+ path: 'nestedField',
+ query: {
+ match_phrase: {
+ 'nestedField.child': 'foo',
+ },
+ },
+ },
+ });
+ });
+
+ it('should return filter untouched if it does not target a nested field', () => {
+ const field = getField('extension');
+ const filter = buildPhraseFilter(field!, 'jpg', indexPattern);
+ const result = handleNestedFilter(filter, indexPattern);
+ expect(result).toBe(filter);
+ });
+
+ it('should return filter untouched if it does not target a field from the given index pattern', () => {
+ const field = { ...getField('extension'), name: 'notarealfield' };
+ const filter = buildPhraseFilter(field as IFieldType, 'jpg', indexPattern);
+ const result = handleNestedFilter(filter, indexPattern);
+ expect(result).toBe(filter);
+ });
+
+ it('should return filter untouched if no index pattern is provided', () => {
+ const field = getField('extension');
+ const filter = buildPhraseFilter(field!, 'jpg', indexPattern);
+ const result = handleNestedFilter(filter);
+ expect(result).toBe(filter);
+ });
+
+ it('should return the filter untouched if a target field cannot be determined', () => {
+ // for example, we don't support query_string queries
+ const filter = buildQueryFilter(
+ {
+ query: {
+ query_string: {
+ query: 'response:200',
+ },
+ },
+ },
+ 'logstash-*',
+ 'foo'
+ );
+ const result = handleNestedFilter(filter);
+ expect(result).toBe(filter);
+ });
+
+ function getField(name: string) {
+ return indexPattern.fields.find(field => field.name === name);
+ }
+});
diff --git a/src/plugins/data/common/es_query/es_query/handle_nested_filter.ts b/src/plugins/data/common/es_query/es_query/handle_nested_filter.ts
new file mode 100644
index 0000000000000..27be7925fe00c
--- /dev/null
+++ b/src/plugins/data/common/es_query/es_query/handle_nested_filter.ts
@@ -0,0 +1,45 @@
+/*
+ * 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 { getFilterField, cleanFilter, Filter } from '../filters';
+import { IIndexPattern } from '../../index_patterns';
+
+export const handleNestedFilter = (filter: Filter, indexPattern?: IIndexPattern) => {
+ if (!indexPattern) return filter;
+
+ const fieldName = getFilterField(filter);
+ if (!fieldName) {
+ return filter;
+ }
+
+ const field = indexPattern.fields.find(indexPatternField => indexPatternField.name === fieldName);
+ if (!field || !field.subType || !field.subType.nested || !field.subType.nested.path) {
+ return filter;
+ }
+
+ const query = cleanFilter(filter);
+
+ return {
+ meta: filter.meta,
+ nested: {
+ path: field.subType.nested.path,
+ query: query.query || query,
+ },
+ };
+};
diff --git a/src/plugins/data/common/es_query/es_query/migrate_filter.test.ts b/src/plugins/data/common/es_query/es_query/migrate_filter.test.ts
index e01240da87543..698d7bb48e685 100644
--- a/src/plugins/data/common/es_query/es_query/migrate_filter.test.ts
+++ b/src/plugins/data/common/es_query/es_query/migrate_filter.test.ts
@@ -23,26 +23,32 @@ import { PhraseFilter, MatchAllFilter } from '../filters';
describe('migrateFilter', function() {
const oldMatchPhraseFilter = ({
- match: {
- fieldFoo: {
- query: 'foobar',
- type: 'phrase',
+ query: {
+ match: {
+ fieldFoo: {
+ query: 'foobar',
+ type: 'phrase',
+ },
},
},
+ meta: {},
} as unknown) as DeprecatedMatchPhraseFilter;
const newMatchPhraseFilter = ({
- match_phrase: {
- fieldFoo: {
- query: 'foobar',
+ query: {
+ match_phrase: {
+ fieldFoo: {
+ query: 'foobar',
+ },
},
},
+ meta: {},
} as unknown) as PhraseFilter;
it('should migrate match filters of type phrase', function() {
const migratedFilter = migrateFilter(oldMatchPhraseFilter, undefined);
- expect(isEqual(migratedFilter, newMatchPhraseFilter)).toBe(true);
+ expect(migratedFilter).toEqual(newMatchPhraseFilter);
});
it('should not modify the original filter', function() {
diff --git a/src/plugins/data/common/es_query/es_query/migrate_filter.ts b/src/plugins/data/common/es_query/es_query/migrate_filter.ts
index fdc40768ebe41..22fbfe0e1ab08 100644
--- a/src/plugins/data/common/es_query/es_query/migrate_filter.ts
+++ b/src/plugins/data/common/es_query/es_query/migrate_filter.ts
@@ -22,31 +22,27 @@ import { getConvertedValueForField } from '../filters';
import { Filter } from '../filters';
import { IIndexPattern } from '../../index_patterns';
-/** @deprecated
- * see https://github.com/elastic/elasticsearch/pull/17508
- * */
export interface DeprecatedMatchPhraseFilter extends Filter {
- match: {
- [field: string]: {
- query: any;
- type: 'phrase';
+ query: {
+ match: {
+ [field: string]: {
+ query: any;
+ type: 'phrase';
+ };
};
};
}
-/** @deprecated
- * see https://github.com/elastic/elasticsearch/pull/17508
- * */
-function isMatchPhraseFilter(filter: any): filter is DeprecatedMatchPhraseFilter {
- const fieldName = filter.match && Object.keys(filter.match)[0];
+function isDeprecatedMatchPhraseFilter(filter: any): filter is DeprecatedMatchPhraseFilter {
+ const fieldName = filter.query && filter.query.match && Object.keys(filter.query.match)[0];
- return Boolean(fieldName && get(filter, ['match', fieldName, 'type']) === 'phrase');
+ return Boolean(fieldName && get(filter, ['query', 'match', fieldName, 'type']) === 'phrase');
}
export function migrateFilter(filter: Filter, indexPattern?: IIndexPattern) {
- if (isMatchPhraseFilter(filter)) {
- const fieldName = Object.keys(filter.match)[0];
- const params: Record = get(filter, ['match', fieldName]);
+ if (isDeprecatedMatchPhraseFilter(filter)) {
+ const fieldName = Object.keys(filter.query.match)[0];
+ const params: Record = get(filter, ['query', 'match', fieldName]);
if (indexPattern) {
const field = indexPattern.fields.find(f => f.name === fieldName);
@@ -55,8 +51,11 @@ export function migrateFilter(filter: Filter, indexPattern?: IIndexPattern) {
}
}
return {
- match_phrase: {
- [fieldName]: omit(params, 'type'),
+ ...filter,
+ query: {
+ match_phrase: {
+ [fieldName]: omit(params, 'type'),
+ },
},
};
}
diff --git a/src/plugins/data/common/es_query/filters/exists_filter.test.ts b/src/plugins/data/common/es_query/filters/exists_filter.test.ts
new file mode 100644
index 0000000000000..af52192dd85e4
--- /dev/null
+++ b/src/plugins/data/common/es_query/filters/exists_filter.test.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 { buildExistsFilter, getExistsFilterField } from './exists_filter';
+import { IIndexPattern } from '../../index_patterns';
+import { fields } from '../../index_patterns/fields/fields.mocks.ts';
+
+describe('exists filter', function() {
+ const indexPattern: IIndexPattern = ({
+ fields,
+ } as unknown) as IIndexPattern;
+
+ describe('getExistsFilterField', function() {
+ it('should return the name of the field an exists query is targeting', () => {
+ const field = indexPattern.fields.find(patternField => patternField.name === 'extension');
+ const filter = buildExistsFilter(field!, indexPattern);
+ const result = getExistsFilterField(filter);
+ expect(result).toBe('extension');
+ });
+ });
+});
diff --git a/src/plugins/data/common/es_query/filters/exists_filter.ts b/src/plugins/data/common/es_query/filters/exists_filter.ts
index a20a4f0634766..035983dc446dc 100644
--- a/src/plugins/data/common/es_query/filters/exists_filter.ts
+++ b/src/plugins/data/common/es_query/filters/exists_filter.ts
@@ -33,6 +33,10 @@ export type ExistsFilter = Filter & {
export const isExistsFilter = (filter: any): filter is ExistsFilter => filter && filter.exists;
+export const getExistsFilterField = (filter: ExistsFilter) => {
+ return filter.exists && filter.exists.field;
+};
+
export const buildExistsFilter = (field: IFieldType, indexPattern: IIndexPattern) => {
return {
meta: {
diff --git a/src/plugins/data/common/es_query/filters/geo_bounding_box_filter.test.ts b/src/plugins/data/common/es_query/filters/geo_bounding_box_filter.test.ts
new file mode 100644
index 0000000000000..63c3a59044c1f
--- /dev/null
+++ b/src/plugins/data/common/es_query/filters/geo_bounding_box_filter.test.ts
@@ -0,0 +1,47 @@
+/*
+ * 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 { getGeoBoundingBoxFilterField } from './geo_bounding_box_filter';
+
+describe('geo_bounding_box filter', function() {
+ describe('getGeoBoundingBoxFilterField', function() {
+ it('should return the name of the field a geo_bounding_box query is targeting', () => {
+ const filter = {
+ geo_bounding_box: {
+ geoPointField: {
+ bottom_right: { lat: 1, lon: 1 },
+ top_left: { lat: 1, lon: 1 },
+ },
+ ignore_unmapped: true,
+ },
+ meta: {
+ disabled: false,
+ negate: false,
+ alias: null,
+ params: {
+ bottom_right: { lat: 1, lon: 1 },
+ top_left: { lat: 1, lon: 1 },
+ },
+ },
+ };
+ const result = getGeoBoundingBoxFilterField(filter);
+ expect(result).toBe('geoPointField');
+ });
+ });
+});
diff --git a/src/plugins/data/common/es_query/filters/geo_bounding_box_filter.ts b/src/plugins/data/common/es_query/filters/geo_bounding_box_filter.ts
index f4673af96b2cd..619903954ff55 100644
--- a/src/plugins/data/common/es_query/filters/geo_bounding_box_filter.ts
+++ b/src/plugins/data/common/es_query/filters/geo_bounding_box_filter.ts
@@ -33,3 +33,10 @@ export type GeoBoundingBoxFilter = Filter & {
export const isGeoBoundingBoxFilter = (filter: any): filter is GeoBoundingBoxFilter =>
filter && filter.geo_bounding_box;
+
+export const getGeoBoundingBoxFilterField = (filter: GeoBoundingBoxFilter) => {
+ return (
+ filter.geo_bounding_box &&
+ Object.keys(filter.geo_bounding_box).find(key => key !== 'ignore_unmapped')
+ );
+};
diff --git a/src/plugins/data/common/es_query/filters/geo_polygon_filter.test.ts b/src/plugins/data/common/es_query/filters/geo_polygon_filter.test.ts
new file mode 100644
index 0000000000000..ba8e43b0cea85
--- /dev/null
+++ b/src/plugins/data/common/es_query/filters/geo_polygon_filter.test.ts
@@ -0,0 +1,45 @@
+/*
+ * 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 { getGeoPolygonFilterField } from './geo_polygon_filter';
+
+describe('geo_polygon filter', function() {
+ describe('getGeoPolygonFilterField', function() {
+ it('should return the name of the field a geo_polygon query is targeting', () => {
+ const filter = {
+ geo_polygon: {
+ geoPointField: {
+ points: [{ lat: 1, lon: 1 }],
+ },
+ ignore_unmapped: true,
+ },
+ meta: {
+ disabled: false,
+ negate: false,
+ alias: null,
+ params: {
+ points: [{ lat: 1, lon: 1 }],
+ },
+ },
+ };
+ const result = getGeoPolygonFilterField(filter);
+ expect(result).toBe('geoPointField');
+ });
+ });
+});
diff --git a/src/plugins/data/common/es_query/filters/geo_polygon_filter.ts b/src/plugins/data/common/es_query/filters/geo_polygon_filter.ts
index 4cf82a92d2cef..03367feb83ee4 100644
--- a/src/plugins/data/common/es_query/filters/geo_polygon_filter.ts
+++ b/src/plugins/data/common/es_query/filters/geo_polygon_filter.ts
@@ -32,3 +32,9 @@ export type GeoPolygonFilter = Filter & {
export const isGeoPolygonFilter = (filter: any): filter is GeoPolygonFilter =>
filter && filter.geo_polygon;
+
+export const getGeoPolygonFilterField = (filter: GeoPolygonFilter) => {
+ return (
+ filter.geo_polygon && Object.keys(filter.geo_polygon).find(key => key !== 'ignore_unmapped')
+ );
+};
diff --git a/src/plugins/data/common/es_query/filters/get_filter_field.test.ts b/src/plugins/data/common/es_query/filters/get_filter_field.test.ts
new file mode 100644
index 0000000000000..2fc8ffef9713b
--- /dev/null
+++ b/src/plugins/data/common/es_query/filters/get_filter_field.test.ts
@@ -0,0 +1,54 @@
+/*
+ * 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 { buildPhraseFilter } from './phrase_filter';
+import { buildQueryFilter } from './query_string_filter';
+import { getFilterField } from './get_filter_field';
+import { IIndexPattern } from '../../index_patterns';
+import { fields } from '../../index_patterns/fields/fields.mocks.ts';
+
+describe('getFilterField', function() {
+ const indexPattern: IIndexPattern = ({
+ id: 'logstash-*',
+ fields,
+ } as unknown) as IIndexPattern;
+
+ it('should return the field name from known filter types that target a specific field', () => {
+ const field = indexPattern.fields.find(patternField => patternField.name === 'extension');
+ const filter = buildPhraseFilter(field!, 'jpg', indexPattern);
+ const result = getFilterField(filter);
+ expect(result).toBe('extension');
+ });
+
+ it('should return undefined for filters that do not target a specific field', () => {
+ const filter = buildQueryFilter(
+ {
+ query: {
+ query_string: {
+ query: 'response:200 and extension:jpg',
+ },
+ },
+ },
+ indexPattern.id!,
+ ''
+ );
+ const result = getFilterField(filter);
+ expect(result).toBe(undefined);
+ });
+});
diff --git a/src/plugins/data/common/es_query/filters/get_filter_field.ts b/src/plugins/data/common/es_query/filters/get_filter_field.ts
new file mode 100644
index 0000000000000..dfb575157d362
--- /dev/null
+++ b/src/plugins/data/common/es_query/filters/get_filter_field.ts
@@ -0,0 +1,53 @@
+/*
+ * 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 { Filter } from './meta_filter';
+import { getExistsFilterField, isExistsFilter } from './exists_filter';
+import { getGeoBoundingBoxFilterField, isGeoBoundingBoxFilter } from './geo_bounding_box_filter';
+import { getGeoPolygonFilterField, isGeoPolygonFilter } from './geo_polygon_filter';
+import { getPhraseFilterField, isPhraseFilter } from './phrase_filter';
+import { getPhrasesFilterField, isPhrasesFilter } from './phrases_filter';
+import { getRangeFilterField, isRangeFilter } from './range_filter';
+import { getMissingFilterField, isMissingFilter } from './missing_filter';
+
+export const getFilterField = (filter: Filter) => {
+ if (isExistsFilter(filter)) {
+ return getExistsFilterField(filter);
+ }
+ if (isGeoBoundingBoxFilter(filter)) {
+ return getGeoBoundingBoxFilterField(filter);
+ }
+ if (isGeoPolygonFilter(filter)) {
+ return getGeoPolygonFilterField(filter);
+ }
+ if (isPhraseFilter(filter)) {
+ return getPhraseFilterField(filter);
+ }
+ if (isPhrasesFilter(filter)) {
+ return getPhrasesFilterField(filter);
+ }
+ if (isRangeFilter(filter)) {
+ return getRangeFilterField(filter);
+ }
+ if (isMissingFilter(filter)) {
+ return getMissingFilterField(filter);
+ }
+
+ return;
+};
diff --git a/src/plugins/data/common/es_query/filters/index.ts b/src/plugins/data/common/es_query/filters/index.ts
index 1bd534bf74ff7..403ff2b79b55f 100644
--- a/src/plugins/data/common/es_query/filters/index.ts
+++ b/src/plugins/data/common/es_query/filters/index.ts
@@ -22,6 +22,7 @@ import { Filter } from './meta_filter';
export * from './build_filters';
export * from './get_filter_params';
+export * from './get_filter_field';
export * from './custom_filter';
export * from './exists_filter';
diff --git a/src/legacy/server/url_shortening/routes/shorten_url.js b/src/plugins/data/common/es_query/filters/missing_filter.test.ts
similarity index 60%
rename from src/legacy/server/url_shortening/routes/shorten_url.js
rename to src/plugins/data/common/es_query/filters/missing_filter.test.ts
index 0203e9373384a..240d8fb26f3e0 100644
--- a/src/legacy/server/url_shortening/routes/shorten_url.js
+++ b/src/plugins/data/common/es_query/filters/missing_filter.test.ts
@@ -17,19 +17,23 @@
* under the License.
*/
-import { handleShortUrlError } from './lib/short_url_error';
-import { shortUrlAssertValid } from './lib/short_url_assert_valid';
+import { getMissingFilterField } from './missing_filter';
-export const createShortenUrlRoute = ({ shortUrlLookup }) => ({
- method: 'POST',
- path: '/api/shorten_url',
- handler: async function (request) {
- try {
- shortUrlAssertValid(request.payload.url);
- const urlId = await shortUrlLookup.generateUrlId(request.payload.url, request);
- return { urlId };
- } catch (err) {
- throw handleShortUrlError(err);
- }
- }
+describe('missing filter', function() {
+ describe('getMissingFilterField', function() {
+ it('should return the name of the field an missing query is targeting', () => {
+ const filter = {
+ missing: {
+ field: 'extension',
+ },
+ meta: {
+ disabled: false,
+ negate: false,
+ alias: null,
+ },
+ };
+ const result = getMissingFilterField(filter);
+ expect(result).toBe('extension');
+ });
+ });
});
diff --git a/src/plugins/data/common/es_query/filters/missing_filter.ts b/src/plugins/data/common/es_query/filters/missing_filter.ts
index 5411187cbcfd7..c8e1194a8f3cc 100644
--- a/src/plugins/data/common/es_query/filters/missing_filter.ts
+++ b/src/plugins/data/common/es_query/filters/missing_filter.ts
@@ -27,3 +27,7 @@ export type MissingFilter = Filter & {
};
export const isMissingFilter = (filter: any): filter is MissingFilter => filter && filter.missing;
+
+export const getMissingFilterField = (filter: MissingFilter) => {
+ return filter.missing && filter.missing.field;
+};
diff --git a/src/plugins/data/common/es_query/filters/phrase_filter.test.ts b/src/plugins/data/common/es_query/filters/phrase_filter.test.ts
index 3c7d00a80fecf..9f90097e55475 100644
--- a/src/plugins/data/common/es_query/filters/phrase_filter.test.ts
+++ b/src/plugins/data/common/es_query/filters/phrase_filter.test.ts
@@ -17,8 +17,12 @@
* under the License.
*/
-import { buildInlineScriptForPhraseFilter, buildPhraseFilter } from './phrase_filter';
-import { getField } from '../../index_patterns/mocks';
+import {
+ buildInlineScriptForPhraseFilter,
+ buildPhraseFilter,
+ getPhraseFilterField,
+} from './phrase_filter';
+import { fields, getField } from '../../index_patterns/mocks';
import { IIndexPattern } from '../../index_patterns';
describe('Phrase filter builder', () => {
@@ -95,3 +99,16 @@ describe('buildInlineScriptForPhraseFilter', () => {
expect(buildInlineScriptForPhraseFilter(field)).toBe(expected);
});
});
+
+describe('getPhraseFilterField', function() {
+ const indexPattern: IIndexPattern = ({
+ fields,
+ } as unknown) as IIndexPattern;
+
+ it('should return the name of the field a phrase query is targeting', () => {
+ const field = indexPattern.fields.find(patternField => patternField.name === 'extension');
+ const filter = buildPhraseFilter(field!, 'jpg', indexPattern);
+ const result = getPhraseFilterField(filter);
+ expect(result).toBe('extension');
+ });
+});
diff --git a/src/plugins/data/common/es_query/filters/phrases_filter.test.ts b/src/plugins/data/common/es_query/filters/phrases_filter.test.ts
new file mode 100644
index 0000000000000..3a121eb9da034
--- /dev/null
+++ b/src/plugins/data/common/es_query/filters/phrases_filter.test.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 { buildPhrasesFilter, getPhrasesFilterField } from './phrases_filter';
+import { IIndexPattern } from '../../index_patterns';
+import { fields } from '../../index_patterns/fields/fields.mocks.ts';
+
+describe('phrases filter', function() {
+ const indexPattern: IIndexPattern = ({
+ fields,
+ } as unknown) as IIndexPattern;
+
+ describe('getPhrasesFilterField', function() {
+ it('should return the name of the field a phrases query is targeting', () => {
+ const field = indexPattern.fields.find(patternField => patternField.name === 'extension');
+ const filter = buildPhrasesFilter(field!, ['jpg', 'png'], indexPattern);
+ const result = getPhrasesFilterField(filter);
+ expect(result).toBe('extension');
+ });
+ });
+});
diff --git a/src/plugins/data/common/es_query/filters/phrases_filter.ts b/src/plugins/data/common/es_query/filters/phrases_filter.ts
index f7164f0ad3c83..006e0623be913 100644
--- a/src/plugins/data/common/es_query/filters/phrases_filter.ts
+++ b/src/plugins/data/common/es_query/filters/phrases_filter.ts
@@ -32,7 +32,13 @@ export type PhrasesFilter = Filter & {
};
export const isPhrasesFilter = (filter: any): filter is PhrasesFilter =>
- filter && filter.meta.type === FILTERS.PHRASES;
+ filter?.meta?.type === FILTERS.PHRASES;
+
+export const getPhrasesFilterField = (filter: PhrasesFilter) => {
+ // Phrases is a newer filter type that has always been created via a constructor that ensures
+ // `meta.key` is set to the field name
+ return filter.meta.key;
+};
// Creates a filter where the given field matches one or more of the given values
// params should be an array of values
diff --git a/src/plugins/data/common/es_query/filters/query_string_filter.test.ts b/src/plugins/data/common/es_query/filters/query_string_filter.test.ts
index 4fcb15ccac44a..18285194c6054 100644
--- a/src/plugins/data/common/es_query/filters/query_string_filter.test.ts
+++ b/src/plugins/data/common/es_query/filters/query_string_filter.test.ts
@@ -19,7 +19,7 @@
import { buildQueryFilter } from './query_string_filter';
-describe('Phrase filter builder', () => {
+describe('Query string filter builder', () => {
it('should be a function', () => {
expect(typeof buildQueryFilter).toBe('function');
});
diff --git a/src/plugins/data/common/es_query/filters/range_filter.test.ts b/src/plugins/data/common/es_query/filters/range_filter.test.ts
index 56b63018b5153..45d59c97941b3 100644
--- a/src/plugins/data/common/es_query/filters/range_filter.test.ts
+++ b/src/plugins/data/common/es_query/filters/range_filter.test.ts
@@ -18,8 +18,8 @@
*/
import { each } from 'lodash';
-import { buildRangeFilter, RangeFilter } from './range_filter';
-import { getField } from '../../index_patterns/mocks';
+import { buildRangeFilter, getRangeFilterField, RangeFilter } from './range_filter';
+import { fields, getField } from '../../index_patterns/mocks';
import { IIndexPattern, IFieldType } from '../../index_patterns';
describe('Range filter builder', () => {
@@ -172,3 +172,16 @@ describe('Range filter builder', () => {
});
});
});
+
+describe('getRangeFilterField', function() {
+ const indexPattern: IIndexPattern = ({
+ fields,
+ } as unknown) as IIndexPattern;
+
+ test('should return the name of the field a range query is targeting', () => {
+ const field = indexPattern.fields.find(patternField => patternField.name === 'bytes');
+ const filter = buildRangeFilter(field!, {}, indexPattern);
+ const result = getRangeFilterField(filter);
+ expect(result).toBe('bytes');
+ });
+});
diff --git a/src/plugins/data/common/es_query/filters/range_filter.ts b/src/plugins/data/common/es_query/filters/range_filter.ts
index 3d819bd145fa6..b300539f4280a 100644
--- a/src/plugins/data/common/es_query/filters/range_filter.ts
+++ b/src/plugins/data/common/es_query/filters/range_filter.ts
@@ -88,6 +88,10 @@ export const isScriptedRangeFilter = (filter: any): filter is RangeFilter => {
return hasRangeKeys(params);
};
+export const getRangeFilterField = (filter: RangeFilter) => {
+ return filter.range && Object.keys(filter.range)[0];
+};
+
const formatValue = (field: IFieldType, params: any[]) =>
map(params, (val: any, key: string) => get(operators, key) + format(field, val)).join(' ');
diff --git a/src/plugins/data/kibana.json b/src/plugins/data/kibana.json
index bd2bc1bab2a1a..998eaa55858d2 100644
--- a/src/plugins/data/kibana.json
+++ b/src/plugins/data/kibana.json
@@ -2,5 +2,6 @@
"id": "data",
"version": "kibana",
"server": true,
- "ui": true
+ "ui": true,
+ "requiredPlugins": ["uiActions"]
}
diff --git a/src/legacy/core_plugins/data/public/filter/action/apply_filter_action.ts b/src/plugins/data/public/actions/apply_filter_action.ts
similarity index 84%
rename from src/legacy/core_plugins/data/public/filter/action/apply_filter_action.ts
rename to src/plugins/data/public/actions/apply_filter_action.ts
index 825b51af96b95..b006889637c50 100644
--- a/src/legacy/core_plugins/data/public/filter/action/apply_filter_action.ts
+++ b/src/plugins/data/public/actions/apply_filter_action.ts
@@ -18,22 +18,17 @@
*/
import { i18n } from '@kbn/i18n';
-import { CoreStart } from 'src/core/public';
-import { toMountPoint } from '../../../../../../plugins/kibana_react/public';
-import {
- IAction,
- createAction,
- IncompatibleActionError,
-} from '../../../../../../plugins/ui_actions/public';
+import { toMountPoint } from '../../../kibana_react/public';
+import { IAction, createAction, IncompatibleActionError } from '../../../ui_actions/public';
+import { getOverlays, getIndexPatterns } from '../services';
+import { applyFiltersPopover } from '../ui/apply_filters';
import {
esFilters,
FilterManager,
TimefilterContract,
- applyFiltersPopover,
changeTimeFilter,
extractTimeFilter,
- IndexPatternsContract,
-} from '../../../../../../plugins/data/public';
+} from '..';
export const GLOBAL_APPLY_FILTER_ACTION = 'GLOBAL_APPLY_FILTER_ACTION';
@@ -47,10 +42,8 @@ async function isCompatible(context: ActionContext) {
}
export function createFilterAction(
- overlays: CoreStart['overlays'],
filterManager: FilterManager,
- timeFilter: TimefilterContract,
- indexPatternsService: IndexPatternsContract
+ timeFilter: TimefilterContract
): IAction {
return createAction({
type: GLOBAL_APPLY_FILTER_ACTION,
@@ -75,12 +68,12 @@ export function createFilterAction(
if (selectedFilters.length > 1) {
const indexPatterns = await Promise.all(
filters.map(filter => {
- return indexPatternsService.get(filter.meta.index!);
+ return getIndexPatterns().get(filter.meta.index!);
})
);
const filterSelectionPromise: Promise = new Promise(resolve => {
- const overlay = overlays.openModal(
+ const overlay = getOverlays().openModal(
toMountPoint(
applyFiltersPopover(
filters,
diff --git a/src/plugins/data/public/actions/index.ts b/src/plugins/data/public/actions/index.ts
new file mode 100644
index 0000000000000..5d469606944a1
--- /dev/null
+++ b/src/plugins/data/public/actions/index.ts
@@ -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 { GLOBAL_APPLY_FILTER_ACTION, createFilterAction } from './apply_filter_action';
diff --git a/src/plugins/data/public/autocomplete_provider/types.ts b/src/plugins/data/public/autocomplete_provider/types.ts
index 3d34b1bc4a2d2..389057f94144d 100644
--- a/src/plugins/data/public/autocomplete_provider/types.ts
+++ b/src/plugins/data/public/autocomplete_provider/types.ts
@@ -40,6 +40,7 @@ export type GetSuggestions = (args: {
query: string;
selectionStart: number;
selectionEnd: number;
+ signal?: AbortSignal;
}) => Promise;
/** @public **/
diff --git a/src/plugins/data/public/index.ts b/src/plugins/data/public/index.ts
index eca6258099141..e54278698a05a 100644
--- a/src/plugins/data/public/index.ts
+++ b/src/plugins/data/public/index.ts
@@ -18,14 +18,10 @@
*/
import { PluginInitializerContext } from '../../../core/public';
-import { DataPublicPlugin } from './plugin';
-
export function plugin(initializerContext: PluginInitializerContext) {
return new DataPublicPlugin(initializerContext);
}
-export { DataPublicPlugin as Plugin };
-
export * from '../common';
export * from './autocomplete_provider';
@@ -39,3 +35,7 @@ export * from './search';
export * from './query';
export * from './ui';
+
+// Export plugin after all other imports
+import { DataPublicPlugin } from './plugin';
+export { DataPublicPlugin as Plugin };
diff --git a/src/plugins/data/public/index_patterns/index_patterns/index_patterns.ts b/src/plugins/data/public/index_patterns/index_patterns/index_patterns.ts
index 6369a2a3dd5f3..da58881b5b96e 100644
--- a/src/plugins/data/public/index_patterns/index_patterns/index_patterns.ts
+++ b/src/plugins/data/public/index_patterns/index_patterns/index_patterns.ts
@@ -17,7 +17,6 @@
* under the License.
*/
-import { idx } from '@kbn/elastic-idx';
import {
SavedObjectsClientContract,
SimpleSavedObject,
@@ -64,7 +63,7 @@ export class IndexPatterns {
if (!this.savedObjectsCache) {
return [];
}
- return this.savedObjectsCache.map(obj => idx(obj, _ => _.id));
+ return this.savedObjectsCache.map(obj => obj?.id);
};
getTitles = async (refresh: boolean = false): Promise => {
@@ -74,7 +73,7 @@ export class IndexPatterns {
if (!this.savedObjectsCache) {
return [];
}
- return this.savedObjectsCache.map(obj => idx(obj, _ => _.attributes.title));
+ return this.savedObjectsCache.map(obj => obj?.attributes?.title);
};
getFields = async (fields: string[], refresh: boolean = false) => {
@@ -86,7 +85,7 @@ export class IndexPatterns {
}
return this.savedObjectsCache.map((obj: Record) => {
const result: Record = {};
- fields.forEach((f: string) => (result[f] = obj[f] || idx(obj, _ => _.attributes[f])));
+ fields.forEach((f: string) => (result[f] = obj[f] || obj?.attributes?.[f]));
return result;
});
};
diff --git a/src/plugins/data/public/plugin.ts b/src/plugins/data/public/plugin.ts
index 6ec0413968a55..2a37be7f3f46a 100644
--- a/src/plugins/data/public/plugin.ts
+++ b/src/plugins/data/public/plugin.ts
@@ -19,7 +19,12 @@
import { PluginInitializerContext, CoreSetup, CoreStart, Plugin } from 'src/core/public';
import { Storage } from '../../kibana_utils/public';
-import { DataPublicPluginSetup, DataPublicPluginStart } from './types';
+import {
+ DataPublicPluginSetup,
+ DataPublicPluginStart,
+ DataSetupDependencies,
+ DataStartDependencies,
+} from './types';
import { AutocompleteProviderRegister } from './autocomplete_provider';
import { getSuggestionsProvider } from './suggestions_provider';
import { SearchService } from './search/search_service';
@@ -27,7 +32,9 @@ import { FieldFormatsService } from './field_formats_provider';
import { QueryService } from './query';
import { createIndexPatternSelect } from './ui/index_pattern_select';
import { IndexPatterns } from './index_patterns';
-import { setNotifications, setFieldFormats } from './services';
+import { setNotifications, setFieldFormats, setOverlays, setIndexPatterns } from './services';
+import { createFilterAction, GLOBAL_APPLY_FILTER_ACTION } from './actions';
+import { APPLY_FILTER_TRIGGER } from '../../embeddable/public';
export class DataPublicPlugin implements Plugin {
private readonly autocomplete = new AutocompleteProviderRegister();
@@ -41,27 +48,36 @@ export class DataPublicPlugin implements Plugin(
'Notifications'
@@ -28,3 +30,9 @@ export const [getNotifications, setNotifications] = createGetterSetter(
'FieldFormats'
);
+
+export const [getOverlays, setOverlays] = createGetterSetter('Overlays');
+
+export const [getIndexPatterns, setIndexPatterns] = createGetterSetter(
+ 'IndexPatterns'
+);
diff --git a/src/plugins/data/public/suggestions_provider/value_suggestions.ts b/src/plugins/data/public/suggestions_provider/value_suggestions.ts
index 282f4ee65dc96..68076cd43c336 100644
--- a/src/plugins/data/public/suggestions_provider/value_suggestions.ts
+++ b/src/plugins/data/public/suggestions_provider/value_suggestions.ts
@@ -28,23 +28,36 @@ export function getSuggestionsProvider(
http: HttpServiceBase
): IGetSuggestions {
const requestSuggestions = memoize(
- (index: string, field: IFieldType, query: string, boolFilter: any = []) => {
+ (
+ index: string,
+ field: IFieldType,
+ query: string,
+ boolFilter: any = [],
+ signal?: AbortSignal
+ ) => {
return http.fetch(`/api/kibana/suggestions/values/${index}`, {
method: 'POST',
body: JSON.stringify({ query, field: field.name, boolFilter }),
+ signal,
});
},
resolver
);
- return async (index: string, field: IFieldType, query: string, boolFilter?: any) => {
+ return async (
+ index: string,
+ field: IFieldType,
+ query: string,
+ boolFilter?: any,
+ signal?: AbortSignal
+ ) => {
const shouldSuggestValues = uiSettings.get('filterEditor:suggestValues');
if (field.type === 'boolean') {
return [true, false];
} else if (!shouldSuggestValues || !field.aggregatable || field.type !== 'string') {
return [];
}
- return await requestSuggestions(index, field, query, boolFilter);
+ return await requestSuggestions(index, field, query, boolFilter, signal);
};
}
diff --git a/src/plugins/data/public/types.ts b/src/plugins/data/public/types.ts
index dd70c5646f708..202a509ee58c9 100644
--- a/src/plugins/data/public/types.ts
+++ b/src/plugins/data/public/types.ts
@@ -19,6 +19,7 @@
import { CoreStart } from 'src/core/public';
import { IStorageWrapper } from 'src/plugins/kibana_utils/public';
+import { IUiActionsSetup, IUiActionsStart } from 'src/plugins/ui_actions/public';
import { AutocompletePublicPluginSetup, AutocompletePublicPluginStart } from '.';
import { FieldFormatsSetup, FieldFormatsStart } from './field_formats_provider';
import { ISearchSetup, ISearchStart } from './search';
@@ -27,6 +28,14 @@ import { QuerySetup, QueryStart } from './query';
import { IndexPatternSelectProps } from './ui/index_pattern_select';
import { IndexPatternsContract } from './index_patterns';
+export interface DataSetupDependencies {
+ uiActions: IUiActionsSetup;
+}
+
+export interface DataStartDependencies {
+ uiActions: IUiActionsStart;
+}
+
export interface DataPublicPluginSetup {
autocomplete: AutocompletePublicPluginSetup;
search: ISearchSetup;
diff --git a/src/plugins/data/public/ui/filter_bar/_global_filter_item.scss b/src/plugins/data/public/ui/filter_bar/_global_filter_item.scss
index 84538a62ca005..51204e2a61168 100644
--- a/src/plugins/data/public/ui/filter_bar/_global_filter_item.scss
+++ b/src/plugins/data/public/ui/filter_bar/_global_filter_item.scss
@@ -1,6 +1,3 @@
-@import '@elastic/eui/src/components/form/variables';
-@import '@elastic/eui/src/components/form/mixins';
-
/**
* 1. Allow wrapping of long filter items
*/
diff --git a/src/plugins/data/public/ui/index.ts b/src/plugins/data/public/ui/index.ts
index 9a4bccc21db3e..8bfccd49bdff3 100644
--- a/src/plugins/data/public/ui/index.ts
+++ b/src/plugins/data/public/ui/index.ts
@@ -20,7 +20,6 @@
export { SuggestionsComponent } from './typeahead/suggestions_component';
export { IndexPatternSelect } from './index_pattern_select';
export { FilterBar } from './filter_bar';
-export { applyFiltersPopover } from './apply_filters';
export { QueryStringInput } from './query_string_input/query_string_input';
// temp export - will be removed as final components are migrated to NP
diff --git a/src/plugins/data/public/ui/query_string_input/query_string_input.tsx b/src/plugins/data/public/ui/query_string_input/query_string_input.tsx
index dcc07f4fd43c5..16b22a164f2f0 100644
--- a/src/plugins/data/public/ui/query_string_input/query_string_input.tsx
+++ b/src/plugins/data/public/ui/query_string_input/query_string_input.tsx
@@ -106,6 +106,7 @@ export class QueryStringInputUI extends Component {
public inputRef: HTMLInputElement | null = null;
private persistedLog: PersistedLog | undefined;
+ private abortController: AbortController | undefined;
private services = this.props.kibana.services;
private componentIsUnmounting = false;
@@ -163,12 +164,22 @@ export class QueryStringInputUI extends Component {
return;
}
- const suggestions: AutocompleteSuggestion[] = await getAutocompleteSuggestions({
- query: queryString,
- selectionStart,
- selectionEnd,
- });
- return [...suggestions, ...recentSearchSuggestions];
+ try {
+ if (this.abortController) this.abortController.abort();
+ this.abortController = new AbortController();
+ const suggestions: AutocompleteSuggestion[] = await getAutocompleteSuggestions({
+ query: queryString,
+ selectionStart,
+ selectionEnd,
+ signal: this.abortController.signal,
+ });
+ return [...suggestions, ...recentSearchSuggestions];
+ } catch (e) {
+ // TODO: Waiting on https://github.com/elastic/kibana/issues/51406 for a properly typed error
+ // Ignore aborted requests
+ if (e.message === 'The user aborted a request.') return;
+ throw e;
+ }
};
private getRecentSearchSuggestions = (query: string) => {
diff --git a/src/plugins/data/public/ui/saved_query_management/_saved_query_management_component.scss b/src/plugins/data/public/ui/saved_query_management/_saved_query_management_component.scss
index d43d14945699e..928cb5a34d6de 100644
--- a/src/plugins/data/public/ui/saved_query_management/_saved_query_management_component.scss
+++ b/src/plugins/data/public/ui/saved_query_management/_saved_query_management_component.scss
@@ -1,5 +1,3 @@
-@import '@elastic/eui/src/components/form/variables';
-
.kbnSavedQueryManagement__popover {
max-width: $euiFormMaxWidth;
}
diff --git a/src/plugins/data/server/index_patterns/fetcher/lib/field_capabilities/field_caps_response.test.js b/src/plugins/data/server/index_patterns/fetcher/lib/field_capabilities/field_caps_response.test.js
index 88d2d873521cb..d9a284d34de6b 100644
--- a/src/plugins/data/server/index_patterns/fetcher/lib/field_capabilities/field_caps_response.test.js
+++ b/src/plugins/data/server/index_patterns/fetcher/lib/field_capabilities/field_caps_response.test.js
@@ -144,6 +144,13 @@ describe('index_patterns/field_capabilities/field_caps_response', () => {
expect(child).toHaveProperty('subType', { nested: { path: 'nested_object_parent' } });
});
+ it('returns nested sub-fields as non-aggregatable', () => {
+ const fields = readFieldCapsResponse(esResponse);
+ // Normally a keyword field would be aggregatable, but the fact that it is nested overrides that
+ const child = fields.find(f => f.name === 'nested_object_parent.child.keyword');
+ expect(child).toHaveProperty('aggregatable', false);
+ });
+
it('handles fields that are both nested and multi', () => {
const fields = readFieldCapsResponse(esResponse);
const child = fields.find(f => f.name === 'nested_object_parent.child.keyword');
diff --git a/src/plugins/data/server/index_patterns/fetcher/lib/field_capabilities/field_caps_response.ts b/src/plugins/data/server/index_patterns/fetcher/lib/field_capabilities/field_caps_response.ts
index 06eb30db0b24b..2215bd8a95a1d 100644
--- a/src/plugins/data/server/index_patterns/fetcher/lib/field_capabilities/field_caps_response.ts
+++ b/src/plugins/data/server/index_patterns/fetcher/lib/field_capabilities/field_caps_response.ts
@@ -182,6 +182,14 @@ export function readFieldCapsResponse(fieldCapsResponse: FieldCapsResponse): Fie
if (Object.keys(subType).length > 0) {
field.subType = subType;
+
+ // We don't support aggregating on nested fields, trying to do so in the UI will return
+ // blank results. For now we will stop showing nested fields as an option for aggregation.
+ // Once we add support for nested fields this condition should be removed and old index
+ // patterns should be migrated.
+ if (field.subType.nested) {
+ field.aggregatable = false;
+ }
}
}
});
diff --git a/src/plugins/embeddable/public/lib/containers/container.ts b/src/plugins/embeddable/public/lib/containers/container.ts
index bce16747ed48e..71e7cca3552bb 100644
--- a/src/plugins/embeddable/public/lib/containers/container.ts
+++ b/src/plugins/embeddable/public/lib/containers/container.ts
@@ -240,6 +240,7 @@ export abstract class Container<
...this.input.panels,
[panelState.explicitInput.id]: panelState,
},
+ isEmptyState: false,
} as Partial);
return await this.untilEmbeddableLoaded(panelState.explicitInput.id);
diff --git a/src/plugins/embeddable/public/lib/embeddables/i_embeddable.ts b/src/plugins/embeddable/public/lib/embeddables/i_embeddable.ts
index 33cb146a056cb..0197582778940 100644
--- a/src/plugins/embeddable/public/lib/embeddables/i_embeddable.ts
+++ b/src/plugins/embeddable/public/lib/embeddables/i_embeddable.ts
@@ -28,7 +28,7 @@ export interface EmbeddableInput {
id: string;
lastReloadRequestTime?: number;
hidePanelTitles?: boolean;
-
+ isEmptyState?: boolean;
/**
* List of action IDs that this embeddable should not render.
*/
diff --git a/src/plugins/es_ui_shared/public/request/np_ready_request.ts b/src/plugins/es_ui_shared/public/request/np_ready_request.ts
index 48c7904661e51..5a3f28ed76486 100644
--- a/src/plugins/es_ui_shared/public/request/np_ready_request.ts
+++ b/src/plugins/es_ui_shared/public/request/np_ready_request.ts
@@ -19,11 +19,12 @@
import { useEffect, useState, useRef } from 'react';
-import { HttpServiceBase } from '../../../../../src/core/public';
+import { HttpServiceBase, HttpFetchQuery } from '../../../../../src/core/public';
export interface SendRequestConfig {
path: string;
method: 'get' | 'post' | 'put' | 'delete' | 'patch' | 'head';
+ query?: HttpFetchQuery;
body?: any;
}
@@ -48,10 +49,10 @@ export interface UseRequestResponse {
export const sendRequest = async (
httpClient: HttpServiceBase,
- { path, method, body }: SendRequestConfig
+ { path, method, body, query }: SendRequestConfig
): Promise => {
try {
- const response = await httpClient[method](path, { body });
+ const response = await httpClient[method](path, { body, query });
return {
data: response.data ? response.data : response,
@@ -70,6 +71,7 @@ export const useRequest = (
{
path,
method,
+ query,
body,
pollIntervalMs,
initialData,
@@ -112,6 +114,7 @@ export const useRequest = (
const requestBody = {
path,
method,
+ query,
body,
};
diff --git a/src/plugins/inspector/public/views/requests/_requests.scss b/src/plugins/inspector/public/views/requests/_requests.scss
index feaef21fc4810..273c9d0ccba2b 100644
--- a/src/plugins/inspector/public/views/requests/_requests.scss
+++ b/src/plugins/inspector/public/views/requests/_requests.scss
@@ -1,5 +1,3 @@
-@import '@elastic/eui/src/components/button/variables';
-
.insRequestDetailsStats__icon {
margin-right: $euiSizeS;
}
diff --git a/src/plugins/kibana_react/public/saved_objects/saved_object_finder.test.tsx b/src/plugins/kibana_react/public/saved_objects/saved_object_finder.test.tsx
index b35ba427378ab..58b396d57639b 100644
--- a/src/plugins/kibana_react/public/saved_objects/saved_object_finder.test.tsx
+++ b/src/plugins/kibana_react/public/saved_objects/saved_object_finder.test.tsx
@@ -35,7 +35,7 @@ import { IconType } from '@elastic/eui';
import { shallow } from 'enzyme';
import React from 'react';
import * as sinon from 'sinon';
-import { SavedObjectFinder } from './saved_object_finder';
+import { SavedObjectFinderUi as SavedObjectFinder } from './saved_object_finder';
// eslint-disable-next-line
import { coreMock } from '../../../../core/public/mocks';
diff --git a/src/plugins/kibana_react/public/saved_objects/saved_object_finder.tsx b/src/plugins/kibana_react/public/saved_objects/saved_object_finder.tsx
index c65d428958767..51fbbd2ba3046 100644
--- a/src/plugins/kibana_react/public/saved_objects/saved_object_finder.tsx
+++ b/src/plugins/kibana_react/public/saved_objects/saved_object_finder.tsx
@@ -46,6 +46,7 @@ import { i18n } from '@kbn/i18n';
import { SavedObjectAttributes } from '../../../../core/server';
import { SimpleSavedObject, CoreStart } from '../../../../core/public';
+import { useKibana } from '../context';
// TODO the typings for EuiListGroup are incorrect - maxWidth is missing. This can be removed when the types are adjusted
const FixedEuiListGroup = (EuiListGroup as any) as React.FunctionComponent<
@@ -104,12 +105,18 @@ interface SavedObjectFinderInitialPageSize extends BaseSavedObjectFinder {
initialPageSize?: 5 | 10 | 15 | 25;
fixedPageSize?: undefined;
}
-export type SavedObjectFinderProps = {
+
+export type SavedObjectFinderProps = SavedObjectFinderFixedPage | SavedObjectFinderInitialPageSize;
+
+export type SavedObjectFinderUiProps = {
savedObjects: CoreStart['savedObjects'];
uiSettings: CoreStart['uiSettings'];
-} & (SavedObjectFinderFixedPage | SavedObjectFinderInitialPageSize);
+} & SavedObjectFinderProps;
-class SavedObjectFinder extends React.Component {
+class SavedObjectFinderUi extends React.Component<
+ SavedObjectFinderUiProps,
+ SavedObjectFinderState
+> {
public static propTypes = {
onChoose: PropTypes.func,
noItemsMessage: PropTypes.node,
@@ -174,7 +181,7 @@ class SavedObjectFinder extends React.Component {
+ const { services } = useKibana();
+ return (
+
+ );
+};
+
+export { SavedObjectFinder, SavedObjectFinderUi };
diff --git a/src/plugins/share/kibana.json b/src/plugins/share/kibana.json
index bbe393a76c5da..dce2ac9281aba 100644
--- a/src/plugins/share/kibana.json
+++ b/src/plugins/share/kibana.json
@@ -1,6 +1,6 @@
{
"id": "share",
"version": "kibana",
- "server": false,
+ "server": true,
"ui": true
}
diff --git a/src/legacy/ui/public/management/index_pattern_creation/register.js b/src/plugins/share/server/index.ts
similarity index 78%
rename from src/legacy/ui/public/management/index_pattern_creation/register.js
rename to src/plugins/share/server/index.ts
index bca4387b496fd..9e574314f8000 100644
--- a/src/legacy/ui/public/management/index_pattern_creation/register.js
+++ b/src/plugins/share/server/index.ts
@@ -17,7 +17,9 @@
* under the License.
*/
-import { IndexPatternCreationConfig } from './index_pattern_creation_config';
-import { addIndexPatternType } from './index_pattern_types';
+import { PluginInitializerContext } from '../../../core/server';
+import { SharePlugin } from './plugin';
-addIndexPatternType(IndexPatternCreationConfig);
+export function plugin(initializerContext: PluginInitializerContext) {
+ return new SharePlugin(initializerContext);
+}
diff --git a/src/legacy/ui/public/utils/find_by_param.ts b/src/plugins/share/server/plugin.ts
similarity index 59%
rename from src/legacy/ui/public/utils/find_by_param.ts
rename to src/plugins/share/server/plugin.ts
index de32fc955a8cd..bcb681a50652a 100644
--- a/src/legacy/ui/public/utils/find_by_param.ts
+++ b/src/plugins/share/server/plugin.ts
@@ -17,22 +17,21 @@
* under the License.
*/
-import _ from 'lodash';
+import { CoreSetup, Plugin, PluginInitializerContext } from 'kibana/server';
+import { createRoutes } from './routes/create_routes';
-interface AnyObject {
- [key: string]: any;
-}
+export class SharePlugin implements Plugin {
+ constructor(private readonly initializerContext: PluginInitializerContext) {}
+
+ public async setup(core: CoreSetup) {
+ createRoutes(core, this.initializerContext.logger.get());
+ }
+
+ public start() {
+ this.initializerContext.logger.get().debug('Starting plugin');
+ }
-// given an object or array of objects, return the value of the passed param
-// if the param is missing, return undefined
-export function findByParam(values: AnyObject | AnyObject[], param: string) {
- if (Array.isArray(values)) {
- // point series chart
- const index = _.findIndex(values, param);
- if (index === -1) {
- return;
- }
- return values[index][param];
+ public stop() {
+ this.initializerContext.logger.get().debug('Stopping plugin');
}
- return values[param]; // pie chart
}
diff --git a/src/plugins/share/server/routes/create_routes.ts b/src/plugins/share/server/routes/create_routes.ts
new file mode 100644
index 0000000000000..bd4b6fdb08791
--- /dev/null
+++ b/src/plugins/share/server/routes/create_routes.ts
@@ -0,0 +1,32 @@
+/*
+ * 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 { CoreSetup, Logger } from 'kibana/server';
+
+import { shortUrlLookupProvider } from './lib/short_url_lookup';
+import { createGotoRoute } from './goto';
+import { createShortenUrlRoute } from './shorten_url';
+
+export function createRoutes({ http }: CoreSetup, logger: Logger) {
+ const shortUrlLookup = shortUrlLookupProvider({ logger });
+ const router = http.createRouter();
+
+ createGotoRoute({ router, shortUrlLookup, http });
+ createShortenUrlRoute({ router, shortUrlLookup });
+}
diff --git a/src/plugins/share/server/routes/goto.ts b/src/plugins/share/server/routes/goto.ts
new file mode 100644
index 0000000000000..7343dc1bd34a2
--- /dev/null
+++ b/src/plugins/share/server/routes/goto.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 { CoreSetup, IRouter } from 'kibana/server';
+import { schema } from '@kbn/config-schema';
+
+import { shortUrlAssertValid } from './lib/short_url_assert_valid';
+import { ShortUrlLookupService } from './lib/short_url_lookup';
+
+export const createGotoRoute = ({
+ router,
+ shortUrlLookup,
+ http,
+}: {
+ router: IRouter;
+ shortUrlLookup: ShortUrlLookupService;
+ http: CoreSetup['http'];
+}) => {
+ router.get(
+ {
+ path: '/goto/{urlId}',
+ validate: {
+ params: schema.object({ urlId: schema.string() }),
+ },
+ },
+ router.handleLegacyErrors(async function(context, request, response) {
+ const url = await shortUrlLookup.getUrl(request.params.urlId, {
+ savedObjects: context.core.savedObjects.client,
+ });
+ shortUrlAssertValid(url);
+
+ const uiSettings = context.core.uiSettings.client;
+ const stateStoreInSessionStorage = await uiSettings.get('state:storeInSessionStorage');
+ if (!stateStoreInSessionStorage) {
+ return response.redirected({
+ headers: {
+ location: http.basePath.prepend(url),
+ },
+ });
+ }
+ return response.redirected({
+ headers: {
+ location: http.basePath.prepend('/goto_LP/' + request.params.urlId),
+ },
+ });
+ })
+ );
+};
diff --git a/src/plugins/share/server/routes/lib/short_url_assert_valid.test.ts b/src/plugins/share/server/routes/lib/short_url_assert_valid.test.ts
new file mode 100644
index 0000000000000..f83073e6aefe9
--- /dev/null
+++ b/src/plugins/share/server/routes/lib/short_url_assert_valid.test.ts
@@ -0,0 +1,63 @@
+/*
+ * 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 { shortUrlAssertValid } from './short_url_assert_valid';
+
+describe('shortUrlAssertValid()', () => {
+ const invalid = [
+ ['protocol', 'http://localhost:5601/app/kibana'],
+ ['protocol', 'https://localhost:5601/app/kibana'],
+ ['protocol', 'mailto:foo@bar.net'],
+ ['protocol', 'javascript:alert("hi")'], // eslint-disable-line no-script-url
+ ['hostname', 'localhost/app/kibana'],
+ ['hostname and port', 'local.host:5601/app/kibana'],
+ ['hostname and auth', 'user:pass@localhost.net/app/kibana'],
+ ['path traversal', '/app/../../not-kibana'],
+ ['deep path', '/app/kibana/foo'],
+ ['deep path', '/app/kibana/foo/bar'],
+ ['base path', '/base/app/kibana'],
+ ];
+
+ invalid.forEach(([desc, url]) => {
+ it(`fails when url has ${desc}`, () => {
+ try {
+ shortUrlAssertValid(url);
+ throw new Error(`expected assertion to throw`);
+ } catch (err) {
+ if (!err || !err.isBoom) {
+ throw err;
+ }
+ }
+ });
+ });
+
+ const valid = [
+ '/app/kibana',
+ '/app/monitoring#angular/route',
+ '/app/text#document-id',
+ '/app/some?with=query',
+ '/app/some?with=query#and-a-hash',
+ ];
+
+ valid.forEach(url => {
+ it(`allows ${url}`, () => {
+ shortUrlAssertValid(url);
+ });
+ });
+});
diff --git a/src/plugins/share/server/routes/lib/short_url_assert_valid.ts b/src/plugins/share/server/routes/lib/short_url_assert_valid.ts
new file mode 100644
index 0000000000000..2f120bbc03cd7
--- /dev/null
+++ b/src/plugins/share/server/routes/lib/short_url_assert_valid.ts
@@ -0,0 +1,41 @@
+/*
+ * 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 { parse } from 'url';
+import { trim } from 'lodash';
+import Boom from 'boom';
+
+export function shortUrlAssertValid(url: string) {
+ const { protocol, hostname, pathname } = parse(url);
+
+ if (protocol) {
+ throw Boom.notAcceptable(`Short url targets cannot have a protocol, found "${protocol}"`);
+ }
+
+ if (hostname) {
+ throw Boom.notAcceptable(`Short url targets cannot have a hostname, found "${hostname}"`);
+ }
+
+ const pathnameParts = trim(pathname, '/').split('/');
+ if (pathnameParts.length !== 2) {
+ throw Boom.notAcceptable(
+ `Short url target path must be in the format "/app/{{appId}}", found "${pathname}"`
+ );
+ }
+}
diff --git a/src/plugins/share/server/routes/lib/short_url_lookup.test.ts b/src/plugins/share/server/routes/lib/short_url_lookup.test.ts
new file mode 100644
index 0000000000000..87e2b7b726e59
--- /dev/null
+++ b/src/plugins/share/server/routes/lib/short_url_lookup.test.ts
@@ -0,0 +1,125 @@
+/*
+ * 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 { shortUrlLookupProvider, ShortUrlLookupService } from './short_url_lookup';
+import { SavedObjectsClientContract, Logger } from 'kibana/server';
+import { SavedObjectsClient } from '../../../../../core/server';
+
+describe('shortUrlLookupProvider', () => {
+ const ID = 'bf00ad16941fc51420f91a93428b27a0';
+ const TYPE = 'url';
+ const URL = 'http://elastic.co';
+
+ let savedObjects: jest.Mocked;
+ let deps: { savedObjects: SavedObjectsClientContract };
+ let shortUrl: ShortUrlLookupService;
+
+ beforeEach(() => {
+ savedObjects = ({
+ get: jest.fn(),
+ create: jest.fn(() => Promise.resolve({ id: ID })),
+ update: jest.fn(),
+ errors: SavedObjectsClient.errors,
+ } as unknown) as jest.Mocked;
+
+ deps = { savedObjects };
+ shortUrl = shortUrlLookupProvider({ logger: ({ warn: () => {} } as unknown) as Logger });
+ });
+
+ describe('generateUrlId', () => {
+ it('returns the document id', async () => {
+ const id = await shortUrl.generateUrlId(URL, deps);
+ expect(id).toEqual(ID);
+ });
+
+ it('provides correct arguments to savedObjectsClient', async () => {
+ await shortUrl.generateUrlId(URL, { savedObjects });
+
+ expect(savedObjects.create).toHaveBeenCalledTimes(1);
+ const [type, attributes, options] = savedObjects.create.mock.calls[0];
+
+ expect(type).toEqual(TYPE);
+ expect(Object.keys(attributes).sort()).toEqual([
+ 'accessCount',
+ 'accessDate',
+ 'createDate',
+ 'url',
+ ]);
+ expect(attributes.url).toEqual(URL);
+ expect(options!.id).toEqual(ID);
+ });
+
+ it('passes persists attributes', async () => {
+ await shortUrl.generateUrlId(URL, deps);
+
+ expect(savedObjects.create).toHaveBeenCalledTimes(1);
+ const [type, attributes] = savedObjects.create.mock.calls[0];
+
+ expect(type).toEqual(TYPE);
+ expect(Object.keys(attributes).sort()).toEqual([
+ 'accessCount',
+ 'accessDate',
+ 'createDate',
+ 'url',
+ ]);
+ expect(attributes.url).toEqual(URL);
+ });
+
+ it('gracefully handles version conflict', async () => {
+ const error = savedObjects.errors.decorateConflictError(new Error());
+ savedObjects.create.mockImplementation(() => {
+ throw error;
+ });
+ const id = await shortUrl.generateUrlId(URL, deps);
+ expect(id).toEqual(ID);
+ });
+ });
+
+ describe('getUrl', () => {
+ beforeEach(() => {
+ const attributes = { accessCount: 2, url: URL };
+ savedObjects.get.mockResolvedValue({ id: ID, attributes, type: 'url', references: [] });
+ });
+
+ it('provides the ID to savedObjectsClient', async () => {
+ await shortUrl.getUrl(ID, { savedObjects });
+
+ expect(savedObjects.get).toHaveBeenCalledTimes(1);
+ expect(savedObjects.get).toHaveBeenCalledWith(TYPE, ID);
+ });
+
+ it('returns the url', async () => {
+ const response = await shortUrl.getUrl(ID, deps);
+ expect(response).toEqual(URL);
+ });
+
+ it('increments accessCount', async () => {
+ await shortUrl.getUrl(ID, { savedObjects });
+
+ expect(savedObjects.update).toHaveBeenCalledTimes(1);
+
+ const [type, id, attributes] = savedObjects.update.mock.calls[0];
+
+ expect(type).toEqual(TYPE);
+ expect(id).toEqual(ID);
+ expect(Object.keys(attributes).sort()).toEqual(['accessCount', 'accessDate']);
+ expect(attributes.accessCount).toEqual(3);
+ });
+ });
+});
diff --git a/src/plugins/share/server/routes/lib/short_url_lookup.ts b/src/plugins/share/server/routes/lib/short_url_lookup.ts
new file mode 100644
index 0000000000000..0d8a9c86621de
--- /dev/null
+++ b/src/plugins/share/server/routes/lib/short_url_lookup.ts
@@ -0,0 +1,84 @@
+/*
+ * 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 crypto from 'crypto';
+import { get } from 'lodash';
+
+import { Logger, SavedObject, SavedObjectsClientContract } from 'kibana/server';
+
+export interface ShortUrlLookupService {
+ generateUrlId(url: string, deps: { savedObjects: SavedObjectsClientContract }): Promise;
+ getUrl(url: string, deps: { savedObjects: SavedObjectsClientContract }): Promise;
+}
+
+export function shortUrlLookupProvider({ logger }: { logger: Logger }): ShortUrlLookupService {
+ async function updateMetadata(
+ doc: SavedObject,
+ { savedObjects }: { savedObjects: SavedObjectsClientContract }
+ ) {
+ try {
+ await savedObjects.update('url', doc.id, {
+ accessDate: new Date().valueOf(),
+ accessCount: get(doc, 'attributes.accessCount', 0) + 1,
+ });
+ } catch (error) {
+ logger.warn('Warning: Error updating url metadata');
+ logger.warn(error);
+ // swallow errors. It isn't critical if there is no update.
+ }
+ }
+
+ return {
+ async generateUrlId(url, { savedObjects }) {
+ const id = crypto
+ .createHash('md5')
+ .update(url)
+ .digest('hex');
+ const { isConflictError } = savedObjects.errors;
+
+ try {
+ const doc = await savedObjects.create(
+ 'url',
+ {
+ url,
+ accessCount: 0,
+ createDate: new Date().valueOf(),
+ accessDate: new Date().valueOf(),
+ },
+ { id }
+ );
+
+ return doc.id;
+ } catch (error) {
+ if (isConflictError(error)) {
+ return id;
+ }
+
+ throw error;
+ }
+ },
+
+ async getUrl(id, { savedObjects }) {
+ const doc = await savedObjects.get('url', id);
+ updateMetadata(doc, { savedObjects });
+
+ return doc.attributes.url;
+ },
+ };
+}
diff --git a/src/plugins/share/server/routes/shorten_url.ts b/src/plugins/share/server/routes/shorten_url.ts
new file mode 100644
index 0000000000000..116b90c6971c5
--- /dev/null
+++ b/src/plugins/share/server/routes/shorten_url.ts
@@ -0,0 +1,48 @@
+/*
+ * 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 { IRouter } from 'kibana/server';
+import { schema } from '@kbn/config-schema';
+
+import { shortUrlAssertValid } from './lib/short_url_assert_valid';
+import { ShortUrlLookupService } from './lib/short_url_lookup';
+
+export const createShortenUrlRoute = ({
+ shortUrlLookup,
+ router,
+}: {
+ shortUrlLookup: ShortUrlLookupService;
+ router: IRouter;
+}) => {
+ router.post(
+ {
+ path: '/api/shorten_url',
+ validate: {
+ body: schema.object({ url: schema.string() }),
+ },
+ },
+ router.handleLegacyErrors(async function(context, request, response) {
+ shortUrlAssertValid(request.body.url);
+ const urlId = await shortUrlLookup.generateUrlId(request.body.url, {
+ savedObjects: context.core.savedObjects.client,
+ });
+ return response.ok({ body: { urlId } });
+ })
+ );
+};
diff --git a/tasks/config/run.js b/tasks/config/run.js
index e4071c8b7d0ab..97a0f381f2aa4 100644
--- a/tasks/config/run.js
+++ b/tasks/config/run.js
@@ -269,7 +269,6 @@ module.exports = function (grunt) {
'--config', 'test/plugin_functional/config.js',
'--bail',
'--debug',
- '--kibana-install-dir', KIBANA_INSTALL_DIR,
],
}),
diff --git a/test/api_integration/apis/index_patterns/fields_for_wildcard_route/response.js b/test/api_integration/apis/index_patterns/fields_for_wildcard_route/response.js
index bc70339bd1a66..d72722af06bff 100644
--- a/test/api_integration/apis/index_patterns/fields_for_wildcard_route/response.js
+++ b/test/api_integration/apis/index_patterns/fields_for_wildcard_route/response.js
@@ -72,7 +72,7 @@ export default function ({ getService }) {
readFromDocValues: true,
},
{
- aggregatable: true,
+ aggregatable: false,
esTypes: [
'keyword'
],
@@ -156,7 +156,7 @@ export default function ({ getService }) {
readFromDocValues: true,
},
{
- aggregatable: true,
+ aggregatable: false,
esTypes: [
'keyword'
],
diff --git a/test/common/services/kibana_server/kibana_server.ts b/test/common/services/kibana_server/kibana_server.ts
index f7b7885840455..16039d6fee833 100644
--- a/test/common/services/kibana_server/kibana_server.ts
+++ b/test/common/services/kibana_server/kibana_server.ts
@@ -32,7 +32,7 @@ export function KibanaServerProvider({ getService }: FtrProviderContext) {
const kbn = new KbnClient(log, [url], defaults);
if (defaults) {
- lifecycle.on('beforeTests', async () => {
+ lifecycle.beforeTests.add(async () => {
await kbn.uiSettings.update(defaults);
});
}
diff --git a/test/examples/README.md b/test/examples/README.md
new file mode 100644
index 0000000000000..44656f949bc72
--- /dev/null
+++ b/test/examples/README.md
@@ -0,0 +1,23 @@
+# Example plugin functional tests
+
+This folder contains functional tests for the example plugins.
+
+## Run the test
+
+To run these tests during development you can use the following commands:
+
+```
+# Start the test server (can continue running)
+node scripts/functional_tests_server.js --config test/examples/config.js
+# Start a test run
+node scripts/functional_test_runner.js --config test/examples/config.js
+```
+
+## Run Kibana with a test plugin
+
+In case you want to start Kibana with the example plugins, you can just run:
+
+```
+yarn start --run-examples
+```
+
diff --git a/test/examples/config.js b/test/examples/config.js
new file mode 100644
index 0000000000000..b954390dc54ad
--- /dev/null
+++ b/test/examples/config.js
@@ -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.
+ */
+
+import path from 'path';
+import { services } from '../plugin_functional/services';
+
+export default async function ({ readConfigFile }) {
+ const functionalConfig = await readConfigFile(require.resolve('../functional/config'));
+
+ return {
+ testFiles: [
+ require.resolve('./search'),
+ ],
+ services: {
+ ...functionalConfig.get('services'),
+ ...services,
+ },
+ pageObjects: functionalConfig.get('pageObjects'),
+ servers: functionalConfig.get('servers'),
+ esTestCluster: functionalConfig.get('esTestCluster'),
+ apps: functionalConfig.get('apps'),
+ esArchiver: {
+ directory: path.resolve(__dirname, '../es_archives')
+ },
+ screenshots: functionalConfig.get('screenshots'),
+ junit: {
+ reportName: 'Example plugin functional tests',
+ },
+ kbnTestServer: {
+ ...functionalConfig.get('kbnTestServer'),
+ serverArgs: [
+ ...functionalConfig.get('kbnTestServer.serverArgs'),
+ '--run-examples',
+ // Required to run examples
+ '--env.name=development',
+ ],
+ },
+ };
+}
diff --git a/test/plugin_functional/test_suites/search/demo_data.ts b/test/examples/search/demo_data.ts
similarity index 100%
rename from test/plugin_functional/test_suites/search/demo_data.ts
rename to test/examples/search/demo_data.ts
diff --git a/test/plugin_functional/test_suites/search/es_search.ts b/test/examples/search/es_search.ts
similarity index 100%
rename from test/plugin_functional/test_suites/search/es_search.ts
rename to test/examples/search/es_search.ts
diff --git a/test/plugin_functional/test_suites/search/index.ts b/test/examples/search/index.ts
similarity index 100%
rename from test/plugin_functional/test_suites/search/index.ts
rename to test/examples/search/index.ts
diff --git a/test/functional/apps/dashboard/full_screen_mode.js b/test/functional/apps/dashboard/full_screen_mode.js
index e18fd47b39b16..bf549ec21a6d3 100644
--- a/test/functional/apps/dashboard/full_screen_mode.js
+++ b/test/functional/apps/dashboard/full_screen_mode.js
@@ -78,7 +78,6 @@ export default function ({ getService, getPageObjects }) {
const logoButton = await PageObjects.dashboard.getExitFullScreenLogoButton();
await logoButton.moveMouseTo();
await PageObjects.dashboard.clickExitFullScreenTextButton();
-
await retry.try(async () => {
const isChromeVisible = await PageObjects.common.isChromeVisible();
expect(isChromeVisible).to.be(true);
diff --git a/test/functional/apps/discover/_discover.js b/test/functional/apps/discover/_discover.js
index 94b2941ecd3d1..58eef9fbf6b87 100644
--- a/test/functional/apps/discover/_discover.js
+++ b/test/functional/apps/discover/_discover.js
@@ -25,7 +25,6 @@ export default function ({ getService, getPageObjects }) {
const esArchiver = getService('esArchiver');
const browser = getService('browser');
const kibanaServer = getService('kibanaServer');
- const filterBar = getService('filterBar');
const queryBar = getService('queryBar');
const PageObjects = getPageObjects(['common', 'discover', 'header', 'timePicker']);
const defaultSettings = {
@@ -173,20 +172,6 @@ export default function ({ getService, getPageObjects }) {
});
- describe('filter editor', function () {
- it('should add a phrases filter', async function () {
- await filterBar.addFilter('extension.raw', 'is one of', 'jpg');
- expect(await filterBar.hasFilter('extension.raw', 'jpg')).to.be(true);
- });
-
- it('should show the phrases if you re-open a phrases filter', async function () {
- await filterBar.clickEditFilter('extension.raw', 'jpg');
- const phrases = await filterBar.getFilterEditorSelectedPhrases();
- expect(phrases.length).to.be(1);
- expect(phrases[0]).to.be('jpg');
- });
- });
-
describe('data-shared-item', function () {
it('should have correct data-shared-item title and description', async () => {
const expected = {
diff --git a/test/functional/apps/discover/_filter_editor.js b/test/functional/apps/discover/_filter_editor.js
new file mode 100644
index 0000000000000..cab16252add4a
--- /dev/null
+++ b/test/functional/apps/discover/_filter_editor.js
@@ -0,0 +1,73 @@
+/*
+ * 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 expect from '@kbn/expect';
+
+export default function ({ getService, getPageObjects }) {
+ const log = getService('log');
+ const retry = getService('retry');
+ const esArchiver = getService('esArchiver');
+ const kibanaServer = getService('kibanaServer');
+ const filterBar = getService('filterBar');
+ const PageObjects = getPageObjects(['common', 'discover', 'timePicker']);
+ const defaultSettings = {
+ defaultIndex: 'logstash-*',
+ };
+
+ describe('discover filter editor', function describeIndexTests() {
+
+ before(async function () {
+ log.debug('load kibana index with default index pattern');
+ await esArchiver.loadIfNeeded('discover');
+
+ // and load a set of makelogs data
+ await esArchiver.loadIfNeeded('logstash_functional');
+ await kibanaServer.uiSettings.replace(defaultSettings);
+ log.debug('discover filter editor');
+ await PageObjects.common.navigateToApp('discover');
+ await PageObjects.timePicker.setDefaultAbsoluteRange();
+ });
+
+ describe('filter editor', function () {
+ it('should add a phrases filter', async function () {
+ await filterBar.addFilter('extension.raw', 'is one of', 'jpg');
+ expect(await filterBar.hasFilter('extension.raw', 'jpg')).to.be(true);
+ });
+
+ it('should show the phrases if you re-open a phrases filter', async function () {
+ await filterBar.clickEditFilter('extension.raw', 'jpg');
+ const phrases = await filterBar.getFilterEditorSelectedPhrases();
+ expect(phrases.length).to.be(1);
+ expect(phrases[0]).to.be('jpg');
+ await filterBar.ensureFieldEditorModalIsClosed();
+ });
+
+ it('should support filtering on nested fields', async () => {
+ await filterBar.addFilter('nestedField.child', 'is', 'nestedValue');
+ expect(await filterBar.hasFilter('nestedField.child', 'nestedValue')).to.be(true);
+ await retry.try(async function () {
+ expect(await PageObjects.discover.getHitCount()).to.be(
+ '1'
+ );
+ });
+ });
+ });
+ });
+}
diff --git a/test/functional/apps/discover/index.js b/test/functional/apps/discover/index.js
index 902490bebd1ac..28df897b67c09 100644
--- a/test/functional/apps/discover/index.js
+++ b/test/functional/apps/discover/index.js
@@ -34,6 +34,7 @@ export default function ({ getService, loadTestFile }) {
loadTestFile(require.resolve('./_saved_queries'));
loadTestFile(require.resolve('./_discover'));
+ loadTestFile(require.resolve('./_filter_editor'));
loadTestFile(require.resolve('./_errors'));
loadTestFile(require.resolve('./_field_data'));
loadTestFile(require.resolve('./_shared_links'));
diff --git a/test/functional/services/failure_debugging.ts b/test/functional/services/failure_debugging.ts
index e2be69d779799..cd12f1b75c828 100644
--- a/test/functional/services/failure_debugging.ts
+++ b/test/functional/services/failure_debugging.ts
@@ -65,5 +65,6 @@ export async function FailureDebuggingProvider({ getService }: FtrProviderContex
await Promise.all([screenshots.takeForFailure(name), logCurrentUrl(), savePageHtml(name)]);
}
- lifecycle.on('testFailure', onFailure).on('testHookFailure', onFailure);
+ lifecycle.testFailure.add(onFailure);
+ lifecycle.testHookFailure.add(onFailure);
}
diff --git a/test/functional/services/filter_bar.ts b/test/functional/services/filter_bar.ts
index adf0f2266ba17..9d494b1e6d950 100644
--- a/test/functional/services/filter_bar.ts
+++ b/test/functional/services/filter_bar.ts
@@ -166,6 +166,7 @@ export function FilterBarProvider({ getService, getPageObjects }: FtrProviderCon
if (cancelSaveFilterModalButtonExists) {
await testSubjects.click('cancelSaveFilter');
}
+ await testSubjects.waitForDeleted('cancelSaveFilter');
}
/**
diff --git a/test/functional/services/remote/poll_for_log_entry.ts b/test/functional/services/remote/poll_for_log_entry.ts
index 71e2711906fce..0bd5d94f892b0 100644
--- a/test/functional/services/remote/poll_for_log_entry.ts
+++ b/test/functional/services/remote/poll_for_log_entry.ts
@@ -29,7 +29,7 @@ export function pollForLogEntry$(
driver: WebDriver,
type: string,
ms: number,
- stop$: Rx.Observable
+ stop$: Rx.Observable
) {
const logCtrl = driver.manage().logs();
const poll$ = new Rx.BehaviorSubject(undefined);
diff --git a/test/functional/services/remote/remote.ts b/test/functional/services/remote/remote.ts
index 380c33e93ad90..90ff55fbebde5 100644
--- a/test/functional/services/remote/remote.ts
+++ b/test/functional/services/remote/remote.ts
@@ -80,7 +80,7 @@ export async function RemoteProvider({ getService }: FtrProviderContext) {
driver,
logging.Type.BROWSER,
config.get('browser.logPollingMs'),
- lifecycle.cleanup$ as any
+ lifecycle.cleanup.after$
)
.pipe(
mergeMap(logEntry => {
@@ -110,7 +110,7 @@ export async function RemoteProvider({ getService }: FtrProviderContext) {
}
}
- lifecycle.on('beforeTests', async () => {
+ lifecycle.beforeTests.add(async () => {
// hard coded default, can be overridden per suite using `browser.setWindowSize()`
// and will be automatically reverted after each suite
await driver
@@ -120,7 +120,7 @@ export async function RemoteProvider({ getService }: FtrProviderContext) {
});
const windowSizeStack: Array<{ width: number; height: number }> = [];
- lifecycle.on('beforeTestSuite', async () => {
+ lifecycle.beforeTestSuite.add(async () => {
windowSizeStack.unshift(
await driver
.manage()
@@ -129,11 +129,11 @@ export async function RemoteProvider({ getService }: FtrProviderContext) {
);
});
- lifecycle.on('beforeEachTest', async () => {
+ lifecycle.beforeEachTest.add(async () => {
await driver.manage().setTimeouts({ implicit: config.get('timeouts.find') });
});
- lifecycle.on('afterTestSuite', async () => {
+ lifecycle.afterTestSuite.add(async () => {
const { width, height } = windowSizeStack.shift()!;
await driver
.manage()
@@ -143,7 +143,7 @@ export async function RemoteProvider({ getService }: FtrProviderContext) {
await clearBrowserStorage('localStorage');
});
- lifecycle.on('cleanup', async () => {
+ lifecycle.cleanup.add(async () => {
if (logSubscription) {
await new Promise(r => logSubscription!.add(r));
}
diff --git a/test/functional/services/remote/webdriver.ts b/test/functional/services/remote/webdriver.ts
index 50303fbad7aab..1a7abc6317075 100644
--- a/test/functional/services/remote/webdriver.ts
+++ b/test/functional/services/remote/webdriver.ts
@@ -115,9 +115,9 @@ async function attemptToCreateCommand(
session,
logging.Type.BROWSER,
logPollingMs,
- lifecycle.cleanup$
+ lifecycle.cleanup.after$
).pipe(
- takeUntil(lifecycle.cleanup$),
+ takeUntil(lifecycle.cleanup.after$),
map(({ message, level: { name: level } }) => ({
message: message.replace(/\\n/g, '\n'),
level,
@@ -151,7 +151,7 @@ async function attemptToCreateCommand(
}
const { input, chunk$, cleanup } = await createStdoutSocket();
- lifecycle.on('cleanup', cleanup);
+ lifecycle.cleanup.add(cleanup);
const session = await new Builder()
.forBrowser(browserType)
diff --git a/test/interpreter_functional/plugins/kbn_tp_run_pipeline/package.json b/test/interpreter_functional/plugins/kbn_tp_run_pipeline/package.json
index 69f958fb91f60..ae4fa1578fb2b 100644
--- a/test/interpreter_functional/plugins/kbn_tp_run_pipeline/package.json
+++ b/test/interpreter_functional/plugins/kbn_tp_run_pipeline/package.json
@@ -7,7 +7,7 @@
},
"license": "Apache-2.0",
"dependencies": {
- "@elastic/eui": "16.1.0",
+ "@elastic/eui": "17.0.0",
"react": "^16.12.0",
"react-dom": "^16.12.0"
}
diff --git a/test/plugin_functional/config.js b/test/plugin_functional/config.js
index a6316c607a7c7..d8ce12d1fc612 100644
--- a/test/plugin_functional/config.js
+++ b/test/plugin_functional/config.js
@@ -33,7 +33,6 @@ export default async function ({ readConfigFile }) {
require.resolve('./test_suites/app_plugins'),
require.resolve('./test_suites/custom_visualizations'),
require.resolve('./test_suites/panel_actions'),
- require.resolve('./test_suites/search'),
/**
* @todo Work on re-enabling this test suite after this is merged. These tests pass
diff --git a/test/plugin_functional/plugins/kbn_tp_custom_visualizations/package.json b/test/plugin_functional/plugins/kbn_tp_custom_visualizations/package.json
index 96a5e26a74109..32da6eade2b42 100644
--- a/test/plugin_functional/plugins/kbn_tp_custom_visualizations/package.json
+++ b/test/plugin_functional/plugins/kbn_tp_custom_visualizations/package.json
@@ -7,7 +7,7 @@
},
"license": "Apache-2.0",
"dependencies": {
- "@elastic/eui": "16.1.0",
+ "@elastic/eui": "17.0.0",
"react": "^16.12.0"
}
}
diff --git a/test/plugin_functional/plugins/kbn_tp_embeddable_explorer/package.json b/test/plugin_functional/plugins/kbn_tp_embeddable_explorer/package.json
index e95aa04ddd6b1..0ab65667d6f82 100644
--- a/test/plugin_functional/plugins/kbn_tp_embeddable_explorer/package.json
+++ b/test/plugin_functional/plugins/kbn_tp_embeddable_explorer/package.json
@@ -8,7 +8,7 @@
},
"license": "Apache-2.0",
"dependencies": {
- "@elastic/eui": "16.1.0",
+ "@elastic/eui": "17.0.0",
"react": "^16.12.0"
},
"scripts": {
diff --git a/test/plugin_functional/plugins/kbn_tp_embeddable_explorer/public/np_ready/public/legacy.ts b/test/plugin_functional/plugins/kbn_tp_embeddable_explorer/public/np_ready/public/legacy.ts
index a310403c86b5d..1928d7ac72313 100644
--- a/test/plugin_functional/plugins/kbn_tp_embeddable_explorer/public/np_ready/public/legacy.ts
+++ b/test/plugin_functional/plugins/kbn_tp_embeddable_explorer/public/np_ready/public/legacy.ts
@@ -22,7 +22,6 @@ import 'uiExports/embeddableFactories';
import 'uiExports/embeddableActions';
import { npSetup, npStart } from 'ui/new_platform';
-import { SavedObjectFinder } from 'ui/saved_objects/components/saved_object_finder';
import { ExitFullScreenButton } from 'ui/exit_full_screen';
import uiRoutes from 'ui/routes';
// @ts-ignore
@@ -39,7 +38,6 @@ export const setup = pluginInstance.setup(npSetup.core, {
embeddable: npSetup.plugins.embeddable,
inspector: npSetup.plugins.inspector,
__LEGACY: {
- SavedObjectFinder,
ExitFullScreenButton,
},
});
@@ -64,7 +62,6 @@ export const start = pluginInstance.start(npStart.core, {
inspector: npStart.plugins.inspector,
uiActions: npStart.plugins.uiActions,
__LEGACY: {
- SavedObjectFinder,
ExitFullScreenButton,
onRenderComplete: (renderCompleteListener: () => void) => {
if (rendered) {
diff --git a/test/plugin_functional/plugins/kbn_tp_embeddable_explorer/public/np_ready/public/plugin.tsx b/test/plugin_functional/plugins/kbn_tp_embeddable_explorer/public/np_ready/public/plugin.tsx
index 6b82a67b9fcda..adf898d9af2c7 100644
--- a/test/plugin_functional/plugins/kbn_tp_embeddable_explorer/public/np_ready/public/plugin.tsx
+++ b/test/plugin_functional/plugins/kbn_tp_embeddable_explorer/public/np_ready/public/plugin.tsx
@@ -38,6 +38,10 @@ import {
ContactCardEmbeddableFactory,
} from './embeddable_api';
import { App } from './app';
+import {
+ SavedObjectFinderProps,
+ SavedObjectFinderUi,
+} from '../../../../../../../src/plugins/kibana_react/public/saved_objects';
import {
IEmbeddableStart,
IEmbeddableSetup,
@@ -47,7 +51,6 @@ export interface SetupDependencies {
embeddable: IEmbeddableSetup;
inspector: InspectorSetupContract;
__LEGACY: {
- SavedObjectFinder: React.ComponentType;
ExitFullScreenButton: React.ComponentType;
};
}
@@ -57,7 +60,6 @@ interface StartDependencies {
uiActions: IUiActionsStart;
inspector: InspectorStartContract;
__LEGACY: {
- SavedObjectFinder: React.ComponentType;
ExitFullScreenButton: React.ComponentType;
onRenderComplete: (onRenderComplete: () => void) => void;
};
@@ -99,6 +101,13 @@ export class EmbeddableExplorerPublicPlugin
plugins.__LEGACY.onRenderComplete(() => {
const root = document.getElementById(REACT_ROOT_ID);
+ const SavedObjectFinder = (props: SavedObjectFinderProps) => (
+
+ );
ReactDOM.render(
,
root
diff --git a/test/plugin_functional/plugins/kbn_tp_sample_panel_action/package.json b/test/plugin_functional/plugins/kbn_tp_sample_panel_action/package.json
index f874cecd5d812..6f661ab2a79e1 100644
--- a/test/plugin_functional/plugins/kbn_tp_sample_panel_action/package.json
+++ b/test/plugin_functional/plugins/kbn_tp_sample_panel_action/package.json
@@ -8,7 +8,7 @@
},
"license": "Apache-2.0",
"dependencies": {
- "@elastic/eui": "16.1.0",
+ "@elastic/eui": "17.0.0",
"react": "^16.12.0"
},
"scripts": {
diff --git a/test/visual_regression/services/visual_testing/visual_testing.ts b/test/visual_regression/services/visual_testing/visual_testing.ts
index fd31a4d8b6e4f..4ad97f8d98717 100644
--- a/test/visual_regression/services/visual_testing/visual_testing.ts
+++ b/test/visual_regression/services/visual_testing/visual_testing.ts
@@ -54,7 +54,7 @@ export async function VisualTestingProvider({ getService }: FtrProviderContext)
const lifecycle = getService('lifecycle');
let currentTest: Test | undefined;
- lifecycle.on('beforeEachTest', (test: Test) => {
+ lifecycle.beforeEachTest.add(test => {
currentTest = test;
});
diff --git a/x-pack/dev-tools/jest/create_jest_config.js b/x-pack/dev-tools/jest/create_jest_config.js
index 199232262773d..f8d07668d0aae 100644
--- a/x-pack/dev-tools/jest/create_jest_config.js
+++ b/x-pack/dev-tools/jest/create_jest_config.js
@@ -20,7 +20,8 @@ export function createJestConfig({ kibanaDirectory, xPackKibanaDirectory }) {
'uiExports/(.*)': fileMockPath,
'^src/core/(.*)': `${kibanaDirectory}/src/core/$1`,
'^src/legacy/(.*)': `${kibanaDirectory}/src/legacy/$1`,
- '^plugins/watcher/models/(.*)': `${xPackKibanaDirectory}/legacy/plugins/watcher/public/models/$1`,
+ '^plugins/watcher/np_ready/application/models/(.*)':
+ `${xPackKibanaDirectory}/legacy/plugins/watcher/public/np_ready/application/models/$1`,
'^plugins/([^/.]*)(.*)': `${kibanaDirectory}/src/legacy/core_plugins/$1/public$2`,
'^legacy/plugins/xpack_main/(.*);': `${xPackKibanaDirectory}/legacy/plugins/xpack_main/public/$1`,
'\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$': fileMockPath,
diff --git a/x-pack/legacy/plugins/actions/server/action_type_registry.test.ts b/x-pack/legacy/plugins/actions/server/action_type_registry.test.ts
index b4d73cc4759d7..c0a01bc85e916 100644
--- a/x-pack/legacy/plugins/actions/server/action_type_registry.test.ts
+++ b/x-pack/legacy/plugins/actions/server/action_type_registry.test.ts
@@ -18,7 +18,7 @@ const actionTypeRegistryParams = {
beforeEach(() => jest.resetAllMocks());
const executor: ExecutorType = async options => {
- return { status: 'ok' };
+ return { status: 'ok', actionId: options.actionId };
};
describe('register()', () => {
diff --git a/x-pack/legacy/plugins/actions/server/actions_client.test.ts b/x-pack/legacy/plugins/actions/server/actions_client.test.ts
index 1c10d1b1a83af..1cbf3949d20f8 100644
--- a/x-pack/legacy/plugins/actions/server/actions_client.test.ts
+++ b/x-pack/legacy/plugins/actions/server/actions_client.test.ts
@@ -30,7 +30,7 @@ const actionTypeRegistryParams = {
let actionsClient: ActionsClient;
let actionTypeRegistry: ActionTypeRegistry;
const executor: ExecutorType = async options => {
- return { status: 'ok' };
+ return { status: 'ok', actionId: options.actionId };
};
beforeEach(() => {
diff --git a/x-pack/legacy/plugins/actions/server/builtin_action_types/email.ts b/x-pack/legacy/plugins/actions/server/builtin_action_types/email.ts
index a378d8a4b9b55..dd2bd328ce53f 100644
--- a/x-pack/legacy/plugins/actions/server/builtin_action_types/email.ts
+++ b/x-pack/legacy/plugins/actions/server/builtin_action_types/email.ts
@@ -174,19 +174,17 @@ async function executor(
result = await sendEmail(logger, sendEmailOptions);
} catch (err) {
const message = i18n.translate('xpack.actions.builtin.email.errorSendingErrorMessage', {
- defaultMessage: 'error in action "{actionId}" sending email: {errorMessage}',
- values: {
- actionId,
- errorMessage: err.message,
- },
+ defaultMessage: 'error sending email',
});
return {
status: 'error',
+ actionId,
message,
+ serviceMessage: err.message,
};
}
- return { status: 'ok', data: result };
+ return { status: 'ok', data: result, actionId };
}
// utilities
diff --git a/x-pack/legacy/plugins/actions/server/builtin_action_types/es_index.ts b/x-pack/legacy/plugins/actions/server/builtin_action_types/es_index.ts
index 01853ee9cb870..0e9fe0483ee1e 100644
--- a/x-pack/legacy/plugins/actions/server/builtin_action_types/es_index.ts
+++ b/x-pack/legacy/plugins/actions/server/builtin_action_types/es_index.ts
@@ -60,13 +60,11 @@ async function executor(
if (config.index == null && params.index == null) {
const message = i18n.translate('xpack.actions.builtin.esIndex.indexParamRequiredErrorMessage', {
- defaultMessage: 'index param needs to be set because not set in config for action {actionId}',
- values: {
- actionId,
- },
+ defaultMessage: 'index param needs to be set because not set in config for action',
});
return {
status: 'error',
+ actionId,
message,
};
}
@@ -101,17 +99,15 @@ async function executor(
result = await services.callCluster('bulk', bulkParams);
} catch (err) {
const message = i18n.translate('xpack.actions.builtin.esIndex.errorIndexingErrorMessage', {
- defaultMessage: 'error in action "{actionId}" indexing data: {errorMessage}',
- values: {
- actionId,
- errorMessage: err.message,
- },
+ defaultMessage: 'error indexing documents',
});
return {
status: 'error',
+ actionId,
message,
+ serviceMessage: err.message,
};
}
- return { status: 'ok', data: result };
+ return { status: 'ok', data: result, actionId };
}
diff --git a/x-pack/legacy/plugins/actions/server/builtin_action_types/pagerduty.test.ts b/x-pack/legacy/plugins/actions/server/builtin_action_types/pagerduty.test.ts
index 1d453d2bd2340..def3b7eea21d9 100644
--- a/x-pack/legacy/plugins/actions/server/builtin_action_types/pagerduty.test.ts
+++ b/x-pack/legacy/plugins/actions/server/builtin_action_types/pagerduty.test.ts
@@ -148,11 +148,12 @@ describe('execute()', () => {
}
`);
expect(actionResponse).toMatchInlineSnapshot(`
- Object {
- "data": "data-here",
- "status": "ok",
- }
- `);
+ Object {
+ "actionId": "some-action-id",
+ "data": "data-here",
+ "status": "ok",
+ }
+ `);
});
test('should succeed with maximal valid params for trigger', async () => {
@@ -212,11 +213,12 @@ describe('execute()', () => {
}
`);
expect(actionResponse).toMatchInlineSnapshot(`
- Object {
- "data": "data-here",
- "status": "ok",
- }
- `);
+ Object {
+ "actionId": "some-action-id",
+ "data": "data-here",
+ "status": "ok",
+ }
+ `);
});
test('should succeed with maximal valid params for acknowledge', async () => {
@@ -267,11 +269,12 @@ describe('execute()', () => {
}
`);
expect(actionResponse).toMatchInlineSnapshot(`
- Object {
- "data": "data-here",
- "status": "ok",
- }
- `);
+ Object {
+ "actionId": "some-action-id",
+ "data": "data-here",
+ "status": "ok",
+ }
+ `);
});
test('should succeed with maximal valid params for resolve', async () => {
@@ -322,11 +325,12 @@ describe('execute()', () => {
}
`);
expect(actionResponse).toMatchInlineSnapshot(`
- Object {
- "data": "data-here",
- "status": "ok",
- }
- `);
+ Object {
+ "actionId": "some-action-id",
+ "data": "data-here",
+ "status": "ok",
+ }
+ `);
});
test('should fail when sendPagerdury throws', async () => {
@@ -348,11 +352,13 @@ describe('execute()', () => {
};
const actionResponse = await actionType.executor(executorOptions);
expect(actionResponse).toMatchInlineSnapshot(`
- Object {
- "message": "error in pagerduty action \\"some-action-id\\" posting event: doing some testing",
- "status": "error",
- }
- `);
+ Object {
+ "actionId": "some-action-id",
+ "message": "error posting pagerduty event",
+ "serviceMessage": "doing some testing",
+ "status": "error",
+ }
+ `);
});
test('should fail when sendPagerdury returns 429', async () => {
@@ -374,12 +380,13 @@ describe('execute()', () => {
};
const actionResponse = await actionType.executor(executorOptions);
expect(actionResponse).toMatchInlineSnapshot(`
- Object {
- "message": "error in pagerduty action \\"some-action-id\\" posting event: status 429, retry later",
- "retry": true,
- "status": "error",
- }
- `);
+ Object {
+ "actionId": "some-action-id",
+ "message": "error posting pagerduty event: http status 429, retry later",
+ "retry": true,
+ "status": "error",
+ }
+ `);
});
test('should fail when sendPagerdury returns 501', async () => {
@@ -401,12 +408,13 @@ describe('execute()', () => {
};
const actionResponse = await actionType.executor(executorOptions);
expect(actionResponse).toMatchInlineSnapshot(`
- Object {
- "message": "error in pagerduty action \\"some-action-id\\" posting event: status 501, retry later",
- "retry": true,
- "status": "error",
- }
- `);
+ Object {
+ "actionId": "some-action-id",
+ "message": "error posting pagerduty event: http status 501, retry later",
+ "retry": true,
+ "status": "error",
+ }
+ `);
});
test('should fail when sendPagerdury returns 418', async () => {
@@ -428,10 +436,11 @@ describe('execute()', () => {
};
const actionResponse = await actionType.executor(executorOptions);
expect(actionResponse).toMatchInlineSnapshot(`
- Object {
- "message": "error in pagerduty action \\"some-action-id\\" posting event: unexpected status 418",
- "status": "error",
- }
- `);
+ Object {
+ "actionId": "some-action-id",
+ "message": "error posting pagerduty event: unexpected status 418",
+ "status": "error",
+ }
+ `);
});
});
diff --git a/x-pack/legacy/plugins/actions/server/builtin_action_types/pagerduty.ts b/x-pack/legacy/plugins/actions/server/builtin_action_types/pagerduty.ts
index ec45e298d3902..e1437b8eef554 100644
--- a/x-pack/legacy/plugins/actions/server/builtin_action_types/pagerduty.ts
+++ b/x-pack/legacy/plugins/actions/server/builtin_action_types/pagerduty.ts
@@ -123,16 +123,14 @@ async function executor(
response = await postPagerduty({ apiUrl, data, headers, services });
} catch (err) {
const message = i18n.translate('xpack.actions.builtin.pagerduty.postingErrorMessage', {
- defaultMessage: 'error in pagerduty action "{actionId}" posting event: {errorMessage}',
- values: {
- actionId,
- errorMessage: err.message,
- },
+ defaultMessage: 'error posting pagerduty event',
});
logger.warn(`error thrown posting pagerduty event: ${err.message}`);
return {
status: 'error',
+ actionId,
message,
+ serviceMessage: err.message,
};
}
@@ -141,38 +139,37 @@ async function executor(
if (response.status === 202) {
return {
status: 'ok',
+ actionId,
data: response.data,
};
}
if (response.status === 429 || response.status >= 500) {
const message = i18n.translate('xpack.actions.builtin.pagerduty.postingRetryErrorMessage', {
- defaultMessage:
- 'error in pagerduty action "{actionId}" posting event: status {status}, retry later',
+ defaultMessage: 'error posting pagerduty event: http status {status}, retry later',
values: {
- actionId,
status: response.status,
},
});
return {
status: 'error',
+ actionId,
message,
retry: true,
};
}
const message = i18n.translate('xpack.actions.builtin.pagerduty.postingUnexpectedErrorMessage', {
- defaultMessage:
- 'error in pagerduty action "{actionId}" posting event: unexpected status {status}',
+ defaultMessage: 'error posting pagerduty event: unexpected status {status}',
values: {
- actionId,
status: response.status,
},
});
return {
status: 'error',
+ actionId,
message,
};
}
diff --git a/x-pack/legacy/plugins/actions/server/builtin_action_types/server_log.ts b/x-pack/legacy/plugins/actions/server/builtin_action_types/server_log.ts
index f17430b734c66..c2af29051d8dd 100644
--- a/x-pack/legacy/plugins/actions/server/builtin_action_types/server_log.ts
+++ b/x-pack/legacy/plugins/actions/server/builtin_action_types/server_log.ts
@@ -52,17 +52,15 @@ async function executor(
logger[params.level](params.message);
} catch (err) {
const message = i18n.translate('xpack.actions.builtin.serverLog.errorLoggingErrorMessage', {
- defaultMessage: 'error in action "{actionId}" logging message: {errorMessage}',
- values: {
- actionId,
- errorMessage: err.message,
- },
+ defaultMessage: 'error logging message',
});
return {
status: 'error',
message,
+ serviceMessage: err.message,
+ actionId,
};
}
- return { status: 'ok' };
+ return { status: 'ok', actionId };
}
diff --git a/x-pack/legacy/plugins/actions/server/builtin_action_types/slack.ts b/x-pack/legacy/plugins/actions/server/builtin_action_types/slack.ts
index 8ec569a69ff23..29b89150e3990 100644
--- a/x-pack/legacy/plugins/actions/server/builtin_action_types/slack.ts
+++ b/x-pack/legacy/plugins/actions/server/builtin_action_types/slack.ts
@@ -69,7 +69,7 @@ async function slackExecutor(
result = await webhook.send(message);
} catch (err) {
if (err.original == null || err.original.response == null) {
- return errorResult(actionId, err.message);
+ return serviceErrorResult(actionId, err.message);
}
const { status, statusText, headers } = err.original.response;
@@ -88,7 +88,17 @@ async function slackExecutor(
);
}
- return errorResult(actionId, `${err.message} - ${statusText}`);
+ const errMessage = i18n.translate(
+ 'xpack.actions.builtin.slack.unexpectedHttpResponseErrorMessage',
+ {
+ defaultMessage: 'unexpected http response from slack: {httpStatus} {httpStatusText}',
+ values: {
+ httpStatus: status,
+ httpStatusText: statusText,
+ },
+ }
+ );
+ return errorResult(actionId, errMessage);
}
if (result == null) {
@@ -102,55 +112,52 @@ async function slackExecutor(
}
if (result.text !== 'ok') {
- const errMessage = i18n.translate(
- 'xpack.actions.builtin.slack.unexpectedTextResponseErrorMessage',
- {
- defaultMessage: 'unexpected text response from slack',
- }
- );
- return errorResult(actionId, errMessage);
+ return serviceErrorResult(actionId, result.text);
}
- return successResult(result);
+ return successResult(actionId, result);
}
-function successResult(data: any): ActionTypeExecutorResult {
- return { status: 'ok', data };
+function successResult(actionId: string, data: any): ActionTypeExecutorResult {
+ return { status: 'ok', data, actionId };
}
-function errorResult(id: string, message: string): ActionTypeExecutorResult {
+function errorResult(actionId: string, message: string): ActionTypeExecutorResult {
+ return {
+ status: 'error',
+ message,
+ actionId,
+ };
+}
+function serviceErrorResult(actionId: string, serviceMessage: string): ActionTypeExecutorResult {
const errMessage = i18n.translate('xpack.actions.builtin.slack.errorPostingErrorMessage', {
- defaultMessage: 'an error occurred in action "{id}" posting a slack message: {message}',
- values: {
- id,
- message,
- },
+ defaultMessage: 'error posting slack message',
});
return {
status: 'error',
message: errMessage,
+ actionId,
+ serviceMessage,
};
}
-function retryResult(id: string, message: string): ActionTypeExecutorResult {
+function retryResult(actionId: string, message: string): ActionTypeExecutorResult {
const errMessage = i18n.translate(
'xpack.actions.builtin.slack.errorPostingRetryLaterErrorMessage',
{
- defaultMessage: 'an error occurred in action "{id}" posting a slack message, retry later',
- values: {
- id,
- },
+ defaultMessage: 'error posting a slack message, retry later',
}
);
return {
status: 'error',
message: errMessage,
retry: true,
+ actionId,
};
}
function retryResultSeconds(
- id: string,
+ actionId: string,
message: string,
retryAfter: number
): ActionTypeExecutorResult {
@@ -160,12 +167,9 @@ function retryResultSeconds(
const errMessage = i18n.translate(
'xpack.actions.builtin.slack.errorPostingRetryDateErrorMessage',
{
- defaultMessage:
- 'an error occurred in action "{id}" posting a slack message, retry at {retryString}: {message}',
+ defaultMessage: 'error posting a slack message, retry at {retryString}',
values: {
- id,
retryString,
- message,
},
}
);
@@ -173,5 +177,7 @@ function retryResultSeconds(
status: 'error',
message: errMessage,
retry,
+ actionId,
+ serviceMessage: message,
};
}
diff --git a/x-pack/legacy/plugins/actions/server/builtin_action_types/webhook.ts b/x-pack/legacy/plugins/actions/server/builtin_action_types/webhook.ts
index b91fd86b0b682..06fe2fb0e591c 100644
--- a/x-pack/legacy/plugins/actions/server/builtin_action_types/webhook.ts
+++ b/x-pack/legacy/plugins/actions/server/builtin_action_types/webhook.ts
@@ -113,7 +113,7 @@ export async function executor(
} = result;
logger.debug(`response from webhook action "${actionId}": [HTTP ${status}] ${statusText}`);
- return successResult(data);
+ return successResult(actionId, data);
} else {
const { error } = result;
@@ -139,70 +139,58 @@ export async function executor(
return errorResultInvalid(actionId, message);
}
- const message = i18n.translate('xpack.actions.builtin.webhook.unreachableRemoteWebhook', {
- defaultMessage: 'Unreachable Remote Webhook, are you sure the address is correct?',
- });
- logger.warn(`error on ${actionId} webhook action: ${message}`);
- return errorResultUnreachable(actionId, message);
+ logger.warn(`error on ${actionId} webhook action: unexpected error`);
+ return errorResultUnexpectedError(actionId);
}
}
// Action Executor Result w/ internationalisation
-function successResult(data: any): ActionTypeExecutorResult {
- return { status: 'ok', data };
+function successResult(actionId: string, data: any): ActionTypeExecutorResult {
+ return { status: 'ok', data, actionId };
}
-function errorResultInvalid(id: string, message: string): ActionTypeExecutorResult {
+function errorResultInvalid(actionId: string, serviceMessage: string): ActionTypeExecutorResult {
const errMessage = i18n.translate('xpack.actions.builtin.webhook.invalidResponseErrorMessage', {
- defaultMessage:
- 'Invalid Response: an error occurred in webhook action "{id}" calling a remote webhook: {message}',
- values: {
- id,
- message,
- },
+ defaultMessage: 'error calling webhook, invalid response',
});
return {
status: 'error',
message: errMessage,
+ actionId,
+ serviceMessage,
};
}
-function errorResultUnreachable(id: string, message: string): ActionTypeExecutorResult {
+function errorResultUnexpectedError(actionId: string): ActionTypeExecutorResult {
const errMessage = i18n.translate('xpack.actions.builtin.webhook.unreachableErrorMessage', {
- defaultMessage:
- 'Unreachable Webhook: an error occurred in webhook action "{id}" calling a remote webhook: {message}',
- values: {
- id,
- message,
- },
+ defaultMessage: 'error calling webhook, unexpected error',
});
return {
status: 'error',
message: errMessage,
+ actionId,
};
}
-function retryResult(id: string, message: string): ActionTypeExecutorResult {
+function retryResult(actionId: string, serviceMessage: string): ActionTypeExecutorResult {
const errMessage = i18n.translate(
'xpack.actions.builtin.webhook.invalidResponseRetryLaterErrorMessage',
{
- defaultMessage:
- 'Invalid Response: an error occurred in webhook action "{id}" calling a remote webhook, retry later',
- values: {
- id,
- },
+ defaultMessage: 'error calling webhook, retry later',
}
);
return {
status: 'error',
message: errMessage,
retry: true,
+ actionId,
+ serviceMessage,
};
}
function retryResultSeconds(
- id: string,
- message: string,
+ actionId: string,
+ serviceMessage: string,
retryAfter: number
): ActionTypeExecutorResult {
@@ -212,12 +200,9 @@ function retryResultSeconds(
const errMessage = i18n.translate(
'xpack.actions.builtin.webhook.invalidResponseRetryDateErrorMessage',
{
- defaultMessage:
- 'Invalid Response: an error occurred in webhook action "{id}" calling a remote webhook, retry at {retryString}: {message}',
+ defaultMessage: 'error calling webhook, retry at {retryString}',
values: {
- id,
retryString,
- message,
},
}
);
@@ -225,5 +210,7 @@ function retryResultSeconds(
status: 'error',
message: errMessage,
retry,
+ actionId,
+ serviceMessage,
};
}
diff --git a/x-pack/legacy/plugins/actions/server/lib/action_executor.test.ts b/x-pack/legacy/plugins/actions/server/lib/action_executor.test.ts
index 5ed67ae82b0ce..6767468509d25 100644
--- a/x-pack/legacy/plugins/actions/server/lib/action_executor.test.ts
+++ b/x-pack/legacy/plugins/actions/server/lib/action_executor.test.ts
@@ -157,6 +157,7 @@ test('throws an error when config is invalid', async () => {
const result = await actionExecutor.execute(executeParams);
expect(result).toEqual({
+ actionId: '1',
status: 'error',
retry: false,
message: `error validating action type config: [param1]: expected value of type [string] but got [undefined]`,
@@ -188,6 +189,7 @@ test('throws an error when params is invalid', async () => {
const result = await actionExecutor.execute(executeParams);
expect(result).toEqual({
+ actionId: '1',
status: 'error',
retry: false,
message: `error validating action params: [param1]: expected value of type [string] but got [undefined]`,
diff --git a/x-pack/legacy/plugins/actions/server/lib/action_executor.ts b/x-pack/legacy/plugins/actions/server/lib/action_executor.ts
index 1afb8a8870215..c532b76a904d5 100644
--- a/x-pack/legacy/plugins/actions/server/lib/action_executor.ts
+++ b/x-pack/legacy/plugins/actions/server/lib/action_executor.ts
@@ -91,7 +91,7 @@ export class ActionExecutor {
validatedConfig = validateConfig(actionType, config);
validatedSecrets = validateSecrets(actionType, secrets);
} catch (err) {
- return { status: 'error', message: err.message, retry: false };
+ return { status: 'error', actionId, message: err.message, retry: false };
}
let result: ActionTypeExecutorResult | null = null;
@@ -113,7 +113,7 @@ export class ActionExecutor {
logger.debug(`action executed successfully: ${actionLabel}`);
// return basic response if none provided
- if (result == null) return { status: 'ok' };
+ if (result == null) return { status: 'ok', actionId };
return result;
}
diff --git a/x-pack/legacy/plugins/actions/server/lib/task_runner_factory.test.ts b/x-pack/legacy/plugins/actions/server/lib/task_runner_factory.test.ts
index a5bf42bc2cc01..41a7c17a02c5a 100644
--- a/x-pack/legacy/plugins/actions/server/lib/task_runner_factory.test.ts
+++ b/x-pack/legacy/plugins/actions/server/lib/task_runner_factory.test.ts
@@ -94,7 +94,7 @@ test('executes the task by calling the executor with proper parameters', async (
taskInstance: mockedTaskInstance,
});
- mockedActionExecutor.execute.mockResolvedValueOnce({ status: 'ok' });
+ mockedActionExecutor.execute.mockResolvedValueOnce({ status: 'ok', actionId: '2' });
spaceIdToNamespace.mockReturnValueOnce('namespace-test');
mockedEncryptedSavedObjectsPlugin.getDecryptedAsInternalUser.mockResolvedValueOnce({
id: '3',
@@ -154,6 +154,7 @@ test('throws an error with suggested retry logic when return status is error', a
});
mockedActionExecutor.execute.mockResolvedValueOnce({
status: 'error',
+ actionId: '2',
message: 'Error message',
data: { foo: true },
retry: false,
@@ -174,7 +175,7 @@ test('uses API key when provided', async () => {
taskInstance: mockedTaskInstance,
});
- mockedActionExecutor.execute.mockResolvedValueOnce({ status: 'ok' });
+ mockedActionExecutor.execute.mockResolvedValueOnce({ status: 'ok', actionId: '2' });
spaceIdToNamespace.mockReturnValueOnce('namespace-test');
mockedEncryptedSavedObjectsPlugin.getDecryptedAsInternalUser.mockResolvedValueOnce({
id: '3',
@@ -217,7 +218,7 @@ test(`doesn't use API key when not provided`, async () => {
factory.initialize(taskRunnerFactoryInitializerParams);
const taskRunner = factory.create({ taskInstance: mockedTaskInstance });
- mockedActionExecutor.execute.mockResolvedValueOnce({ status: 'ok' });
+ mockedActionExecutor.execute.mockResolvedValueOnce({ status: 'ok', actionId: '2' });
spaceIdToNamespace.mockReturnValueOnce('namespace-test');
mockedEncryptedSavedObjectsPlugin.getDecryptedAsInternalUser.mockResolvedValueOnce({
id: '3',
diff --git a/x-pack/legacy/plugins/actions/server/lib/validate_with_schema.test.ts b/x-pack/legacy/plugins/actions/server/lib/validate_with_schema.test.ts
index 4cb28728fb421..28122c72baf65 100644
--- a/x-pack/legacy/plugins/actions/server/lib/validate_with_schema.test.ts
+++ b/x-pack/legacy/plugins/actions/server/lib/validate_with_schema.test.ts
@@ -10,7 +10,7 @@ import { validateParams, validateConfig, validateSecrets } from './validate_with
import { ActionType, ExecutorType } from '../types';
const executor: ExecutorType = async options => {
- return { status: 'ok' };
+ return { status: 'ok', actionId: options.actionId };
};
test('should validate when there are no validators', () => {
diff --git a/x-pack/legacy/plugins/actions/server/routes/execute.test.ts b/x-pack/legacy/plugins/actions/server/routes/execute.test.ts
index cd5b9c7c4a7e8..b0ba5a8a0f566 100644
--- a/x-pack/legacy/plugins/actions/server/routes/execute.test.ts
+++ b/x-pack/legacy/plugins/actions/server/routes/execute.test.ts
@@ -31,11 +31,11 @@ it('executes an action with proper parameters', async () => {
callCluster: jest.fn(),
savedObjectsClient: jest.fn(),
});
- mockedActionExecutor.execute.mockResolvedValueOnce({ status: 'ok' });
+ mockedActionExecutor.execute.mockResolvedValueOnce({ status: 'ok', actionId: '1' });
const { payload, statusCode } = await server.inject(request);
expect(statusCode).toBe(200);
- expect(payload).toBe('{"status":"ok"}');
+ expect(JSON.parse(payload)).toEqual({ status: 'ok', actionId: '1' });
expect(mockedActionExecutor.execute).toHaveBeenCalledWith({
actionId: '1',
diff --git a/x-pack/legacy/plugins/actions/server/types.ts b/x-pack/legacy/plugins/actions/server/types.ts
index 5a74241bc4829..94b34034cd8b2 100644
--- a/x-pack/legacy/plugins/actions/server/types.ts
+++ b/x-pack/legacy/plugins/actions/server/types.ts
@@ -51,8 +51,10 @@ export interface FindActionResult extends ActionResult {
// the result returned from an action type executor function
export interface ActionTypeExecutorResult {
+ actionId: string;
status: 'ok' | 'error';
message?: string;
+ serviceMessage?: string;
data?: any;
retry?: null | boolean | Date;
}
diff --git a/x-pack/legacy/plugins/alerting/mappings.json b/x-pack/legacy/plugins/alerting/mappings.json
index f840c019d5e02..7a7446602351d 100644
--- a/x-pack/legacy/plugins/alerting/mappings.json
+++ b/x-pack/legacy/plugins/alerting/mappings.json
@@ -25,6 +25,9 @@
"actionRef": {
"type": "keyword"
},
+ "actionTypeId": {
+ "type": "keyword"
+ },
"params": {
"enabled": false,
"type": "object"
diff --git a/x-pack/legacy/plugins/alerting/server/alerts_client.test.ts b/x-pack/legacy/plugins/alerting/server/alerts_client.test.ts
index 08607f04a5235..8ff54e25a0c99 100644
--- a/x-pack/legacy/plugins/alerting/server/alerts_client.test.ts
+++ b/x-pack/legacy/plugins/alerting/server/alerts_client.test.ts
@@ -74,6 +74,18 @@ describe('create()', () => {
actionGroups: ['default'],
async executor() {},
});
+ savedObjectsClient.bulkGet.mockResolvedValueOnce({
+ saved_objects: [
+ {
+ id: '1',
+ type: 'action',
+ attributes: {
+ actionTypeId: 'test',
+ },
+ references: [],
+ },
+ ],
+ });
savedObjectsClient.create.mockResolvedValueOnce({
id: '1',
type: 'alert',
@@ -87,6 +99,7 @@ describe('create()', () => {
{
group: 'default',
actionRef: 'action_0',
+ actionTypeId: 'test',
params: {
foo: true,
},
@@ -133,6 +146,7 @@ describe('create()', () => {
Object {
"actions": Array [
Object {
+ "actionTypeId": "test",
"group": "default",
"id": "1",
"params": Object {
@@ -157,6 +171,7 @@ describe('create()', () => {
"actions": Array [
Object {
"actionRef": "action_0",
+ "actionTypeId": "test",
"group": "default",
"params": Object {
"foo": true,
@@ -224,6 +239,184 @@ describe('create()', () => {
`);
});
+ test('creates an alert with multiple actions', async () => {
+ const alertsClient = new AlertsClient(alertsClientParams);
+ const data = getMockData({
+ actions: [
+ {
+ group: 'default',
+ id: '1',
+ params: {
+ foo: true,
+ },
+ },
+ {
+ group: 'default',
+ id: '1',
+ params: {
+ foo: true,
+ },
+ },
+ {
+ group: 'default',
+ id: '2',
+ params: {
+ foo: true,
+ },
+ },
+ ],
+ });
+ alertTypeRegistry.get.mockReturnValueOnce({
+ id: '123',
+ name: 'Test',
+ actionGroups: ['default'],
+ async executor() {},
+ });
+ savedObjectsClient.bulkGet.mockResolvedValueOnce({
+ saved_objects: [
+ {
+ id: '1',
+ type: 'action',
+ attributes: {
+ actionTypeId: 'test',
+ },
+ references: [],
+ },
+ {
+ id: '2',
+ type: 'action',
+ attributes: {
+ actionTypeId: 'test2',
+ },
+ references: [],
+ },
+ ],
+ });
+ savedObjectsClient.create.mockResolvedValueOnce({
+ id: '1',
+ type: 'alert',
+ attributes: {
+ alertTypeId: '123',
+ interval: '10s',
+ params: {
+ bar: true,
+ },
+ actions: [
+ {
+ group: 'default',
+ actionRef: 'action_0',
+ actionTypeId: 'test',
+ params: {
+ foo: true,
+ },
+ },
+ {
+ group: 'default',
+ actionRef: 'action_1',
+ actionTypeId: 'test',
+ params: {
+ foo: true,
+ },
+ },
+ {
+ group: 'default',
+ actionRef: 'action_2',
+ actionTypeId: 'test2',
+ params: {
+ foo: true,
+ },
+ },
+ ],
+ },
+ references: [
+ {
+ name: 'action_0',
+ type: 'action',
+ id: '1',
+ },
+ {
+ name: 'action_1',
+ type: 'action',
+ id: '1',
+ },
+ {
+ name: 'action_2',
+ type: 'action',
+ id: '2',
+ },
+ ],
+ });
+ taskManager.schedule.mockResolvedValueOnce({
+ id: 'task-123',
+ taskType: 'alerting:123',
+ scheduledAt: new Date(),
+ attempts: 1,
+ status: 'idle',
+ runAt: new Date(),
+ startedAt: null,
+ retryAt: null,
+ state: {},
+ params: {},
+ ownerId: null,
+ });
+ savedObjectsClient.update.mockResolvedValueOnce({
+ id: '1',
+ type: 'alert',
+ attributes: {
+ scheduledTaskId: 'task-123',
+ },
+ references: [],
+ });
+ const result = await alertsClient.create({ data });
+ expect(result).toMatchInlineSnapshot(`
+ Object {
+ "actions": Array [
+ Object {
+ "actionTypeId": "test",
+ "group": "default",
+ "id": "1",
+ "params": Object {
+ "foo": true,
+ },
+ },
+ Object {
+ "actionTypeId": "test",
+ "group": "default",
+ "id": "1",
+ "params": Object {
+ "foo": true,
+ },
+ },
+ Object {
+ "actionTypeId": "test2",
+ "group": "default",
+ "id": "2",
+ "params": Object {
+ "foo": true,
+ },
+ },
+ ],
+ "alertTypeId": "123",
+ "id": "1",
+ "interval": "10s",
+ "params": Object {
+ "bar": true,
+ },
+ "scheduledTaskId": "task-123",
+ }
+ `);
+ expect(savedObjectsClient.bulkGet).toHaveBeenCalledWith([
+ {
+ id: '1',
+ type: 'action',
+ },
+ {
+ id: '2',
+ type: 'action',
+ },
+ ]);
+ });
+
test('creates a disabled alert', async () => {
const alertsClient = new AlertsClient(alertsClientParams);
const data = getMockData({ enabled: false });
@@ -233,6 +426,18 @@ describe('create()', () => {
actionGroups: ['default'],
async executor() {},
});
+ savedObjectsClient.bulkGet.mockResolvedValueOnce({
+ saved_objects: [
+ {
+ id: '1',
+ type: 'action',
+ attributes: {
+ actionTypeId: 'test',
+ },
+ references: [],
+ },
+ ],
+ });
savedObjectsClient.create.mockResolvedValueOnce({
id: '1',
type: 'alert',
@@ -247,6 +452,7 @@ describe('create()', () => {
{
group: 'default',
actionRef: 'action_0',
+ actionTypeId: 'test',
params: {
foo: true,
},
@@ -266,6 +472,7 @@ describe('create()', () => {
Object {
"actions": Array [
Object {
+ "actionTypeId": "test",
"group": "default",
"id": "1",
"params": Object {
@@ -306,6 +513,23 @@ describe('create()', () => {
);
});
+ test('throws error if loading actions fails', async () => {
+ const alertsClient = new AlertsClient(alertsClientParams);
+ const data = getMockData();
+ alertTypeRegistry.get.mockReturnValueOnce({
+ id: '123',
+ name: 'Test',
+ actionGroups: ['default'],
+ async executor() {},
+ });
+ savedObjectsClient.bulkGet.mockRejectedValueOnce(new Error('Test Error'));
+ await expect(alertsClient.create({ data })).rejects.toThrowErrorMatchingInlineSnapshot(
+ `"Test Error"`
+ );
+ expect(savedObjectsClient.create).not.toHaveBeenCalled();
+ expect(taskManager.schedule).not.toHaveBeenCalled();
+ });
+
test('throws error if create saved object fails', async () => {
const alertsClient = new AlertsClient(alertsClientParams);
const data = getMockData();
@@ -315,6 +539,18 @@ describe('create()', () => {
actionGroups: ['default'],
async executor() {},
});
+ savedObjectsClient.bulkGet.mockResolvedValueOnce({
+ saved_objects: [
+ {
+ id: '1',
+ type: 'action',
+ attributes: {
+ actionTypeId: 'test',
+ },
+ references: [],
+ },
+ ],
+ });
savedObjectsClient.create.mockRejectedValueOnce(new Error('Test failure'));
await expect(alertsClient.create({ data })).rejects.toThrowErrorMatchingInlineSnapshot(
`"Test failure"`
@@ -331,6 +567,18 @@ describe('create()', () => {
actionGroups: ['default'],
async executor() {},
});
+ savedObjectsClient.bulkGet.mockResolvedValueOnce({
+ saved_objects: [
+ {
+ id: '1',
+ type: 'action',
+ attributes: {
+ actionTypeId: 'test',
+ },
+ references: [],
+ },
+ ],
+ });
savedObjectsClient.create.mockResolvedValueOnce({
id: '1',
type: 'alert',
@@ -344,6 +592,7 @@ describe('create()', () => {
{
group: 'default',
actionRef: 'action_0',
+ actionTypeId: 'test',
params: {
foo: true,
},
@@ -381,6 +630,18 @@ describe('create()', () => {
actionGroups: ['default'],
async executor() {},
});
+ savedObjectsClient.bulkGet.mockResolvedValueOnce({
+ saved_objects: [
+ {
+ id: '1',
+ type: 'action',
+ attributes: {
+ actionTypeId: 'test',
+ },
+ references: [],
+ },
+ ],
+ });
savedObjectsClient.create.mockResolvedValueOnce({
id: '1',
type: 'alert',
@@ -394,6 +655,7 @@ describe('create()', () => {
{
group: 'default',
actionRef: 'action_0',
+ actionTypeId: 'test',
params: {
foo: true,
},
@@ -442,6 +704,18 @@ describe('create()', () => {
created: true,
result: { id: '123', api_key: 'abc' },
});
+ savedObjectsClient.bulkGet.mockResolvedValueOnce({
+ saved_objects: [
+ {
+ id: '1',
+ type: 'action',
+ attributes: {
+ actionTypeId: 'test',
+ },
+ references: [],
+ },
+ ],
+ });
savedObjectsClient.create.mockResolvedValueOnce({
id: '1',
type: 'alert',
@@ -455,6 +729,7 @@ describe('create()', () => {
{
group: 'default',
actionRef: 'action_0',
+ actionTypeId: 'test',
params: {
foo: true,
},
@@ -506,6 +781,7 @@ describe('create()', () => {
{
actionRef: 'action_0',
group: 'default',
+ actionTypeId: 'test',
params: { foo: true },
},
],
@@ -1149,6 +1425,18 @@ describe('update()', () => {
references: [],
version: '123',
});
+ savedObjectsClient.bulkGet.mockResolvedValueOnce({
+ saved_objects: [
+ {
+ id: '1',
+ type: 'action',
+ attributes: {
+ actionTypeId: 'test',
+ },
+ references: [],
+ },
+ ],
+ });
savedObjectsClient.update.mockResolvedValueOnce({
id: '1',
type: 'alert',
@@ -1162,6 +1450,7 @@ describe('update()', () => {
{
group: 'default',
actionRef: 'action_0',
+ actionTypeId: 'test',
params: {
foo: true,
},
@@ -1201,6 +1490,7 @@ describe('update()', () => {
Object {
"actions": Array [
Object {
+ "actionTypeId": "test",
"group": "default",
"id": "1",
"params": Object {
@@ -1226,6 +1516,7 @@ describe('update()', () => {
"actions": Array [
Object {
"actionRef": "action_0",
+ "actionTypeId": "test",
"group": "default",
"params": Object {
"foo": true,
@@ -1262,6 +1553,183 @@ describe('update()', () => {
`);
});
+ it('updates with multiple actions', async () => {
+ const alertsClient = new AlertsClient(alertsClientParams);
+ alertTypeRegistry.get.mockReturnValueOnce({
+ id: '123',
+ name: 'Test',
+ actionGroups: ['default'],
+ async executor() {},
+ });
+ savedObjectsClient.get.mockResolvedValueOnce({
+ id: '1',
+ type: 'alert',
+ attributes: {
+ enabled: true,
+ alertTypeId: '123',
+ scheduledTaskId: 'task-123',
+ },
+ references: [],
+ version: '123',
+ });
+ savedObjectsClient.bulkGet.mockResolvedValueOnce({
+ saved_objects: [
+ {
+ id: '1',
+ type: 'action',
+ attributes: {
+ actionTypeId: 'test',
+ },
+ references: [],
+ },
+ {
+ id: '2',
+ type: 'action',
+ attributes: {
+ actionTypeId: 'test2',
+ },
+ references: [],
+ },
+ ],
+ });
+ savedObjectsClient.update.mockResolvedValueOnce({
+ id: '1',
+ type: 'alert',
+ attributes: {
+ enabled: true,
+ interval: '10s',
+ params: {
+ bar: true,
+ },
+ actions: [
+ {
+ group: 'default',
+ actionRef: 'action_0',
+ actionTypeId: 'test',
+ params: {
+ foo: true,
+ },
+ },
+ {
+ group: 'default',
+ actionRef: 'action_1',
+ actionTypeId: 'test',
+ params: {
+ foo: true,
+ },
+ },
+ {
+ group: 'default',
+ actionRef: 'action_2',
+ actionTypeId: 'test2',
+ params: {
+ foo: true,
+ },
+ },
+ ],
+ scheduledTaskId: 'task-123',
+ },
+ references: [
+ {
+ name: 'action_0',
+ type: 'action',
+ id: '1',
+ },
+ {
+ name: 'action_1',
+ type: 'action',
+ id: '1',
+ },
+ {
+ name: 'action_2',
+ type: 'action',
+ id: '2',
+ },
+ ],
+ });
+ const result = await alertsClient.update({
+ id: '1',
+ data: {
+ interval: '10s',
+ name: 'abc',
+ tags: ['foo'],
+ params: {
+ bar: true,
+ },
+ actions: [
+ {
+ group: 'default',
+ id: '1',
+ params: {
+ foo: true,
+ },
+ },
+ {
+ group: 'default',
+ id: '1',
+ params: {
+ foo: true,
+ },
+ },
+ {
+ group: 'default',
+ id: '2',
+ params: {
+ foo: true,
+ },
+ },
+ ],
+ },
+ });
+ expect(result).toMatchInlineSnapshot(`
+ Object {
+ "actions": Array [
+ Object {
+ "actionTypeId": "test",
+ "group": "default",
+ "id": "1",
+ "params": Object {
+ "foo": true,
+ },
+ },
+ Object {
+ "actionTypeId": "test",
+ "group": "default",
+ "id": "1",
+ "params": Object {
+ "foo": true,
+ },
+ },
+ Object {
+ "actionTypeId": "test2",
+ "group": "default",
+ "id": "2",
+ "params": Object {
+ "foo": true,
+ },
+ },
+ ],
+ "enabled": true,
+ "id": "1",
+ "interval": "10s",
+ "params": Object {
+ "bar": true,
+ },
+ "scheduledTaskId": "task-123",
+ }
+ `);
+ expect(savedObjectsClient.bulkGet).toHaveBeenCalledWith([
+ {
+ id: '1',
+ type: 'action',
+ },
+ {
+ id: '2',
+ type: 'action',
+ },
+ ]);
+ });
+
it('calls the createApiKey function', async () => {
const alertsClient = new AlertsClient(alertsClientParams);
alertTypeRegistry.get.mockReturnValueOnce({
@@ -1281,6 +1749,18 @@ describe('update()', () => {
references: [],
version: '123',
});
+ savedObjectsClient.bulkGet.mockResolvedValueOnce({
+ saved_objects: [
+ {
+ id: '1',
+ type: 'action',
+ attributes: {
+ actionTypeId: 'test',
+ },
+ references: [],
+ },
+ ],
+ });
alertsClientParams.createAPIKey.mockResolvedValueOnce({
created: true,
result: { id: '123', api_key: 'abc' },
@@ -1298,6 +1778,7 @@ describe('update()', () => {
{
group: 'default',
actionRef: 'action_0',
+ actionTypeId: 'test',
params: {
foo: true,
},
@@ -1338,6 +1819,7 @@ describe('update()', () => {
Object {
"actions": Array [
Object {
+ "actionTypeId": "test",
"group": "default",
"id": "1",
"params": Object {
@@ -1364,6 +1846,7 @@ describe('update()', () => {
"actions": Array [
Object {
"actionRef": "action_0",
+ "actionTypeId": "test",
"group": "default",
"params": Object {
"foo": true,
diff --git a/x-pack/legacy/plugins/alerting/server/alerts_client.ts b/x-pack/legacy/plugins/alerting/server/alerts_client.ts
index 3916ec1d62b6c..27fda9871e685 100644
--- a/x-pack/legacy/plugins/alerting/server/alerts_client.ts
+++ b/x-pack/legacy/plugins/alerting/server/alerts_client.ts
@@ -21,6 +21,7 @@ interface SuccessCreateAPIKeyResult {
result: SecurityPluginCreateAPIKeyResult;
}
export type CreateAPIKeyResult = FailedCreateAPIKeyResult | SuccessCreateAPIKeyResult;
+type NormalizedAlertAction = Omit;
interface ConstructorOptions {
logger: Logger;
@@ -62,9 +63,15 @@ interface CreateOptions {
Alert,
Exclude<
keyof Alert,
- 'createdBy' | 'updatedBy' | 'apiKey' | 'apiKeyOwner' | 'muteAll' | 'mutedInstanceIds'
+ | 'createdBy'
+ | 'updatedBy'
+ | 'apiKey'
+ | 'apiKeyOwner'
+ | 'muteAll'
+ | 'mutedInstanceIds'
+ | 'actions'
>
- >;
+ > & { actions: NormalizedAlertAction[] };
options?: {
migrationVersion?: Record;
};
@@ -76,7 +83,7 @@ interface UpdateOptions {
name: string;
tags: string[];
interval: string;
- actions: AlertAction[];
+ actions: NormalizedAlertAction[];
params: Record;
};
}
@@ -117,8 +124,10 @@ export class AlertsClient {
this.validateActions(alertType, data.actions);
- const { alert: rawAlert, references } = this.getRawAlert({
+ const { references, actions } = await this.denormalizeActions(data.actions);
+ const rawAlert: RawAlert = {
...data,
+ actions,
createdBy: username,
updatedBy: username,
apiKeyOwner: apiKey.created && username ? username : undefined,
@@ -128,7 +137,7 @@ export class AlertsClient {
params: validatedAlertTypeParams,
muteAll: false,
mutedInstanceIds: [],
- });
+ };
const createdAlert = await this.savedObjectsClient.create('alert', rawAlert, {
...options,
references,
@@ -202,7 +211,7 @@ export class AlertsClient {
const validatedAlertTypeParams = validateAlertTypeParams(alertType, data.params);
this.validateActions(alertType, data.actions);
- const { actions, references } = this.extractReferences(data.actions);
+ const { actions, references } = await this.denormalizeActions(data.actions);
const username = await this.getUserName();
const updatedObject = await this.savedObjectsClient.update(
'alert',
@@ -371,26 +380,6 @@ export class AlertsClient {
});
}
- private extractReferences(actions: Alert['actions']) {
- const references: SavedObjectReference[] = [];
- const rawActions = actions.map((action, i) => {
- const actionRef = `action_${i}`;
- references.push({
- name: actionRef,
- type: 'action',
- id: action.id,
- });
- return {
- ...omit(action, 'id'),
- actionRef,
- };
- }) as RawAlert['actions'];
- return {
- actions: rawActions,
- references,
- };
- }
-
private injectReferencesIntoActions(
actions: RawAlert['actions'],
references: SavedObjectReference[]
@@ -426,19 +415,7 @@ export class AlertsClient {
};
}
- private getRawAlert(alert: Alert): { alert: RawAlert; references: SavedObjectReference[] } {
- const { references, actions } = this.extractReferences(alert.actions);
- return {
- alert: {
- ...alert,
- actions,
- },
- references,
- };
- }
-
- private validateActions(alertType: AlertType, actions: Alert['actions']) {
- // TODO: Should also ensure user has access to each action
+ private validateActions(alertType: AlertType, actions: NormalizedAlertAction[]): void {
const { actionGroups: alertTypeActionGroups } = alertType;
const usedAlertActionGroups = actions.map(action => action.group);
const invalidActionGroups = usedAlertActionGroups.filter(
@@ -455,4 +432,41 @@ export class AlertsClient {
);
}
}
+
+ private async denormalizeActions(
+ alertActions: NormalizedAlertAction[]
+ ): Promise<{ actions: RawAlert['actions']; references: SavedObjectReference[] }> {
+ // Fetch action objects in bulk
+ const actionIds = [...new Set(alertActions.map(alertAction => alertAction.id))];
+ const bulkGetOpts = actionIds.map(id => ({ id, type: 'action' }));
+ const bulkGetResult = await this.savedObjectsClient.bulkGet(bulkGetOpts);
+ const actionMap = new Map();
+ for (const action of bulkGetResult.saved_objects) {
+ if (action.error) {
+ throw Boom.badRequest(
+ `Failed to load action ${action.id} (${action.error.statusCode}): ${action.error.message}`
+ );
+ }
+ actionMap.set(action.id, action);
+ }
+ // Extract references and set actionTypeId
+ const references: SavedObjectReference[] = [];
+ const actions = alertActions.map(({ id, ...alertAction }, i) => {
+ const actionRef = `action_${i}`;
+ references.push({
+ id,
+ name: actionRef,
+ type: 'action',
+ });
+ return {
+ ...alertAction,
+ actionRef,
+ actionTypeId: actionMap.get(id).attributes.actionTypeId,
+ };
+ });
+ return {
+ actions,
+ references,
+ };
+ }
}
diff --git a/x-pack/legacy/plugins/alerting/server/lib/create_execution_handler.test.ts b/x-pack/legacy/plugins/alerting/server/lib/create_execution_handler.test.ts
index 4f523f203f87a..d86a06767c9d1 100644
--- a/x-pack/legacy/plugins/alerting/server/lib/create_execution_handler.test.ts
+++ b/x-pack/legacy/plugins/alerting/server/lib/create_execution_handler.test.ts
@@ -28,6 +28,7 @@ const createExecutionHandlerParams = {
{
id: '1',
group: 'default',
+ actionTypeId: 'test',
params: {
foo: true,
contextVal: 'My {{context.value}} goes here',
diff --git a/x-pack/legacy/plugins/alerting/server/routes/create.test.ts b/x-pack/legacy/plugins/alerting/server/routes/create.test.ts
index 318dbdf068d6a..634a797880812 100644
--- a/x-pack/legacy/plugins/alerting/server/routes/create.test.ts
+++ b/x-pack/legacy/plugins/alerting/server/routes/create.test.ts
@@ -41,6 +41,12 @@ test('creates an alert with proper parameters', async () => {
alertsClient.create.mockResolvedValueOnce({
...mockedAlert,
id: '123',
+ actions: [
+ {
+ ...mockedAlert.actions[0],
+ actionTypeId: 'test',
+ },
+ ],
});
const { payload, statusCode } = await server.inject(request);
expect(statusCode).toBe(200);
@@ -49,6 +55,7 @@ test('creates an alert with proper parameters', async () => {
Object {
"actions": Array [
Object {
+ "actionTypeId": "test",
"group": "default",
"id": "2",
"params": Object {
@@ -97,33 +104,4 @@ test('creates an alert with proper parameters', async () => {
},
]
`);
- expect(alertsClient.create).toHaveBeenCalledTimes(1);
- expect(alertsClient.create.mock.calls[0]).toMatchInlineSnapshot(`
- Array [
- Object {
- "data": Object {
- "actions": Array [
- Object {
- "group": "default",
- "id": "2",
- "params": Object {
- "foo": true,
- },
- },
- ],
- "alertTypeId": "1",
- "enabled": true,
- "interval": "10s",
- "name": "abc",
- "params": Object {
- "bar": true,
- },
- "tags": Array [
- "foo",
- ],
- "throttle": null,
- },
- },
- ]
- `);
});
diff --git a/x-pack/legacy/plugins/alerting/server/routes/create.ts b/x-pack/legacy/plugins/alerting/server/routes/create.ts
index fb82a03f172b3..cb5277ae19100 100644
--- a/x-pack/legacy/plugins/alerting/server/routes/create.ts
+++ b/x-pack/legacy/plugins/alerting/server/routes/create.ts
@@ -6,7 +6,6 @@
import Hapi from 'hapi';
import Joi from 'joi';
-import { AlertAction } from '../types';
import { getDurationSchema } from '../lib';
interface ScheduleRequest extends Hapi.Request {
@@ -16,7 +15,11 @@ interface ScheduleRequest extends Hapi.Request {
tags: string[];
alertTypeId: string;
interval: string;
- actions: AlertAction[];
+ actions: Array<{
+ group: string;
+ id: string;
+ params: Record;
+ }>;
params: Record;
throttle: string | null;
};
diff --git a/x-pack/legacy/plugins/alerting/server/routes/get.test.ts b/x-pack/legacy/plugins/alerting/server/routes/get.test.ts
index 19618bc9e39fe..4d44ee9dfe6bd 100644
--- a/x-pack/legacy/plugins/alerting/server/routes/get.test.ts
+++ b/x-pack/legacy/plugins/alerting/server/routes/get.test.ts
@@ -21,6 +21,7 @@ const mockedAlert = {
{
group: 'default',
id: '2',
+ actionTypeId: 'test',
params: {
foo: true,
},
diff --git a/x-pack/legacy/plugins/alerting/server/routes/update.test.ts b/x-pack/legacy/plugins/alerting/server/routes/update.test.ts
index 7fc3f45911010..334fb2120319d 100644
--- a/x-pack/legacy/plugins/alerting/server/routes/update.test.ts
+++ b/x-pack/legacy/plugins/alerting/server/routes/update.test.ts
@@ -24,6 +24,7 @@ const mockedResponse = {
{
group: 'default',
id: '2',
+ actionTypeId: 'test',
params: {
baz: true,
},
diff --git a/x-pack/legacy/plugins/alerting/server/routes/update.ts b/x-pack/legacy/plugins/alerting/server/routes/update.ts
index 6aeedb93a1098..6e8f8557fb24a 100644
--- a/x-pack/legacy/plugins/alerting/server/routes/update.ts
+++ b/x-pack/legacy/plugins/alerting/server/routes/update.ts
@@ -6,7 +6,6 @@
import Joi from 'joi';
import Hapi from 'hapi';
-import { AlertAction } from '../types';
import { getDurationSchema } from '../lib';
interface UpdateRequest extends Hapi.Request {
@@ -18,7 +17,11 @@ interface UpdateRequest extends Hapi.Request {
name: string;
tags: string[];
interval: string;
- actions: AlertAction[];
+ actions: Array<{
+ group: string;
+ id: string;
+ params: Record;
+ }>;
params: Record;
throttle: string | null;
};
diff --git a/x-pack/legacy/plugins/alerting/server/types.ts b/x-pack/legacy/plugins/alerting/server/types.ts
index e2460c549c05d..1bec2632d8082 100644
--- a/x-pack/legacy/plugins/alerting/server/types.ts
+++ b/x-pack/legacy/plugins/alerting/server/types.ts
@@ -49,12 +49,14 @@ export type AlertActionParams = SavedObjectAttributes;
export interface AlertAction {
group: string;
id: string;
+ actionTypeId: string;
params: AlertActionParams;
}
export interface RawAlertAction extends SavedObjectAttributes {
group: string;
actionRef: string;
+ actionTypeId: string;
params: AlertActionParams;
}
diff --git a/x-pack/legacy/plugins/apm/public/components/app/TransactionOverview/__jest__/TransactionOverview.test.tsx b/x-pack/legacy/plugins/apm/public/components/app/TransactionOverview/__jest__/TransactionOverview.test.tsx
index a5356be72f5e4..91e0ae11a652e 100644
--- a/x-pack/legacy/plugins/apm/public/components/app/TransactionOverview/__jest__/TransactionOverview.test.tsx
+++ b/x-pack/legacy/plugins/apm/public/components/app/TransactionOverview/__jest__/TransactionOverview.test.tsx
@@ -18,6 +18,7 @@ import { history } from '../../../../utils/history';
import { TransactionOverview } from '..';
import { IUrlParams } from '../../../../context/UrlParamsContext/types';
import * as useServiceTransactionTypesHook from '../../../../hooks/useServiceTransactionTypes';
+import * as useFetcherHook from '../../../../hooks/useFetcher';
import { fromQuery } from '../../../shared/Links/url_helpers';
import { Router } from 'react-router-dom';
import { UrlParamsProvider } from '../../../../context/UrlParamsContext';
@@ -51,6 +52,8 @@ function setup({
.spyOn(useServiceTransactionTypesHook, 'useServiceTransactionTypes')
.mockReturnValue(serviceTransactionTypes);
+ jest.spyOn(useFetcherHook, 'useFetcher').mockReturnValue({} as any);
+
return render(
diff --git a/x-pack/legacy/plugins/apm/public/components/shared/DatePicker/__test__/DatePicker.test.tsx b/x-pack/legacy/plugins/apm/public/components/shared/DatePicker/__test__/DatePicker.test.tsx
index 05094c59712a9..32379325c4020 100644
--- a/x-pack/legacy/plugins/apm/public/components/shared/DatePicker/__test__/DatePicker.test.tsx
+++ b/x-pack/legacy/plugins/apm/public/components/shared/DatePicker/__test__/DatePicker.test.tsx
@@ -10,13 +10,13 @@ import {
UrlParamsContext,
useUiFilters
} from '../../../../context/UrlParamsContext';
-import { tick } from '../../../../utils/testHelpers';
import { DatePicker } from '../index';
import { IUrlParams } from '../../../../context/UrlParamsContext/types';
import { history } from '../../../../utils/history';
import { mount } from 'enzyme';
import { EuiSuperDatePicker } from '@elastic/eui';
import { MemoryRouter } from 'react-router-dom';
+import { wait } from '@testing-library/react';
const mockHistoryPush = jest.spyOn(history, 'push');
const mockRefreshTimeRange = jest.fn();
@@ -84,7 +84,7 @@ describe('DatePicker', () => {
});
expect(mockRefreshTimeRange).not.toHaveBeenCalled();
jest.advanceTimersByTime(1000);
- await tick();
+ await wait();
expect(mockRefreshTimeRange).toHaveBeenCalled();
wrapper.unmount();
});
@@ -94,7 +94,7 @@ describe('DatePicker', () => {
mountDatePicker({ refreshPaused: true, refreshInterval: 1000 });
expect(mockRefreshTimeRange).not.toHaveBeenCalled();
jest.advanceTimersByTime(1000);
- await tick();
+ await wait();
expect(mockRefreshTimeRange).not.toHaveBeenCalled();
});
});
diff --git a/x-pack/legacy/plugins/apm/public/components/shared/useDelayedVisibility/Delayed/index.ts b/x-pack/legacy/plugins/apm/public/components/shared/useDelayedVisibility/Delayed/index.ts
index 798e872dbc472..9048afe57153d 100644
--- a/x-pack/legacy/plugins/apm/public/components/shared/useDelayedVisibility/Delayed/index.ts
+++ b/x-pack/legacy/plugins/apm/public/components/shared/useDelayedVisibility/Delayed/index.ts
@@ -57,4 +57,10 @@ export class Delayed {
public onChange(onChangeCallback: Callback) {
this.onChangeCallback = onChangeCallback;
}
+
+ public destroy() {
+ if (this.timeoutId) {
+ window.clearTimeout(this.timeoutId);
+ }
+ }
}
diff --git a/x-pack/legacy/plugins/apm/public/components/shared/useDelayedVisibility/index.test.tsx b/x-pack/legacy/plugins/apm/public/components/shared/useDelayedVisibility/index.test.tsx
index 57e634df22837..c55c6ab351848 100644
--- a/x-pack/legacy/plugins/apm/public/components/shared/useDelayedVisibility/index.test.tsx
+++ b/x-pack/legacy/plugins/apm/public/components/shared/useDelayedVisibility/index.test.tsx
@@ -4,11 +4,16 @@
* you may not use this file except in compliance with the Elastic License.
*/
-import { renderHook } from '@testing-library/react-hooks';
+import {
+ renderHook,
+ act,
+ RenderHookResult
+} from '@testing-library/react-hooks';
import { useDelayedVisibility } from '.';
describe('useFetcher', () => {
- let hook;
+ let hook: RenderHookResult;
+
beforeEach(() => {
jest.useFakeTimers();
});
@@ -26,9 +31,15 @@ describe('useFetcher', () => {
});
hook.rerender(true);
- jest.advanceTimersByTime(10);
+ act(() => {
+ jest.advanceTimersByTime(10);
+ });
+
expect(hook.result.current).toEqual(false);
- jest.advanceTimersByTime(50);
+ act(() => {
+ jest.advanceTimersByTime(50);
+ });
+
expect(hook.result.current).toEqual(true);
});
@@ -38,8 +49,11 @@ describe('useFetcher', () => {
});
hook.rerender(true);
- jest.advanceTimersByTime(100);
+ act(() => {
+ jest.advanceTimersByTime(100);
+ });
hook.rerender(false);
+
expect(hook.result.current).toEqual(true);
});
@@ -49,11 +63,22 @@ describe('useFetcher', () => {
});
hook.rerender(true);
- jest.advanceTimersByTime(100);
+
+ act(() => {
+ jest.advanceTimersByTime(100);
+ });
+
hook.rerender(false);
- jest.advanceTimersByTime(900);
+ act(() => {
+ jest.advanceTimersByTime(900);
+ });
+
expect(hook.result.current).toEqual(true);
- jest.advanceTimersByTime(100);
+
+ act(() => {
+ jest.advanceTimersByTime(100);
+ });
+
expect(hook.result.current).toEqual(false);
});
});
diff --git a/x-pack/legacy/plugins/apm/public/components/shared/useDelayedVisibility/index.ts b/x-pack/legacy/plugins/apm/public/components/shared/useDelayedVisibility/index.ts
index 5acbbd1d45737..c4465c7b42339 100644
--- a/x-pack/legacy/plugins/apm/public/components/shared/useDelayedVisibility/index.ts
+++ b/x-pack/legacy/plugins/apm/public/components/shared/useDelayedVisibility/index.ts
@@ -26,6 +26,10 @@ export function useDelayedVisibility(
setIsVisible(visibility);
});
delayedRef.current = delayed;
+
+ return () => {
+ delayed.destroy();
+ };
}, [hideDelayMs, showDelayMs, minimumVisibleDuration]);
useEffect(() => {
diff --git a/x-pack/legacy/plugins/apm/public/context/UrlParamsContext/__tests__/UrlParamsContext.test.tsx b/x-pack/legacy/plugins/apm/public/context/UrlParamsContext/__tests__/UrlParamsContext.test.tsx
index 2604a3a122574..d2d8036e864ae 100644
--- a/x-pack/legacy/plugins/apm/public/context/UrlParamsContext/__tests__/UrlParamsContext.test.tsx
+++ b/x-pack/legacy/plugins/apm/public/context/UrlParamsContext/__tests__/UrlParamsContext.test.tsx
@@ -11,8 +11,8 @@ import { Location, History } from 'history';
import { MemoryRouter, Router } from 'react-router-dom';
import moment from 'moment-timezone';
import { IUrlParams } from '../types';
-import { tick } from '../../../utils/testHelpers';
import { getParsedDate } from '../helpers';
+import { wait } from '@testing-library/react';
function mountParams(location: Location) {
return mount(
@@ -143,13 +143,13 @@ describe('UrlParamsContext', () => {
);
- await tick();
+ await wait();
expect(calls.length).toBe(1);
wrapper.find('button').simulate('click');
- await tick();
+ await wait();
expect(calls.length).toBe(2);
@@ -194,11 +194,11 @@ describe('UrlParamsContext', () => {
);
- await tick();
+ await wait();
wrapper.find('button').simulate('click');
- await tick();
+ await wait();
const params = getDataFromOutput(wrapper);
expect(params.start).toEqual('2000-06-14T00:00:00.000Z');
diff --git a/x-pack/legacy/plugins/apm/public/hooks/useFetcher.integration.test.tsx b/x-pack/legacy/plugins/apm/public/hooks/useFetcher.integration.test.tsx
index 36a8377c02527..743cf4e01e555 100644
--- a/x-pack/legacy/plugins/apm/public/hooks/useFetcher.integration.test.tsx
+++ b/x-pack/legacy/plugins/apm/public/hooks/useFetcher.integration.test.tsx
@@ -5,8 +5,8 @@
*/
import React from 'react';
-import { render } from '@testing-library/react';
-import { delay, tick } from '../utils/testHelpers';
+import { render, wait } from '@testing-library/react';
+import { delay } from '../utils/testHelpers';
import { useFetcher } from './useFetcher';
import { KibanaCoreContext } from '../../../observability/public/context/kibana_core';
import { LegacyCoreStart } from 'kibana/public';
@@ -76,7 +76,8 @@ describe('when simulating race condition', () => {
it('should render "Hello from Peter" after 200ms', async () => {
jest.advanceTimersByTime(200);
- await tick();
+
+ await wait();
expect(renderSpy).lastCalledWith({
data: 'Hello from Peter',
@@ -87,7 +88,7 @@ describe('when simulating race condition', () => {
it('should render "Hello from Peter" after 600ms', async () => {
jest.advanceTimersByTime(600);
- await tick();
+ await wait();
expect(renderSpy).lastCalledWith({
data: 'Hello from Peter',
@@ -98,7 +99,7 @@ describe('when simulating race condition', () => {
it('should should NOT have rendered "Hello from John" at any point', async () => {
jest.advanceTimersByTime(600);
- await tick();
+ await wait();
expect(renderSpy).not.toHaveBeenCalledWith({
data: 'Hello from John',
@@ -109,7 +110,7 @@ describe('when simulating race condition', () => {
it('should send and receive calls in the right order', async () => {
jest.advanceTimersByTime(600);
- await tick();
+ await wait();
expect(requestCallOrder).toEqual([
['request', 'John', 500],
diff --git a/x-pack/legacy/plugins/apm/public/utils/testHelpers.tsx b/x-pack/legacy/plugins/apm/public/utils/testHelpers.tsx
index b5cee4a78b01c..9e3c486715a1f 100644
--- a/x-pack/legacy/plugins/apm/public/utils/testHelpers.tsx
+++ b/x-pack/legacy/plugins/apm/public/utils/testHelpers.tsx
@@ -58,7 +58,6 @@ export async function getRenderedHref(Component: React.FC, location: Location) {
);
- await tick();
await waitForElement(() => el.container.querySelector('a'));
const a = el.container.querySelector('a');
@@ -74,9 +73,6 @@ export function delay(ms: number) {
return new Promise(resolve => setTimeout(resolve, ms));
}
-// Await this when you need to "flush" promises to immediately resolve or throw in tests
-export const tick = () => new Promise(resolve => setImmediate(resolve, 0));
-
export function expectTextsNotInDocument(output: any, texts: string[]) {
texts.forEach(text => {
try {
diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/renderers/embeddable.tsx b/x-pack/legacy/plugins/canvas/canvas_plugin_src/renderers/embeddable.tsx
index 8810871e9161b..5c7ef1a8c1799 100644
--- a/x-pack/legacy/plugins/canvas/canvas_plugin_src/renderers/embeddable.tsx
+++ b/x-pack/legacy/plugins/canvas/canvas_plugin_src/renderers/embeddable.tsx
@@ -16,8 +16,11 @@ import {
} from '../../../../../../src/legacy/core_plugins/embeddable_api/public/np_ready/public';
import { start } from '../../../../../../src/legacy/core_plugins/embeddable_api/public/np_ready/public/legacy';
import { EmbeddableExpression } from '../expression_types/embeddable';
-import { SavedObjectFinder } from '../../../../../../src/legacy/ui/public/saved_objects/components/saved_object_finder';
import { RendererStrings } from '../../i18n';
+import {
+ SavedObjectFinderProps,
+ SavedObjectFinderUi,
+} from '../../../../../../src/plugins/kibana_react/public';
const { embeddable: strings } = RendererStrings;
@@ -34,6 +37,13 @@ interface Handlers {
}
const renderEmbeddable = (embeddableObject: IEmbeddable, domNode: HTMLElement) => {
+ const SavedObjectFinder = (props: SavedObjectFinderProps) => (
+
+ );
return (
{
-
> {
const { help, args: argHelp } = getFunctionHelp().timelion;
@@ -64,8 +87,8 @@ export function timelion(): ExpressionFunction<'timelion', Filter, Arguments, Pr
// workpad, if it exists. Otherwise fall back on the function args.
const timeFilter = context.and.find(and => and.type === 'time');
const range = timeFilter
- ? { from: timeFilter.from, to: timeFilter.to }
- : { from: args.from, to: args.to };
+ ? { min: timeFilter.from, max: timeFilter.to }
+ : parseDateMath({ from: args.from, to: args.to }, args.timezone);
const body = {
extended: {
@@ -79,8 +102,8 @@ export function timelion(): ExpressionFunction<'timelion', Filter, Arguments, Pr
},
sheet: [args.query],
time: {
- from: range.from,
- to: range.to,
+ from: range.min,
+ to: range.max,
interval: args.interval,
timezone: args.timezone,
},
diff --git a/x-pack/legacy/plugins/canvas/public/legacy_start.ts b/x-pack/legacy/plugins/canvas/public/legacy_start.ts
index 49ec7acd6375d..972427e166afc 100644
--- a/x-pack/legacy/plugins/canvas/public/legacy_start.ts
+++ b/x-pack/legacy/plugins/canvas/public/legacy_start.ts
@@ -11,7 +11,6 @@ import 'ui/autoload/all';
import 'uiExports/visTypes';
import 'uiExports/visResponseHandlers';
import 'uiExports/visRequestHandlers';
-import 'uiExports/visEditorTypes';
import 'uiExports/savedObjectTypes';
import 'uiExports/spyModes';
import 'uiExports/embeddableFactories';
diff --git a/x-pack/legacy/plugins/canvas/server/lib/build_embeddable_filters.ts b/x-pack/legacy/plugins/canvas/server/lib/build_embeddable_filters.ts
index 254a7ad8b3637..52fcc9813a93d 100644
--- a/x-pack/legacy/plugins/canvas/server/lib/build_embeddable_filters.ts
+++ b/x-pack/legacy/plugins/canvas/server/lib/build_embeddable_filters.ts
@@ -7,7 +7,13 @@
import { Filter } from '../../types';
// @ts-ignore Untyped Local
import { buildBoolArray } from './build_bool_array';
-import { TimeRange, esFilters } from '../../../../../../src/plugins/data/server';
+
+// TODO: We should be importing from `data/server` below instead of `data/common`, but
+// need to keep `data/common` since the contents of this file are currently imported
+// by the browser. This file should probably be refactored so that the pieces required
+// on the client live in a `public` directory instead. See kibana/issues/52343
+// eslint-disable-next-line @kbn/eslint/no-restricted-paths
+import { TimeRange, esFilters } from '../../../../../../src/plugins/data/common';
export interface EmbeddableFilterInput {
filters: esFilters.Filter[];
diff --git a/x-pack/legacy/plugins/canvas/shareable_runtime/components/footer/settings/__examples__/__snapshots__/autoplay_settings.examples.storyshot b/x-pack/legacy/plugins/canvas/shareable_runtime/components/footer/settings/__examples__/__snapshots__/autoplay_settings.examples.storyshot
index 27d82a664ff2a..57641882f2d84 100644
--- a/x-pack/legacy/plugins/canvas/shareable_runtime/components/footer/settings/__examples__/__snapshots__/autoplay_settings.examples.storyshot
+++ b/x-pack/legacy/plugins/canvas/shareable_runtime/components/footer/settings/__examples__/__snapshots__/autoplay_settings.examples.storyshot
@@ -65,13 +65,13 @@ exports[`Storyshots shareables/Footer/Settings/AutoplaySettings component: off,
-
Cycle Slides
-
+
can navigate Autoplay Settings 2`] = `
-
Cycle Slides
-
+
can navigate Autoplay Settings 2`] = `
>