From b54388746dedfadd8f5432f9005c063271afc129 Mon Sep 17 00:00:00 2001 From: The SpaceCake Project Date: Mon, 13 Apr 2020 18:42:10 -0400 Subject: [PATCH 01/12] investigation notes field (documentation / metadata) (#63386) * notes field added text to the "investigation notes" field in md which the field supports. * Revert "notes field" This reverts commit dae6ffc683150b9c471f3591073427ae62949a6e. * Revert "Revert "notes field"" This reverts commit f9de4bfc920217740fde316d3462cba409afa654. * Update linux_anomalous_network_activity.json * text change change to "Signals from this rule indicate" --- .../prepackaged_rules/linux_anomalous_network_activity.json | 3 ++- .../prepackaged_rules/linux_anomalous_process_all_hosts.json | 3 ++- .../rules/prepackaged_rules/linux_anomalous_user_name.json | 3 ++- .../rules/prepackaged_rules/rare_process_by_host_linux.json | 3 ++- .../rules/prepackaged_rules/rare_process_by_host_windows.json | 3 ++- .../prepackaged_rules/windows_anomalous_network_activity.json | 3 ++- .../prepackaged_rules/windows_anomalous_process_all_hosts.json | 3 ++- .../rules/prepackaged_rules/windows_anomalous_user_name.json | 3 ++- .../windows_rare_user_type10_remote_login.json | 3 ++- 9 files changed, 18 insertions(+), 9 deletions(-) diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_anomalous_network_activity.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_anomalous_network_activity.json index fe248a6c1e23ea..41f38173dba33b 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_anomalous_network_activity.json +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_anomalous_network_activity.json @@ -20,5 +20,6 @@ "ML" ], "type": "machine_learning", + "note": "### Investigating Unusual Network Activity ###\nSignals from this rule indicate the presence of network activity from a Linux process for which network activity is rare and unusual. Here are some possible avenues of investigation:\n- Consider the IP addresses and ports. Are these used by normal but infrequent network workflows? Are they expected or unexpected? \n- If the destination IP address is remote or external, does it associate with an expected domain, organization or geography? Note: avoid interacting directly with suspected malicious IP addresses.\n- Consider the user as identified by the username field. Is this network activity part of an expected workflow for the user who ran the program?\n- Examine the history of execution. If this process manifested only very recently, it might be part of a new software package. If it has a consistent cadence - for example if it runs monthly or quarterly - it might be part of a monthly or quarterly business or maintenance process.\n- Examine the process arguments, title and working directory. These may provide indications as to the source of the program or the nature of the tasks it is performing.", "version": 1 -} \ No newline at end of file +} diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_anomalous_process_all_hosts.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_anomalous_process_all_hosts.json index d15c4fc7943782..103171bcdfe501 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_anomalous_process_all_hosts.json +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_anomalous_process_all_hosts.json @@ -20,5 +20,6 @@ "ML" ], "type": "machine_learning", + "note": "### Investigating an Unusual Linux Process ###\nSignals from this rule indicate the presence of a Linux process that is rare and unusual for all of the monitored Linux hosts for which Auditbeat data is available. Here are some possible avenues of investigation:\n- Consider the user as identified by the username field. Is this program part of an expected workflow for the user who ran this program on this host?\n- Examine the history of execution. If this process manifested only very recently, it might be part of a new software package. If it has a consistent cadence - for example if it runs monthly or quarterly - it might be part of a monthly or quarterly business process.\n- Examine the process arguments, title and working directory. These may provide indications as to the source of the program or the nature of the tasks it is performing.", "version": 1 -} \ No newline at end of file +} diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_anomalous_user_name.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_anomalous_user_name.json index 2f33948b0a93e4..6642bb5d73fbdd 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_anomalous_user_name.json +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_anomalous_user_name.json @@ -20,5 +20,6 @@ "ML" ], "type": "machine_learning", + "note": "### Investigating an Unusual Linux User ###\nSignals from this rule indicate activity for a Linux user name that is rare and unusual. Here are some possible avenues of investigation:\n- Consider the user as identified by the username field. Is this program part of an expected workflow for the user who ran this program on this host? Could this be related to troubleshooting or debugging activity by a developer or site reliability engineer?\n- Examine the history of user activity. If this user manifested only very recently, it might be a service account for a new software package. If it has a consistent cadence - for example if it runs monthly or quarterly - it might be part of a monthly or quarterly business process.\n- Examine the process arguments, title and working directory. These may provide indications as to the source of the program or the nature of the tasks that the user is performing.", "version": 1 -} \ No newline at end of file +} diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/rare_process_by_host_linux.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/rare_process_by_host_linux.json index f071677ae8d330..8ae1b84aaf1997 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/rare_process_by_host_linux.json +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/rare_process_by_host_linux.json @@ -20,5 +20,6 @@ "ML" ], "type": "machine_learning", + "note": "### Investigating an Unusual Linux Process ###\nSignals from this rule indicate the presence of a Linux process that is rare and unusual for the host it ran on. Here are some possible avenues of investigation:\n- Consider the user as identified by the username field. Is this program part of an expected workflow for the user who ran this program on this host?\n- Examine the history of execution. If this process manifested only very recently, it might be part of a new software package. If it has a consistent cadence - for example if it runs monthly or quarterly - it might be part of a monthly or quarterly business process.\n- Examine the process arguments, title and working directory. These may provide indications as to the source of the program or the nature of the tasks it is performing.", "version": 1 -} \ No newline at end of file +} diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/rare_process_by_host_windows.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/rare_process_by_host_windows.json index 5e0050c6c25ec9..879cee388f5ddf 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/rare_process_by_host_windows.json +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/rare_process_by_host_windows.json @@ -20,5 +20,6 @@ "Windows" ], "type": "machine_learning", + "note": "### Investigating an Unusual Windows Process ###\nSignals from this rule indicate the presence of a Windows process that is rare and unusual for the host it ran on. Here are some possible avenues of investigation:\n- Consider the user as identified by the username field. Is this program part of an expected workflow for the user who ran this program on this host?\n- Examine the history of execution. If this process manifested only very recently, it might be part of a new software package. If it has a consistent cadence - for example if it runs monthly or quarterly - it might be part of a monthly or quarterly business process.\n- Examine the process metadata like the values of the Company, Description and Product fields which may indicate whether the program is associated with an expected software vendor or package. \n- Examine arguments and working directory. These may provide indications as to the source of the program or the nature of the tasks it is performing.\n- Consider the same for the parent process. If the parent process is a legitimate system utility or service, this could be related to software updates or system management. If the parent process is something user-facing like an Office application, this process could be more suspicious.\n- If you have file hash values in the event data, and you suspect malware, you can optionally run a search for the file hash to see if the file is identified as malware by anti-malware tools. ", "version": 1 -} \ No newline at end of file +} diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_anomalous_network_activity.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_anomalous_network_activity.json index ca18fe95b1fc1a..1092bcb20bcc35 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_anomalous_network_activity.json +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_anomalous_network_activity.json @@ -20,5 +20,6 @@ "Windows" ], "type": "machine_learning", + "note": "### Investigating Unusual Network Activity ###\nSignals from this rule indicate the presence of network activity from a Windows process for which network activity is very unusual. Here are some possible avenues of investigation:\n- Consider the IP addresses, protocol and ports. Are these used by normal but infrequent network workflows? Are they expected or unexpected? \n- If the destination IP address is remote or external, does it associate with an expected domain, organization or geography? Note: avoid interacting directly with suspected malicious IP addresses.\n- Consider the user as identified by the username field. Is this network activity part of an expected workflow for the user who ran the program?\n- Examine the history of execution. If this process manifested only very recently, it might be part of a new software package. If it has a consistent cadence - for example if it runs monthly or quarterly - it might be part of a monthly or quarterly business process.\n- Examine the process arguments, title and working directory. These may provide indications as to the source of the program or the nature of the tasks it is performing.\n- Consider the same for the parent process. If the parent process is a legitimate system utility or service, this could be related to software updates or system management. If the parent process is something user-facing like an Office application, this process could be more suspicious.\n- If you have file hash values in the event data, and you suspect malware, you can optionally run a search for the file hash to see if the file is identified as malware by anti-malware tools. ", "version": 1 -} \ No newline at end of file +} diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_anomalous_process_all_hosts.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_anomalous_process_all_hosts.json index 1229c4a52b97d8..f9adfeb830618a 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_anomalous_process_all_hosts.json +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_anomalous_process_all_hosts.json @@ -20,5 +20,6 @@ "Windows" ], "type": "machine_learning", + "note": "### Investigating an Unusual Windows Process ###\nSignals from this rule indicate the presence of a Windows process that is rare and unusual for all of the Windows hosts for which Winlogbeat data is available. Here are some possible avenues of investigation:\n- Consider the user as identified by the username field. Is this program part of an expected workflow for the user who ran this program on this host?\n- Examine the history of execution. If this process manifested only very recently, it might be part of a new software package. If it has a consistent cadence - for example if it runs monthly or quarterly - it might be part of a monthly or quarterly business process.\n- Examine the process metadata like the values of the Company, Description and Product fields which may indicate whether the program is associated with an expected software vendor or package. \n- Examine arguments and working directory. These may provide indications as to the source of the program or the nature of the tasks it is performing.\n- Consider the same for the parent process. If the parent process is a legitimate system utility or service, this could be related to software updates or system management. If the parent process is something user-facing like an Office application, this process could be more suspicious.\n- If you have file hash values in the event data, and you suspect malware, you can optionally run a search for the file hash to see if the file is identified as malware by anti-malware tools. ", "version": 1 -} \ No newline at end of file +} diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_anomalous_user_name.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_anomalous_user_name.json index 703dc1a1dc6338..a0c6ff5c938f1c 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_anomalous_user_name.json +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_anomalous_user_name.json @@ -20,5 +20,6 @@ "Windows" ], "type": "machine_learning", + "note": "### Investigating an Unusual Windows User ###\nSignals from this rule indicate activity for a Windows user name that is rare and unusual. Here are some possible avenues of investigation:\n- Consider the user as identified by the username field. Is this program part of an expected workflow for the user who ran this program on this host? Could this be related to occasional troubleshooting or support activity?\n- Examine the history of user activity. If this user manifested only very recently, it might be a service account for a new software package. If it has a consistent cadence - for example if it runs monthly or quarterly - it might be part of a monthly or quarterly business process.\n- Examine the process arguments, title and working directory. These may provide indications as to the source of the program or the nature of the tasks that the user is performing.\n- Consider the same for the parent process. If the parent process is a legitimate system utility or service, this could be related to software updates or system management. If the parent process is something user-facing like an Office application, this process could be more suspicious.", "version": 1 -} \ No newline at end of file +} diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_rare_user_type10_remote_login.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_rare_user_type10_remote_login.json index 946cdb95b8e702..7318364c3aac27 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_rare_user_type10_remote_login.json +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_rare_user_type10_remote_login.json @@ -20,5 +20,6 @@ "Windows" ], "type": "machine_learning", + "note": "### Investigating an Unusual Windows User ###\nSignals from this rule indicate activity for a rare and unusual Windows RDP (remote desktop) user. Here are some possible avenues of investigation:\n- Consider the user as identified by the username field. Is the user part of a group who normally logs into Windows hosts using RDP (remote desktop protocol)? Is this logon activity part of an expected workflow for the user? \n- Consider the source of the login. If the source is remote, could this be related to occasional troubleshooting or support activity by a vendor or an employee working remotely?", "version": 1 -} \ No newline at end of file +} From 5bc539c6db8c1f735876e0f16adb7bbd5d4b41eb Mon Sep 17 00:00:00 2001 From: Gil Raphaelli Date: Mon, 13 Apr 2020 22:06:09 -0400 Subject: [PATCH 02/12] update in-app links to metricbeat configuration docs (#63295) --- .../flyout/__snapshots__/flyout.test.js.snap | 24 +++++++++---------- .../apm/enable_metricbeat_instructions.js | 6 ++--- .../beats/enable_metricbeat_instructions.js | 2 +- .../kibana/enable_metricbeat_instructions.js | 2 +- .../enable_metricbeat_instructions.js | 2 +- 5 files changed, 18 insertions(+), 18 deletions(-) diff --git a/x-pack/legacy/plugins/monitoring/public/components/metricbeat_migration/flyout/__snapshots__/flyout.test.js.snap b/x-pack/legacy/plugins/monitoring/public/components/metricbeat_migration/flyout/__snapshots__/flyout.test.js.snap index eb1c65c6a696da..4a7537166bd8af 100644 --- a/x-pack/legacy/plugins/monitoring/public/components/metricbeat_migration/flyout/__snapshots__/flyout.test.js.snap +++ b/x-pack/legacy/plugins/monitoring/public/components/metricbeat_migration/flyout/__snapshots__/flyout.test.js.snap @@ -161,7 +161,7 @@ exports[`Flyout apm part two should show instructions to migrate to metricbeat 1 "children":

Date: Tue, 14 Apr 2020 02:05:06 -0400 Subject: [PATCH 03/12] [Endpoint] Update cli mapping to match endpoint package (#63372) * Update cli mapping to match endpoint package --- x-pack/plugins/endpoint/scripts/alert_mapping.json | 3 ++- x-pack/plugins/endpoint/scripts/event_mapping.json | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/x-pack/plugins/endpoint/scripts/alert_mapping.json b/x-pack/plugins/endpoint/scripts/alert_mapping.json index a21e48b4bc95fc..2e0041d0af9867 100644 --- a/x-pack/plugins/endpoint/scripts/alert_mapping.json +++ b/x-pack/plugins/endpoint/scripts/alert_mapping.json @@ -394,7 +394,8 @@ "type": "nested" }, "file_extension": { - "type": "long" + "ignore_above": 1024, + "type": "keyword" }, "project_file": { "properties": { diff --git a/x-pack/plugins/endpoint/scripts/event_mapping.json b/x-pack/plugins/endpoint/scripts/event_mapping.json index 59d1ed17852b16..f410edc7abe5ef 100644 --- a/x-pack/plugins/endpoint/scripts/event_mapping.json +++ b/x-pack/plugins/endpoint/scripts/event_mapping.json @@ -386,7 +386,8 @@ "type": "nested" }, "file_extension": { - "type": "long" + "ignore_above": 1024, + "type": "keyword" }, "project_file": { "properties": { From f4abaabaee04ed78cb38f32defed37ac969834a5 Mon Sep 17 00:00:00 2001 From: Jean-Louis Leysens Date: Tue, 14 Apr 2020 08:47:23 +0200 Subject: [PATCH 04/12] Escape single quotes surrounded by double quotes (#63229) Co-authored-by: Elastic Machine --- .../models/sense_editor/__tests__/editor_input1.txt | 6 ++++++ .../sense_editor/__tests__/sense_editor.test.js | 12 ++++++++++++ .../application/models/sense_editor/sense_editor.ts | 5 +++-- 3 files changed, 21 insertions(+), 2 deletions(-) diff --git a/src/plugins/console/public/application/models/sense_editor/__tests__/editor_input1.txt b/src/plugins/console/public/application/models/sense_editor/__tests__/editor_input1.txt index f9a4bcb85034d1..398a0fdeab61f1 100644 --- a/src/plugins/console/public/application/models/sense_editor/__tests__/editor_input1.txt +++ b/src/plugins/console/public/application/models/sense_editor/__tests__/editor_input1.txt @@ -25,3 +25,9 @@ GET index_1/type1/1/_source?_source_include=f DELETE index_2 + +POST /_sql?format=txt +{ + "query": "SELECT prenom FROM claude_index WHERE prenom = 'claude' ", + "fetch_size": 1 +} diff --git a/src/plugins/console/public/application/models/sense_editor/__tests__/sense_editor.test.js b/src/plugins/console/public/application/models/sense_editor/__tests__/sense_editor.test.js index 6afc03df13b4cd..34b4cad7fbb6bb 100644 --- a/src/plugins/console/public/application/models/sense_editor/__tests__/sense_editor.test.js +++ b/src/plugins/console/public/application/models/sense_editor/__tests__/sense_editor.test.js @@ -470,6 +470,18 @@ curl -XGET "http://localhost:9200/_stats?level=shards" curl -XPUT "http://localhost:9200/index_1/type1/1" -H 'Content-Type: application/json' -d' { "f": 1 +}'`.trim() + ); + + multiReqCopyAsCurlTest( + 'with single quotes', + editorInput1, + { start: { lineNumber: 29 }, end: { lineNumber: 33 } }, + ` +curl -XPOST "http://localhost:9200/_sql?format=txt" -H 'Content-Type: application/json' -d' +{ + "query": "SELECT prenom FROM claude_index WHERE prenom = '\\''claude'\\'' ", + "fetch_size": 1 }'`.trim() ); }); diff --git a/src/plugins/console/public/application/models/sense_editor/sense_editor.ts b/src/plugins/console/public/application/models/sense_editor/sense_editor.ts index 9bcd3a68721968..d326543bbe00bb 100644 --- a/src/plugins/console/public/application/models/sense_editor/sense_editor.ts +++ b/src/plugins/console/public/application/models/sense_editor/sense_editor.ts @@ -484,8 +484,9 @@ export class SenseEditor { if (esData && esData.length) { ret += " -H 'Content-Type: application/json' -d'\n"; const dataAsString = collapseLiteralStrings(esData.join('\n')); - // since Sense doesn't allow single quote json string any single qoute is within a string. - ret += dataAsString.replace(/'/g, '\\"'); + + // We escape single quoted strings that that are wrapped in single quoted strings + ret += dataAsString.replace(/'/g, "'\\''"); if (esData.length > 1) { ret += '\n'; } // end with a new line From f44d951300169f7fefeb621e5642f42131dae9fc Mon Sep 17 00:00:00 2001 From: Mikhail Shustov Date: Tue, 14 Apr 2020 09:11:03 +0200 Subject: [PATCH 05/12] document code splitting for client code (#62593) * add lazy loading section for client bundles * add Pierres suggestion --- src/core/MIGRATION.md | 61 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 61 insertions(+) diff --git a/src/core/MIGRATION.md b/src/core/MIGRATION.md index 5d7b467052029e..368d1f47e9c3fa 100644 --- a/src/core/MIGRATION.md +++ b/src/core/MIGRATION.md @@ -24,6 +24,7 @@ - [7. Switch to new platform services](#7-switch-to-new-platform-services) - [8. Migrate to the new plugin system](#8-migrate-to-the-new-plugin-system) - [Bonus: Tips for complex migration scenarios](#bonus-tips-for-complex-migration-scenarios) + - [Keep Kibana fast](#keep-kibana-fast) - [Frequently asked questions](#frequently-asked-questions) - [Is migrating a plugin an all-or-nothing thing?](#is-migrating-a-plugin-an-all-or-nothing-thing) - [Do plugins need to be converted to TypeScript?](#do-plugins-need-to-be-converted-to-typescript) @@ -933,6 +934,66 @@ For a few plugins, some of these steps (such as angular removal) could be a mont One convention that is useful for this is creating a dedicated `public/np_ready` directory to house the code that is ready to migrate, and gradually move more and more code into it until the rest of your plugin is essentially empty. At that point, you'll be able to copy your `index.ts`, `plugin.ts`, and the contents of `./np_ready` over into your plugin in the new platform, leaving your legacy shim behind. This carries the added benefit of providing a way for us to introduce helpful tooling in the future, such as [custom eslint rules](https://github.com/elastic/kibana/pull/40537), which could be run against that specific directory to ensure your code is ready to migrate. +## Keep Kibana fast +**tl;dr**: Load as much code lazily as possible. +Everyone loves snappy applications with responsive UI and hates spinners. Users deserve the best user experiences regardless of whether they run Kibana locally or in the cloud, regardless of their hardware & environment. +There are 2 main aspects of the perceived speed of an application: loading time and responsiveness to user actions. +New platform loads and bootstraps **all** the plugins whenever a user lands on any page. It means that adding every new application affects overall **loading performance** in the new platform, as plugin code is loaded **eagerly** to initialize the plugin and provide plugin API to dependent plugins. +However, it's usually not necessary that the whole plugin code should be loaded and initialized at once. The plugin could keep on loading code covering API functionality on Kibana bootstrap but load UI related code lazily on-demand, when an application page or management section is mounted. +Always prefer to require UI root components lazily when possible (such as in mount handlers). Even if their size may seem negligible, they are likely using some heavy-weight libraries that will also be removed from the initial plugin bundle, therefore, reducing its size by a significant amount. + +```typescript +import { Plugin, CoreSetup, AppMountParameters } from 'src/core/public'; +export class MyPlugin implements Plugin { + setup(core: CoreSetup, plugins: SetupDeps){ + core.application.register({ + id: 'app', + title: 'My app', + async mount(params: AppMountParameters) { + const { mountApp } = await import('./app/mount_app'); + return mountApp(await core.getStartServices(), params); + }, + }); + plugins.management.sections.getSection('another').registerApp({ + id: 'app', + title: 'My app', + order: 1, + async mount(params) { + const { mountManagementSection } = await import('./app/mount_management_section'); + return mountManagementSection(coreSetup, params); + }, + }) + return { + doSomething(){} + } + } +} +``` + +#### How to understand how big the bundle size of my plugin is? +New platform plugins are distributed as a pre-built with `@kbn/optimizer` package artifacts. It allows us to get rid of the shipping of `optimizer` in the distributable version of Kibana. +Every NP plugin artifact contains all plugin dependencies required to run the plugin, except some stateful dependencies shared across plugin bundles via `@kbn/ui-shared-deps`. +It means that NP plugin artifacts tend to have a bigger size than the legacy platform version. +To understand the current size of your plugin artifact, run `@kbn/optimizer` as +```bash +node scripts/build_kibana_platform_plugins.js --dist --no-examples +``` +and check the output in the `target` sub-folder of your plugin folder +```bash +ls -lh plugins/my_plugin/target/public/ +# output +# an async chunk loaded on demand +... 262K 0.plugin.js +# eagerly loaded chunk +... 50K my_plugin.plugin.js +``` +you might see at least one js bundle - `my_plugin.plugin.js`. This is the only artifact loaded by the platform during bootstrap in the browser. The rule of thumb is to keep its size as small as possible. +Other lazily loaded parts of your plugin present in the same folder as separate chunks under `{number}.plugin.js` names. +If you want to investigate what your plugin bundle consists of you need to run `@kbn/optimizer` with `--profile` flag to get generated [webpack stats file](https://webpack.js.org/api/stats/). +Many OSS tools are allowing you to analyze generated stats file +- [an official tool](http://webpack.github.io/analyse/#modules) from webpack authors +- [webpack-visualizer](https://chrisbateman.github.io/webpack-visualizer/) + ## Frequently asked questions ### Is migrating a plugin an all-or-nothing thing? From 1f732ad29ac7f386d9255d016f80c51367abd685 Mon Sep 17 00:00:00 2001 From: Gidi Meir Morris Date: Tue, 14 Apr 2020 10:57:46 +0100 Subject: [PATCH 06/12] [Event Log] Adds namespace into save objects (#62974) Adds a namespace attribute to the saved object object within the Event Log so that each Saved Object can have its own. This change also removes the existing kibana.namespace field. As Event Log is not yet in use, this does not include a migration. --- .../plugins/actions/server/lib/action_executor.ts | 9 ++++----- .../task_runner/create_execution_handler.test.ts | 1 - .../task_runner/create_execution_handler.ts | 7 ++++--- .../server/task_runner/task_runner.test.ts | 15 ++++++++------- .../alerting/server/task_runner/task_runner.ts | 5 ++--- x-pack/plugins/event_log/README.md | 1 - x-pack/plugins/event_log/generated/mappings.json | 6 +----- x-pack/plugins/event_log/generated/schemas.ts | 3 +-- x-pack/plugins/event_log/scripts/mappings.js | 12 +++--------- .../server/routes/_mock_handler_arguments.ts | 2 +- .../event_log/public_api_integration.ts | 2 +- 11 files changed, 25 insertions(+), 38 deletions(-) diff --git a/x-pack/plugins/actions/server/lib/action_executor.ts b/x-pack/plugins/actions/server/lib/action_executor.ts index af0353247d99f1..ba8bb79170c63b 100644 --- a/x-pack/plugins/actions/server/lib/action_executor.ts +++ b/x-pack/plugins/actions/server/lib/action_executor.ts @@ -75,7 +75,8 @@ export class ActionExecutor { } = this.actionExecutorContext!; const services = getServices(request); - const namespace = spaces && spaces.getSpaceId(request); + const spaceId = spaces && spaces.getSpaceId(request); + const namespace = spaceId && spaceId !== 'default' ? { namespace: spaceId } : {}; // Ensure user can read the action before processing const { @@ -91,9 +92,7 @@ export class ActionExecutor { } = await encryptedSavedObjectsPlugin.getDecryptedAsInternalUser( 'action', actionId, - { - namespace: namespace === 'default' ? undefined : namespace, - } + namespace ); const actionType = actionTypeRegistry.get(actionTypeId); @@ -112,7 +111,7 @@ export class ActionExecutor { const actionLabel = `${actionTypeId}:${actionId}: ${name}`; const event: IEvent = { event: { action: EVENT_LOG_ACTIONS.execute }, - kibana: { namespace, saved_objects: [{ type: 'action', id: actionId }] }, + kibana: { saved_objects: [{ type: 'action', id: actionId, ...namespace }] }, }; eventLogger.startTiming(event); diff --git a/x-pack/plugins/alerting/server/task_runner/create_execution_handler.test.ts b/x-pack/plugins/alerting/server/task_runner/create_execution_handler.test.ts index 8d037a1ecee913..756080baba6266 100644 --- a/x-pack/plugins/alerting/server/task_runner/create_execution_handler.test.ts +++ b/x-pack/plugins/alerting/server/task_runner/create_execution_handler.test.ts @@ -91,7 +91,6 @@ test('calls actionsPlugin.execute per selected action', async () => { "alerting": Object { "instance_id": "2", }, - "namespace": "default", "saved_objects": Array [ Object { "id": "1", diff --git a/x-pack/plugins/alerting/server/task_runner/create_execution_handler.ts b/x-pack/plugins/alerting/server/task_runner/create_execution_handler.ts index de06c8bbb374a8..72f9e70905dc28 100644 --- a/x-pack/plugins/alerting/server/task_runner/create_execution_handler.ts +++ b/x-pack/plugins/alerting/server/task_runner/create_execution_handler.ts @@ -87,16 +87,17 @@ export function createExecutionHandler({ apiKey, }); + const namespace = spaceId === 'default' ? {} : { namespace: spaceId }; + const event: IEvent = { event: { action: EVENT_LOG_ACTIONS.executeAction }, kibana: { alerting: { instance_id: alertInstanceId, }, - namespace: spaceId, saved_objects: [ - { type: 'alert', id: alertId }, - { type: 'action', id: action.id }, + { type: 'alert', id: alertId, ...namespace }, + { type: 'action', id: action.id, ...namespace }, ], }, }; diff --git a/x-pack/plugins/alerting/server/task_runner/task_runner.test.ts b/x-pack/plugins/alerting/server/task_runner/task_runner.test.ts index 520f8d5c99b16d..4e6d959f0ce602 100644 --- a/x-pack/plugins/alerting/server/task_runner/task_runner.test.ts +++ b/x-pack/plugins/alerting/server/task_runner/task_runner.test.ts @@ -169,10 +169,10 @@ describe('Task Runner', () => { "action": "execute", }, "kibana": Object { - "namespace": undefined, "saved_objects": Array [ Object { "id": "1", + "namespace": undefined, "type": "alert", }, ], @@ -229,10 +229,10 @@ describe('Task Runner', () => { "action": "execute", }, "kibana": Object { - "namespace": undefined, "saved_objects": Array [ Object { "id": "1", + "namespace": undefined, "type": "alert", }, ], @@ -249,10 +249,10 @@ describe('Task Runner', () => { "alerting": Object { "instance_id": "1", }, - "namespace": undefined, "saved_objects": Array [ Object { "id": "1", + "namespace": undefined, "type": "alert", }, ], @@ -269,14 +269,15 @@ describe('Task Runner', () => { "alerting": Object { "instance_id": "1", }, - "namespace": undefined, "saved_objects": Array [ Object { "id": "1", + "namespace": undefined, "type": "alert", }, Object { "id": "1", + "namespace": undefined, "type": "action", }, ], @@ -344,10 +345,10 @@ describe('Task Runner', () => { "action": "execute", }, "kibana": Object { - "namespace": undefined, "saved_objects": Array [ Object { "id": "1", + "namespace": undefined, "type": "alert", }, ], @@ -364,10 +365,10 @@ describe('Task Runner', () => { "alerting": Object { "instance_id": "2", }, - "namespace": undefined, "saved_objects": Array [ Object { "id": "1", + "namespace": undefined, "type": "alert", }, ], @@ -560,10 +561,10 @@ describe('Task Runner', () => { "action": "execute", }, "kibana": Object { - "namespace": undefined, "saved_objects": Array [ Object { "id": "1", + "namespace": undefined, "type": "alert", }, ], diff --git a/x-pack/plugins/alerting/server/task_runner/task_runner.ts b/x-pack/plugins/alerting/server/task_runner/task_runner.ts index 2ba56396279ea2..190cdc184930ce 100644 --- a/x-pack/plugins/alerting/server/task_runner/task_runner.ts +++ b/x-pack/plugins/alerting/server/task_runner/task_runner.ts @@ -173,7 +173,7 @@ export class TaskRunner { const alertLabel = `${this.alertType.id}:${alertId}: '${name}'`; const event: IEvent = { event: { action: EVENT_LOG_ACTIONS.execute }, - kibana: { namespace, saved_objects: [{ type: 'alert', id: alertId }] }, + kibana: { saved_objects: [{ type: 'alert', id: alertId, namespace }] }, }; eventLogger.startTiming(event); @@ -378,11 +378,10 @@ function generateNewAndResolvedInstanceEvents(params: GenerateNewAndResolvedInst action, }, kibana: { - namespace: params.namespace, alerting: { instance_id: id, }, - saved_objects: [{ type: 'alert', id: params.alertId }], + saved_objects: [{ type: 'alert', id: params.alertId, namespace: params.namespace }], }, message, }; diff --git a/x-pack/plugins/event_log/README.md b/x-pack/plugins/event_log/README.md index 027bbc694801f6..38364033cb70be 100644 --- a/x-pack/plugins/event_log/README.md +++ b/x-pack/plugins/event_log/README.md @@ -125,7 +125,6 @@ Here's the event written to the event log index: "duration": 1000000 }, "kibana": { - "namespace": "default", "saved_objects": [ { "type": "action", diff --git a/x-pack/plugins/event_log/generated/mappings.json b/x-pack/plugins/event_log/generated/mappings.json index ab1b4096d17f2c..9c1dff60f9727a 100644 --- a/x-pack/plugins/event_log/generated/mappings.json +++ b/x-pack/plugins/event_log/generated/mappings.json @@ -72,10 +72,6 @@ "type": "keyword", "ignore_above": 1024 }, - "namespace": { - "type": "keyword", - "ignore_above": 1024 - }, "alerting": { "properties": { "instance_id": { @@ -86,7 +82,7 @@ }, "saved_objects": { "properties": { - "store": { + "namespace": { "type": "keyword", "ignore_above": 1024 }, diff --git a/x-pack/plugins/event_log/generated/schemas.ts b/x-pack/plugins/event_log/generated/schemas.ts index b731093b33b06e..5e93f320c009f2 100644 --- a/x-pack/plugins/event_log/generated/schemas.ts +++ b/x-pack/plugins/event_log/generated/schemas.ts @@ -56,7 +56,6 @@ export const EventSchema = schema.maybe( kibana: schema.maybe( schema.object({ server_uuid: ecsString(), - namespace: ecsString(), alerting: schema.maybe( schema.object({ instance_id: ecsString(), @@ -65,7 +64,7 @@ export const EventSchema = schema.maybe( saved_objects: schema.maybe( schema.arrayOf( schema.object({ - store: ecsString(), + namespace: ecsString(), id: ecsString(), type: ecsString(), }) diff --git a/x-pack/plugins/event_log/scripts/mappings.js b/x-pack/plugins/event_log/scripts/mappings.js index 9e721b06ec3351..de3c9d631fbca6 100644 --- a/x-pack/plugins/event_log/scripts/mappings.js +++ b/x-pack/plugins/event_log/scripts/mappings.js @@ -20,17 +20,12 @@ exports.EcsKibanaExtensionsMappings = { }, }, }, - // relevant kibana space - namespace: { - type: 'keyword', - ignore_above: 1024, - }, // array of saved object references, for "linking" via search saved_objects: { type: 'nested', properties: { - // 'kibana' for typical saved object, 'task_manager' for TM, etc - store: { + // relevant kibana space + namespace: { type: 'keyword', ignore_above: 1024, }, @@ -61,9 +56,8 @@ exports.EcsEventLogProperties = [ 'error.message', 'user.name', 'kibana.server_uuid', - 'kibana.namespace', 'kibana.alerting.instance_id', - 'kibana.saved_objects.store', + 'kibana.saved_objects.namespace', 'kibana.saved_objects.id', 'kibana.saved_objects.name', 'kibana.saved_objects.type', diff --git a/x-pack/plugins/event_log/server/routes/_mock_handler_arguments.ts b/x-pack/plugins/event_log/server/routes/_mock_handler_arguments.ts index 6640683bf6005e..19933649277aa3 100644 --- a/x-pack/plugins/event_log/server/routes/_mock_handler_arguments.ts +++ b/x-pack/plugins/event_log/server/routes/_mock_handler_arguments.ts @@ -50,9 +50,9 @@ export function fakeEvent(overrides = {}) { duration: 1000000, }, kibana: { - namespace: 'default', saved_objects: [ { + namespace: 'default', type: 'action', id: '968f1b82-0414-4a10-becc-56b6473e4a29', }, diff --git a/x-pack/test/plugin_api_integration/test_suites/event_log/public_api_integration.ts b/x-pack/test/plugin_api_integration/test_suites/event_log/public_api_integration.ts index c440971225d78f..d664357c3ba126 100644 --- a/x-pack/test/plugin_api_integration/test_suites/event_log/public_api_integration.ts +++ b/x-pack/test/plugin_api_integration/test_suites/event_log/public_api_integration.ts @@ -220,9 +220,9 @@ export default function({ getService }: FtrProviderContext) { duration: 1000000, }, kibana: { - namespace: 'default', saved_objects: [ { + namespace: 'default', type: 'event_log_test', id, }, From 637a9e11a2d713b8aa82d134ebf0c3d09abeace7 Mon Sep 17 00:00:00 2001 From: Dmitry Lemeshko Date: Tue, 14 Apr 2020 14:25:26 +0300 Subject: [PATCH 07/12] Revert FTR: add chromium-based Edge browser support (#61684) (#63448) --- package.json | 5 +- packages/kbn-pm/dist/index.js | 1105 ++++++++++++++--- .../lib/config/schema.ts | 2 +- test/functional/config.edge.js | 34 - test/functional/services/browser.ts | 4 +- .../web_element_wrapper.ts | 9 +- test/functional/services/remote/browsers.ts | 1 - test/functional/services/remote/remote.ts | 17 +- test/functional/services/remote/webdriver.ts | 50 +- x-pack/test/functional/config.edge.js | 21 - yarn.lock | 322 +---- 11 files changed, 1013 insertions(+), 557 deletions(-) delete mode 100644 test/functional/config.edge.js delete mode 100644 x-pack/test/functional/config.edge.js diff --git a/package.json b/package.json index 2bad3116c9ef2b..388e46aedf37d2 100644 --- a/package.json +++ b/package.json @@ -376,7 +376,7 @@ "@types/recompose": "^0.30.6", "@types/redux-actions": "^2.6.1", "@types/request": "^2.48.2", - "@types/selenium-webdriver": "4.0.9", + "@types/selenium-webdriver": "^4.0.5", "@types/semver": "^5.5.0", "@types/sinon": "^7.0.13", "@types/strip-ansi": "^3.0.0", @@ -462,7 +462,6 @@ "load-grunt-config": "^3.0.1", "mocha": "^7.1.1", "mock-http-server": "1.3.0", - "ms-chromium-edge-driver": "^0.2.0", "multistream": "^2.1.1", "murmurhash3js": "3.0.1", "mutation-observer": "^1.0.3", @@ -481,7 +480,7 @@ "react-textarea-autosize": "^7.1.2", "regenerate": "^1.4.0", "sass-lint": "^1.12.1", - "selenium-webdriver": "^4.0.0-alpha.7", + "selenium-webdriver": "^4.0.0-alpha.5", "simple-git": "1.116.0", "simplebar-react": "^2.1.0", "sinon": "^7.4.2", diff --git a/packages/kbn-pm/dist/index.js b/packages/kbn-pm/dist/index.js index 399720f310f67f..fa8884e2ece758 100644 --- a/packages/kbn-pm/dist/index.js +++ b/packages/kbn-pm/dist/index.js @@ -79185,7 +79185,7 @@ __webpack_require__.r(__webpack_exports__); /* harmony import */ var _build_production_projects__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(704); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "buildProductionProjects", function() { return _build_production_projects__WEBPACK_IMPORTED_MODULE_0__["buildProductionProjects"]; }); -/* harmony import */ var _prepare_project_dependencies__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(922); +/* harmony import */ var _prepare_project_dependencies__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(927); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "prepareExternalProjectDependencies", function() { return _prepare_project_dependencies__WEBPACK_IMPORTED_MODULE_1__["prepareExternalProjectDependencies"]; }); /* @@ -79370,9 +79370,9 @@ const pAll = __webpack_require__(706); const arrify = __webpack_require__(708); const globby = __webpack_require__(709); const isGlob = __webpack_require__(603); -const cpFile = __webpack_require__(907); -const junk = __webpack_require__(919); -const CpyError = __webpack_require__(920); +const cpFile = __webpack_require__(912); +const junk = __webpack_require__(924); +const CpyError = __webpack_require__(925); const defaultOptions = { ignoreJunk: true @@ -79622,8 +79622,8 @@ const fs = __webpack_require__(23); const arrayUnion = __webpack_require__(710); const glob = __webpack_require__(712); const fastGlob = __webpack_require__(717); -const dirGlob = __webpack_require__(900); -const gitignore = __webpack_require__(903); +const dirGlob = __webpack_require__(905); +const gitignore = __webpack_require__(908); const DEFAULT_FILTER = () => false; @@ -81456,11 +81456,11 @@ module.exports.generateTasks = pkg.generateTasks; Object.defineProperty(exports, "__esModule", { value: true }); var optionsManager = __webpack_require__(719); var taskManager = __webpack_require__(720); -var reader_async_1 = __webpack_require__(871); -var reader_stream_1 = __webpack_require__(895); -var reader_sync_1 = __webpack_require__(896); -var arrayUtils = __webpack_require__(898); -var streamUtils = __webpack_require__(899); +var reader_async_1 = __webpack_require__(876); +var reader_stream_1 = __webpack_require__(900); +var reader_sync_1 = __webpack_require__(901); +var arrayUtils = __webpack_require__(903); +var streamUtils = __webpack_require__(904); /** * Synchronous API. */ @@ -82100,9 +82100,9 @@ var extend = __webpack_require__(837); */ var compilers = __webpack_require__(840); -var parsers = __webpack_require__(867); -var cache = __webpack_require__(868); -var utils = __webpack_require__(869); +var parsers = __webpack_require__(872); +var cache = __webpack_require__(873); +var utils = __webpack_require__(874); var MAX_LENGTH = 1024 * 64; /** @@ -100635,9 +100635,9 @@ var toRegex = __webpack_require__(728); */ var compilers = __webpack_require__(857); -var parsers = __webpack_require__(863); -var Extglob = __webpack_require__(866); -var utils = __webpack_require__(865); +var parsers = __webpack_require__(868); +var Extglob = __webpack_require__(871); +var utils = __webpack_require__(870); var MAX_LENGTH = 1024 * 64; /** @@ -101147,7 +101147,7 @@ var parsers = __webpack_require__(861); * Module dependencies */ -var debug = __webpack_require__(800)('expand-brackets'); +var debug = __webpack_require__(863)('expand-brackets'); var extend = __webpack_require__(737); var Snapdragon = __webpack_require__(767); var toRegex = __webpack_require__(728); @@ -101741,12 +101741,839 @@ exports.createRegex = function(pattern, include) { /* 863 */ /***/ (function(module, exports, __webpack_require__) { +/** + * Detect Electron renderer process, which is node, but we should + * treat as a browser. + */ + +if (typeof process !== 'undefined' && process.type === 'renderer') { + module.exports = __webpack_require__(864); +} else { + module.exports = __webpack_require__(867); +} + + +/***/ }), +/* 864 */ +/***/ (function(module, exports, __webpack_require__) { + +/** + * This is the web browser implementation of `debug()`. + * + * Expose `debug()` as the module. + */ + +exports = module.exports = __webpack_require__(865); +exports.log = log; +exports.formatArgs = formatArgs; +exports.save = save; +exports.load = load; +exports.useColors = useColors; +exports.storage = 'undefined' != typeof chrome + && 'undefined' != typeof chrome.storage + ? chrome.storage.local + : localstorage(); + +/** + * Colors. + */ + +exports.colors = [ + 'lightseagreen', + 'forestgreen', + 'goldenrod', + 'dodgerblue', + 'darkorchid', + 'crimson' +]; + +/** + * Currently only WebKit-based Web Inspectors, Firefox >= v31, + * and the Firebug extension (any Firefox version) are known + * to support "%c" CSS customizations. + * + * TODO: add a `localStorage` variable to explicitly enable/disable colors + */ + +function useColors() { + // NB: In an Electron preload script, document will be defined but not fully + // initialized. Since we know we're in Chrome, we'll just detect this case + // explicitly + if (typeof window !== 'undefined' && window.process && window.process.type === 'renderer') { + return true; + } + + // is webkit? http://stackoverflow.com/a/16459606/376773 + // document is undefined in react-native: https://github.com/facebook/react-native/pull/1632 + return (typeof document !== 'undefined' && document.documentElement && document.documentElement.style && document.documentElement.style.WebkitAppearance) || + // is firebug? http://stackoverflow.com/a/398120/376773 + (typeof window !== 'undefined' && window.console && (window.console.firebug || (window.console.exception && window.console.table))) || + // is firefox >= v31? + // https://developer.mozilla.org/en-US/docs/Tools/Web_Console#Styling_messages + (typeof navigator !== 'undefined' && navigator.userAgent && navigator.userAgent.toLowerCase().match(/firefox\/(\d+)/) && parseInt(RegExp.$1, 10) >= 31) || + // double check webkit in userAgent just in case we are in a worker + (typeof navigator !== 'undefined' && navigator.userAgent && navigator.userAgent.toLowerCase().match(/applewebkit\/(\d+)/)); +} + +/** + * Map %j to `JSON.stringify()`, since no Web Inspectors do that by default. + */ + +exports.formatters.j = function(v) { + try { + return JSON.stringify(v); + } catch (err) { + return '[UnexpectedJSONParseError]: ' + err.message; + } +}; + + +/** + * Colorize log arguments if enabled. + * + * @api public + */ + +function formatArgs(args) { + var useColors = this.useColors; + + args[0] = (useColors ? '%c' : '') + + this.namespace + + (useColors ? ' %c' : ' ') + + args[0] + + (useColors ? '%c ' : ' ') + + '+' + exports.humanize(this.diff); + + if (!useColors) return; + + var c = 'color: ' + this.color; + args.splice(1, 0, c, 'color: inherit') + + // the final "%c" is somewhat tricky, because there could be other + // arguments passed either before or after the %c, so we need to + // figure out the correct index to insert the CSS into + var index = 0; + var lastC = 0; + args[0].replace(/%[a-zA-Z%]/g, function(match) { + if ('%%' === match) return; + index++; + if ('%c' === match) { + // we only are interested in the *last* %c + // (the user may have provided their own) + lastC = index; + } + }); + + args.splice(lastC, 0, c); +} + +/** + * Invokes `console.log()` when available. + * No-op when `console.log` is not a "function". + * + * @api public + */ + +function log() { + // this hackery is required for IE8/9, where + // the `console.log` function doesn't have 'apply' + return 'object' === typeof console + && console.log + && Function.prototype.apply.call(console.log, console, arguments); +} + +/** + * Save `namespaces`. + * + * @param {String} namespaces + * @api private + */ + +function save(namespaces) { + try { + if (null == namespaces) { + exports.storage.removeItem('debug'); + } else { + exports.storage.debug = namespaces; + } + } catch(e) {} +} + +/** + * Load `namespaces`. + * + * @return {String} returns the previously persisted debug modes + * @api private + */ + +function load() { + var r; + try { + r = exports.storage.debug; + } catch(e) {} + + // If debug isn't set in LS, and we're in Electron, try to load $DEBUG + if (!r && typeof process !== 'undefined' && 'env' in process) { + r = process.env.DEBUG; + } + + return r; +} + +/** + * Enable namespaces listed in `localStorage.debug` initially. + */ + +exports.enable(load()); + +/** + * Localstorage attempts to return the localstorage. + * + * This is necessary because safari throws + * when a user disables cookies/localstorage + * and you attempt to access it. + * + * @return {LocalStorage} + * @api private + */ + +function localstorage() { + try { + return window.localStorage; + } catch (e) {} +} + + +/***/ }), +/* 865 */ +/***/ (function(module, exports, __webpack_require__) { + + +/** + * This is the common logic for both the Node.js and web browser + * implementations of `debug()`. + * + * Expose `debug()` as the module. + */ + +exports = module.exports = createDebug.debug = createDebug['default'] = createDebug; +exports.coerce = coerce; +exports.disable = disable; +exports.enable = enable; +exports.enabled = enabled; +exports.humanize = __webpack_require__(866); + +/** + * The currently active debug mode names, and names to skip. + */ + +exports.names = []; +exports.skips = []; + +/** + * Map of special "%n" handling functions, for the debug "format" argument. + * + * Valid key names are a single, lower or upper-case letter, i.e. "n" and "N". + */ + +exports.formatters = {}; + +/** + * Previous log timestamp. + */ + +var prevTime; + +/** + * Select a color. + * @param {String} namespace + * @return {Number} + * @api private + */ + +function selectColor(namespace) { + var hash = 0, i; + + for (i in namespace) { + hash = ((hash << 5) - hash) + namespace.charCodeAt(i); + hash |= 0; // Convert to 32bit integer + } + + return exports.colors[Math.abs(hash) % exports.colors.length]; +} + +/** + * Create a debugger with the given `namespace`. + * + * @param {String} namespace + * @return {Function} + * @api public + */ + +function createDebug(namespace) { + + function debug() { + // disabled? + if (!debug.enabled) return; + + var self = debug; + + // set `diff` timestamp + var curr = +new Date(); + var ms = curr - (prevTime || curr); + self.diff = ms; + self.prev = prevTime; + self.curr = curr; + prevTime = curr; + + // turn the `arguments` into a proper Array + var args = new Array(arguments.length); + for (var i = 0; i < args.length; i++) { + args[i] = arguments[i]; + } + + args[0] = exports.coerce(args[0]); + + if ('string' !== typeof args[0]) { + // anything else let's inspect with %O + args.unshift('%O'); + } + + // apply any `formatters` transformations + var index = 0; + args[0] = args[0].replace(/%([a-zA-Z%])/g, function(match, format) { + // if we encounter an escaped % then don't increase the array index + if (match === '%%') return match; + index++; + var formatter = exports.formatters[format]; + if ('function' === typeof formatter) { + var val = args[index]; + match = formatter.call(self, val); + + // now we need to remove `args[index]` since it's inlined in the `format` + args.splice(index, 1); + index--; + } + return match; + }); + + // apply env-specific formatting (colors, etc.) + exports.formatArgs.call(self, args); + + var logFn = debug.log || exports.log || console.log.bind(console); + logFn.apply(self, args); + } + + debug.namespace = namespace; + debug.enabled = exports.enabled(namespace); + debug.useColors = exports.useColors(); + debug.color = selectColor(namespace); + + // env-specific initialization logic for debug instances + if ('function' === typeof exports.init) { + exports.init(debug); + } + + return debug; +} + +/** + * Enables a debug mode by namespaces. This can include modes + * separated by a colon and wildcards. + * + * @param {String} namespaces + * @api public + */ + +function enable(namespaces) { + exports.save(namespaces); + + exports.names = []; + exports.skips = []; + + var split = (typeof namespaces === 'string' ? namespaces : '').split(/[\s,]+/); + var len = split.length; + + for (var i = 0; i < len; i++) { + if (!split[i]) continue; // ignore empty strings + namespaces = split[i].replace(/\*/g, '.*?'); + if (namespaces[0] === '-') { + exports.skips.push(new RegExp('^' + namespaces.substr(1) + '$')); + } else { + exports.names.push(new RegExp('^' + namespaces + '$')); + } + } +} + +/** + * Disable debug output. + * + * @api public + */ + +function disable() { + exports.enable(''); +} + +/** + * Returns true if the given mode name is enabled, false otherwise. + * + * @param {String} name + * @return {Boolean} + * @api public + */ + +function enabled(name) { + var i, len; + for (i = 0, len = exports.skips.length; i < len; i++) { + if (exports.skips[i].test(name)) { + return false; + } + } + for (i = 0, len = exports.names.length; i < len; i++) { + if (exports.names[i].test(name)) { + return true; + } + } + return false; +} + +/** + * Coerce `val`. + * + * @param {Mixed} val + * @return {Mixed} + * @api private + */ + +function coerce(val) { + if (val instanceof Error) return val.stack || val.message; + return val; +} + + +/***/ }), +/* 866 */ +/***/ (function(module, exports) { + +/** + * Helpers. + */ + +var s = 1000; +var m = s * 60; +var h = m * 60; +var d = h * 24; +var y = d * 365.25; + +/** + * Parse or format the given `val`. + * + * Options: + * + * - `long` verbose formatting [false] + * + * @param {String|Number} val + * @param {Object} [options] + * @throws {Error} throw an error if val is not a non-empty string or a number + * @return {String|Number} + * @api public + */ + +module.exports = function(val, options) { + options = options || {}; + var type = typeof val; + if (type === 'string' && val.length > 0) { + return parse(val); + } else if (type === 'number' && isNaN(val) === false) { + return options.long ? fmtLong(val) : fmtShort(val); + } + throw new Error( + 'val is not a non-empty string or a valid number. val=' + + JSON.stringify(val) + ); +}; + +/** + * Parse the given `str` and return milliseconds. + * + * @param {String} str + * @return {Number} + * @api private + */ + +function parse(str) { + str = String(str); + if (str.length > 100) { + return; + } + var match = /^((?:\d+)?\.?\d+) *(milliseconds?|msecs?|ms|seconds?|secs?|s|minutes?|mins?|m|hours?|hrs?|h|days?|d|years?|yrs?|y)?$/i.exec( + str + ); + if (!match) { + return; + } + var n = parseFloat(match[1]); + var type = (match[2] || 'ms').toLowerCase(); + switch (type) { + case 'years': + case 'year': + case 'yrs': + case 'yr': + case 'y': + return n * y; + case 'days': + case 'day': + case 'd': + return n * d; + case 'hours': + case 'hour': + case 'hrs': + case 'hr': + case 'h': + return n * h; + case 'minutes': + case 'minute': + case 'mins': + case 'min': + case 'm': + return n * m; + case 'seconds': + case 'second': + case 'secs': + case 'sec': + case 's': + return n * s; + case 'milliseconds': + case 'millisecond': + case 'msecs': + case 'msec': + case 'ms': + return n; + default: + return undefined; + } +} + +/** + * Short format for `ms`. + * + * @param {Number} ms + * @return {String} + * @api private + */ + +function fmtShort(ms) { + if (ms >= d) { + return Math.round(ms / d) + 'd'; + } + if (ms >= h) { + return Math.round(ms / h) + 'h'; + } + if (ms >= m) { + return Math.round(ms / m) + 'm'; + } + if (ms >= s) { + return Math.round(ms / s) + 's'; + } + return ms + 'ms'; +} + +/** + * Long format for `ms`. + * + * @param {Number} ms + * @return {String} + * @api private + */ + +function fmtLong(ms) { + return plural(ms, d, 'day') || + plural(ms, h, 'hour') || + plural(ms, m, 'minute') || + plural(ms, s, 'second') || + ms + ' ms'; +} + +/** + * Pluralization helper. + */ + +function plural(ms, n, name) { + if (ms < n) { + return; + } + if (ms < n * 1.5) { + return Math.floor(ms / n) + ' ' + name; + } + return Math.ceil(ms / n) + ' ' + name + 's'; +} + + +/***/ }), +/* 867 */ +/***/ (function(module, exports, __webpack_require__) { + +/** + * Module dependencies. + */ + +var tty = __webpack_require__(478); +var util = __webpack_require__(29); + +/** + * This is the Node.js implementation of `debug()`. + * + * Expose `debug()` as the module. + */ + +exports = module.exports = __webpack_require__(865); +exports.init = init; +exports.log = log; +exports.formatArgs = formatArgs; +exports.save = save; +exports.load = load; +exports.useColors = useColors; + +/** + * Colors. + */ + +exports.colors = [6, 2, 3, 4, 5, 1]; + +/** + * Build up the default `inspectOpts` object from the environment variables. + * + * $ DEBUG_COLORS=no DEBUG_DEPTH=10 DEBUG_SHOW_HIDDEN=enabled node script.js + */ + +exports.inspectOpts = Object.keys(process.env).filter(function (key) { + return /^debug_/i.test(key); +}).reduce(function (obj, key) { + // camel-case + var prop = key + .substring(6) + .toLowerCase() + .replace(/_([a-z])/g, function (_, k) { return k.toUpperCase() }); + + // coerce string value into JS value + var val = process.env[key]; + if (/^(yes|on|true|enabled)$/i.test(val)) val = true; + else if (/^(no|off|false|disabled)$/i.test(val)) val = false; + else if (val === 'null') val = null; + else val = Number(val); + + obj[prop] = val; + return obj; +}, {}); + +/** + * The file descriptor to write the `debug()` calls to. + * Set the `DEBUG_FD` env variable to override with another value. i.e.: + * + * $ DEBUG_FD=3 node script.js 3>debug.log + */ + +var fd = parseInt(process.env.DEBUG_FD, 10) || 2; + +if (1 !== fd && 2 !== fd) { + util.deprecate(function(){}, 'except for stderr(2) and stdout(1), any other usage of DEBUG_FD is deprecated. Override debug.log if you want to use a different log function (https://git.io/debug_fd)')() +} + +var stream = 1 === fd ? process.stdout : + 2 === fd ? process.stderr : + createWritableStdioStream(fd); + +/** + * Is stdout a TTY? Colored output is enabled when `true`. + */ + +function useColors() { + return 'colors' in exports.inspectOpts + ? Boolean(exports.inspectOpts.colors) + : tty.isatty(fd); +} + +/** + * Map %o to `util.inspect()`, all on a single line. + */ + +exports.formatters.o = function(v) { + this.inspectOpts.colors = this.useColors; + return util.inspect(v, this.inspectOpts) + .split('\n').map(function(str) { + return str.trim() + }).join(' '); +}; + +/** + * Map %o to `util.inspect()`, allowing multiple lines if needed. + */ + +exports.formatters.O = function(v) { + this.inspectOpts.colors = this.useColors; + return util.inspect(v, this.inspectOpts); +}; + +/** + * Adds ANSI color escape codes if enabled. + * + * @api public + */ + +function formatArgs(args) { + var name = this.namespace; + var useColors = this.useColors; + + if (useColors) { + var c = this.color; + var prefix = ' \u001b[3' + c + ';1m' + name + ' ' + '\u001b[0m'; + + args[0] = prefix + args[0].split('\n').join('\n' + prefix); + args.push('\u001b[3' + c + 'm+' + exports.humanize(this.diff) + '\u001b[0m'); + } else { + args[0] = new Date().toUTCString() + + ' ' + name + ' ' + args[0]; + } +} + +/** + * Invokes `util.format()` with the specified arguments and writes to `stream`. + */ + +function log() { + return stream.write(util.format.apply(util, arguments) + '\n'); +} + +/** + * Save `namespaces`. + * + * @param {String} namespaces + * @api private + */ + +function save(namespaces) { + if (null == namespaces) { + // If you set a process.env field to null or undefined, it gets cast to the + // string 'null' or 'undefined'. Just delete instead. + delete process.env.DEBUG; + } else { + process.env.DEBUG = namespaces; + } +} + +/** + * Load `namespaces`. + * + * @return {String} returns the previously persisted debug modes + * @api private + */ + +function load() { + return process.env.DEBUG; +} + +/** + * Copied from `node/src/node.js`. + * + * XXX: It's lame that node doesn't expose this API out-of-the-box. It also + * relies on the undocumented `tty_wrap.guessHandleType()` which is also lame. + */ + +function createWritableStdioStream (fd) { + var stream; + var tty_wrap = process.binding('tty_wrap'); + + // Note stream._type is used for test-module-load-list.js + + switch (tty_wrap.guessHandleType(fd)) { + case 'TTY': + stream = new tty.WriteStream(fd); + stream._type = 'tty'; + + // Hack to have stream not keep the event loop alive. + // See https://github.com/joyent/node/issues/1726 + if (stream._handle && stream._handle.unref) { + stream._handle.unref(); + } + break; + + case 'FILE': + var fs = __webpack_require__(23); + stream = new fs.SyncWriteStream(fd, { autoClose: false }); + stream._type = 'fs'; + break; + + case 'PIPE': + case 'TCP': + var net = __webpack_require__(805); + stream = new net.Socket({ + fd: fd, + readable: false, + writable: true + }); + + // FIXME Should probably have an option in net.Socket to create a + // stream from an existing fd which is writable only. But for now + // we'll just add this hack and set the `readable` member to false. + // Test: ./node test/fixtures/echo.js < /etc/passwd + stream.readable = false; + stream.read = null; + stream._type = 'pipe'; + + // FIXME Hack to have stream not keep the event loop alive. + // See https://github.com/joyent/node/issues/1726 + if (stream._handle && stream._handle.unref) { + stream._handle.unref(); + } + break; + + default: + // Probably an error on in uv_guess_handle() + throw new Error('Implement me. Unknown stream file type!'); + } + + // For supporting legacy API we put the FD here. + stream.fd = fd; + + stream._isStdio = true; + + return stream; +} + +/** + * Init logic for `debug` instances. + * + * Create a new `inspectOpts` object in case `useColors` is set + * differently for a particular `debug` instance. + */ + +function init (debug) { + debug.inspectOpts = {}; + + var keys = Object.keys(exports.inspectOpts); + for (var i = 0; i < keys.length; i++) { + debug.inspectOpts[keys[i]] = exports.inspectOpts[keys[i]]; + } +} + +/** + * Enable namespaces listed in `process.env.DEBUG` initially. + */ + +exports.enable(load()); + + +/***/ }), +/* 868 */ +/***/ (function(module, exports, __webpack_require__) { + "use strict"; var brackets = __webpack_require__(858); -var define = __webpack_require__(864); -var utils = __webpack_require__(865); +var define = __webpack_require__(869); +var utils = __webpack_require__(870); /** * Characters to use in text regex (we want to "not" match @@ -101901,7 +102728,7 @@ module.exports = parsers; /***/ }), -/* 864 */ +/* 869 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -101939,7 +102766,7 @@ module.exports = function defineProperty(obj, prop, val) { /***/ }), -/* 865 */ +/* 870 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -102015,7 +102842,7 @@ utils.createRegex = function(str) { /***/ }), -/* 866 */ +/* 871 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -102026,7 +102853,7 @@ utils.createRegex = function(str) { */ var Snapdragon = __webpack_require__(767); -var define = __webpack_require__(864); +var define = __webpack_require__(869); var extend = __webpack_require__(737); /** @@ -102034,7 +102861,7 @@ var extend = __webpack_require__(737); */ var compilers = __webpack_require__(857); -var parsers = __webpack_require__(863); +var parsers = __webpack_require__(868); /** * Customize Snapdragon parser and renderer @@ -102100,7 +102927,7 @@ module.exports = Extglob; /***/ }), -/* 867 */ +/* 872 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -102190,14 +103017,14 @@ function textRegex(pattern) { /***/ }), -/* 868 */ +/* 873 */ /***/ (function(module, exports, __webpack_require__) { module.exports = new (__webpack_require__(849))(); /***/ }), -/* 869 */ +/* 874 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -102215,7 +103042,7 @@ utils.define = __webpack_require__(836); utils.diff = __webpack_require__(853); utils.extend = __webpack_require__(837); utils.pick = __webpack_require__(854); -utils.typeOf = __webpack_require__(870); +utils.typeOf = __webpack_require__(875); utils.unique = __webpack_require__(740); /** @@ -102513,7 +103340,7 @@ utils.unixify = function(options) { /***/ }), -/* 870 */ +/* 875 */ /***/ (function(module, exports) { var toString = Object.prototype.toString; @@ -102648,7 +103475,7 @@ function isBuffer(val) { /***/ }), -/* 871 */ +/* 876 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -102667,9 +103494,9 @@ var __extends = (this && this.__extends) || (function () { }; })(); Object.defineProperty(exports, "__esModule", { value: true }); -var readdir = __webpack_require__(872); -var reader_1 = __webpack_require__(885); -var fs_stream_1 = __webpack_require__(889); +var readdir = __webpack_require__(877); +var reader_1 = __webpack_require__(890); +var fs_stream_1 = __webpack_require__(894); var ReaderAsync = /** @class */ (function (_super) { __extends(ReaderAsync, _super); function ReaderAsync() { @@ -102730,15 +103557,15 @@ exports.default = ReaderAsync; /***/ }), -/* 872 */ +/* 877 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const readdirSync = __webpack_require__(873); -const readdirAsync = __webpack_require__(881); -const readdirStream = __webpack_require__(884); +const readdirSync = __webpack_require__(878); +const readdirAsync = __webpack_require__(886); +const readdirStream = __webpack_require__(889); module.exports = exports = readdirAsyncPath; exports.readdir = exports.readdirAsync = exports.async = readdirAsyncPath; @@ -102822,7 +103649,7 @@ function readdirStreamStat (dir, options) { /***/ }), -/* 873 */ +/* 878 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -102830,11 +103657,11 @@ function readdirStreamStat (dir, options) { module.exports = readdirSync; -const DirectoryReader = __webpack_require__(874); +const DirectoryReader = __webpack_require__(879); let syncFacade = { - fs: __webpack_require__(879), - forEach: __webpack_require__(880), + fs: __webpack_require__(884), + forEach: __webpack_require__(885), sync: true }; @@ -102863,7 +103690,7 @@ function readdirSync (dir, options, internalOptions) { /***/ }), -/* 874 */ +/* 879 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -102872,9 +103699,9 @@ function readdirSync (dir, options, internalOptions) { const Readable = __webpack_require__(27).Readable; const EventEmitter = __webpack_require__(379).EventEmitter; const path = __webpack_require__(16); -const normalizeOptions = __webpack_require__(875); -const stat = __webpack_require__(877); -const call = __webpack_require__(878); +const normalizeOptions = __webpack_require__(880); +const stat = __webpack_require__(882); +const call = __webpack_require__(883); /** * Asynchronously reads the contents of a directory and streams the results @@ -103250,14 +104077,14 @@ module.exports = DirectoryReader; /***/ }), -/* 875 */ +/* 880 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; const path = __webpack_require__(16); -const globToRegExp = __webpack_require__(876); +const globToRegExp = __webpack_require__(881); module.exports = normalizeOptions; @@ -103434,7 +104261,7 @@ function normalizeOptions (options, internalOptions) { /***/ }), -/* 876 */ +/* 881 */ /***/ (function(module, exports) { module.exports = function (glob, opts) { @@ -103571,13 +104398,13 @@ module.exports = function (glob, opts) { /***/ }), -/* 877 */ +/* 882 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const call = __webpack_require__(878); +const call = __webpack_require__(883); module.exports = stat; @@ -103652,7 +104479,7 @@ function symlinkStat (fs, path, lstats, callback) { /***/ }), -/* 878 */ +/* 883 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -103713,14 +104540,14 @@ function callOnce (fn) { /***/ }), -/* 879 */ +/* 884 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; const fs = __webpack_require__(23); -const call = __webpack_require__(878); +const call = __webpack_require__(883); /** * A facade around {@link fs.readdirSync} that allows it to be called @@ -103784,7 +104611,7 @@ exports.lstat = function (path, callback) { /***/ }), -/* 880 */ +/* 885 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -103813,7 +104640,7 @@ function syncForEach (array, iterator, done) { /***/ }), -/* 881 */ +/* 886 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -103821,12 +104648,12 @@ function syncForEach (array, iterator, done) { module.exports = readdirAsync; -const maybe = __webpack_require__(882); -const DirectoryReader = __webpack_require__(874); +const maybe = __webpack_require__(887); +const DirectoryReader = __webpack_require__(879); let asyncFacade = { fs: __webpack_require__(23), - forEach: __webpack_require__(883), + forEach: __webpack_require__(888), async: true }; @@ -103868,7 +104695,7 @@ function readdirAsync (dir, options, callback, internalOptions) { /***/ }), -/* 882 */ +/* 887 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -103895,7 +104722,7 @@ module.exports = function maybe (cb, promise) { /***/ }), -/* 883 */ +/* 888 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -103931,7 +104758,7 @@ function asyncForEach (array, iterator, done) { /***/ }), -/* 884 */ +/* 889 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -103939,11 +104766,11 @@ function asyncForEach (array, iterator, done) { module.exports = readdirStream; -const DirectoryReader = __webpack_require__(874); +const DirectoryReader = __webpack_require__(879); let streamFacade = { fs: __webpack_require__(23), - forEach: __webpack_require__(883), + forEach: __webpack_require__(888), async: true }; @@ -103963,16 +104790,16 @@ function readdirStream (dir, options, internalOptions) { /***/ }), -/* 885 */ +/* 890 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var path = __webpack_require__(16); -var deep_1 = __webpack_require__(886); -var entry_1 = __webpack_require__(888); -var pathUtil = __webpack_require__(887); +var deep_1 = __webpack_require__(891); +var entry_1 = __webpack_require__(893); +var pathUtil = __webpack_require__(892); var Reader = /** @class */ (function () { function Reader(options) { this.options = options; @@ -104038,13 +104865,13 @@ exports.default = Reader; /***/ }), -/* 886 */ +/* 891 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -var pathUtils = __webpack_require__(887); +var pathUtils = __webpack_require__(892); var patternUtils = __webpack_require__(721); var DeepFilter = /** @class */ (function () { function DeepFilter(options, micromatchOptions) { @@ -104128,7 +104955,7 @@ exports.default = DeepFilter; /***/ }), -/* 887 */ +/* 892 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -104159,13 +104986,13 @@ exports.makeAbsolute = makeAbsolute; /***/ }), -/* 888 */ +/* 893 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -var pathUtils = __webpack_require__(887); +var pathUtils = __webpack_require__(892); var patternUtils = __webpack_require__(721); var EntryFilter = /** @class */ (function () { function EntryFilter(options, micromatchOptions) { @@ -104251,7 +105078,7 @@ exports.default = EntryFilter; /***/ }), -/* 889 */ +/* 894 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -104271,8 +105098,8 @@ var __extends = (this && this.__extends) || (function () { })(); Object.defineProperty(exports, "__esModule", { value: true }); var stream = __webpack_require__(27); -var fsStat = __webpack_require__(890); -var fs_1 = __webpack_require__(894); +var fsStat = __webpack_require__(895); +var fs_1 = __webpack_require__(899); var FileSystemStream = /** @class */ (function (_super) { __extends(FileSystemStream, _super); function FileSystemStream() { @@ -104322,14 +105149,14 @@ exports.default = FileSystemStream; /***/ }), -/* 890 */ +/* 895 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -const optionsManager = __webpack_require__(891); -const statProvider = __webpack_require__(893); +const optionsManager = __webpack_require__(896); +const statProvider = __webpack_require__(898); /** * Asynchronous API. */ @@ -104360,13 +105187,13 @@ exports.statSync = statSync; /***/ }), -/* 891 */ +/* 896 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -const fsAdapter = __webpack_require__(892); +const fsAdapter = __webpack_require__(897); function prepare(opts) { const options = Object.assign({ fs: fsAdapter.getFileSystemAdapter(opts ? opts.fs : undefined), @@ -104379,7 +105206,7 @@ exports.prepare = prepare; /***/ }), -/* 892 */ +/* 897 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -104402,7 +105229,7 @@ exports.getFileSystemAdapter = getFileSystemAdapter; /***/ }), -/* 893 */ +/* 898 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -104454,7 +105281,7 @@ exports.isFollowedSymlink = isFollowedSymlink; /***/ }), -/* 894 */ +/* 899 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -104485,7 +105312,7 @@ exports.default = FileSystem; /***/ }), -/* 895 */ +/* 900 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -104505,9 +105332,9 @@ var __extends = (this && this.__extends) || (function () { })(); Object.defineProperty(exports, "__esModule", { value: true }); var stream = __webpack_require__(27); -var readdir = __webpack_require__(872); -var reader_1 = __webpack_require__(885); -var fs_stream_1 = __webpack_require__(889); +var readdir = __webpack_require__(877); +var reader_1 = __webpack_require__(890); +var fs_stream_1 = __webpack_require__(894); var TransformStream = /** @class */ (function (_super) { __extends(TransformStream, _super); function TransformStream(reader) { @@ -104575,7 +105402,7 @@ exports.default = ReaderStream; /***/ }), -/* 896 */ +/* 901 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -104594,9 +105421,9 @@ var __extends = (this && this.__extends) || (function () { }; })(); Object.defineProperty(exports, "__esModule", { value: true }); -var readdir = __webpack_require__(872); -var reader_1 = __webpack_require__(885); -var fs_sync_1 = __webpack_require__(897); +var readdir = __webpack_require__(877); +var reader_1 = __webpack_require__(890); +var fs_sync_1 = __webpack_require__(902); var ReaderSync = /** @class */ (function (_super) { __extends(ReaderSync, _super); function ReaderSync() { @@ -104656,7 +105483,7 @@ exports.default = ReaderSync; /***/ }), -/* 897 */ +/* 902 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -104675,8 +105502,8 @@ var __extends = (this && this.__extends) || (function () { }; })(); Object.defineProperty(exports, "__esModule", { value: true }); -var fsStat = __webpack_require__(890); -var fs_1 = __webpack_require__(894); +var fsStat = __webpack_require__(895); +var fs_1 = __webpack_require__(899); var FileSystemSync = /** @class */ (function (_super) { __extends(FileSystemSync, _super); function FileSystemSync() { @@ -104722,7 +105549,7 @@ exports.default = FileSystemSync; /***/ }), -/* 898 */ +/* 903 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -104738,7 +105565,7 @@ exports.flatten = flatten; /***/ }), -/* 899 */ +/* 904 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -104759,13 +105586,13 @@ exports.merge = merge; /***/ }), -/* 900 */ +/* 905 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; const path = __webpack_require__(16); -const pathType = __webpack_require__(901); +const pathType = __webpack_require__(906); const getExtensions = extensions => extensions.length > 1 ? `{${extensions.join(',')}}` : extensions[0]; @@ -104831,13 +105658,13 @@ module.exports.sync = (input, opts) => { /***/ }), -/* 901 */ +/* 906 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; const fs = __webpack_require__(23); -const pify = __webpack_require__(902); +const pify = __webpack_require__(907); function type(fn, fn2, fp) { if (typeof fp !== 'string') { @@ -104880,7 +105707,7 @@ exports.symlinkSync = typeSync.bind(null, 'lstatSync', 'isSymbolicLink'); /***/ }), -/* 902 */ +/* 907 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -104971,7 +105798,7 @@ module.exports = (obj, opts) => { /***/ }), -/* 903 */ +/* 908 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -104979,9 +105806,9 @@ module.exports = (obj, opts) => { const fs = __webpack_require__(23); const path = __webpack_require__(16); const fastGlob = __webpack_require__(717); -const gitIgnore = __webpack_require__(904); -const pify = __webpack_require__(905); -const slash = __webpack_require__(906); +const gitIgnore = __webpack_require__(909); +const pify = __webpack_require__(910); +const slash = __webpack_require__(911); const DEFAULT_IGNORE = [ '**/node_modules/**', @@ -105079,7 +105906,7 @@ module.exports.sync = options => { /***/ }), -/* 904 */ +/* 909 */ /***/ (function(module, exports) { // A simple implementation of make-array @@ -105548,7 +106375,7 @@ module.exports = options => new IgnoreBase(options) /***/ }), -/* 905 */ +/* 910 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -105623,7 +106450,7 @@ module.exports = (input, options) => { /***/ }), -/* 906 */ +/* 911 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -105641,17 +106468,17 @@ module.exports = input => { /***/ }), -/* 907 */ +/* 912 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; const path = __webpack_require__(16); const {constants: fsConstants} = __webpack_require__(23); -const pEvent = __webpack_require__(908); -const CpFileError = __webpack_require__(911); -const fs = __webpack_require__(915); -const ProgressEmitter = __webpack_require__(918); +const pEvent = __webpack_require__(913); +const CpFileError = __webpack_require__(916); +const fs = __webpack_require__(920); +const ProgressEmitter = __webpack_require__(923); const cpFileAsync = async (source, destination, options, progressEmitter) => { let readError; @@ -105765,12 +106592,12 @@ module.exports.sync = (source, destination, options) => { /***/ }), -/* 908 */ +/* 913 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const pTimeout = __webpack_require__(909); +const pTimeout = __webpack_require__(914); const symbolAsyncIterator = Symbol.asyncIterator || '@@asyncIterator'; @@ -106061,12 +106888,12 @@ module.exports.iterator = (emitter, event, options) => { /***/ }), -/* 909 */ +/* 914 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const pFinally = __webpack_require__(910); +const pFinally = __webpack_require__(915); class TimeoutError extends Error { constructor(message) { @@ -106112,7 +106939,7 @@ module.exports.TimeoutError = TimeoutError; /***/ }), -/* 910 */ +/* 915 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -106134,12 +106961,12 @@ module.exports = (promise, onFinally) => { /***/ }), -/* 911 */ +/* 916 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const NestedError = __webpack_require__(912); +const NestedError = __webpack_require__(917); class CpFileError extends NestedError { constructor(message, nested) { @@ -106153,10 +106980,10 @@ module.exports = CpFileError; /***/ }), -/* 912 */ +/* 917 */ /***/ (function(module, exports, __webpack_require__) { -var inherits = __webpack_require__(913); +var inherits = __webpack_require__(918); var NestedError = function (message, nested) { this.nested = nested; @@ -106207,7 +107034,7 @@ module.exports = NestedError; /***/ }), -/* 913 */ +/* 918 */ /***/ (function(module, exports, __webpack_require__) { try { @@ -106215,12 +107042,12 @@ try { if (typeof util.inherits !== 'function') throw ''; module.exports = util.inherits; } catch (e) { - module.exports = __webpack_require__(914); + module.exports = __webpack_require__(919); } /***/ }), -/* 914 */ +/* 919 */ /***/ (function(module, exports) { if (typeof Object.create === 'function') { @@ -106249,16 +107076,16 @@ if (typeof Object.create === 'function') { /***/ }), -/* 915 */ +/* 920 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; const {promisify} = __webpack_require__(29); const fs = __webpack_require__(22); -const makeDir = __webpack_require__(916); -const pEvent = __webpack_require__(908); -const CpFileError = __webpack_require__(911); +const makeDir = __webpack_require__(921); +const pEvent = __webpack_require__(913); +const CpFileError = __webpack_require__(916); const stat = promisify(fs.stat); const lstat = promisify(fs.lstat); @@ -106355,7 +107182,7 @@ exports.copyFileSync = (source, destination, flags) => { /***/ }), -/* 916 */ +/* 921 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -106363,7 +107190,7 @@ exports.copyFileSync = (source, destination, flags) => { const fs = __webpack_require__(23); const path = __webpack_require__(16); const {promisify} = __webpack_require__(29); -const semver = __webpack_require__(917); +const semver = __webpack_require__(922); const defaults = { mode: 0o777 & (~process.umask()), @@ -106512,7 +107339,7 @@ module.exports.sync = (input, options) => { /***/ }), -/* 917 */ +/* 922 */ /***/ (function(module, exports) { exports = module.exports = SemVer @@ -108114,7 +108941,7 @@ function coerce (version, options) { /***/ }), -/* 918 */ +/* 923 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -108155,7 +108982,7 @@ module.exports = ProgressEmitter; /***/ }), -/* 919 */ +/* 924 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -108201,12 +109028,12 @@ exports.default = module.exports; /***/ }), -/* 920 */ +/* 925 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const NestedError = __webpack_require__(921); +const NestedError = __webpack_require__(926); class CpyError extends NestedError { constructor(message, nested) { @@ -108220,7 +109047,7 @@ module.exports = CpyError; /***/ }), -/* 921 */ +/* 926 */ /***/ (function(module, exports, __webpack_require__) { var inherits = __webpack_require__(29).inherits; @@ -108276,7 +109103,7 @@ module.exports = NestedError; /***/ }), -/* 922 */ +/* 927 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; diff --git a/packages/kbn-test/src/functional_test_runner/lib/config/schema.ts b/packages/kbn-test/src/functional_test_runner/lib/config/schema.ts index f4b91d154cbb88..66f17ab579ec39 100644 --- a/packages/kbn-test/src/functional_test_runner/lib/config/schema.ts +++ b/packages/kbn-test/src/functional_test_runner/lib/config/schema.ts @@ -136,7 +136,7 @@ export const schema = Joi.object() browser: Joi.object() .keys({ type: Joi.string() - .valid('chrome', 'firefox', 'ie', 'msedge') + .valid('chrome', 'firefox', 'ie') .default('chrome'), logPollingMs: Joi.number().default(100), diff --git a/test/functional/config.edge.js b/test/functional/config.edge.js deleted file mode 100644 index ed68b41e8c89ab..00000000000000 --- a/test/functional/config.edge.js +++ /dev/null @@ -1,34 +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. - */ - -export default async function({ readConfigFile }) { - const defaultConfig = await readConfigFile(require.resolve('./config')); - - return { - ...defaultConfig.getAll(), - - browser: { - type: 'msedge', - }, - - junit: { - reportName: 'MS Chromium Edge UI Functional Tests', - }, - }; -} diff --git a/test/functional/services/browser.ts b/test/functional/services/browser.ts index 13d2365c07191b..5017947e95d03b 100644 --- a/test/functional/services/browser.ts +++ b/test/functional/services/browser.ts @@ -47,9 +47,7 @@ export async function BrowserProvider({ getService }: FtrProviderContext) { */ public readonly browserType: string = browserType; - public readonly isChromium: boolean = [Browsers.Chrome, Browsers.ChromiumEdge].includes( - browserType - ); + public readonly isChrome: boolean = browserType === Browsers.Chrome; public readonly isFirefox: boolean = browserType === Browsers.Firefox; diff --git a/test/functional/services/lib/web_element_wrapper/web_element_wrapper.ts b/test/functional/services/lib/web_element_wrapper/web_element_wrapper.ts index 8b57ecd3c82350..157918df874c82 100644 --- a/test/functional/services/lib/web_element_wrapper/web_element_wrapper.ts +++ b/test/functional/services/lib/web_element_wrapper/web_element_wrapper.ts @@ -55,7 +55,6 @@ export class WebElementWrapper { private driver: WebDriver = this.webDriver.driver; private Keys = Key; public isW3CEnabled: boolean = (this.webDriver.driver as any).executor_.w3c === true; - public isChromium: boolean = [Browsers.Chrome, Browsers.ChromiumEdge].includes(this.browserType); public static create( webElement: WebElement | WebElementWrapper, @@ -64,7 +63,7 @@ export class WebElementWrapper { timeout: number, fixedHeaderHeight: number, logger: ToolingLog, - browserType: Browsers + browserType: string ): WebElementWrapper { if (webElement instanceof WebElementWrapper) { return webElement; @@ -88,7 +87,7 @@ export class WebElementWrapper { private timeout: number, private fixedHeaderHeight: number, private logger: ToolingLog, - private browserType: Browsers + private browserType: string ) {} private async _findWithCustomTimeout( @@ -244,7 +243,7 @@ export class WebElementWrapper { return this.clearValueWithKeyboard(); } await this.retryCall(async function clearValue(wrapper) { - if (wrapper.isChromium || options.withJS) { + if (wrapper.browserType === Browsers.Chrome || options.withJS) { // https://bugs.chromium.org/p/chromedriver/issues/detail?id=2702 await wrapper.driver.executeScript(`arguments[0].value=''`, wrapper._webElement); } else { @@ -276,7 +275,7 @@ export class WebElementWrapper { await delay(100); } } else { - if (this.isChromium) { + if (this.browserType === Browsers.Chrome) { // https://bugs.chromium.org/p/chromedriver/issues/detail?id=30 await this.retryCall(async function clearValueWithKeyboard(wrapper) { await wrapper.driver.executeScript(`arguments[0].select();`, wrapper._webElement); diff --git a/test/functional/services/remote/browsers.ts b/test/functional/services/remote/browsers.ts index aa6e364d0a09d0..46d81f1737a55f 100644 --- a/test/functional/services/remote/browsers.ts +++ b/test/functional/services/remote/browsers.ts @@ -21,5 +21,4 @@ export enum Browsers { Chrome = 'chrome', Firefox = 'firefox', InternetExplorer = 'ie', - ChromiumEdge = 'msedge', } diff --git a/test/functional/services/remote/remote.ts b/test/functional/services/remote/remote.ts index b0724488cb5db8..e571a1a7e55512 100644 --- a/test/functional/services/remote/remote.ts +++ b/test/functional/services/remote/remote.ts @@ -64,23 +64,18 @@ export async function RemoteProvider({ getService }: FtrProviderContext) { lifecycle, config.get('browser.logPollingMs') ); - const isW3CEnabled = (driver as any).executor_.w3c; const caps = await driver.getCapabilities(); - const browserVersion = caps.get( - isW3CEnabled || browserType === Browsers.ChromiumEdge ? 'browserVersion' : 'version' - ); + const browserVersion = caps.get(isW3CEnabled ? 'browserVersion' : 'version'); - log.info( - `Remote initialized: ${caps.get( - 'browserName' - )} ${browserVersion}, w3c compliance=${isW3CEnabled}, collectingCoverage=${collectCoverage}` - ); + log.info(`Remote initialized: ${caps.get('browserName')} ${browserVersion}`); - if ([Browsers.Chrome, Browsers.ChromiumEdge].includes(browserType)) { + if (browserType === Browsers.Chrome) { log.info( - `${browserType}driver version: ${caps.get(browserType)[`${browserType}driverVersion`]}` + `Chromedriver version: ${ + caps.get('chrome').chromedriverVersion + }, w3c=${isW3CEnabled}, codeCoverage=${collectCoverage}` ); } diff --git a/test/functional/services/remote/webdriver.ts b/test/functional/services/remote/webdriver.ts index fc0b5bbb787c81..3bf5b865aa7ba5 100644 --- a/test/functional/services/remote/webdriver.ts +++ b/test/functional/services/remote/webdriver.ts @@ -31,12 +31,10 @@ import { Builder, Capabilities, By, logging, until } from 'selenium-webdriver'; import chrome from 'selenium-webdriver/chrome'; import firefox from 'selenium-webdriver/firefox'; // @ts-ignore internal modules are not typed -import edge from 'selenium-webdriver/edge'; -import { installDriver } from 'ms-chromium-edge-driver'; -// @ts-ignore internal modules are not typed import { Executor } from 'selenium-webdriver/lib/http'; // @ts-ignore internal modules are not typed import { getLogger } from 'selenium-webdriver/lib/logging'; + import { pollForLogEntry$ } from './poll_for_log_entry'; import { createStdoutSocket } from './create_stdout_stream'; import { preventParallelCalls } from './prevent_parallel_calls'; @@ -65,7 +63,6 @@ Executor.prototype.execute = preventParallelCalls( ); let attemptCounter = 0; -let edgePaths: { driverPath: string | undefined; browserPath: string | undefined }; async function attemptToCreateCommand( log: ToolingLog, browserType: Browsers, @@ -77,46 +74,6 @@ async function attemptToCreateCommand( const buildDriverInstance = async () => { switch (browserType) { - case 'msedge': { - if (edgePaths && edgePaths.browserPath && edgePaths.driverPath) { - const edgeOptions = new edge.Options(); - if (headlessBrowser === '1') { - // @ts-ignore internal modules are not typed - edgeOptions.headless(); - } - // @ts-ignore internal modules are not typed - edgeOptions.setEdgeChromium(true); - // @ts-ignore internal modules are not typed - edgeOptions.setBinaryPath(edgePaths.browserPath); - const session = await new Builder() - .forBrowser('MicrosoftEdge') - .setEdgeOptions(edgeOptions) - .setEdgeService(new edge.ServiceBuilder(edgePaths.driverPath)) - .build(); - return { - session, - consoleLog$: pollForLogEntry$( - session, - logging.Type.BROWSER, - logPollingMs, - lifecycle.cleanup.after$ - ).pipe( - takeUntil(lifecycle.cleanup.after$), - map(({ message, level: { name: level } }) => ({ - message: message.replace(/\\n/g, '\n'), - level, - })) - ), - }; - } else { - throw new Error( - `Chromium Edge session requires browser or driver path to be defined: ${JSON.stringify( - edgePaths - )}` - ); - } - } - case 'chrome': { const chromeCapabilities = Capabilities.chrome(); const chromeOptions = [ @@ -308,11 +265,6 @@ export async function initWebDriver( log.verbose(entry.message); }); - // download Edge driver only in case of usage - if (browserType === Browsers.ChromiumEdge) { - edgePaths = await installDriver(); - } - return await Promise.race([ (async () => { await delay(2 * MINUTE); diff --git a/x-pack/test/functional/config.edge.js b/x-pack/test/functional/config.edge.js deleted file mode 100644 index 882fb6fea36861..00000000000000 --- a/x-pack/test/functional/config.edge.js +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -export default async function({ readConfigFile }) { - const chromeConfig = await readConfigFile(require.resolve('./config')); - - return { - ...chromeConfig.getAll(), - - browser: { - type: 'msedge', - }, - - junit: { - reportName: 'MS Chromium Edge XPack UI Functional Tests', - }, - }; -} diff --git a/yarn.lock b/yarn.lock index 8ca25cc18a8a29..fdfdcada62e2cc 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2562,11 +2562,6 @@ resolved "https://registry.yarnpkg.com/@sindresorhus/is/-/is-0.7.0.tgz#9a06f4f137ee84d7df0460c1fdb1135ffa6c50fd" integrity sha512-ONhaKPIufzzrlNbqtWFFd+jlnemX6lJAgq9ZeiZtS7I1PIf/la7CW4m83rTXRnVnsMbW2k56pGYu7AUFJD9Pow== -"@sindresorhus/is@^2.0.0": - version "2.1.0" - resolved "https://registry.yarnpkg.com/@sindresorhus/is/-/is-2.1.0.tgz#6ad4ca610f696098e92954ab431ff83bea0ce13f" - integrity sha512-lXKXfypKo644k4Da4yXkPCrwcvn6SlUW2X2zFbuflKHNjf0w9htru01bo26uMhleMXsDmnZ12eJLdrAZa9MANg== - "@sinonjs/commons@^1", "@sinonjs/commons@^1.3.0", "@sinonjs/commons@^1.4.0": version "1.6.0" resolved "https://registry.yarnpkg.com/@sinonjs/commons/-/commons-1.6.0.tgz#ec7670432ae9c8eb710400d112c201a362d83393" @@ -3466,13 +3461,6 @@ "@svgr/plugin-svgo" "^4.2.0" loader-utils "^1.2.3" -"@szmarczak/http-timer@^4.0.0": - version "4.0.5" - resolved "https://registry.yarnpkg.com/@szmarczak/http-timer/-/http-timer-4.0.5.tgz#bfbd50211e9dfa51ba07da58a14cdfd333205152" - integrity sha512-PyRA9sm1Yayuj5OIoJ1hGt2YISX45w9WcFbh6ddT0Z/0yaFxOtGLInr4jUfU1EAFVs0Yfyfev4RNwBlUaHdlDQ== - dependencies: - defer-to-connect "^2.0.0" - "@testim/chrome-version@^1.0.7": version "1.0.7" resolved "https://registry.yarnpkg.com/@testim/chrome-version/-/chrome-version-1.0.7.tgz#0cd915785ec4190f08a3a6acc9b61fc38fb5f1a9" @@ -3721,16 +3709,6 @@ resolved "https://registry.yarnpkg.com/@types/browserslist-useragent/-/browserslist-useragent-3.0.0.tgz#d425c9818182ce71ce53866798cee9c7d41d6e53" integrity sha512-ZBvKzg3yyWNYEkwxAzdmUzp27sFvw+1m080/+2lwrt+eltNefn1f4fnpMyrjOla31p8zLleCYqQXw+3EETfn0w== -"@types/cacheable-request@^6.0.1": - version "6.0.1" - resolved "https://registry.yarnpkg.com/@types/cacheable-request/-/cacheable-request-6.0.1.tgz#5d22f3dded1fd3a84c0bbeb5039a7419c2c91976" - integrity sha512-ykFq2zmBGOCbpIXtoVbz4SKY5QriWPh3AjyU4G74RYbtt5yOc5OfaY75ftjg7mikMOla1CTGpX3lLbuJh8DTrQ== - dependencies: - "@types/http-cache-semantics" "*" - "@types/keyv" "*" - "@types/node" "*" - "@types/responselike" "*" - "@types/caseless@*": version "0.12.2" resolved "https://registry.yarnpkg.com/@types/caseless/-/caseless-0.12.2.tgz#f65d3d6389e01eeb458bd54dc8f52b95a9463bc8" @@ -4100,11 +4078,6 @@ "@types/react" "*" hoist-non-react-statics "^3.3.0" -"@types/http-cache-semantics@*": - version "4.0.0" - resolved "https://registry.yarnpkg.com/@types/http-cache-semantics/-/http-cache-semantics-4.0.0.tgz#9140779736aa2655635ee756e2467d787cfe8a2a" - integrity sha512-c3Xy026kOF7QOTn00hbIllV1dLR9hG9NkSrLQgCVs8NF6sBU+VGWjD3wLPhmh1TYAc7ugCFsvHYMN4VcBN1U1A== - "@types/indent-string@^3.0.0": version "3.0.0" resolved "https://registry.yarnpkg.com/@types/indent-string/-/indent-string-3.0.0.tgz#9ebb391ceda548926f5819ad16405349641b999f" @@ -4236,13 +4209,6 @@ dependencies: "@types/node" "*" -"@types/keyv@*": - version "3.1.1" - resolved "https://registry.yarnpkg.com/@types/keyv/-/keyv-3.1.1.tgz#e45a45324fca9dab716ab1230ee249c9fb52cfa7" - integrity sha512-MPtoySlAZQ37VoLaPcTHCu1RWJ4llDkULYZIzOYxlhxBqYPB0RsRlmMU0R6tahtFe27mIdkHV+551ZWV4PLmVw== - dependencies: - "@types/node" "*" - "@types/license-checker@15.0.0": version "15.0.0" resolved "https://registry.yarnpkg.com/@types/license-checker/-/license-checker-15.0.0.tgz#685d69e2cf61ffd862320434601f51c85e28bba1" @@ -4714,13 +4680,6 @@ "@types/tough-cookie" "*" form-data "^2.5.0" -"@types/responselike@*": - version "1.0.0" - resolved "https://registry.yarnpkg.com/@types/responselike/-/responselike-1.0.0.tgz#251f4fe7d154d2bad125abe1b429b23afd262e29" - integrity sha512-85Y2BjiufFzaMIlvJDvTTB8Fxl2xfLo4HgmHzVBz08w4wDePCTjYw66PdrolO0kzli3yam/YCgRufyo1DdQVTA== - dependencies: - "@types/node" "*" - "@types/retry@^0.12.0": version "0.12.0" resolved "https://registry.yarnpkg.com/@types/retry/-/retry-0.12.0.tgz#2b35eccfcee7d38cd72ad99232fbd58bffb3c84d" @@ -4736,10 +4695,10 @@ resolved "https://registry.yarnpkg.com/@types/seedrandom/-/seedrandom-2.4.28.tgz#9ce8fa048c1e8c85cb71d7fe4d704e000226036f" integrity sha512-SMA+fUwULwK7sd/ZJicUztiPs8F1yCPwF3O23Z9uQ32ME5Ha0NmDK9+QTsYE4O2tHXChzXomSWWeIhCnoN1LqA== -"@types/selenium-webdriver@4.0.9": - version "4.0.9" - resolved "https://registry.yarnpkg.com/@types/selenium-webdriver/-/selenium-webdriver-4.0.9.tgz#12621e55b2ef8f6c98bd17fe23fa720c6cba16bd" - integrity sha512-HopIwBE7GUXsscmt/J0DhnFXLSmO04AfxT6b8HAprknwka7pqEWquWDMXxCjd+NUHK9MkCe1SDKKsMiNmCItbQ== +"@types/selenium-webdriver@^4.0.5": + version "4.0.5" + resolved "https://registry.yarnpkg.com/@types/selenium-webdriver/-/selenium-webdriver-4.0.5.tgz#23041a4948c82daf2df9836e4d2358fec10d3e24" + integrity sha512-ma1aL1znI3ptEbSQgbywgadrRCJouPIACSfOl/bPwu/TPNSyyE/+o9jZ6+bpDVTtIdksZuVKpq4SR1ip3DRduw== "@types/semver@^5.5.0": version "5.5.0" @@ -7470,18 +7429,13 @@ binaryextensions@2: resolved "https://registry.yarnpkg.com/binaryextensions/-/binaryextensions-2.1.1.tgz#3209a51ca4a4ad541a3b8d3d6a6d5b83a2485935" integrity sha512-XBaoWE9RW8pPdPQNibZsW2zh8TW6gcarXp1FZPwT8Uop8ScSNldJEWf2k9l3HeTqdrEwsOsFcq74RiJECW34yA== -bindings@1, bindings@^1.5.0: +bindings@^1.5.0: version "1.5.0" resolved "https://registry.yarnpkg.com/bindings/-/bindings-1.5.0.tgz#10353c9e945334bc0511a6d90b38fbc7c9c504df" integrity sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ== dependencies: file-uri-to-path "1.0.0" -bindings@~1.2.0: - version "1.2.1" - resolved "https://registry.yarnpkg.com/bindings/-/bindings-1.2.1.tgz#14ad6113812d2d37d72e67b4cacb4bb726505f11" - integrity sha1-FK1hE4EtLTfXLme0ystLtyZQXxE= - bit-twiddle@^1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/bit-twiddle/-/bit-twiddle-1.0.2.tgz#0c6c1fabe2b23d17173d9a61b7b7093eb9e1769e" @@ -8015,7 +7969,7 @@ buffer@^5.1.0, buffer@^5.2.0: base64-js "^1.0.2" ieee754 "^1.1.4" -builtin-modules@^1.0.0, builtin-modules@^1.1.1: +builtin-modules@^1.0.0: version "1.1.1" resolved "https://registry.yarnpkg.com/builtin-modules/-/builtin-modules-1.1.1.tgz#270f076c5a72c02f5b65a47df94c5fe3a278892f" integrity sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8= @@ -8162,13 +8116,6 @@ cache-loader@^4.1.0: neo-async "^2.6.1" schema-utils "^2.0.0" -cacheable-lookup@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/cacheable-lookup/-/cacheable-lookup-2.0.0.tgz#33b1e56f17507f5cf9bb46075112d65473fb7713" - integrity sha512-s2piO6LvA7xnL1AR03wuEdSx3BZT3tIJpZ56/lcJwzO/6DTJZlTs7X3lrvPxk6d1PlDe6PrVe2TjlUIZNFglAQ== - dependencies: - keyv "^4.0.0" - cacheable-request@^2.1.1: version "2.1.4" resolved "https://registry.yarnpkg.com/cacheable-request/-/cacheable-request-2.1.4.tgz#0d808801b6342ad33c91df9d0b44dc09b91e5c3d" @@ -8182,19 +8129,6 @@ cacheable-request@^2.1.1: normalize-url "2.0.1" responselike "1.0.2" -cacheable-request@^7.0.1: - version "7.0.1" - resolved "https://registry.yarnpkg.com/cacheable-request/-/cacheable-request-7.0.1.tgz#062031c2856232782ed694a257fa35da93942a58" - integrity sha512-lt0mJ6YAnsrBErpTMWeu5kl/tg9xMAWjavYTN6VQXM1A/teBITuNcccXsCxF0tDQQJf9DfAaX5O4e0zp0KlfZw== - dependencies: - clone-response "^1.0.2" - get-stream "^5.1.0" - http-cache-semantics "^4.0.0" - keyv "^4.0.0" - lowercase-keys "^2.0.0" - normalize-url "^4.1.0" - responselike "^2.0.0" - cachedir@2.3.0: version "2.3.0" resolved "https://registry.yarnpkg.com/cachedir/-/cachedir-2.3.0.tgz#0c75892a052198f0b21c7c1804d8331edfcae0e8" @@ -9023,7 +8957,7 @@ clone-regexp@^1.0.0: is-regexp "^1.0.0" is-supported-regexp-flag "^1.0.0" -clone-response@1.0.2, clone-response@^1.0.2: +clone-response@1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/clone-response/-/clone-response-1.0.2.tgz#d1dc973920314df67fbeb94223b4ee350239e96b" integrity sha1-0dyXOSAxTfZ/vrlCI7TuNQI56Ws= @@ -9287,16 +9221,16 @@ commander@4.1.0: resolved "https://registry.yarnpkg.com/commander/-/commander-4.1.0.tgz#545983a0603fe425bc672d66c9e3c89c42121a83" integrity sha512-NIQrwvv9V39FHgGFm36+U9SMQzbiHvU79k+iADraJTpmrFFfx7Ds0IvDoAdZsDrknlkRk14OYoWXb57uTh7/sw== -commander@^2.12.1, commander@^2.20.0, commander@^2.7.1: - version "2.20.3" - resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33" - integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ== - commander@^2.13.0, commander@^2.15.1, commander@^2.16.0, commander@^2.19.0: version "2.20.0" resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.0.tgz#d58bb2b5c1ee8f87b0d340027e9e94e222c5a422" integrity sha512-7j2y+40w61zy6YC2iRNpUe/NwhNyoXrYpHMrSunaMG64nRnaf96zO/KMQR4OyN/UnE5KLyEBnKHd4aG3rskjpQ== +commander@^2.20.0, commander@^2.7.1: + version "2.20.3" + resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33" + integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ== + commander@^2.8.1: version "2.18.0" resolved "https://registry.yarnpkg.com/commander/-/commander-2.18.0.tgz#2bf063ddee7c7891176981a2cc798e5754bc6970" @@ -10701,7 +10635,7 @@ debug-fabulous@1.X: memoizee "0.4.X" object-assign "4.X" -debug@2, debug@2.6.9, debug@^2.0.0, debug@^2.1.0, debug@^2.1.1, debug@^2.2.0, debug@^2.3.3, debug@^2.6.0, debug@^2.6.8, debug@^2.6.9: +debug@2.6.9, debug@^2.0.0, debug@^2.1.0, debug@^2.1.1, debug@^2.2.0, debug@^2.3.3, debug@^2.6.0, debug@^2.6.8, debug@^2.6.9: version "2.6.9" resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA== @@ -10773,13 +10707,6 @@ decompress-response@^4.2.0: dependencies: mimic-response "^2.0.0" -decompress-response@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/decompress-response/-/decompress-response-5.0.0.tgz#7849396e80e3d1eba8cb2f75ef4930f76461cb0f" - integrity sha512-TLZWWybuxWgoW7Lykv+gq9xvzOsUjQ9tF09Tj6NSTYGMTCHNXzrPnD6Hi+TgZq19PyTAGH4Ll/NIM/eTGglnMw== - dependencies: - mimic-response "^2.0.0" - decompress-tar@^4.0.0, decompress-tar@^4.1.0, decompress-tar@^4.1.1: version "4.1.1" resolved "https://registry.yarnpkg.com/decompress-tar/-/decompress-tar-4.1.1.tgz#718cbd3fcb16209716e70a26b84e7ba4592e5af1" @@ -10931,11 +10858,6 @@ defaults@^1.0.3: dependencies: clone "^1.0.2" -defer-to-connect@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/defer-to-connect/-/defer-to-connect-2.0.0.tgz#83d6b199db041593ac84d781b5222308ccf4c2c1" - integrity sha512-bYL2d05vOSf1JEZNx5vSAtPuBMkX8K9EUutg7zlKvTqKXHt7RhWJFbmd7qakVuf13i+IkGmp6FwSsONOf6VYIg== - define-properties@^1.1.2, define-properties@^1.1.3: version "1.1.3" resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.1.3.tgz#cf88da6cbee26fe6db7094f61d870cbd84cee9f1" @@ -13158,7 +13080,7 @@ extract-zip@1.6.7: mkdirp "0.5.1" yauzl "2.4.1" -extract-zip@^1.6.6, extract-zip@^1.6.7, extract-zip@^1.7.0: +extract-zip@^1.6.6, extract-zip@^1.7.0: version "1.7.0" resolved "https://registry.yarnpkg.com/extract-zip/-/extract-zip-1.7.0.tgz#556cc3ae9df7f452c493a0cfb51cc30277940927" integrity sha512-xoh5G1W/PB0/27lXgMQyIhP5DSY/LhoCsOyZgb+6iMmRtCwVBo55uKaMoEYrDCKQhWvqEip5ZPKAc6eFNyf/MA== @@ -13388,17 +13310,6 @@ fetch-mock@^7.3.9: path-to-regexp "^2.2.1" whatwg-url "^6.5.0" -ffi@^2.0.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/ffi/-/ffi-2.3.0.tgz#fa1a7b3d85c0fa8c83d96947a64b5192bc47f858" - integrity sha512-vkPA9Hf9CVuQ5HeMZykYvrZF2QNJ/iKGLkyDkisBnoOOFeFXZQhUPxBARPBIZMJVulvBI2R+jgofW03gyPpJcQ== - dependencies: - bindings "~1.2.0" - debug "2" - nan "2" - ref "1" - ref-struct "1" - figgy-pudding@^3.5.1: version "3.5.1" resolved "https://registry.yarnpkg.com/figgy-pudding/-/figgy-pudding-3.5.1.tgz#862470112901c727a0e495a80744bd5baa1d6790" @@ -14881,27 +14792,6 @@ got@5.6.0: unzip-response "^1.0.0" url-parse-lax "^1.0.0" -got@^10.6.0: - version "10.6.0" - resolved "https://registry.yarnpkg.com/got/-/got-10.6.0.tgz#ac3876261a4d8e5fc4f81186f79955ce7b0501dc" - integrity sha512-3LIdJNTdCFbbJc+h/EH0V5lpNpbJ6Bfwykk21lcQvQsEcrzdi/ltCyQehFHLzJ/ka0UMH4Slg0hkYvAZN9qUDg== - dependencies: - "@sindresorhus/is" "^2.0.0" - "@szmarczak/http-timer" "^4.0.0" - "@types/cacheable-request" "^6.0.1" - cacheable-lookup "^2.0.0" - cacheable-request "^7.0.1" - decompress-response "^5.0.0" - duplexer3 "^0.1.4" - get-stream "^5.0.0" - lowercase-keys "^2.0.0" - mimic-response "^2.1.0" - p-cancelable "^2.0.0" - p-event "^4.0.0" - responselike "^2.0.0" - to-readable-stream "^2.0.0" - type-fest "^0.10.0" - got@^3.2.0: version "3.3.1" resolved "https://registry.yarnpkg.com/got/-/got-3.3.1.tgz#e5d0ed4af55fc3eef4d56007769d98192bcb2eca" @@ -16008,11 +15898,6 @@ http-cache-semantics@3.8.1: resolved "https://registry.yarnpkg.com/http-cache-semantics/-/http-cache-semantics-3.8.1.tgz#39b0e16add9b605bf0a9ef3d9daaf4843b4cacd2" integrity sha512-5ai2iksyV8ZXmnZhHH4rWPoxxistEexSi5936zIQ1bnNTW5VnA85B6P/VpXiRM017IgRvb2kKo1a//y+0wSp3w== -http-cache-semantics@^4.0.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/http-cache-semantics/-/http-cache-semantics-4.1.0.tgz#49e91c5cbf36c9b94bcfcd71c23d5249ec74e390" - integrity sha512-carPklcUh7ROWRK7Cv27RPtdhYhUsela/ue5/jKzjegVvXDqM2ILE9Q2BGn9JZJh1g87cp56su/FgQSzcWS8cQ== - http-deceiver@^1.2.7: version "1.2.7" resolved "https://registry.yarnpkg.com/http-deceiver/-/http-deceiver-1.2.7.tgz#fa7168944ab9a519d337cb0bec7284dc3e723d87" @@ -17051,11 +16936,6 @@ is-generator-fn@^2.0.0: resolved "https://registry.yarnpkg.com/is-generator-fn/-/is-generator-fn-2.0.0.tgz#038c31b774709641bda678b1f06a4e3227c10b3e" integrity sha512-elzyIdM7iKoFHzcrndIqjYomImhxrFRnGP3galODoII4TB9gI7mZ+FnlLQmmjf27SxHS2gKEeyhX5/+YRS6H9g== -is-generator-function@^1.0.7: - version "1.0.7" - resolved "https://registry.yarnpkg.com/is-generator-function/-/is-generator-function-1.0.7.tgz#d2132e529bb0000a7f80794d4bdf5cd5e5813522" - integrity sha512-YZc5EwyO4f2kWCax7oegfuSr9mFz1ZvieNYBEjmukLxgXfBUbxAWGVF7GZf0zidYtoBl3WvC07YK0wT76a+Rtw== - is-glob@4.0.0, is-glob@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.0.tgz#9521c76845cc2610a85203ddf080a958c2ffabc0" @@ -18345,11 +18225,6 @@ json-buffer@3.0.0: resolved "https://registry.yarnpkg.com/json-buffer/-/json-buffer-3.0.0.tgz#5b1f397afc75d677bde8bcfc0e47e1f9a3d9a898" integrity sha1-Wx85evx11ne96Lz8Dkfh+aPZqJg= -json-buffer@3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/json-buffer/-/json-buffer-3.0.1.tgz#9338802a30d3b6605fbe0613e094008ca8c05a13" - integrity sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ== - json-parse-better-errors@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/json-parse-better-errors/-/json-parse-better-errors-1.0.1.tgz#50183cd1b2d25275de069e9e71b467ac9eab973a" @@ -18585,7 +18460,7 @@ jsx-to-string@^1.4.0: json-stringify-pretty-compact "^1.0.1" react "^0.14.0" -jszip@^3.2.2: +jszip@^3.1.5: version "3.2.2" resolved "https://registry.yarnpkg.com/jszip/-/jszip-3.2.2.tgz#b143816df7e106a9597a94c77493385adca5bd1d" integrity sha512-NmKajvAFQpbg3taXQXr/ccS2wcucR1AZ+NtyWp2Nq7HHVsXhcJFR8p0Baf32C2yVvBylFWVeKf+WI2AnvlPhpA== @@ -18761,13 +18636,6 @@ keyv@3.0.0: dependencies: json-buffer "3.0.0" -keyv@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/keyv/-/keyv-4.0.0.tgz#2d1dab694926b2d427e4c74804a10850be44c12f" - integrity sha512-U7ioE8AimvRVLfw4LffyOIRhL2xVgmE8T22L6i0BucSnBUyv4w+I7VN/zVZwRKHOI6ZRUcdMdWHQ8KSUvGpEog== - dependencies: - json-buffer "3.0.1" - killable@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/killable/-/killable-1.0.1.tgz#4c8ce441187a061c7474fb87ca08e2a638194892" @@ -19736,11 +19604,6 @@ lowercase-keys@^1.0.0: resolved "https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-1.0.1.tgz#6f9e30b47084d971a7c820ff15a6c5167b74c26f" integrity sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA== -lowercase-keys@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-2.0.0.tgz#2603e78b7b4b0006cbca2fbcc8a3202558ac9479" - integrity sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA== - lowlight@~1.9.1: version "1.9.1" resolved "https://registry.yarnpkg.com/lowlight/-/lowlight-1.9.1.tgz#ed7c3dffc36f8c1f263735c0fe0c907847c11250" @@ -20394,11 +20257,6 @@ mimic-response@^2.0.0: resolved "https://registry.yarnpkg.com/mimic-response/-/mimic-response-2.0.0.tgz#996a51c60adf12cb8a87d7fb8ef24c2f3d5ebb46" integrity sha512-8ilDoEapqA4uQ3TwS0jakGONKXVJqpy+RpM+3b7pLdOjghCrEiGp9SRkFbUHAmZW9vdnrENWHjaweIoTIJExSQ== -mimic-response@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/mimic-response/-/mimic-response-2.1.0.tgz#d13763d35f613d09ec37ebb30bac0469c0ee8f43" - integrity sha512-wXqjST+SLt7R009ySCglWBCFpjUygmCIfD790/kVbiGmUgfYGuB14PiTd5DwVxSV4NcYHjzMkoj5LjQZwTQLEA== - mimos@4.x.x: version "4.0.0" resolved "https://registry.yarnpkg.com/mimos/-/mimos-4.0.0.tgz#76e3d27128431cb6482fd15b20475719ad626a5a" @@ -20827,19 +20685,6 @@ move-concurrently@^1.0.1: rimraf "^2.5.4" run-queue "^1.0.3" -ms-chromium-edge-driver@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/ms-chromium-edge-driver/-/ms-chromium-edge-driver-0.2.0.tgz#0e0c6fd9fd1d1d36db97b2b3d7e9d4ba4d2de456" - integrity sha512-RkDsBPnMLjRna7q4LlvtLb+CHPei9gZapnlxm3ayWKk3Ab6HmDsz/17xG2eyqkKX5UcKeo04YlLZ345tO7OolA== - dependencies: - extract-zip "^1.6.7" - got "^10.6.0" - lodash "4.17.15" - tslint "^6.1.0" - tslint-config-prettier "^1.18.0" - util "^0.12.2" - windows-registry "^0.1.5" - ms@2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" @@ -20952,7 +20797,7 @@ mute-stream@0.0.8: resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.8.tgz#1630c42b2251ff81e2a283de96a5497ea92e5e0d" integrity sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA== -nan@2, nan@^2.12.1, nan@^2.13.2: +nan@^2.12.1, nan@^2.13.2: version "2.14.0" resolved "https://registry.yarnpkg.com/nan/-/nan-2.14.0.tgz#7818f722027b2459a86f0295d434d1fc2336c52c" integrity sha512-INOFj37C7k3AfaNTtX8RhsTw7qRy7eLET14cROi9+5HAVbbHuIWUHEauBv5qT4Av2tWasiTY1Jw6puUNqRJXQg== @@ -21462,11 +21307,6 @@ normalize-url@^3.3.0: resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-3.3.0.tgz#b2e1c4dc4f7c6d57743df733a4f5978d18650559" integrity sha512-U+JJi7duF1o+u2pynbp2zXDW2/PADgC30f0GsHZtRh+HOcXHnw137TrNlyxxRvWW5fjKd3bcLHPxofWuCjaeZg== -normalize-url@^4.1.0: - version "4.5.0" - resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-4.5.0.tgz#453354087e6ca96957bd8f5baf753f5982142129" - integrity sha512-2s47yzUxdexf1OhyRi4Em83iQk0aPvwTddtFz4hnSSw9dCEsLEGf6SwIO8ss/19S9iBb5sJaOuTvTGDeZI00BQ== - now-and-later@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/now-and-later/-/now-and-later-2.0.0.tgz#bc61cbb456d79cb32207ce47ca05136ff2e7d6ee" @@ -22153,11 +21993,6 @@ p-cancelable@^0.4.0: resolved "https://registry.yarnpkg.com/p-cancelable/-/p-cancelable-0.4.1.tgz#35f363d67d52081c8d9585e37bcceb7e0bbcb2a0" integrity sha512-HNa1A8LvB1kie7cERyy21VNeHb2CWJJYqyyC2o3klWFfMGlFmWv2Z7sFgZH8ZiaYL95ydToKTFVXgMV/Os0bBQ== -p-cancelable@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/p-cancelable/-/p-cancelable-2.0.0.tgz#4a3740f5bdaf5ed5d7c3e34882c6fb5d6b266a6e" - integrity sha512-wvPXDmbMmu2ksjkB4Z3nZWTSkJEb9lqVdMaCKpZUGJG9TMiNp9XcbG3fn9fPKjem04fJMJnXoyFPk2FmgiaiNg== - p-defer@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/p-defer/-/p-defer-1.0.0.tgz#9f6eb182f6c9aa8cd743004a7d4f96b196b0fb0c" @@ -22170,7 +22005,7 @@ p-each-series@^1.0.0: dependencies: p-reduce "^1.0.0" -p-event@^4.0.0, p-event@^4.1.0: +p-event@^4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/p-event/-/p-event-4.1.0.tgz#e92bb866d7e8e5b732293b1c8269d38e9982bf8e" integrity sha512-4vAd06GCsgflX4wHN1JqrMzBh/8QZ4j+rzp0cd2scXRwuBEv+QR3wrVA5aLhWDLw4y2WgDKvzWF3CCLmVM1UgA== @@ -25226,31 +25061,6 @@ redux@^4.0.5: loose-envify "^1.4.0" symbol-observable "^1.2.0" -ref-struct@1, ref-struct@^1.0.2: - version "1.1.0" - resolved "https://registry.yarnpkg.com/ref-struct/-/ref-struct-1.1.0.tgz#5d5ee65ad41cefc3a5c5feb40587261e479edc13" - integrity sha1-XV7mWtQc78Olxf60BYcmHkee3BM= - dependencies: - debug "2" - ref "1" - -ref-union@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/ref-union/-/ref-union-1.0.1.tgz#3a2397f862f1e75171d687268f43b3f17729f120" - integrity sha1-OiOX+GLx51Fx1ocmj0Oz8Xcp8SA= - dependencies: - debug "2" - ref "1" - -ref@1, ref@^1.2.0: - version "1.3.5" - resolved "https://registry.yarnpkg.com/ref/-/ref-1.3.5.tgz#0e33f080cdb94a3d95312b2b3b1fd0f82044ca0f" - integrity sha512-2cBCniTtxcGUjDpvFfVpw323a83/0RLSGJJY5l5lcomZWhYpU2cuLdsvYqMixvsdLJ9+sTdzEkju8J8ZHDM2nA== - dependencies: - bindings "1" - debug "2" - nan "2" - reflect.ownkeys@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/reflect.ownkeys/-/reflect.ownkeys-0.2.0.tgz#749aceec7f3fdf8b63f927a04809e90c5c0b3460" @@ -25990,13 +25800,6 @@ responselike@1.0.2: dependencies: lowercase-keys "^1.0.0" -responselike@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/responselike/-/responselike-2.0.0.tgz#26391bcc3174f750f9a79eacc40a12a5c42d7723" - integrity sha512-xH48u3FTB9VsZw7R+vvgaKeLKzT6jOogbQhEe/jewwnZgzPcnyWui2Av6JpoYZF/91uueC+lqhWqeURw5/qhCw== - dependencies: - lowercase-keys "^2.0.0" - restore-cursor@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-1.0.1.tgz#34661f46886327fed2991479152252df92daa541" @@ -26555,14 +26358,15 @@ select@^1.1.2: resolved "https://registry.yarnpkg.com/select/-/select-1.1.2.tgz#0e7350acdec80b1108528786ec1d4418d11b396d" integrity sha1-DnNQrN7ICxEIUoeG7B1EGNEbOW0= -selenium-webdriver@^4.0.0-alpha.7: - version "4.0.0-alpha.7" - resolved "https://registry.yarnpkg.com/selenium-webdriver/-/selenium-webdriver-4.0.0-alpha.7.tgz#e3879d8457fd7ad8e4424094b7dc0540d99e6797" - integrity sha512-D4qnTsyTr91jT8f7MfN+OwY0IlU5+5FmlO5xlgRUV6hDEV8JyYx2NerdTEqDDkNq7RZDYc4VoPALk8l578RBHw== +selenium-webdriver@^4.0.0-alpha.5: + version "4.0.0-alpha.5" + resolved "https://registry.yarnpkg.com/selenium-webdriver/-/selenium-webdriver-4.0.0-alpha.5.tgz#e4683b3dbf827d70df09a7e43bf02ebad20fa7c1" + integrity sha512-hktl3DSrhzM59yLhWzDGHIX9o56DvA+cVK7Dw6FcJR6qQ4CGzkaHeXQPcdrslkWMTeq0Ci9AmCxq0EMOvm2Rkg== dependencies: - jszip "^3.2.2" - rimraf "^2.7.1" + jszip "^3.1.5" + rimraf "^2.6.3" tmp "0.0.30" + xml2js "^0.4.19" selfsigned@^1.10.7: version "1.10.7" @@ -28962,11 +28766,6 @@ to-object-path@^0.3.0: dependencies: kind-of "^3.0.2" -to-readable-stream@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/to-readable-stream/-/to-readable-stream-2.1.0.tgz#82880316121bea662cdc226adb30addb50cb06e8" - integrity sha512-o3Qa6DGg1CEXshSdvWNX2sN4QHqg03SPq7U6jPXRahlQdl5dK8oXjkU/2/sGrnOZKeGV1zLSO8qPwyKklPPE7w== - to-regex-range@^2.1.0: version "2.1.1" resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-2.1.1.tgz#7c80c17b9dfebe599e27367e0d4dd5590141db38" @@ -29246,37 +29045,6 @@ tslib@^1.8.1, tslib@^1.9.0, tslib@^1.9.2, tslib@^1.9.3: resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.9.3.tgz#d7e4dd79245d85428c4d7e4822a79917954ca286" integrity sha512-4krF8scpejhaOgqzBEcGM7yDIEfi0/8+8zDRZhNZZ2kjmHJ4hv3zCbQWxoJGz1iw5U0Jl0nma13xzHXcncMavQ== -tslint-config-prettier@^1.18.0: - version "1.18.0" - resolved "https://registry.yarnpkg.com/tslint-config-prettier/-/tslint-config-prettier-1.18.0.tgz#75f140bde947d35d8f0d238e0ebf809d64592c37" - integrity sha512-xPw9PgNPLG3iKRxmK7DWr+Ea/SzrvfHtjFt5LBl61gk2UBG/DB9kCXRjv+xyIU1rUtnayLeMUVJBcMX8Z17nDg== - -tslint@^6.1.0: - version "6.1.0" - resolved "https://registry.yarnpkg.com/tslint/-/tslint-6.1.0.tgz#c6c611b8ba0eed1549bf5a59ba05a7732133d851" - integrity sha512-fXjYd/61vU6da04E505OZQGb2VCN2Mq3doeWcOIryuG+eqdmFUXTYVwdhnbEu2k46LNLgUYt9bI5icQze/j0bQ== - dependencies: - "@babel/code-frame" "^7.0.0" - builtin-modules "^1.1.1" - chalk "^2.3.0" - commander "^2.12.1" - diff "^4.0.1" - glob "^7.1.1" - js-yaml "^3.13.1" - minimatch "^3.0.4" - mkdirp "^0.5.1" - resolve "^1.3.2" - semver "^5.3.0" - tslib "^1.10.0" - tsutils "^2.29.0" - -tsutils@^2.29.0: - version "2.29.0" - resolved "https://registry.yarnpkg.com/tsutils/-/tsutils-2.29.0.tgz#32b488501467acbedd4b85498673a0812aca0b99" - integrity sha512-g5JVHCIJwzfISaXpXE1qvNalca5Jwob6FjI4AoPlqMusJ6ftFE7IkkFoMhVLRgK+4Kx3gkzb8UZK5t5yTTvEmA== - dependencies: - tslib "^1.8.1" - tsutils@^3.17.1: version "3.17.1" resolved "https://registry.yarnpkg.com/tsutils/-/tsutils-3.17.1.tgz#ed719917f11ca0dee586272b2ac49e015a2dd759" @@ -29781,11 +29549,6 @@ type-detect@^1.0.0: resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-1.0.0.tgz#762217cc06db258ec48908a1298e8b95121e8ea2" integrity sha1-diIXzAbbJY7EiQihKY6LlRIejqI= -type-fest@^0.10.0: - version "0.10.0" - resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.10.0.tgz#7f06b2b9fbfc581068d1341ffabd0349ceafc642" - integrity sha512-EUV9jo4sffrwlg8s0zDhP0T2WD3pru5Xi0+HTE3zTUmBaZNhfkite9PdSJwdXLwPVW0jnAHT56pZHIOYckPEiw== - type-fest@^0.3.0, type-fest@^0.3.1: version "0.3.1" resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.3.1.tgz#63d00d204e059474fe5e1b7c011112bbd1dc29e1" @@ -30483,16 +30246,6 @@ util@^0.11.0: dependencies: inherits "2.0.3" -util@^0.12.2: - version "0.12.2" - resolved "https://registry.yarnpkg.com/util/-/util-0.12.2.tgz#54adb634c9e7c748707af2bf5a8c7ab640cbba2b" - integrity sha512-XE+MkWQvglYa+IOfBt5UFG93EmncEMP23UqpgDvVZVFBPxwmkK10QRp6pgU4xICPnWRf/t0zPv4noYSUq9gqUQ== - dependencies: - inherits "^2.0.3" - is-arguments "^1.0.4" - is-generator-function "^1.0.7" - safe-buffer "^5.1.2" - utila@^0.4.0, utila@~0.4: version "0.4.0" resolved "https://registry.yarnpkg.com/utila/-/utila-0.4.0.tgz#8a16a05d445657a3aea5eecc5b12a4fa5379772c" @@ -31654,17 +31407,6 @@ window-size@^0.2.0: resolved "https://registry.yarnpkg.com/window-size/-/window-size-0.2.0.tgz#b4315bb4214a3d7058ebeee892e13fa24d98b075" integrity sha1-tDFbtCFKPXBY6+7okuE/ok2YsHU= -windows-registry@^0.1.5: - version "0.1.5" - resolved "https://registry.yarnpkg.com/windows-registry/-/windows-registry-0.1.5.tgz#92c25c960884b0d215e69395f52d8dfaa0ba4ad0" - integrity sha512-gMN3ets1fbdP+TApEbbX2TIfBK3MIH5+p9GMvIFS3CNLr7U0Khe5mRj/T5zvwo/pKdhJgDrCLYyaNSs7HYiBCw== - dependencies: - debug "^2.2.0" - ffi "^2.0.0" - ref "^1.2.0" - ref-struct "^1.0.2" - ref-union "^1.0.0" - windows-release@^3.1.0: version "3.2.0" resolved "https://registry.yarnpkg.com/windows-release/-/windows-release-3.2.0.tgz#8122dad5afc303d833422380680a79cdfa91785f" @@ -31973,6 +31715,14 @@ xml-parse-from-string@^1.0.0: resolved "https://registry.yarnpkg.com/xml-parse-from-string/-/xml-parse-from-string-1.0.1.tgz#a9029e929d3dbcded169f3c6e28238d95a5d5a28" integrity sha1-qQKekp09vN7RafPG4oI42VpdWig= +xml2js@^0.4.19, xml2js@^0.4.5: + version "0.4.19" + resolved "https://registry.yarnpkg.com/xml2js/-/xml2js-0.4.19.tgz#686c20f213209e94abf0d1bcf1efaa291c7827a7" + integrity sha512-esZnJZJOiJR9wWKMyuvSE1y6Dq5LCuJanqhxslH2bxM6duahNZ+HMpCLhBQGZkbX6xRf8x1Y2eJlgt2q3qo49Q== + dependencies: + sax ">=0.6.0" + xmlbuilder "~9.0.1" + xml2js@^0.4.22: version "0.4.22" resolved "https://registry.yarnpkg.com/xml2js/-/xml2js-0.4.22.tgz#4fa2d846ec803237de86f30aa9b5f70b6600de02" @@ -31982,14 +31732,6 @@ xml2js@^0.4.22: util.promisify "~1.0.0" xmlbuilder "~11.0.0" -xml2js@^0.4.5: - version "0.4.19" - resolved "https://registry.yarnpkg.com/xml2js/-/xml2js-0.4.19.tgz#686c20f213209e94abf0d1bcf1efaa291c7827a7" - integrity sha512-esZnJZJOiJR9wWKMyuvSE1y6Dq5LCuJanqhxslH2bxM6duahNZ+HMpCLhBQGZkbX6xRf8x1Y2eJlgt2q3qo49Q== - dependencies: - sax ">=0.6.0" - xmlbuilder "~9.0.1" - xml@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/xml/-/xml-1.0.1.tgz#78ba72020029c5bc87b8a81a3cfcd74b4a2fc1e5" From 040e7b464edfe58de4612278fbb33f21a99c62d1 Mon Sep 17 00:00:00 2001 From: Larry Gregory Date: Tue, 14 Apr 2020 07:33:14 -0400 Subject: [PATCH 08/12] Adjust API authorization logging (#63350) --- .../security/server/authorization/api_authorization.ts | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/x-pack/plugins/security/server/authorization/api_authorization.ts b/x-pack/plugins/security/server/authorization/api_authorization.ts index cc672fbc69e068..88b3f2c6f71554 100644 --- a/x-pack/plugins/security/server/authorization/api_authorization.ts +++ b/x-pack/plugins/security/server/authorization/api_authorization.ts @@ -24,7 +24,6 @@ export function initAPIAuthorization( // if there are no tags starting with "access:", just continue if (actionTags.length === 0) { - logger.debug('API endpoint is not marked with "access:" tags, skipping.'); return toolkit.next(); } @@ -34,11 +33,11 @@ export function initAPIAuthorization( // we've actually authorized the request if (checkPrivilegesResponse.hasAllRequested) { - logger.debug(`authorized for "${request.url.path}"`); + logger.debug(`User authorized for "${request.url.path}"`); return toolkit.next(); } - logger.debug(`not authorized for "${request.url.path}"`); + logger.warn(`User not authorized for "${request.url.path}": responding with 404`); return response.notFound(); }); } From 1a6398b983ee3645b175009f150c92dc1a8b70cd Mon Sep 17 00:00:00 2001 From: Sandra Gonzales Date: Tue, 14 Apr 2020 07:56:24 -0400 Subject: [PATCH 09/12] [EPM] add/remove package in package settings page (#63389) * fix bug where assets were not being returned, use archive info for assets * add settings page, add install/remove button and text * check existence of datasources associated with this package * add package title variable to text * update modal text and rename to uninstall --- .../ingest_manager/common/types/models/epm.ts | 2 +- .../common/types/rest_spec/datasource.ts | 15 ++- .../hooks/use_request/datasource.ts | 12 +- .../sections/epm/hooks/index.tsx | 2 +- .../epm/hooks/use_package_install.tsx | 101 +++++++++------ .../screens/detail/confirm_package_delete.tsx | 32 ----- .../detail/confirm_package_install.tsx | 41 +++++- .../detail/confirm_package_uninstall.tsx | 73 +++++++++++ .../sections/epm/screens/detail/content.tsx | 5 +- .../screens/detail/installation_button.tsx | 83 ++++++++---- .../epm/screens/detail/settings_panel.tsx | 118 ++++++++++++++++++ .../epm/screens/detail/side_nav_links.tsx | 1 + .../server/services/epm/packages/get.ts | 4 +- 13 files changed, 381 insertions(+), 108 deletions(-) delete mode 100644 x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/screens/detail/confirm_package_delete.tsx create mode 100644 x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/screens/detail/confirm_package_uninstall.tsx create mode 100644 x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/screens/detail/settings_panel.tsx diff --git a/x-pack/plugins/ingest_manager/common/types/models/epm.ts b/x-pack/plugins/ingest_manager/common/types/models/epm.ts index 5524e7505d74b3..064341c68a97a1 100644 --- a/x-pack/plugins/ingest_manager/common/types/models/epm.ts +++ b/x-pack/plugins/ingest_manager/common/types/models/epm.ts @@ -19,7 +19,7 @@ export enum InstallStatus { uninstalling = 'uninstalling', } -export type DetailViewPanelName = 'overview' | 'data-sources'; +export type DetailViewPanelName = 'overview' | 'data-sources' | 'settings'; export type ServiceName = 'kibana' | 'elasticsearch'; export type AssetType = KibanaAssetType | ElasticsearchAssetType | AgentAssetType; diff --git a/x-pack/plugins/ingest_manager/common/types/rest_spec/datasource.ts b/x-pack/plugins/ingest_manager/common/types/rest_spec/datasource.ts index f630602503f0af..66f734b904cfcb 100644 --- a/x-pack/plugins/ingest_manager/common/types/rest_spec/datasource.ts +++ b/x-pack/plugins/ingest_manager/common/types/rest_spec/datasource.ts @@ -4,10 +4,13 @@ * you may not use this file except in compliance with the Elastic License. */ import { Datasource, NewDatasource } from '../models'; -import { ListWithKuery } from './common'; export interface GetDatasourcesRequest { - query: ListWithKuery; + query: { + page: number; + perPage: number; + kuery?: string; + }; } export interface GetOneDatasourceRequest { @@ -16,6 +19,14 @@ export interface GetOneDatasourceRequest { }; } +export interface GetDatasourcesResponse { + items: Datasource[]; + total: number; + page: number; + perPage: number; + success: boolean; +} + export interface CreateDatasourceRequest { body: NewDatasource; } diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/hooks/use_request/datasource.ts b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/hooks/use_request/datasource.ts index d0072f03559932..0d19ecd0cb7351 100644 --- a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/hooks/use_request/datasource.ts +++ b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/hooks/use_request/datasource.ts @@ -3,12 +3,14 @@ * or more contributor license agreements. Licensed under the Elastic License; * you may not use this file except in compliance with the Elastic License. */ -import { sendRequest } from './use_request'; +import { sendRequest, useRequest } from './use_request'; import { datasourceRouteService } from '../../services'; import { CreateDatasourceRequest, CreateDatasourceResponse } from '../../types'; import { DeleteDatasourcesRequest, DeleteDatasourcesResponse, + GetDatasourcesRequest, + GetDatasourcesResponse, } from '../../../../../common/types/rest_spec'; export const sendCreateDatasource = (body: CreateDatasourceRequest['body']) => { @@ -26,3 +28,11 @@ export const sendDeleteDatasource = (body: DeleteDatasourcesRequest['body']) => body: JSON.stringify(body), }); }; + +export function useGetDatasources(query: GetDatasourcesRequest['query']) { + return useRequest({ + method: 'get', + path: datasourceRouteService.getListPath(), + query, + }); +} diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/hooks/index.tsx b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/hooks/index.tsx index 48986481b6061a..fbc00fbadcfaad 100644 --- a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/hooks/index.tsx +++ b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/hooks/index.tsx @@ -7,7 +7,7 @@ export { useLinks } from './use_links'; export { useLocalSearch, searchIdField } from './use_local_search'; export { PackageInstallProvider, - useDeletePackage, + useUninstallPackage, useGetPackageInstallStatus, useInstallPackage, useSetPackageInstallStatus, diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/hooks/use_package_install.tsx b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/hooks/use_package_install.tsx index 537a2616f17862..0c5f45cdc47a71 100644 --- a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/hooks/use_package_install.tsx +++ b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/hooks/use_package_install.tsx @@ -6,8 +6,8 @@ import createContainer from 'constate'; import React, { useCallback, useState } from 'react'; +import { FormattedMessage } from '@kbn/i18n/react'; import { NotificationsStart } from 'src/core/public'; -import { useLinks } from '.'; import { toMountPoint } from '../../../../../../../../../src/plugins/kibana_react/public'; import { PackageInfo } from '../../../types'; import { sendInstallPackage, sendRemovePackage } from '../../../hooks'; @@ -25,7 +25,6 @@ type InstallPackageProps = Pick; function usePackageInstall({ notifications }: { notifications: NotificationsStart }) { const [packages, setPackage] = useState({}); - const { toDetailView } = useLinks(); const setPackageInstallStatus = useCallback( ({ name, status }: { name: PackageInfo['name']; status: InstallStatus }) => { @@ -46,34 +45,43 @@ function usePackageInstall({ notifications }: { notifications: NotificationsStar if (res.error) { setPackageInstallStatus({ name, status: InstallStatus.notInstalled }); notifications.toasts.addWarning({ - title: `Failed to install ${title} package`, - text: - 'Something went wrong while trying to install this package. Please try again later.', + title: toMountPoint( + + ), + text: toMountPoint( + + ), iconType: 'alert', }); } else { setPackageInstallStatus({ name, status: InstallStatus.installed }); - const SuccessMsg =

Successfully installed {name}

; notifications.toasts.addSuccess({ - title: `Installed ${title} package`, - text: toMountPoint(SuccessMsg), + title: toMountPoint( + + ), + text: toMountPoint( + + ), }); - - // TODO: this should probably live somewhere else and use , - // this hook could return the request state and a component could - // use that state. the component should be able to unsubscribe to prevent memory leaks - const packageUrl = toDetailView({ name, version }); - const dataSourcesUrl = toDetailView({ - name, - version, - panel: 'data-sources', - withAppRoot: false, - }); - if (window.location.href.includes(packageUrl)) window.location.hash = dataSourcesUrl; } }, - [notifications.toasts, setPackageInstallStatus, toDetailView] + [notifications.toasts, setPackageInstallStatus] ); const getPackageInstallStatus = useCallback( @@ -83,7 +91,7 @@ function usePackageInstall({ notifications }: { notifications: NotificationsStar [packages] ); - const deletePackage = useCallback( + const uninstallPackage = useCallback( async ({ name, version, title }: Pick) => { setPackageInstallStatus({ name, status: InstallStatus.uninstalling }); const pkgkey = `${name}-${version}`; @@ -92,30 +100,43 @@ function usePackageInstall({ notifications }: { notifications: NotificationsStar if (res.error) { setPackageInstallStatus({ name, status: InstallStatus.installed }); notifications.toasts.addWarning({ - title: `Failed to delete ${title} package`, - text: 'Something went wrong while trying to delete this package. Please try again later.', + title: toMountPoint( + + ), + text: toMountPoint( + + ), iconType: 'alert', }); } else { setPackageInstallStatus({ name, status: InstallStatus.notInstalled }); - const SuccessMsg =

Successfully deleted {title}

; - notifications.toasts.addSuccess({ - title: `Deleted ${title} package`, - text: toMountPoint(SuccessMsg), - }); - - const packageUrl = toDetailView({ name, version }); - const dataSourcesUrl = toDetailView({ - name, - version, - panel: 'data-sources', + title: toMountPoint( + + ), + text: toMountPoint( + + ), }); - if (window.location.href.includes(packageUrl)) window.location.href = dataSourcesUrl; } }, - [notifications.toasts, setPackageInstallStatus, toDetailView] + [notifications.toasts, setPackageInstallStatus] ); return { @@ -123,7 +144,7 @@ function usePackageInstall({ notifications }: { notifications: NotificationsStar installPackage, setPackageInstallStatus, getPackageInstallStatus, - deletePackage, + uninstallPackage, }; } @@ -132,11 +153,11 @@ export const [ useInstallPackage, useSetPackageInstallStatus, useGetPackageInstallStatus, - useDeletePackage, + useUninstallPackage, ] = createContainer( usePackageInstall, value => value.installPackage, value => value.setPackageInstallStatus, value => value.getPackageInstallStatus, - value => value.deletePackage + value => value.uninstallPackage ); diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/screens/detail/confirm_package_delete.tsx b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/screens/detail/confirm_package_delete.tsx deleted file mode 100644 index 2b3be04ac476b4..00000000000000 --- a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/screens/detail/confirm_package_delete.tsx +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ -import { EuiCallOut, EuiConfirmModal, EuiOverlayMask } from '@elastic/eui'; -import React from 'react'; - -interface ConfirmPackageDeleteProps { - onCancel: () => void; - onConfirm: () => void; - packageName: string; - numOfAssets: number; -} -export const ConfirmPackageDelete = (props: ConfirmPackageDeleteProps) => { - const { onCancel, onConfirm, packageName, numOfAssets } = props; - return ( - - - - - - ); -}; diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/screens/detail/confirm_package_install.tsx b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/screens/detail/confirm_package_install.tsx index 137d9cf226b4d2..ac30815a941ee7 100644 --- a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/screens/detail/confirm_package_install.tsx +++ b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/screens/detail/confirm_package_install.tsx @@ -5,6 +5,7 @@ */ import { EuiCallOut, EuiConfirmModal, EuiOverlayMask, EuiSpacer } from '@elastic/eui'; import React from 'react'; +import { FormattedMessage } from '@kbn/i18n/react'; interface ConfirmPackageInstallProps { onCancel: () => void; @@ -17,18 +18,46 @@ export const ConfirmPackageInstall = (props: ConfirmPackageInstallProps) => { return ( + } onCancel={onCancel} onConfirm={onConfirm} - cancelButtonText="Cancel" - confirmButtonText="Install package" + cancelButtonText={ + + } + confirmButtonText={ + + } defaultFocusedButton="confirm" > - + + } + />

- and will only be accessible to users who have permission to view this Space. Elasticsearch - assets are installed globally and will be accessible to all Kibana users. +

diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/screens/detail/confirm_package_uninstall.tsx b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/screens/detail/confirm_package_uninstall.tsx new file mode 100644 index 00000000000000..14b9bf77c3a007 --- /dev/null +++ b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/screens/detail/confirm_package_uninstall.tsx @@ -0,0 +1,73 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ +import { EuiCallOut, EuiConfirmModal, EuiOverlayMask, EuiSpacer } from '@elastic/eui'; +import React from 'react'; +import { FormattedMessage } from '@kbn/i18n/react'; + +interface ConfirmPackageUninstallProps { + onCancel: () => void; + onConfirm: () => void; + packageName: string; + numOfAssets: number; +} +export const ConfirmPackageUninstall = (props: ConfirmPackageUninstallProps) => { + const { onCancel, onConfirm, packageName, numOfAssets } = props; + return ( + + + } + onCancel={onCancel} + onConfirm={onConfirm} + cancelButtonText={ + + } + confirmButtonText={ + + } + defaultFocusedButton="confirm" + buttonColor="danger" + > + + } + > +

+ +

+
+ +

+ +

+
+
+ ); +}; diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/screens/detail/content.tsx b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/screens/detail/content.tsx index 384cbbeed378e7..0d4b3958953225 100644 --- a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/screens/detail/content.tsx +++ b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/screens/detail/content.tsx @@ -15,6 +15,7 @@ import { CenterColumn, LeftColumn, RightColumn } from './layout'; import { OverviewPanel } from './overview_panel'; import { SideNavLinks } from './side_nav_links'; import { DataSourcesPanel } from './data_sources_panel'; +import { SettingsPanel } from './settings_panel'; type ContentProps = PackageInfo & Pick & { hasIconPanel: boolean }; export function Content(props: ContentProps) { @@ -49,8 +50,10 @@ export function Content(props: ContentProps) { type ContentPanelProps = PackageInfo & Pick; export function ContentPanel(props: ContentPanelProps) { - const { panel, name, version } = props; + const { panel, name, version, assets, title } = props; switch (panel) { + case 'settings': + return ; case 'data-sources': return ; case 'overview': diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/screens/detail/installation_button.tsx b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/screens/detail/installation_button.tsx index 8a8afed5570ed9..cbbf1ce53c4ea3 100644 --- a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/screens/detail/installation_button.tsx +++ b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/screens/detail/installation_button.tsx @@ -5,21 +5,21 @@ */ import { EuiButton } from '@elastic/eui'; import React, { Fragment, useCallback, useMemo, useState } from 'react'; +import { FormattedMessage } from '@kbn/i18n/react'; import { PackageInfo, InstallStatus } from '../../../../types'; import { useCapabilities } from '../../../../hooks'; -import { useDeletePackage, useGetPackageInstallStatus, useInstallPackage } from '../../hooks'; -import { ConfirmPackageDelete } from './confirm_package_delete'; +import { useUninstallPackage, useGetPackageInstallStatus, useInstallPackage } from '../../hooks'; +import { ConfirmPackageUninstall } from './confirm_package_uninstall'; import { ConfirmPackageInstall } from './confirm_package_install'; -interface InstallationButtonProps { - package: PackageInfo; -} - +type InstallationButtonProps = Pick & { + disabled: boolean; +}; export function InstallationButton(props: InstallationButtonProps) { - const { assets, name, title, version } = props.package; + const { assets, name, title, version, disabled = true } = props; const hasWriteCapabilites = useCapabilities().write; const installPackage = useInstallPackage(); - const deletePackage = useDeletePackage(); + const uninstallPackage = useUninstallPackage(); const getPackageInstallStatus = useGetPackageInstallStatus(); const installationStatus = getPackageInstallStatus(name); @@ -36,11 +36,12 @@ export function InstallationButton(props: InstallationButtonProps) { toggleModal(); }, [installPackage, name, title, toggleModal, version]); - const handleClickDelete = useCallback(() => { - deletePackage({ name, version, title }); + const handleClickUninstall = useCallback(() => { + uninstallPackage({ name, version, title }); toggleModal(); - }, [deletePackage, name, title, toggleModal, version]); + }, [uninstallPackage, name, title, toggleModal, version]); + // counts the number of assets in the package const numOfAssets = useMemo( () => Object.entries(assets).reduce( @@ -56,30 +57,68 @@ export function InstallationButton(props: InstallationButtonProps) { ); const installButton = ( - - {isInstalling ? 'Installing' : 'Install package'} + + {isInstalling ? ( + + ) : ( + + )} ); - const installedButton = ( - - {isInstalling ? 'Deleting' : 'Delete package'} + const uninstallButton = ( + + {isRemoving ? ( + + ) : ( + + )} ); - const deletionModal = ( - ); - const installationModal = ( + const installModal = ( - {isInstalled ? installedButton : installButton} - {isModalVisible && (isInstalled ? deletionModal : installationModal)} + {isInstalled || isRemoving ? uninstallButton : installButton} + {isModalVisible && (isInstalled ? uninstallModal : installModal)} ) : null; } diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/screens/detail/settings_panel.tsx b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/screens/detail/settings_panel.tsx new file mode 100644 index 00000000000000..ff7ecf97714b6b --- /dev/null +++ b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/screens/detail/settings_panel.tsx @@ -0,0 +1,118 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import React from 'react'; +import { FormattedMessage } from '@kbn/i18n/react'; +import { EuiTitle, EuiFlexGroup, EuiFlexItem, EuiText } from '@elastic/eui'; +import { EuiSpacer } from '@elastic/eui'; +import { useGetPackageInstallStatus } from '../../hooks'; +import { InstallStatus, PackageInfo } from '../../../../types'; +import { InstallationButton } from './installation_button'; +import { useGetDatasources } from '../../../../hooks'; + +export const SettingsPanel = ( + props: Pick +) => { + const getPackageInstallStatus = useGetPackageInstallStatus(); + const { data: datasourcesData } = useGetDatasources({ + perPage: 0, + page: 1, + kuery: `datasources.package.name:${props.name}`, + }); + const { name, title } = props; + const packageInstallStatus = getPackageInstallStatus(name); + const packageHasDatasources = !!datasourcesData?.total; + + return ( + + +

+ +

+
+ + {packageInstallStatus === InstallStatus.notInstalled || + packageInstallStatus === InstallStatus.installing ? ( +
+ +

+ +

+
+ +

+ +

+
+ ) : ( +
+ +

+ +

+
+ +

+ +

+
+ )} + + +

+ +

+
+
+ {packageHasDatasources && ( +

+ + + + ), + }} + /> +

+ )} +
+ ); +}; diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/screens/detail/side_nav_links.tsx b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/screens/detail/side_nav_links.tsx index 39a6fca2e43180..05729ccfc1af42 100644 --- a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/screens/detail/side_nav_links.tsx +++ b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/screens/detail/side_nav_links.tsx @@ -17,6 +17,7 @@ export type NavLinkProps = Pick & { const PanelDisplayNames: Record = { overview: 'Overview', 'data-sources': 'Data Sources', + settings: 'Settings', }; export function SideNavLinks({ name, version, active }: NavLinkProps) { diff --git a/x-pack/plugins/ingest_manager/server/services/epm/packages/get.ts b/x-pack/plugins/ingest_manager/server/services/epm/packages/get.ts index 0e2c2a3d260736..d76584225877c2 100644 --- a/x-pack/plugins/ingest_manager/server/services/epm/packages/get.ts +++ b/x-pack/plugins/ingest_manager/server/services/epm/packages/get.ts @@ -67,7 +67,7 @@ export async function getPackageInfo(options: { pkgVersion: string; }): Promise { const { savedObjectsClient, pkgName, pkgVersion } = options; - const [item, savedObject] = await Promise.all([ + const [item, savedObject, assets] = await Promise.all([ Registry.fetchInfo(pkgName, pkgVersion), getInstallationObject({ savedObjectsClient, pkgName }), Registry.getArchiveInfo(pkgName, pkgVersion), @@ -80,7 +80,7 @@ export async function getPackageInfo(options: { const updated = { ...item, title: item.title || nameAsTitle(item.name), - assets: Registry.groupPathsByService(item?.assets || []), + assets: Registry.groupPathsByService(assets || []), }; return createInstallableFrom(updated, savedObject); } From 69ed664dd93a2825679a3d1ff920dd7ccc7823d4 Mon Sep 17 00:00:00 2001 From: Matthew Kime Date: Tue, 14 Apr 2020 06:58:56 -0500 Subject: [PATCH 10/12] Index Pattern Field class - factor out copy_field code for future typescripting (#63083) * Index Pattern Field class - factor out copy_field code for future typescripting --- ...n-plugins-data-public.indexpatternfield.md | 1 - ...ns-data-public.indexpatternfield.routes.md | 11 --- ...ugins-data-public.indexpatternfieldlist.md | 2 +- ...ata-public.indexpatternfieldlist.update.md | 2 +- .../create_edit_field/create_edit_field.js | 1 - .../edit_index_pattern/edit_index_pattern.js | 10 ++- .../indexed_fields_table.test.js.snap | 5 -- .../indexed_fields_table.js | 3 +- .../scripted_fields_table.tsx | 2 +- .../ui/public/field_editor/field_editor.js | 13 +-- .../lib/__tests__/copy_field.test.js | 48 ----------- .../ui/public/field_editor/lib/copy_field.js | 82 ------------------- .../ui/public/field_editor/lib/index.js | 1 - .../public/index_patterns/fields/field.ts | 7 -- .../index_patterns/fields/field_list.ts | 13 +-- src/plugins/data/public/public.api.md | 4 +- 16 files changed, 22 insertions(+), 183 deletions(-) delete mode 100644 docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternfield.routes.md delete mode 100644 src/legacy/ui/public/field_editor/lib/__tests__/copy_field.test.js delete mode 100644 src/legacy/ui/public/field_editor/lib/copy_field.js diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternfield.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternfield.md index 430590c7a25058..121ae80734dfd3 100644 --- a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternfield.md +++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternfield.md @@ -29,7 +29,6 @@ export declare class Field implements IFieldType | [format](./kibana-plugin-plugins-data-public.indexpatternfield.format.md) | | any | | | [lang](./kibana-plugin-plugins-data-public.indexpatternfield.lang.md) | | string | | | [name](./kibana-plugin-plugins-data-public.indexpatternfield.name.md) | | string | | -| [routes](./kibana-plugin-plugins-data-public.indexpatternfield.routes.md) | | Record<string, string> | | | [script](./kibana-plugin-plugins-data-public.indexpatternfield.script.md) | | string | | | [scripted](./kibana-plugin-plugins-data-public.indexpatternfield.scripted.md) | | boolean | | | [searchable](./kibana-plugin-plugins-data-public.indexpatternfield.searchable.md) | | boolean | | diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternfield.routes.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternfield.routes.md deleted file mode 100644 index 664a7b7b7ca0e5..00000000000000 --- a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternfield.routes.md +++ /dev/null @@ -1,11 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [IndexPatternField](./kibana-plugin-plugins-data-public.indexpatternfield.md) > [routes](./kibana-plugin-plugins-data-public.indexpatternfield.routes.md) - -## IndexPatternField.routes property - -Signature: - -```typescript -routes: Record; -``` diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternfieldlist.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternfieldlist.md index 4b7184b7dc151e..478b73f5f85813 100644 --- a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternfieldlist.md +++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternfieldlist.md @@ -24,5 +24,5 @@ export declare class FieldList extends Array implements IFieldList | [getByName](./kibana-plugin-plugins-data-public.indexpatternfieldlist.getbyname.md) | | (name: string) => Field | undefined | | | [getByType](./kibana-plugin-plugins-data-public.indexpatternfieldlist.getbytype.md) | | (type: string) => any[] | | | [remove](./kibana-plugin-plugins-data-public.indexpatternfieldlist.remove.md) | | (field: IFieldType) => void | | -| [update](./kibana-plugin-plugins-data-public.indexpatternfieldlist.update.md) | | (field: Field) => void | | +| [update](./kibana-plugin-plugins-data-public.indexpatternfieldlist.update.md) | | (field: Record<string, any>) => void | | diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternfieldlist.update.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternfieldlist.update.md index ca03ec4b728932..d5156ed41e493e 100644 --- a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternfieldlist.update.md +++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternfieldlist.update.md @@ -7,5 +7,5 @@ Signature: ```typescript -update: (field: Field) => void; +update: (field: Record) => void; ``` diff --git a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/create_edit_field/create_edit_field.js b/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/create_edit_field/create_edit_field.js index 0dcf778a5a6629..3569e9caf4e275 100644 --- a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/create_edit_field/create_edit_field.js +++ b/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/create_edit_field/create_edit_field.js @@ -53,7 +53,6 @@ const renderFieldEditor = ( indexPattern={indexPattern} field={field} helpers={{ - Field: IndexPatternField, getConfig, $http, fieldFormatEditors, 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 594430ca01f4ce..c65054f583ef2d 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 @@ -49,6 +49,8 @@ const TAB_INDEXED_FIELDS = 'indexedFields'; const TAB_SCRIPTED_FIELDS = 'scriptedFields'; const TAB_SOURCE_FILTERS = 'sourceFilters'; +const EDIT_FIELD_PATH = '/management/kibana/index_patterns/{{indexPattern.id}}/field/{{name}}'; + function updateSourceFiltersTable($scope) { $scope.$$postDigest(() => { const node = document.getElementById(REACT_SOURCE_FILTERS_DOM_ELEMENT_ID); @@ -97,8 +99,8 @@ function updateScriptedFieldsTable($scope) { fieldFilter={$scope.fieldFilter} scriptedFieldLanguageFilter={$scope.scriptedFieldLanguageFilter} helpers={{ - redirectToRoute: (obj, route) => { - $scope.kbnUrl.changeToRoute(obj, route); + redirectToRoute: field => { + $scope.kbnUrl.changePath(EDIT_FIELD_PATH, field); $scope.$apply(); }, getRouteHref: (obj, route) => $scope.kbnUrl.getRouteHref(obj, route), @@ -140,8 +142,8 @@ function updateIndexedFieldsTable($scope) { fieldWildcardMatcher={$scope.fieldWildcardMatcher} indexedFieldTypeFilter={$scope.indexedFieldTypeFilter} helpers={{ - redirectToRoute: (obj, route) => { - $scope.kbnUrl.changeToRoute(obj, route); + redirectToRoute: field => { + $scope.kbnUrl.changePath(EDIT_FIELD_PATH, field); $scope.$apply(); }, getFieldInfo: $scope.getFieldInfo, diff --git a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/indexed_fields_table/__jest__/__snapshots__/indexed_fields_table.test.js.snap b/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/indexed_fields_table/__jest__/__snapshots__/indexed_fields_table.test.js.snap index dc77fe6c8a69d6..b38036a0c2bf0f 100644 --- a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/indexed_fields_table/__jest__/__snapshots__/indexed_fields_table.test.js.snap +++ b/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/indexed_fields_table/__jest__/__snapshots__/indexed_fields_table.test.js.snap @@ -18,7 +18,6 @@ exports[`IndexedFieldsTable should filter based on the query bar 1`] = ` "indexPattern": undefined, "info": undefined, "name": "Elastic", - "routes": undefined, "searchable": true, }, ] @@ -45,7 +44,6 @@ exports[`IndexedFieldsTable should filter based on the type filter 1`] = ` "indexPattern": undefined, "info": undefined, "name": "timestamp", - "routes": undefined, "type": "date", }, ] @@ -72,7 +70,6 @@ exports[`IndexedFieldsTable should render normally 1`] = ` "indexPattern": undefined, "info": undefined, "name": "Elastic", - "routes": undefined, "searchable": true, }, Object { @@ -82,7 +79,6 @@ exports[`IndexedFieldsTable should render normally 1`] = ` "indexPattern": undefined, "info": undefined, "name": "timestamp", - "routes": undefined, "type": "date", }, Object { @@ -92,7 +88,6 @@ exports[`IndexedFieldsTable should render normally 1`] = ` "indexPattern": undefined, "info": undefined, "name": "conflictingField", - "routes": undefined, "type": "conflict", }, ] diff --git a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/indexed_fields_table/indexed_fields_table.js b/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/indexed_fields_table/indexed_fields_table.js index 652efbe98067f1..074e5784f3dae6 100644 --- a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/indexed_fields_table/indexed_fields_table.js +++ b/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/indexed_fields_table/indexed_fields_table.js @@ -65,7 +65,6 @@ export class IndexedFieldsTable extends Component { return { ...field, displayName: field.displayName, - routes: field.routes, indexPattern: field.indexPattern, format: getFieldFormat(indexPattern, field.name), excluded: fieldWildcardMatch ? fieldWildcardMatch(field.name) : false, @@ -104,7 +103,7 @@ export class IndexedFieldsTable extends Component { this.props.helpers.redirectToRoute(field, 'edit')} + editField={field => this.props.helpers.redirectToRoute(field)} /> ); diff --git a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/scripted_fields_table/scripted_fields_table.tsx b/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/scripted_fields_table/scripted_fields_table.tsx index ba044296a693a9..e8dfbd6496057f 100644 --- a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/scripted_fields_table/scripted_fields_table.tsx +++ b/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/scripted_fields_table/scripted_fields_table.tsx @@ -155,7 +155,7 @@ export class ScriptedFieldsTable extends Component<
this.props.helpers.redirectToRoute(field, 'edit')} + editField={field => this.props.helpers.redirectToRoute(field)} deleteField={this.startDeleteField} /> diff --git a/src/legacy/ui/public/field_editor/field_editor.js b/src/legacy/ui/public/field_editor/field_editor.js index 43461c4c689be6..e90cb110ac3048 100644 --- a/src/legacy/ui/public/field_editor/field_editor.js +++ b/src/legacy/ui/public/field_editor/field_editor.js @@ -66,7 +66,7 @@ import { ScriptingHelpFlyout } from './components/scripting_help'; import { FieldFormatEditor } from './components/field_format_editor'; import { FIELD_TYPES_BY_LANG, DEFAULT_FIELD_TYPES } from './constants'; -import { copyField, executeScript, isScriptValid } from './lib'; +import { executeScript, isScriptValid } from './lib'; import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n/react'; @@ -100,7 +100,6 @@ export class FieldEditor extends PureComponent { indexPattern: PropTypes.object.isRequired, field: PropTypes.object.isRequired, helpers: PropTypes.shape({ - Field: PropTypes.func.isRequired, getConfig: PropTypes.func.isRequired, $http: PropTypes.func.isRequired, fieldFormatEditors: PropTypes.object.isRequired, @@ -111,11 +110,7 @@ export class FieldEditor extends PureComponent { constructor(props) { super(props); - const { - field, - indexPattern, - helpers: { Field }, - } = props; + const { field, indexPattern } = props; this.state = { isReady: false, @@ -125,7 +120,7 @@ export class FieldEditor extends PureComponent { fieldTypes: [], fieldTypeFormats: [], existingFieldNames: indexPattern.fields.map(f => f.name), - field: copyField(field, indexPattern, Field), + field: { ...field, format: field.format }, fieldFormatId: undefined, fieldFormatParams: {}, showScriptingHelp: false, @@ -730,7 +725,7 @@ export class FieldEditor extends PureComponent { }; saveField = async () => { - const field = this.state.field.toActualField(); + const field = this.state.field; const { indexPattern } = this.props; const { fieldFormatId } = this.state; diff --git a/src/legacy/ui/public/field_editor/lib/__tests__/copy_field.test.js b/src/legacy/ui/public/field_editor/lib/__tests__/copy_field.test.js deleted file mode 100644 index 2cee45742ab81d..00000000000000 --- a/src/legacy/ui/public/field_editor/lib/__tests__/copy_field.test.js +++ /dev/null @@ -1,48 +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 { copyField } from '../copy_field'; - -const field = { - name: 'test_field', - scripted: true, - type: 'number', - lang: 'painless', -}; - -describe('copyField', () => { - it('should copy a field', () => { - const copiedField = copyField(field, {}, {}); - copiedField.name = 'test_name_change'; - - // Check that copied field has `toActualField()` method - expect(typeof copiedField.toActualField).toEqual('function'); - - // Check that we did not modify the original field object when - // modifying copied field - expect(field.toActualField).toEqual(undefined); - expect(field.name).toEqual('test_field'); - - expect(copiedField).not.toEqual(field); - expect(copiedField.name).toEqual('test_name_change'); - expect(copiedField.scripted).toEqual(field.scripted); - expect(copiedField.type).toEqual(field.type); - expect(copiedField.lang).toEqual(field.lang); - }); -}); diff --git a/src/legacy/ui/public/field_editor/lib/copy_field.js b/src/legacy/ui/public/field_editor/lib/copy_field.js deleted file mode 100644 index bfc1cb8480d5d4..00000000000000 --- a/src/legacy/ui/public/field_editor/lib/copy_field.js +++ /dev/null @@ -1,82 +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 { has } from 'lodash'; - -/** - * Fully clones a Field object, so that modifications can be performed on - * the copy without affecting original field. Field objects contain - * enumerable and non-eumerable properties that may or may not be writable. - * The function copies all properties as property descriptors into - * `newFieldProps`, overrides getter and setter, and returns a new object - * created from that. - * - * @param {object} field - Field object to copy - * @param {object} indexPattern - index pattern object the field belongs to - * @param {object} Field - Field object type - * @return {object} the cloned object - */ -export const copyField = (field, indexPattern, Field) => { - const changes = {}; - const newFieldProps = { - // When we are ready to save the copied field back into the index pattern, - // we use `toActualField()` to retrieve an actual `Field` type object, using - // its original properties with our "changes" applied. - toActualField: { - value: () => { - return new Field(indexPattern, { - ...field.$$spec, - ...changes, - }); - }, - }, - }; - - // Index pattern `Field` objects are created with custom property - // descriptors using `ObjDefine`. - // - // Each property of a `Field` type object could be enumerable/non-enumerable, - // writable/not writable, configurable/not configurable, and have custom - // getter and setter. We can't use the original `field` object directly for - // creating a new field or editing a new field, since we need all the - // properties to be editable. - // - // A normal copy of `field` (i.e. `const newField = { ...field }`) will only - // copy enumerable properties and copy each property's descriptors (not - // writable, etc). - // - // So we copy `field`'s **property descriptors** into `newFieldProps` - // and modify them so that they are "writable" with a getter/setter that - // stores and retrieves changes into/from another object (`changes`). - Object.getOwnPropertyNames(field).forEach(function(prop) { - const desc = Object.getOwnPropertyDescriptor(field, prop); - - newFieldProps[prop] = { - enumerable: desc.enumerable, - get: function() { - return has(changes, prop) ? changes[prop] : field[prop]; - }, - set: function(v) { - changes[prop] = v; - }, - }; - }); - - return Object.create(null, newFieldProps); -}; diff --git a/src/legacy/ui/public/field_editor/lib/index.js b/src/legacy/ui/public/field_editor/lib/index.js index c74bb0cc2ef8ab..c9dd9d03b74f7b 100644 --- a/src/legacy/ui/public/field_editor/lib/index.js +++ b/src/legacy/ui/public/field_editor/lib/index.js @@ -17,5 +17,4 @@ * under the License. */ -export { copyField } from './copy_field'; export { executeScript, isScriptValid } from './validate_script'; diff --git a/src/plugins/data/public/index_patterns/fields/field.ts b/src/plugins/data/public/index_patterns/fields/field.ts index 1554565d1403ee..6370dcdf2db6f4 100644 --- a/src/plugins/data/public/index_patterns/fields/field.ts +++ b/src/plugins/data/public/index_patterns/fields/field.ts @@ -45,9 +45,6 @@ export class Field implements IFieldType { subType?: IFieldSubType; displayName?: string; format: any; - routes: Record = { - edit: '/management/kibana/index_patterns/{{indexPattern.id}}/field/{{name}}', - }; $$spec: FieldSpec; constructor( @@ -146,7 +143,3 @@ export class Field implements IFieldType { return obj.create(); } } - -Field.prototype.routes = { - edit: '/management/kibana/index_patterns/{{indexPattern.id}}/field/{{name}}', -}; diff --git a/src/plugins/data/public/index_patterns/fields/field_list.ts b/src/plugins/data/public/index_patterns/fields/field_list.ts index 03214a8c96427a..d6067280fd7b67 100644 --- a/src/plugins/data/public/index_patterns/fields/field_list.ts +++ b/src/plugins/data/public/index_patterns/fields/field_list.ts @@ -70,11 +70,12 @@ export class FieldList extends Array implements IFieldList { this.splice(fieldIndex, 1); }; - update = (field: Field) => { - const index = this.findIndex(f => f.name === field.name); - this.splice(index, 1, field); - this.setByName(field); - this.removeByGroup(field); - this.setByGroup(field); + update = (field: FieldSpec) => { + const newField = new Field(this.indexPattern, field, this.shortDotsEnable); + const index = this.findIndex(f => f.name === newField.name); + this.splice(index, 1, newField); + this.setByName(newField); + this.removeByGroup(newField); + this.setByGroup(newField); }; } diff --git a/src/plugins/data/public/public.api.md b/src/plugins/data/public/public.api.md index cef82b27b1b5bc..62967a7071d825 100644 --- a/src/plugins/data/public/public.api.md +++ b/src/plugins/data/public/public.api.md @@ -947,8 +947,6 @@ export class IndexPatternField implements IFieldType { // (undocumented) name: string; // (undocumented) - routes: Record; - // (undocumented) script?: string; // (undocumented) scripted?: boolean; @@ -978,7 +976,7 @@ export class IndexPatternFieldList extends Array implements I // (undocumented) remove: (field: IFieldType) => void; // (undocumented) - update: (field: IndexPatternField) => void; + update: (field: Record) => void; } // Warning: (ae-missing-release-tag) "indexPatterns" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) From e6095fcd03120b62c6d65dcdd23ea7a0ba6d3aab Mon Sep 17 00:00:00 2001 From: Justin Kambic Date: Tue, 14 Apr 2020 08:35:31 -0400 Subject: [PATCH 11/12] [Uptime] Remove pings graphql (#59392) * WIP replacing GQL with redux/rest. * Finish implementing migration. * Introduce new connected component for ping list. * Replace GraphQL type with io-ts. * Update some broken tests. * Add test for new helper function. * Write test snapshots. * Migrate api tests from graphql to rest. * Update fixtures that rely on pings. * Move ping types to runtime_types folder with rest of io-ts files. * Update Ping type location and imports, type checking. * Remove reliance on fixtures for ping functional API tests. * Fix broken unit tests. * Fix broken types. * Remove local state storage from parent components. * Add functional test to cover Ping List functionality. * Fix monitor page functional test that was broken by merge conflicts. * Fix broken tests. * Fix broken API test. * Replace a test with a describe block that will pre-navigate all tests. * Delete unused reducer keys. * Re-introduce loading to ping list reducer. * Inroduce code that will cause PingList to re-fetch when refresh button is pressed. * Update expanded rows to support multiple concurrent expanded rows. * Modify pingList reducer to have singular optional error field. * Delete unnecessary helper code. * Delete unused interface. * Add runtime_type to parse getPings params, fix pagination index. * Add dedicated monitor type to runtime_types. * Fix broken tests. * Fix broken tests. * Rename '@timestamp' property to 'timestamp' on Ping type. * Fix broken type and key pings list table on document ID instead of timestamp. * Fix broken unit tests. * Fix broken tests and types. * Fix broken functional test. --- .../plugins/uptime/common/graphql/types.ts | 340 ---- .../uptime/common/runtime_types/common.ts | 6 + .../uptime/common/runtime_types/index.ts | 1 + .../ping/histogram.ts | 12 + .../runtime_types/ping}/index.ts | 3 +- .../uptime/common/runtime_types/ping/ping.ts | 181 ++ .../plugins/uptime/common/types/index.ts | 2 - .../connected/charts/ping_histogram.tsx | 2 +- .../public/components/connected/index.ts | 1 + .../monitor/status_bar_container.tsx | 2 +- .../components/connected/pings/index.ts | 7 + .../components/connected/pings/ping_list.tsx | 52 + .../functional/charts/ping_histogram.tsx | 2 +- .../public/components/functional/index.ts | 2 +- .../__test__/monitor_ssl_certificate.test.tsx | 4 +- .../__test__/monitor_status.bar.test.tsx | 6 +- .../monitor_ssl_certificate.tsx | 5 +- .../monitor_status_bar/monitor_status_bar.tsx | 2 +- .../__snapshots__/ping_list.test.tsx.snap | 665 ++++--- .../ping_list/__tests__/expanded_row.test.tsx | 14 +- .../ping_list/__tests__/ping_list.test.tsx | 418 +++-- .../functional/ping_list/expanded_row.tsx | 4 +- .../components/functional/ping_list/index.tsx | 2 +- .../functional/ping_list/ping_list.tsx | 343 ++-- .../plugins/uptime/public/hooks/index.ts | 1 + .../plugins/uptime/public/pages/monitor.tsx | 46 +- .../uptime/public/queries/pings_query.ts | 73 - .../public/state/actions/monitor_status.ts | 2 +- .../uptime/public/state/actions/ping.ts | 11 +- .../uptime/public/state/api/monitor_status.ts | 4 +- .../plugins/uptime/public/state/api/ping.ts | 19 +- .../public/state/effects/fetch_effect.ts | 2 +- .../uptime/public/state/effects/index.ts | 3 +- .../uptime/public/state/effects/ping.ts | 15 +- .../uptime/public/state/reducers/index.ts | 2 + .../public/state/reducers/monitor_status.ts | 2 +- .../uptime/public/state/reducers/ping.ts | 2 +- .../uptime/public/state/reducers/ping_list.ts | 48 + .../state/selectors/__tests__/index.test.ts | 8 + .../uptime/public/state/selectors/index.ts | 5 + x-pack/plugins/uptime/server/graphql/index.ts | 3 +- .../graphql/monitor_states/schema.gql.ts | 2 +- .../uptime/server/graphql/pings/index.ts | 1 - .../uptime/server/graphql/pings/resolvers.ts | 59 - .../uptime/server/graphql/pings/schema.gql.ts | 26 - .../__tests__/get_latest_monitor.test.ts | 25 +- .../lib/requests/__tests__/get_pings.test.ts | 273 ++- .../server/lib/requests/get_latest_monitor.ts | 12 +- .../server/lib/requests/get_ping_histogram.ts | 6 +- .../uptime/server/lib/requests/get_pings.ts | 65 +- .../uptime/server/lib/requests/index.ts | 2 +- .../uptime/server/lib/requests/types.ts | 72 - .../server/lib/requests/uptime_requests.ts | 13 +- .../plugins/uptime/server/rest_api/index.ts | 4 +- .../uptime/server/rest_api/pings/get_all.ts | 47 - .../uptime/server/rest_api/pings/get_pings.ts | 24 +- .../uptime/server/rest_api/pings/index.ts | 1 + .../apis/uptime/feature_controls.ts | 2 +- .../apis/uptime/get_all_pings.ts | 18 +- .../uptime/graphql/fixtures/ping_list.json | 320 ---- .../graphql/fixtures/ping_list_count.json | 1569 ----------------- .../fixtures/ping_list_monitor_id.json | 475 ----- .../graphql/fixtures/ping_list_sort.json | 165 -- .../apis/uptime/graphql/index.ts | 1 - .../apis/uptime/graphql/ping_list.ts | 116 -- .../test/api_integration/apis/uptime/index.ts | 11 +- .../rest/fixtures/monitor_latest_status.json | 15 +- .../api_integration/apis/uptime/rest/index.ts | 5 +- .../apis/uptime/rest/ping_list.ts | 178 ++ x-pack/test/functional/apps/uptime/monitor.ts | 29 +- .../functional/page_objects/uptime_page.ts | 16 +- .../functional/services/uptime/monitor.ts | 17 + 72 files changed, 1695 insertions(+), 4196 deletions(-) rename x-pack/legacy/plugins/uptime/common/{types => runtime_types}/ping/histogram.ts (77%) rename x-pack/legacy/plugins/uptime/{public/queries => common/runtime_types/ping}/index.ts (79%) create mode 100644 x-pack/legacy/plugins/uptime/common/runtime_types/ping/ping.ts create mode 100644 x-pack/legacy/plugins/uptime/public/components/connected/pings/index.ts create mode 100644 x-pack/legacy/plugins/uptime/public/components/connected/pings/ping_list.tsx delete mode 100644 x-pack/legacy/plugins/uptime/public/queries/pings_query.ts create mode 100644 x-pack/legacy/plugins/uptime/public/state/reducers/ping_list.ts delete mode 100644 x-pack/plugins/uptime/server/graphql/pings/resolvers.ts delete mode 100644 x-pack/plugins/uptime/server/lib/requests/types.ts delete mode 100644 x-pack/plugins/uptime/server/rest_api/pings/get_all.ts delete mode 100644 x-pack/test/api_integration/apis/uptime/graphql/fixtures/ping_list.json delete mode 100644 x-pack/test/api_integration/apis/uptime/graphql/fixtures/ping_list_count.json delete mode 100644 x-pack/test/api_integration/apis/uptime/graphql/fixtures/ping_list_monitor_id.json delete mode 100644 x-pack/test/api_integration/apis/uptime/graphql/fixtures/ping_list_sort.json delete mode 100644 x-pack/test/api_integration/apis/uptime/graphql/ping_list.ts create mode 100644 x-pack/test/api_integration/apis/uptime/rest/ping_list.ts diff --git a/x-pack/legacy/plugins/uptime/common/graphql/types.ts b/x-pack/legacy/plugins/uptime/common/graphql/types.ts index c8beb91d807d56..506966ec6b5c9c 100644 --- a/x-pack/legacy/plugins/uptime/common/graphql/types.ts +++ b/x-pack/legacy/plugins/uptime/common/graphql/types.ts @@ -15,294 +15,15 @@ export type UnsignedInteger = any; // ==================================================== export interface Query { - /** Get a list of all recorded pings for all monitors */ - allPings: PingResults; - /** Fetches the current state of Uptime monitors for the given parameters. */ getMonitorStates?: MonitorSummaryResult | null; } -export interface PingResults { - /** Total number of matching pings */ - total: UnsignedInteger; - /** Unique list of all locations the query matched */ - locations: string[]; - /** List of pings */ - pings: Ping[]; -} -/** A request sent from a monitor to a host */ -export interface Ping { - /** unique ID for this ping */ - id: string; - /** The timestamp of the ping's creation */ - timestamp: string; - /** The agent that recorded the ping */ - beat?: Beat | null; - - container?: Container | null; - - docker?: Docker | null; - - ecs?: Ecs | null; - - error?: Error | null; - - host?: Host | null; - - http?: Http | null; - - icmp?: Icmp | null; - - kubernetes?: Kubernetes | null; - - meta?: Meta | null; - - monitor?: Monitor | null; - - observer?: Observer | null; - - resolve?: Resolve | null; - - socks5?: Socks5 | null; - - summary?: Summary | null; - - tags?: string | null; - - tcp?: Tcp | null; - - tls?: PingTls | null; - - url?: Url | null; -} -/** An agent for recording a beat */ -export interface Beat { - hostname?: string | null; - - name?: string | null; - - timezone?: string | null; - - type?: string | null; -} - -export interface Container { - id?: string | null; - - image?: ContainerImage | null; - - name?: string | null; - - runtime?: string | null; -} - -export interface ContainerImage { - name?: string | null; - - tag?: string | null; -} - -export interface Docker { - id?: string | null; - - image?: string | null; - - name?: string | null; -} - -export interface Ecs { - version?: string | null; -} - -export interface Error { - code?: number | null; - - message?: string | null; - - type?: string | null; -} - -export interface Host { - architecture?: string | null; - - id?: string | null; - - hostname?: string | null; - - ip?: string | null; - - mac?: string | null; - - name?: string | null; - - os?: Os | null; -} - -export interface Os { - family?: string | null; - - kernel?: string | null; - - platform?: string | null; - - version?: string | null; - - name?: string | null; - - build?: string | null; -} - -export interface Http { - response?: HttpResponse | null; - - rtt?: HttpRtt | null; - - url?: string | null; -} - -export interface HttpResponse { - status_code?: UnsignedInteger | null; - - body?: HttpBody | null; -} - -export interface HttpBody { - /** Size of HTTP response body in bytes */ - bytes?: UnsignedInteger | null; - /** Hash of the HTTP response body */ - hash?: string | null; - /** Response body of the HTTP Response. May be truncated based on client settings. */ - content?: string | null; - /** Byte length of the content string, taking into account multibyte chars. */ - content_bytes?: UnsignedInteger | null; -} - -export interface HttpRtt { - content?: Duration | null; - - response_header?: Duration | null; - - total?: Duration | null; - - validate?: Duration | null; - - validate_body?: Duration | null; - - write_request?: Duration | null; -} /** The monitor's status for a ping */ export interface Duration { us?: UnsignedInteger | null; } -export interface Icmp { - requests?: number | null; - - rtt?: number | null; -} - -export interface Kubernetes { - container?: KubernetesContainer | null; - - namespace?: string | null; - - node?: KubernetesNode | null; - - pod?: KubernetesPod | null; -} - -export interface KubernetesContainer { - image?: string | null; - - name?: string | null; -} - -export interface KubernetesNode { - name?: string | null; -} - -export interface KubernetesPod { - name?: string | null; - - uid?: string | null; -} - -export interface Meta { - cloud?: MetaCloud | null; -} - -export interface MetaCloud { - availability_zone?: string | null; - - instance_id?: string | null; - - instance_name?: string | null; - - machine_type?: string | null; - - project_id?: string | null; - - provider?: string | null; - - region?: string | null; -} - -export interface Monitor { - duration?: Duration | null; - - host?: string | null; - /** The id of the monitor */ - id?: string | null; - /** The IP pinged by the monitor */ - ip?: string | null; - /** The name of the protocol being monitored */ - name?: string | null; - /** The protocol scheme of the monitored host */ - scheme?: string | null; - /** The status of the monitored host */ - status?: string | null; - /** The type of host being monitored */ - type?: string | null; - - check_group?: string | null; -} -/** Metadata added by a proccessor, which is specified in its configuration. */ -export interface Observer { - /** Geolocation data for the agent. */ - geo?: Geo | null; -} -/** Geolocation data added via processors to enrich events. */ -export interface Geo { - /** Name of the city in which the agent is running. */ - city_name?: string | null; - /** The name of the continent on which the agent is running. */ - continent_name?: string | null; - /** ISO designation for the agent's country. */ - country_iso_code?: string | null; - /** The name of the agent's country. */ - country_name?: string | null; - /** The lat/long of the agent. */ - location?: string | null; - /** A name for the host's location, e.g. 'us-east-1' or 'LAX'. */ - name?: string | null; - /** ISO designation of the agent's region. */ - region_iso_code?: string | null; - /** Name of the region hosting the agent. */ - region_name?: string | null; -} - -export interface Resolve { - host?: string | null; - - ip?: string | null; - - rtt?: Duration | null; -} - -export interface Socks5 { - rtt?: Rtt | null; -} - export interface Rtt { connect?: Duration | null; @@ -331,53 +52,10 @@ export interface Location { lon?: number | null; } -export interface Tcp { - port?: number | null; - - rtt?: Rtt | null; -} -/** Contains monitor transmission encryption information. */ -export interface PingTls { - /** The date and time after which the certificate is invalid. */ - certificate_not_valid_after?: string | null; - - certificate_not_valid_before?: string | null; - - certificates?: string | null; - - rtt?: Rtt | null; -} - -export interface Url { - full?: string | null; - - scheme?: string | null; - - domain?: string | null; - - port?: number | null; - - path?: string | null; - - query?: string | null; -} - export interface DocCount { count: UnsignedInteger; } -export interface Snapshot { - counts: SnapshotCount; -} - -export interface SnapshotCount { - up: number; - - down: number; - - total: number; -} - /** The primary object returned for monitor states. */ export interface MonitorSummaryResult { /** Used to go to the next page of results */ @@ -521,24 +199,6 @@ export interface SummaryHistogramPoint { down: number; } -export interface AllPingsQueryArgs { - /** Optional: the direction to sort by. Accepts 'asc' and 'desc'. Defaults to 'desc'. */ - sort?: string | null; - /** Optional: the number of results to return. */ - size?: number | null; - /** Optional: the monitor ID filter. */ - monitorId?: string | null; - /** Optional: the check status to filter by. */ - status?: string | null; - /** The lower limit of the date range. */ - dateRangeStart: string; - /** The upper limit of the date range. */ - dateRangeEnd: string; - /** Optional: agent location to filter by. */ - location?: string | null; - page?: number; -} - export interface GetMonitorStatesQueryArgs { dateRangeStart: string; diff --git a/x-pack/legacy/plugins/uptime/common/runtime_types/common.ts b/x-pack/legacy/plugins/uptime/common/runtime_types/common.ts index 37101b5b46fd2b..9018f4acaa3204 100644 --- a/x-pack/legacy/plugins/uptime/common/runtime_types/common.ts +++ b/x-pack/legacy/plugins/uptime/common/runtime_types/common.ts @@ -27,7 +27,13 @@ export const StatesIndexStatusType = t.type({ docCount: t.number, }); +export const DateRangeType = t.type({ + from: t.string, + to: t.string, +}); + export type Summary = t.TypeOf; export type CheckGeo = t.TypeOf; export type Location = t.TypeOf; export type StatesIndexStatus = t.TypeOf; +export type DateRange = t.TypeOf; diff --git a/x-pack/legacy/plugins/uptime/common/runtime_types/index.ts b/x-pack/legacy/plugins/uptime/common/runtime_types/index.ts index 5e3fb2326bdb97..652d60cbe304de 100644 --- a/x-pack/legacy/plugins/uptime/common/runtime_types/index.ts +++ b/x-pack/legacy/plugins/uptime/common/runtime_types/index.ts @@ -8,5 +8,6 @@ export * from './alerts'; export * from './common'; export * from './monitor'; export * from './overview_filters'; +export * from './ping'; export * from './snapshot'; export * from './dynamic_settings'; diff --git a/x-pack/legacy/plugins/uptime/common/types/ping/histogram.ts b/x-pack/legacy/plugins/uptime/common/runtime_types/ping/histogram.ts similarity index 77% rename from x-pack/legacy/plugins/uptime/common/types/ping/histogram.ts rename to x-pack/legacy/plugins/uptime/common/runtime_types/ping/histogram.ts index 3ae32e15ca55ca..2c3b52051be0fc 100644 --- a/x-pack/legacy/plugins/uptime/common/types/ping/histogram.ts +++ b/x-pack/legacy/plugins/uptime/common/runtime_types/ping/histogram.ts @@ -28,3 +28,15 @@ export interface HistogramResult { histogram: HistogramDataPoint[]; interval: string; } + +export interface HistogramQueryResult { + key: number; + key_as_string: string; + doc_count: number; + down: { + doc_count: number; + }; + up: { + doc_count: number; + }; +} diff --git a/x-pack/legacy/plugins/uptime/public/queries/index.ts b/x-pack/legacy/plugins/uptime/common/runtime_types/ping/index.ts similarity index 79% rename from x-pack/legacy/plugins/uptime/public/queries/index.ts rename to x-pack/legacy/plugins/uptime/common/runtime_types/ping/index.ts index 283382ec1b7baa..a2fc7c1b243ba6 100644 --- a/x-pack/legacy/plugins/uptime/public/queries/index.ts +++ b/x-pack/legacy/plugins/uptime/common/runtime_types/ping/index.ts @@ -4,4 +4,5 @@ * you may not use this file except in compliance with the Elastic License. */ -export { pingsQuery, pingsQueryString } from './pings_query'; +export * from './histogram'; +export * from './ping'; diff --git a/x-pack/legacy/plugins/uptime/common/runtime_types/ping/ping.ts b/x-pack/legacy/plugins/uptime/common/runtime_types/ping/ping.ts new file mode 100644 index 00000000000000..ee14b298f38104 --- /dev/null +++ b/x-pack/legacy/plugins/uptime/common/runtime_types/ping/ping.ts @@ -0,0 +1,181 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import * as t from 'io-ts'; +import { DateRangeType } from '../common'; + +export const HttpResponseBodyType = t.partial({ + bytes: t.number, + content: t.string, + content_bytes: t.number, + hash: t.string, +}); + +export type HttpResponseBody = t.TypeOf; + +export const TlsType = t.partial({ + certificate_not_valid_after: t.string, + certificate_not_valid_before: t.string, +}); + +export type Tls = t.TypeOf; + +export const MonitorType = t.intersection([ + t.type({ + duration: t.type({ + us: t.number, + }), + id: t.string, + status: t.string, + type: t.string, + }), + t.partial({ + check_group: t.string, + ip: t.string, + name: t.string, + timespan: t.partial({ + gte: t.string, + lte: t.string, + }), + }), +]); + +export type Monitor = t.TypeOf; + +export const PingType = t.intersection([ + t.type({ + timestamp: t.string, + monitor: MonitorType, + docId: t.string, + }), + t.partial({ + agent: t.intersection([ + t.type({ + ephemeral_id: t.string, + hostname: t.string, + id: t.string, + type: t.string, + version: t.string, + }), + t.partial({ + name: t.string, + }), + ]), + container: t.partial({ + id: t.string, + image: t.partial({ + name: t.string, + tag: t.string, + }), + name: t.string, + runtime: t.string, + }), + ecs: t.partial({ + version: t.string, + }), + error: t.intersection([ + t.partial({ + code: t.string, + id: t.string, + stack_trace: t.string, + type: t.string, + }), + t.type({ + // this is _always_ on the error field + message: t.string, + }), + ]), + http: t.partial({ + request: t.partial({ + body: t.partial({ + bytes: t.number, + content: t.partial({ + text: t.string, + }), + }), + bytes: t.number, + method: t.string, + referrer: t.string, + }), + response: t.partial({ + body: HttpResponseBodyType, + bytes: t.number, + redirects: t.string, + status_code: t.number, + }), + version: t.string, + }), + icmp: t.partial({ + requests: t.number, + rtt: t.partial({ + us: t.number, + }), + }), + kubernetes: t.partial({ + pod: t.partial({ + name: t.string, + uid: t.string, + }), + }), + observer: t.partial({ + geo: t.partial({ + name: t.string, + }), + }), + resolve: t.partial({ + ip: t.string, + rtt: t.partial({ + us: t.number, + }), + }), + summary: t.partial({ + down: t.number, + up: t.number, + }), + tags: t.array(t.string), + tcp: t.partial({ + rtt: t.partial({ + connect: t.partial({ + us: t.number, + }), + }), + }), + tls: TlsType, + // should this be partial? + url: t.partial({ + domain: t.string, + full: t.string, + port: t.number, + scheme: t.string, + }), + }), +]); + +export type Ping = t.TypeOf; + +export const PingsResponseType = t.type({ + total: t.number, + locations: t.array(t.string), + pings: t.array(PingType), +}); + +export type PingsResponse = t.TypeOf; + +export const GetPingsParamsType = t.intersection([ + t.type({ + dateRange: DateRangeType, + }), + t.partial({ + index: t.number, + size: t.number, + location: t.string, + monitorId: t.string, + sort: t.string, + status: t.string, + }), +]); + +export type GetPingsParams = t.TypeOf; diff --git a/x-pack/legacy/plugins/uptime/common/types/index.ts b/x-pack/legacy/plugins/uptime/common/types/index.ts index 2c39f2a3b73147..1d0003addd7618 100644 --- a/x-pack/legacy/plugins/uptime/common/types/index.ts +++ b/x-pack/legacy/plugins/uptime/common/types/index.ts @@ -41,5 +41,3 @@ export interface MonitorDurationResult { /** The maximum duration value in this chart. */ durationMaxValue: number; } - -export * from './ping/histogram'; diff --git a/x-pack/legacy/plugins/uptime/public/components/connected/charts/ping_histogram.tsx b/x-pack/legacy/plugins/uptime/public/components/connected/charts/ping_histogram.tsx index 6428ddfd10f8c5..cf35dbf4e5206e 100644 --- a/x-pack/legacy/plugins/uptime/public/components/connected/charts/ping_histogram.tsx +++ b/x-pack/legacy/plugins/uptime/public/components/connected/charts/ping_histogram.tsx @@ -14,7 +14,7 @@ import { import { getPingHistogram } from '../../../state/actions'; import { selectPingHistogram } from '../../../state/selectors'; import { withResponsiveWrapper, ResponsiveWrapperProps } from '../../higher_order'; -import { GetPingHistogramParams, HistogramResult } from '../../../../common/types'; +import { GetPingHistogramParams, HistogramResult } from '../../../../common/runtime_types'; import { useGetUrlParams } from '../../../hooks'; type Props = ResponsiveWrapperProps & diff --git a/x-pack/legacy/plugins/uptime/public/components/connected/index.ts b/x-pack/legacy/plugins/uptime/public/components/connected/index.ts index 7e442cbe850baa..be3cc5b65aa0ee 100644 --- a/x-pack/legacy/plugins/uptime/public/components/connected/index.ts +++ b/x-pack/legacy/plugins/uptime/public/components/connected/index.ts @@ -13,5 +13,6 @@ export { MonitorStatusDetails } from './monitor/status_details_container'; export { MonitorStatusBar } from './monitor/status_bar_container'; export { MonitorListDrawer } from './monitor/list_drawer_container'; export { MonitorListActionsPopover } from './monitor/drawer_popover_container'; +export { PingList, PingListProps } from './pings'; export { DurationChart } from './charts/monitor_duration'; export { EmptyState } from './empty_state/empty_state'; diff --git a/x-pack/legacy/plugins/uptime/public/components/connected/monitor/status_bar_container.tsx b/x-pack/legacy/plugins/uptime/public/components/connected/monitor/status_bar_container.tsx index 00cfd02d8dc326..3a96aa7c0275b7 100644 --- a/x-pack/legacy/plugins/uptime/public/components/connected/monitor/status_bar_container.tsx +++ b/x-pack/legacy/plugins/uptime/public/components/connected/monitor/status_bar_container.tsx @@ -12,7 +12,7 @@ import { monitorLocationsSelector, monitorStatusSelector } from '../../../state/ import { MonitorStatusBarComponent } from '../../functional/monitor_status_details/monitor_status_bar'; import { getMonitorStatusAction } from '../../../state/actions'; import { useGetUrlParams } from '../../../hooks'; -import { Ping } from '../../../../common/graphql/types'; +import { Ping } from '../../../../common/runtime_types'; import { MonitorLocations } from '../../../../common/runtime_types/monitor'; import { UptimeRefreshContext } from '../../../contexts'; diff --git a/x-pack/legacy/plugins/uptime/public/components/connected/pings/index.ts b/x-pack/legacy/plugins/uptime/public/components/connected/pings/index.ts new file mode 100644 index 00000000000000..95ced104e51882 --- /dev/null +++ b/x-pack/legacy/plugins/uptime/public/components/connected/pings/index.ts @@ -0,0 +1,7 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +export { PingList, PingListProps } from './ping_list'; diff --git a/x-pack/legacy/plugins/uptime/public/components/connected/pings/ping_list.tsx b/x-pack/legacy/plugins/uptime/public/components/connected/pings/ping_list.tsx new file mode 100644 index 00000000000000..5b32a623495f16 --- /dev/null +++ b/x-pack/legacy/plugins/uptime/public/components/connected/pings/ping_list.tsx @@ -0,0 +1,52 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { useSelector, useDispatch } from 'react-redux'; +import React, { useContext, useCallback } from 'react'; +import { selectPingList } from '../../../state/selectors'; +import { getPings } from '../../../state/actions'; +import { GetPingsParams } from '../../../../common/runtime_types'; +import { UptimeSettingsContext } from '../../../contexts'; +import { PingListComponent } from '../../functional'; + +export interface PingListProps { + monitorId: string; +} + +export const PingList = (props: PingListProps) => { + const { + lastRefresh, + pings: { + error, + loading, + pingList: { locations, pings, total }, + }, + } = useSelector(selectPingList); + + const { dateRangeStart: drs, dateRangeEnd: dre } = useContext(UptimeSettingsContext); + + const dispatch = useDispatch(); + const getPingsCallback = useCallback((params: GetPingsParams) => dispatch(getPings(params)), [ + dispatch, + ]); + + return ( + + ); +}; diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/charts/ping_histogram.tsx b/x-pack/legacy/plugins/uptime/public/components/functional/charts/ping_histogram.tsx index f988afc7fc84df..66e86d67312360 100644 --- a/x-pack/legacy/plugins/uptime/public/components/functional/charts/ping_histogram.tsx +++ b/x-pack/legacy/plugins/uptime/public/components/functional/charts/ping_histogram.tsx @@ -13,7 +13,7 @@ import moment from 'moment'; import { getChartDateLabel } from '../../../lib/helper'; import { ChartWrapper } from './chart_wrapper'; import { UptimeThemeContext } from '../../../contexts'; -import { HistogramResult } from '../../../../common/types'; +import { HistogramResult } from '../../../../common/runtime_types'; import { useUrlParams } from '../../../hooks'; import { ChartEmptyState } from './chart_empty_state'; diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/index.ts b/x-pack/legacy/plugins/uptime/public/components/functional/index.ts index 8d0352e01d40ed..d82912a6216e86 100644 --- a/x-pack/legacy/plugins/uptime/public/components/functional/index.ts +++ b/x-pack/legacy/plugins/uptime/public/components/functional/index.ts @@ -15,6 +15,6 @@ export { KueryBarComponent } from './kuery_bar/kuery_bar'; export { MonitorCharts } from './monitor_charts'; export { MonitorList } from './monitor_list'; export { OverviewPageParsingErrorCallout } from './overview_page_parsing_error_callout'; -export { PingList } from './ping_list'; +export { PingListComponent } from './ping_list'; export { PingHistogramComponent } from './charts'; export { StatusPanel } from './status_panel'; diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/monitor_status_details/__test__/monitor_ssl_certificate.test.tsx b/x-pack/legacy/plugins/uptime/public/components/functional/monitor_status_details/__test__/monitor_ssl_certificate.test.tsx index 2eae14301fd4d9..57ed09cc30ef15 100644 --- a/x-pack/legacy/plugins/uptime/public/components/functional/monitor_status_details/__test__/monitor_ssl_certificate.test.tsx +++ b/x-pack/legacy/plugins/uptime/public/components/functional/monitor_status_details/__test__/monitor_ssl_certificate.test.tsx @@ -9,11 +9,11 @@ import moment from 'moment'; import { mountWithIntl } from 'test_utils/enzyme_helpers'; import { EuiBadge } from '@elastic/eui'; import { renderWithIntl } from 'test_utils/enzyme_helpers'; -import { PingTls } from '../../../../../common/graphql/types'; +import { Tls } from '../../../../../common/runtime_types'; import { MonitorSSLCertificate } from '../monitor_status_bar'; describe('MonitorStatusBar component', () => { - let monitorTls: PingTls; + let monitorTls: Tls; beforeEach(() => { const dateInTwoMonths = moment() diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/monitor_status_details/__test__/monitor_status.bar.test.tsx b/x-pack/legacy/plugins/uptime/public/components/functional/monitor_status_details/__test__/monitor_status.bar.test.tsx index 0a53eeb89d793f..5fd32c808da42c 100644 --- a/x-pack/legacy/plugins/uptime/public/components/functional/monitor_status_details/__test__/monitor_status.bar.test.tsx +++ b/x-pack/legacy/plugins/uptime/public/components/functional/monitor_status_details/__test__/monitor_status.bar.test.tsx @@ -8,7 +8,7 @@ import moment from 'moment'; import React from 'react'; import { renderWithIntl } from 'test_utils/enzyme_helpers'; import { MonitorStatusBarComponent } from '../monitor_status_bar'; -import { Ping } from '../../../../../common/graphql/types'; +import { Ping } from '../../../../../common/runtime_types'; describe('MonitorStatusBar component', () => { let monitorStatus: Ping; @@ -16,7 +16,7 @@ describe('MonitorStatusBar component', () => { beforeEach(() => { monitorStatus = { - id: 'id1', + docId: 'few213kl', timestamp: moment(new Date()) .subtract(15, 'm') .toString(), @@ -24,7 +24,9 @@ describe('MonitorStatusBar component', () => { duration: { us: 1234567, }, + id: 'id1', status: 'up', + type: 'http', }, url: { full: 'https://www.example.com/', diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/monitor_status_details/monitor_status_bar/monitor_ssl_certificate.tsx b/x-pack/legacy/plugins/uptime/public/components/functional/monitor_status_details/monitor_status_bar/monitor_ssl_certificate.tsx index c57348c4ab4cd4..d92534aecd1754 100644 --- a/x-pack/legacy/plugins/uptime/public/components/functional/monitor_status_details/monitor_status_bar/monitor_ssl_certificate.tsx +++ b/x-pack/legacy/plugins/uptime/public/components/functional/monitor_status_details/monitor_status_bar/monitor_ssl_certificate.tsx @@ -9,14 +9,13 @@ import moment from 'moment'; import { EuiSpacer, EuiText, EuiBadge } from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n/react'; import { i18n } from '@kbn/i18n'; - -import { PingTls } from '../../../../../common/graphql/types'; +import { Tls } from '../../../../../common/runtime_types'; interface Props { /** * TLS information coming from monitor in ES heartbeat index */ - tls: PingTls | null | undefined; + tls: Tls | null | undefined; } export const MonitorSSLCertificate = ({ tls }: Props) => { diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/monitor_status_details/monitor_status_bar/monitor_status_bar.tsx b/x-pack/legacy/plugins/uptime/public/components/functional/monitor_status_details/monitor_status_bar/monitor_status_bar.tsx index 22e4377944be13..ac3cedc5179956 100644 --- a/x-pack/legacy/plugins/uptime/public/components/functional/monitor_status_details/monitor_status_bar/monitor_status_bar.tsx +++ b/x-pack/legacy/plugins/uptime/public/components/functional/monitor_status_details/monitor_status_bar/monitor_status_bar.tsx @@ -17,7 +17,7 @@ import { import { MonitorSSLCertificate } from './monitor_ssl_certificate'; import * as labels from './translations'; import { StatusByLocations } from './status_by_location'; -import { Ping } from '../../../../../common/graphql/types'; +import { Ping } from '../../../../../common/runtime_types'; import { MonitorLocations } from '../../../../../common/runtime_types'; interface MonitorStatusBarProps { diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/ping_list/__tests__/__snapshots__/ping_list.test.tsx.snap b/x-pack/legacy/plugins/uptime/public/components/functional/ping_list/__tests__/__snapshots__/ping_list.test.tsx.snap index 2e59ec5e57337b..154ab6399452d6 100644 --- a/x-pack/legacy/plugins/uptime/public/components/functional/ping_list/__tests__/__snapshots__/ping_list.test.tsx.snap +++ b/x-pack/legacy/plugins/uptime/public/components/functional/ping_list/__tests__/__snapshots__/ping_list.test.tsx.snap @@ -1,384 +1,349 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP exports[`PingList component renders sorted list without errors 1`] = ` - - - + +

+ +

+
+ + + -

- + -

-
- - - + + + - - - - - - - - - - - - - - - - - - - - + + + + + + Response code + , + "render": [Function], + }, + Object { + "align": "right", + "isExpander": true, + "render": [Function], + "width": "24px", + }, + ] + } + hasActions={true} + isExpandable={true} + itemId="docId" + itemIdToExpandedRowMap={Object {}} + items={ + Array [ + Object { + "docId": "fewjio21", + "error": Object { + "message": "dial tcp 127.0.0.1:9200: connect: connection refused", + "type": "io", }, - Object { - "align": "right", - "dataType": "number", - "field": "monitor.ip", - "name": "IP", + "monitor": Object { + "duration": Object { + "us": 1430, + }, + "id": "auto-tcp-0X81440A68E839814F", + "ip": "127.0.0.1", + "name": "", + "status": "down", + "type": "tcp", }, - Object { - "align": "right", - "field": "monitor.duration.us", - "name": "Duration", - "render": [Function], + "timestamp": "2019-01-28T17:47:08.078Z", + }, + Object { + "docId": "fewjoo21", + "error": Object { + "message": "dial tcp 127.0.0.1:9200: connect: connection refused", + "type": "io", }, - Object { - "align": "right", - "field": "error.type", - "name": "Error type", - "render": [Function], + "monitor": Object { + "duration": Object { + "us": 1370, + }, + "id": "auto-tcp-0X81440A68E839814D", + "ip": "127.0.0.1", + "name": "", + "status": "down", + "type": "tcp", }, - Object { - "align": "right", - "field": "http.response.status_code", - "name": - Response code - , - "render": [Function], + "timestamp": "2019-01-28T17:47:09.075Z", + }, + Object { + "docId": "fejjio21", + "monitor": Object { + "duration": Object { + "us": 1452, + }, + "id": "auto-tcp-0X81440A68E839814D", + "ip": "127.0.0.1", + "name": "", + "status": "up", + "type": "tcp", }, - Object { - "align": "right", - "isExpander": true, - "render": [Function], - "width": "24px", + "timestamp": "2019-01-28T17:47:06.077Z", + }, + Object { + "docId": "fewzio21", + "error": Object { + "message": "dial tcp 127.0.0.1:9200: connect: connection refused", + "type": "io", }, - ] - } - hasActions={true} - isExpandable={true} - itemId="id" - itemIdToExpandedRowMap={Object {}} - items={ - Array [ - Object { - "error": Object { - "message": "dial tcp 127.0.0.1:9200: connect: connection refused", - "type": "io", + "monitor": Object { + "duration": Object { + "us": 1094, }, - "http": null, - "id": "id1", - "monitor": Object { - "duration": Object { - "us": 1430, - }, - "id": "auto-tcp-0X81440A68E839814C", - "ip": "127.0.0.1", - "name": "", - "scheme": null, - "status": "down", - "type": "tcp", - }, - "timestamp": "2019-01-28T17:47:08.078Z", + "id": "auto-tcp-0X81440A68E839814E", + "ip": "127.0.0.1", + "name": "", + "status": "down", + "type": "tcp", }, - Object { - "error": Object { - "message": "dial tcp 127.0.0.1:9200: connect: connection refused", - "type": "io", - }, - "http": null, - "id": "id2", - "monitor": Object { - "duration": Object { - "us": 1370, - }, - "id": "auto-tcp-0X81440A68E839814C", - "ip": "127.0.0.1", - "name": "", - "scheme": null, - "status": "down", - "type": "tcp", - }, - "timestamp": "2019-01-28T17:47:09.075Z", + "timestamp": "2019-01-28T17:47:07.075Z", + }, + Object { + "docId": "fewpi321", + "error": Object { + "message": "Get http://localhost:12349/: dial tcp 127.0.0.1:12349: connect: connection refused", + "type": "io", }, - Object { - "error": null, - "http": null, - "id": "id3", - "monitor": Object { - "duration": Object { - "us": 1452, - }, - "id": "auto-tcp-0X81440A68E839814C", - "ip": "127.0.0.1", - "name": "", - "scheme": null, - "status": "up", - "type": "tcp", + "monitor": Object { + "duration": Object { + "us": 1597, }, - "timestamp": "2019-01-28T17:47:06.077Z", + "id": "auto-http-0X3675F89EF061209G", + "ip": "127.0.0.1", + "name": "", + "status": "down", + "type": "http", }, - Object { - "error": Object { - "message": "dial tcp 127.0.0.1:9200: connect: connection refused", - "type": "io", - }, - "http": null, - "id": "id4", - "monitor": Object { - "duration": Object { - "us": 1094, - }, - "id": "auto-tcp-0X81440A68E839814C", - "ip": "127.0.0.1", - "name": "", - "scheme": null, - "status": "down", - "type": "tcp", - }, - "timestamp": "2019-01-28T17:47:07.075Z", + "timestamp": "2019-01-28T17:47:07.074Z", + }, + Object { + "docId": "0ewjio21", + "error": Object { + "message": "dial tcp 127.0.0.1:9200: connect: connection refused", + "type": "io", }, - Object { - "error": Object { - "message": "Get http://localhost:12349/: dial tcp 127.0.0.1:12349: connect: connection refused", - "type": "io", + "monitor": Object { + "duration": Object { + "us": 1699, }, - "http": null, - "id": "id5", - "monitor": Object { - "duration": Object { - "us": 1597, - }, - "id": "auto-http-0X3675F89EF0612091", - "ip": "127.0.0.1", - "name": "", - "scheme": null, - "status": "down", - "type": "http", - }, - "timestamp": "2019-01-28T17:47:07.074Z", + "id": "auto-tcp-0X81440A68E839814H", + "ip": "127.0.0.1", + "name": "", + "status": "down", + "type": "tcp", }, - Object { - "error": Object { - "message": "dial tcp 127.0.0.1:9200: connect: connection refused", - "type": "io", - }, - "http": null, - "id": "id6", - "monitor": Object { - "duration": Object { - "us": 1699, - }, - "id": "auto-tcp-0X81440A68E839814C", - "ip": "127.0.0.1", - "name": "", - "scheme": null, - "status": "down", - "type": "tcp", - }, - "timestamp": "2019-01-28T17:47:18.080Z", + "timestamp": "2019-01-28T17:47:18.080Z", + }, + Object { + "docId": "3ewjio21", + "error": Object { + "message": "dial tcp 127.0.0.1:9200: connect: connection refused", + "type": "io", }, - Object { - "error": Object { - "message": "dial tcp 127.0.0.1:9200: connect: connection refused", - "type": "io", - }, - "http": null, - "id": "id7", - "monitor": Object { - "duration": Object { - "us": 5384, - }, - "id": "auto-tcp-0X81440A68E839814C", - "ip": "127.0.0.1", - "name": "", - "scheme": null, - "status": "down", - "type": "tcp", + "monitor": Object { + "duration": Object { + "us": 5384, }, - "timestamp": "2019-01-28T17:47:19.076Z", + "id": "auto-tcp-0X81440A68E839814I", + "ip": "127.0.0.1", + "name": "", + "status": "down", + "type": "tcp", }, - Object { - "error": Object { - "message": "Get http://localhost:12349/: dial tcp 127.0.0.1:12349: connect: connection refused", - "type": "io", - }, - "http": null, - "id": "id8", - "monitor": Object { - "duration": Object { - "us": 5397, - }, - "id": "auto-http-0X3675F89EF0612091", - "ip": "127.0.0.1", - "name": "", - "scheme": null, - "status": "down", - "type": "http", + "timestamp": "2019-01-28T17:47:19.076Z", + }, + Object { + "docId": "fewjip21", + "error": Object { + "message": "Get http://localhost:12349/: dial tcp 127.0.0.1:12349: connect: connection refused", + "type": "io", + }, + "monitor": Object { + "duration": Object { + "us": 5397, }, - "timestamp": "2019-01-28T17:47:19.076Z", + "id": "auto-http-0X3675F89EF061209J", + "ip": "127.0.0.1", + "name": "", + "status": "down", + "type": "http", }, - Object { - "error": null, - "http": Object { - "response": Object { - "status_code": 200, - }, + "timestamp": "2019-01-28T17:47:19.076Z", + }, + Object { + "docId": "fewjio21", + "http": Object { + "response": Object { + "status_code": 200, }, - "id": "id9", - "monitor": Object { - "duration": Object { - "us": 127511, - }, - "id": "auto-http-0X131221E73F825974", - "ip": "172.217.7.4", - "name": "", - "scheme": null, - "status": "up", - "type": "http", + }, + "monitor": Object { + "duration": Object { + "us": 127511, }, - "timestamp": "2019-01-28T17:47:19.077Z", + "id": "auto-tcp-0X81440A68E839814C", + "ip": "172.217.7.4", + "name": "", + "status": "up", + "type": "http", }, - Object { - "error": null, - "http": Object { - "response": Object { - "status_code": 200, - }, + "timestamp": "2019-01-28T17:47:19.077Z", + }, + Object { + "docId": "fewjik81", + "http": Object { + "response": Object { + "status_code": 200, }, - "id": "id10", - "monitor": Object { - "duration": Object { - "us": 287543, - }, - "id": "auto-http-0X9CB71300ABD5A2A8", - "ip": "192.30.253.112", - "name": "", - "scheme": null, - "status": "up", - "type": "http", + }, + "monitor": Object { + "duration": Object { + "us": 287543, }, - "timestamp": "2019-01-28T17:47:19.077Z", + "id": "auto-http-0X131221E73F825974", + "ip": "192.30.253.112", + "name": "", + "status": "up", + "type": "http", }, - ] - } - loading={false} - noItemsMessage="No items found" - onChange={[Function]} - pagination={ - Object { - "initialPageSize": 25, - "pageIndex": 0, - "pageSize": 10, - "pageSizeOptions": Array [ - 10, - 25, - 50, - 100, - ], - "totalItemCount": 9231, - } + "timestamp": "2019-01-28T17:47:19.077Z", + }, + ] + } + loading={false} + noItemsMessage="No items found" + onChange={[Function]} + pagination={ + Object { + "initialPageSize": 10, + "pageIndex": 0, + "pageSize": 10, + "pageSizeOptions": Array [ + 10, + 25, + 50, + 100, + ], + "totalItemCount": 10, } - responsive={true} - tableLayout="fixed" - /> -
-
+ } + responsive={true} + tableLayout="fixed" + /> + `; diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/ping_list/__tests__/expanded_row.test.tsx b/x-pack/legacy/plugins/uptime/public/components/functional/ping_list/__tests__/expanded_row.test.tsx index 9dbe48ec5553a0..2c1434cfd64bd5 100644 --- a/x-pack/legacy/plugins/uptime/public/components/functional/ping_list/__tests__/expanded_row.test.tsx +++ b/x-pack/legacy/plugins/uptime/public/components/functional/ping_list/__tests__/expanded_row.test.tsx @@ -7,15 +7,23 @@ import { mountWithIntl, renderWithIntl, shallowWithIntl } from 'test_utils/enzyme_helpers'; import React from 'react'; import { PingListExpandedRowComponent } from '../expanded_row'; -import { Ping } from '../../../../../common/graphql/types'; +import { Ping } from '../../../../../common/runtime_types'; import { DocLinkForBody } from '../doc_link_body'; describe('PingListExpandedRow', () => { let ping: Ping; beforeEach(() => { ping = { - id: '123', + docId: 'fdeio12', timestamp: '19290310', + monitor: { + duration: { + us: 12345, + }, + id: '123', + status: 'down', + type: 'http', + }, http: { response: { body: { @@ -34,7 +42,7 @@ describe('PingListExpandedRow', () => { it('renders error information when an error field is present', () => { ping.error = { - code: 403, + code: '403', message: 'Forbidden', }; expect(shallowWithIntl()).toMatchSnapshot(); diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/ping_list/__tests__/ping_list.test.tsx b/x-pack/legacy/plugins/uptime/public/components/functional/ping_list/__tests__/ping_list.test.tsx index 68d285bd0baf15..ec256a886aa16b 100644 --- a/x-pack/legacy/plugins/uptime/public/components/functional/ping_list/__tests__/ping_list.test.tsx +++ b/x-pack/legacy/plugins/uptime/public/components/functional/ping_list/__tests__/ping_list.test.tsx @@ -6,211 +6,188 @@ import React from 'react'; import { shallowWithIntl } from 'test_utils/enzyme_helpers'; -import { PingResults, Ping } from '../../../../../common/graphql/types'; -import { PingListComponent, AllLocationOption, toggleDetails } from '../ping_list'; +import { PingListComponent, toggleDetails } from '../ping_list'; import { ExpandedRowMap } from '../../monitor_list/types'; +import { Ping, PingsResponse } from '../../../../../common/runtime_types'; describe('PingList component', () => { - let pingList: { allPings: PingResults }; + let response: PingsResponse; beforeEach(() => { - pingList = { - allPings: { - total: 9231, - pings: [ - { - id: 'id1', - timestamp: '2019-01-28T17:47:08.078Z', - http: null, - error: { - message: 'dial tcp 127.0.0.1:9200: connect: connection refused', - type: 'io', - }, - monitor: { - duration: { us: 1430 }, - id: 'auto-tcp-0X81440A68E839814C', - ip: '127.0.0.1', - name: '', - scheme: null, - status: 'down', - type: 'tcp', - }, - }, - { - id: 'id2', - timestamp: '2019-01-28T17:47:09.075Z', - http: null, - error: { - message: 'dial tcp 127.0.0.1:9200: connect: connection refused', - type: 'io', - }, - monitor: { - duration: { us: 1370 }, - id: 'auto-tcp-0X81440A68E839814C', - ip: '127.0.0.1', - name: '', - scheme: null, - status: 'down', - type: 'tcp', - }, - }, - { - id: 'id3', - timestamp: '2019-01-28T17:47:06.077Z', - http: null, - error: null, - monitor: { - duration: { us: 1452 }, - id: 'auto-tcp-0X81440A68E839814C', - ip: '127.0.0.1', - name: '', - scheme: null, - status: 'up', - type: 'tcp', - }, - }, - { - id: 'id4', - timestamp: '2019-01-28T17:47:07.075Z', - http: null, - error: { - message: 'dial tcp 127.0.0.1:9200: connect: connection refused', - type: 'io', - }, - monitor: { - duration: { us: 1094 }, - id: 'auto-tcp-0X81440A68E839814C', - ip: '127.0.0.1', - name: '', - scheme: null, - status: 'down', - type: 'tcp', - }, - }, - { - id: 'id5', - timestamp: '2019-01-28T17:47:07.074Z', - http: null, - error: { - message: - 'Get http://localhost:12349/: dial tcp 127.0.0.1:12349: connect: connection refused', - type: 'io', - }, - monitor: { - duration: { us: 1597 }, - id: 'auto-http-0X3675F89EF0612091', - ip: '127.0.0.1', - name: '', - scheme: null, - status: 'down', - type: 'http', - }, - }, - { - id: 'id6', - timestamp: '2019-01-28T17:47:18.080Z', - http: null, - error: { - message: 'dial tcp 127.0.0.1:9200: connect: connection refused', - type: 'io', - }, - monitor: { - duration: { us: 1699 }, - id: 'auto-tcp-0X81440A68E839814C', - ip: '127.0.0.1', - name: '', - scheme: null, - status: 'down', - type: 'tcp', - }, - }, - { - id: 'id7', - timestamp: '2019-01-28T17:47:19.076Z', - http: null, - error: { - message: 'dial tcp 127.0.0.1:9200: connect: connection refused', - type: 'io', - }, - monitor: { - duration: { us: 5384 }, - id: 'auto-tcp-0X81440A68E839814C', - ip: '127.0.0.1', - name: '', - scheme: null, - status: 'down', - type: 'tcp', - }, - }, - { - id: 'id8', - timestamp: '2019-01-28T17:47:19.076Z', - http: null, - error: { - message: - 'Get http://localhost:12349/: dial tcp 127.0.0.1:12349: connect: connection refused', - type: 'io', - }, - monitor: { - duration: { us: 5397 }, - id: 'auto-http-0X3675F89EF0612091', - ip: '127.0.0.1', - name: '', - scheme: null, - status: 'down', - type: 'http', - }, - }, - { - id: 'id9', - timestamp: '2019-01-28T17:47:19.077Z', - http: { response: { status_code: 200 } }, - error: null, - monitor: { - duration: { us: 127511 }, - id: 'auto-http-0X131221E73F825974', - ip: '172.217.7.4', - name: '', - scheme: null, - status: 'up', - type: 'http', - }, - }, - { - id: 'id10', - timestamp: '2019-01-28T17:47:19.077Z', - http: { response: { status_code: 200 } }, - error: null, - monitor: { - duration: { us: 287543 }, - id: 'auto-http-0X9CB71300ABD5A2A8', - ip: '192.30.253.112', - name: '', - scheme: null, - status: 'up', - type: 'http', - }, - }, - ], - locations: ['nyc'], - }, + response = { + total: 9231, + locations: ['nyc'], + pings: [ + { + docId: 'fewjio21', + timestamp: '2019-01-28T17:47:08.078Z', + error: { + message: 'dial tcp 127.0.0.1:9200: connect: connection refused', + type: 'io', + }, + monitor: { + duration: { us: 1430 }, + id: 'auto-tcp-0X81440A68E839814F', + ip: '127.0.0.1', + name: '', + status: 'down', + type: 'tcp', + }, + }, + { + docId: 'fewjoo21', + timestamp: '2019-01-28T17:47:09.075Z', + error: { + message: 'dial tcp 127.0.0.1:9200: connect: connection refused', + type: 'io', + }, + monitor: { + duration: { us: 1370 }, + id: 'auto-tcp-0X81440A68E839814D', + ip: '127.0.0.1', + name: '', + status: 'down', + type: 'tcp', + }, + }, + { + docId: 'fejjio21', + timestamp: '2019-01-28T17:47:06.077Z', + monitor: { + duration: { us: 1452 }, + id: 'auto-tcp-0X81440A68E839814D', + ip: '127.0.0.1', + name: '', + status: 'up', + type: 'tcp', + }, + }, + { + docId: 'fewzio21', + timestamp: '2019-01-28T17:47:07.075Z', + error: { + message: 'dial tcp 127.0.0.1:9200: connect: connection refused', + type: 'io', + }, + monitor: { + duration: { us: 1094 }, + id: 'auto-tcp-0X81440A68E839814E', + ip: '127.0.0.1', + name: '', + status: 'down', + type: 'tcp', + }, + }, + { + docId: 'fewpi321', + timestamp: '2019-01-28T17:47:07.074Z', + error: { + message: + 'Get http://localhost:12349/: dial tcp 127.0.0.1:12349: connect: connection refused', + type: 'io', + }, + monitor: { + duration: { us: 1597 }, + id: 'auto-http-0X3675F89EF061209G', + ip: '127.0.0.1', + name: '', + status: 'down', + type: 'http', + }, + }, + { + docId: '0ewjio21', + timestamp: '2019-01-28T17:47:18.080Z', + error: { + message: 'dial tcp 127.0.0.1:9200: connect: connection refused', + type: 'io', + }, + monitor: { + duration: { us: 1699 }, + id: 'auto-tcp-0X81440A68E839814H', + ip: '127.0.0.1', + name: '', + status: 'down', + type: 'tcp', + }, + }, + { + docId: '3ewjio21', + timestamp: '2019-01-28T17:47:19.076Z', + error: { + message: 'dial tcp 127.0.0.1:9200: connect: connection refused', + type: 'io', + }, + monitor: { + duration: { us: 5384 }, + id: 'auto-tcp-0X81440A68E839814I', + ip: '127.0.0.1', + name: '', + status: 'down', + type: 'tcp', + }, + }, + { + docId: 'fewjip21', + timestamp: '2019-01-28T17:47:19.076Z', + error: { + message: + 'Get http://localhost:12349/: dial tcp 127.0.0.1:12349: connect: connection refused', + type: 'io', + }, + monitor: { + duration: { us: 5397 }, + id: 'auto-http-0X3675F89EF061209J', + ip: '127.0.0.1', + name: '', + status: 'down', + type: 'http', + }, + }, + { + docId: 'fewjio21', + timestamp: '2019-01-28T17:47:19.077Z', + http: { response: { status_code: 200 } }, + monitor: { + duration: { us: 127511 }, + id: 'auto-tcp-0X81440A68E839814C', + ip: '172.217.7.4', + name: '', + status: 'up', + type: 'http', + }, + }, + { + docId: 'fewjik81', + timestamp: '2019-01-28T17:47:19.077Z', + http: { response: { status_code: 200 } }, + monitor: { + duration: { us: 287543 }, + id: 'auto-http-0X131221E73F825974', + ip: '192.30.253.112', + name: '', + status: 'up', + type: 'http', + }, + }, + ], }; }); it('renders sorted list without errors', () => { - const { allPings } = pingList; const component = shallowWithIntl( {}} - onSelectedStatusChange={jest.fn()} - pageIndex={0} - pageSize={10} - selectedOption="down" - selectedLocation={AllLocationOption.value} + locations={[]} + monitorId="foo" + pings={response.pings} + total={10} /> ); expect(component).toMatchSnapshot(); @@ -224,13 +201,38 @@ describe('PingList component', () => { beforeEach(() => { itemIdToExpandedRowMap = {}; - pings = pingList.allPings.pings; + pings = response.pings; }); it('should expand an item if empty', () => { const ping = pings[0]; toggleDetails(ping, itemIdToExpandedRowMap, setItemIdToExpandedRowMap); - expect(itemIdToExpandedRowMap).toHaveProperty(ping.id); + expect(itemIdToExpandedRowMap).toMatchInlineSnapshot(` + Object { + "fewjio21": , + } + `); }); it('should un-expand an item if clicked again', () => { @@ -245,7 +247,31 @@ describe('PingList component', () => { const pingB = pings[1]; toggleDetails(pingA, itemIdToExpandedRowMap, setItemIdToExpandedRowMap); toggleDetails(pingB, itemIdToExpandedRowMap, setItemIdToExpandedRowMap); - expect(itemIdToExpandedRowMap).toHaveProperty(pingB.id); + expect(pingA.docId).not.toEqual(pingB.docId); + expect(itemIdToExpandedRowMap[pingB.docId]).toMatchInlineSnapshot(` + + `); }); }); }); diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/ping_list/expanded_row.tsx b/x-pack/legacy/plugins/uptime/public/components/functional/ping_list/expanded_row.tsx index c684235122e34b..28b96fcb1bf7b1 100644 --- a/x-pack/legacy/plugins/uptime/public/components/functional/ping_list/expanded_row.tsx +++ b/x-pack/legacy/plugins/uptime/public/components/functional/ping_list/expanded_row.tsx @@ -16,14 +16,14 @@ import { } from '@elastic/eui'; import React from 'react'; import { i18n } from '@kbn/i18n'; -import { Ping, HttpBody } from '../../../../common/graphql/types'; +import { Ping, HttpResponseBody } from '../../../../common/runtime_types'; import { DocLinkForBody } from './doc_link_body'; interface Props { ping: Ping; } -const BodyDescription = ({ body }: { body: HttpBody }) => { +const BodyDescription = ({ body }: { body: HttpResponseBody }) => { const contentBytes = body.content_bytes || 0; const bodyBytes = body.bytes || 0; diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/ping_list/index.tsx b/x-pack/legacy/plugins/uptime/public/components/functional/ping_list/index.tsx index e57b229dfd9738..808f3f90ef0150 100644 --- a/x-pack/legacy/plugins/uptime/public/components/functional/ping_list/index.tsx +++ b/x-pack/legacy/plugins/uptime/public/components/functional/ping_list/index.tsx @@ -4,4 +4,4 @@ * you may not use this file except in compliance with the Elastic License. */ -export * from './ping_list'; +export { PingListComponent } from './ping_list'; diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/ping_list/ping_list.tsx b/x-pack/legacy/plugins/uptime/public/components/functional/ping_list/ping_list.tsx index 19768c7104e91d..934dfd961f9e08 100644 --- a/x-pack/legacy/plugins/uptime/public/components/functional/ping_list/ping_list.tsx +++ b/x-pack/legacy/plugins/uptime/public/components/functional/ping_list/ping_list.tsx @@ -20,109 +20,127 @@ import { } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n/react'; -import { get } from 'lodash'; import moment from 'moment'; -import React, { Fragment, useState } from 'react'; +import React, { useState, useEffect } from 'react'; import styled from 'styled-components'; -import { CriteriaWithPagination } from '@elastic/eui/src/components/basic_table/basic_table'; -import { Ping, PingResults } from '../../../../common/graphql/types'; +import { Ping, GetPingsParams, DateRange } from '../../../../common/runtime_types'; import { convertMicrosecondsToMilliseconds as microsToMillis } from '../../../lib/helper'; -import { UptimeGraphQLQueryProps, withUptimeGraphQL } from '../../higher_order'; -import { pingsQuery } from '../../../queries'; import { LocationName } from './location_name'; import { Pagination } from './../monitor_list'; import { PingListExpandedRowComponent } from './expanded_row'; +import { PingListProps } from '../../connected/pings'; -interface PingListQueryResult { - allPings?: PingResults; -} - -interface PingListProps { - onSelectedStatusChange: (status: string | undefined) => void; - onSelectedLocationChange: (location: any) => void; - onPageCountChange: (itemCount: number) => void; - onPageIndexChange: (index: number) => void; - pageSize: number; - pageIndex: number; - selectedOption: string; - selectedLocation: string | undefined; -} - -type Props = UptimeGraphQLQueryProps & PingListProps; -interface ExpandedRowMap { - [key: string]: JSX.Element; -} - -export const AllLocationOption = { text: 'All', value: '' }; +export const AllLocationOption = { + 'data-test-subj': 'xpack.uptime.pingList.locationOptions.all', + text: 'All', + value: '', +}; export const toggleDetails = ( ping: Ping, - itemIdToExpandedRowMap: ExpandedRowMap, - setItemIdToExpandedRowMap: (update: ExpandedRowMap) => any + expandedRows: Record, + setExpandedRows: (update: Record) => any ) => { - // If the user has clicked on the expanded map, close all expanded rows. - if (itemIdToExpandedRowMap[ping.id]) { - setItemIdToExpandedRowMap({}); + // If already expanded, collapse + if (expandedRows[ping.docId]) { + delete expandedRows[ping.docId]; + setExpandedRows({ ...expandedRows }); return; } // Otherwise expand this row - const newItemIdToExpandedRowMap: ExpandedRowMap = {}; - newItemIdToExpandedRowMap[ping.id] = ; - setItemIdToExpandedRowMap(newItemIdToExpandedRowMap); + setExpandedRows({ + ...expandedRows, + [ping.docId]: , + }); }; const SpanWithMargin = styled.span` margin-right: 16px; `; -export const PingListComponent = ({ - data, - loading, - onPageCountChange, - onPageIndexChange, - onSelectedLocationChange, - onSelectedStatusChange, - pageIndex, - pageSize, - selectedOption, - selectedLocation, -}: Props) => { - const [itemIdToExpandedRowMap, setItemIdToExpandedRowMap] = useState({}); +interface Props extends PingListProps { + dateRange: DateRange; + error?: Error; + getPings: (props: GetPingsParams) => void; + lastRefresh: number; + loading: boolean; + locations: string[]; + pings: Ping[]; + total: number; +} + +const DEFAULT_PAGE_SIZE = 10; + +const statusOptions = [ + { + 'data-test-subj': 'xpack.uptime.pingList.statusOptions.all', + text: i18n.translate('xpack.uptime.pingList.statusOptions.allStatusOptionLabel', { + defaultMessage: 'All', + }), + value: '', + }, + { + 'data-test-subj': 'xpack.uptime.pingList.statusOptions.up', + text: i18n.translate('xpack.uptime.pingList.statusOptions.upStatusOptionLabel', { + defaultMessage: 'Up', + }), + value: 'up', + }, + { + 'data-test-subj': 'xpack.uptime.pingList.statusOptions.down', + text: i18n.translate('xpack.uptime.pingList.statusOptions.downStatusOptionLabel', { + defaultMessage: 'Down', + }), + value: 'down', + }, +]; + +export const PingListComponent = (props: Props) => { + const [selectedLocation, setSelectedLocation] = useState(''); + const [status, setStatus] = useState(''); + const [pageSize, setPageSize] = useState(DEFAULT_PAGE_SIZE); + const [pageIndex, setPageIndex] = useState(0); + const { + dateRange: { from, to }, + error, + getPings, + lastRefresh, + loading, + locations, + monitorId, + pings, + total, + } = props; + + useEffect(() => { + getPings({ + dateRange: { + from, + to, + }, + location: selectedLocation, + monitorId, + index: pageIndex, + size: pageSize, + status: status !== 'all' ? status : '', + }); + }, [from, to, getPings, monitorId, lastRefresh, selectedLocation, pageIndex, pageSize, status]); + + const [expandedRows, setExpandedRows] = useState>({}); - const statusOptions = [ - { - text: i18n.translate('xpack.uptime.pingList.statusOptions.allStatusOptionLabel', { - defaultMessage: 'All', - }), - value: '', - }, - { - text: i18n.translate('xpack.uptime.pingList.statusOptions.upStatusOptionLabel', { - defaultMessage: 'Up', - }), - value: 'up', - }, - { - text: i18n.translate('xpack.uptime.pingList.statusOptions.downStatusOptionLabel', { - defaultMessage: 'Down', - }), - value: 'down', - }, - ]; - const locations = get(data, 'allPings.locations'); const locationOptions = !locations ? [AllLocationOption] : [AllLocationOption].concat( - locations.map(name => { - return { text: name, value: name }; - }) + locations.map(name => ({ + text: name, + 'data-test-subj': `xpack.uptime.pingList.locationOptions.${name}`, + value: name, + })) ); - const pings: Ping[] = data?.allPings?.pings ?? []; - const hasStatus: boolean = pings.reduce( - (hasHttpStatus: boolean, currentPing: Ping) => + (hasHttpStatus: boolean, currentPing) => hasHttpStatus || !!currentPing.http?.response?.status_code, false ); @@ -134,7 +152,7 @@ export const PingListComponent = ({ defaultMessage: 'Status', }), render: (pingStatus: string, item: Ping) => ( -
+
{pingStatus === 'up' ? i18n.translate('xpack.uptime.pingList.statusColumnHealthUpLabel', { @@ -189,7 +207,7 @@ export const PingListComponent = ({ name: i18n.translate('xpack.uptime.pingList.errorTypeColumnLabel', { defaultMessage: 'Error type', }), - render: (error: string) => error ?? '-', + render: (errorType: string) => errorType ?? '-', }, // Only add this column is there is any status present in list ...(hasStatus @@ -219,16 +237,16 @@ export const PingListComponent = ({ render: (item: Ping) => { return ( toggleDetails(item, itemIdToExpandedRowMap, setItemIdToExpandedRowMap)} - disabled={!item.error && !(item.http?.response?.body?.bytes > 0)} + onClick={() => toggleDetails(item, expandedRows, setExpandedRows)} + disabled={!item.error && !(item.http?.response?.body?.bytes ?? 0 > 0)} aria-label={ - itemIdToExpandedRowMap[item.id] + expandedRows[item.docId] ? i18n.translate('xpack.uptime.pingList.collapseRow', { defaultMessage: 'Collapse', }) : i18n.translate('xpack.uptime.pingList.expandRow', { defaultMessage: 'Expand' }) } - iconType={itemIdToExpandedRowMap[item.id] ? 'arrowUp' : 'arrowDown'} + iconType={expandedRows[item.docId] ? 'arrowUp' : 'arrowDown'} /> ); }, @@ -236,104 +254,83 @@ export const PingListComponent = ({ ]; const pagination: Pagination = { - initialPageSize: 25, + initialPageSize: DEFAULT_PAGE_SIZE, pageIndex, pageSize, pageSizeOptions: [10, 25, 50, 100], - totalItemCount: data?.allPings?.total ?? pageSize, + /** + * we're not currently supporting pagination in this component + * so the first page is the only page + */ + totalItemCount: total, }; return ( - - - -

- + +

+ +

+
+ + + + + { + setStatus(selected.target.value); + }} /> -

-
- - - - - - - - - { - if (typeof selected.target.value === 'string') { - onSelectedStatusChange( - selected.target && selected.target.value !== '' - ? selected.target.value - : undefined - ); - } - }} - /> - - - - - { - onSelectedLocationChange( - selected.target && selected.target.value !== '' - ? selected.target.value - : null - ); - }} - /> - - - - - - - - - ) => { - onPageCountChange(criteria.page!.size); - onPageIndexChange(criteria.page!.index); - }} - /> -
-
+ + + + + { + setSelectedLocation(selected.target.value); + }} + /> + + + + + { + setPageSize(criteria.page!.size); + setPageIndex(criteria.page!.index); + }} + /> + ); }; - -export const PingList = withUptimeGraphQL( - PingListComponent, - pingsQuery -); diff --git a/x-pack/legacy/plugins/uptime/public/hooks/index.ts b/x-pack/legacy/plugins/uptime/public/hooks/index.ts index e022248df407a7..1f50e995eda495 100644 --- a/x-pack/legacy/plugins/uptime/public/hooks/index.ts +++ b/x-pack/legacy/plugins/uptime/public/hooks/index.ts @@ -4,6 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ +export * from './use_monitor'; export * from './use_url_params'; export * from './use_telemetry'; export * from './update_kuery_string'; diff --git a/x-pack/legacy/plugins/uptime/public/pages/monitor.tsx b/x-pack/legacy/plugins/uptime/public/pages/monitor.tsx index 5016ccebbab54d..683af81239c992 100644 --- a/x-pack/legacy/plugins/uptime/public/pages/monitor.tsx +++ b/x-pack/legacy/plugins/uptime/public/pages/monitor.tsx @@ -5,39 +5,21 @@ */ import { EuiSpacer } from '@elastic/eui'; -import React, { useContext, useState } from 'react'; +import React from 'react'; import { useSelector } from 'react-redux'; -import { MonitorCharts, PingList } from '../components/functional'; -import { UptimeRefreshContext } from '../contexts'; -import { useUptimeTelemetry, useUrlParams, UptimePage } from '../hooks'; import { useTrackPageview } from '../../../../../plugins/observability/public'; -import { MonitorStatusDetails } from '../components/connected'; +import { MonitorStatusDetails, PingList } from '../components/connected'; import { monitorStatusSelector } from '../state/selectors'; import { PageHeader } from './page_header'; +import { MonitorCharts } from '../components/functional'; import { useBreadcrumbs } from '../hooks/use_breadcrumbs'; -import { useMonitorId } from '../hooks/use_monitor'; +import { useMonitorId, useUptimeTelemetry, UptimePage } from '../hooks'; export const MonitorPage: React.FC = () => { const monitorId = useMonitorId(); - const [pingListPageCount, setPingListPageCount] = useState(10); - const { refreshApp } = useContext(UptimeRefreshContext); - const [getUrlParams, updateUrlParams] = useUrlParams(); - const { absoluteDateRangeStart, absoluteDateRangeEnd, ...params } = getUrlParams(); - const { dateRangeStart, dateRangeEnd, selectedPingStatus } = params; - - const [selectedLocation, setSelectedLocation] = useState(undefined); - const [pingListIndex, setPingListIndex] = useState(0); - const selectedMonitor = useSelector(monitorStatusSelector); - const sharedVariables = { - dateRangeStart, - dateRangeEnd, - monitorId, - location: selectedLocation, - }; - useUptimeTelemetry(UptimePage.Monitor); useTrackPageview({ app: 'uptime', path: 'monitor' }); @@ -53,25 +35,7 @@ export const MonitorPage: React.FC = () => { - { - updateUrlParams({ selectedPingStatus: selectedStatus || '' }); - refreshApp(); - }} - onPageIndexChange={(index: number) => setPingListIndex(index)} - pageIndex={pingListIndex} - pageSize={pingListPageCount} - selectedOption={selectedPingStatus} - selectedLocation={selectedLocation} - variables={{ - ...sharedVariables, - page: pingListIndex, - size: pingListPageCount, - status: selectedPingStatus, - }} - /> + ); }; diff --git a/x-pack/legacy/plugins/uptime/public/queries/pings_query.ts b/x-pack/legacy/plugins/uptime/public/queries/pings_query.ts deleted file mode 100644 index ed20fe8eb2931c..00000000000000 --- a/x-pack/legacy/plugins/uptime/public/queries/pings_query.ts +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import gql from 'graphql-tag'; - -export const pingsQueryString = ` -query PingList( - $dateRangeStart: String! - $dateRangeEnd: String! - $monitorId: String - $status: String - $sort: String - $size: Int - $location: String - $page: Int -) { - allPings( - dateRangeStart: $dateRangeStart - dateRangeEnd: $dateRangeEnd - monitorId: $monitorId - status: $status - sort: $sort - size: $size - location: $location - page: $page - ) { - total - locations - pings { - id - timestamp - http { - response { - status_code - body { - bytes - hash - content - content_bytes - } - } - } - error { - message - type - } - monitor { - duration { - us - } - id - ip - name - scheme - status - type - } - observer { - geo { - name - } - } - } - } - } -`; - -export const pingsQuery = gql` - ${pingsQueryString} -`; diff --git a/x-pack/legacy/plugins/uptime/public/state/actions/monitor_status.ts b/x-pack/legacy/plugins/uptime/public/state/actions/monitor_status.ts index a8f37d38ebae6c..e8c862e209739a 100644 --- a/x-pack/legacy/plugins/uptime/public/state/actions/monitor_status.ts +++ b/x-pack/legacy/plugins/uptime/public/state/actions/monitor_status.ts @@ -5,7 +5,7 @@ */ import { createAction } from 'redux-actions'; import { QueryParams } from './types'; -import { Ping } from '../../../common/graphql/types'; +import { Ping } from '../../../common/runtime_types'; export const getMonitorStatusAction = createAction('GET_MONITOR_STATUS'); export const getMonitorStatusActionSuccess = createAction('GET_MONITOR_STATUS_SUCCESS'); diff --git a/x-pack/legacy/plugins/uptime/public/state/actions/ping.ts b/x-pack/legacy/plugins/uptime/public/state/actions/ping.ts index bb7258d9a54b2f..70918a4cc70e56 100644 --- a/x-pack/legacy/plugins/uptime/public/state/actions/ping.ts +++ b/x-pack/legacy/plugins/uptime/public/state/actions/ping.ts @@ -5,8 +5,17 @@ */ import { createAction } from 'redux-actions'; -import { GetPingHistogramParams, HistogramResult } from '../../../common/types'; +import { + GetPingHistogramParams, + HistogramResult, + PingsResponse, + GetPingsParams, +} from '../../../common/runtime_types'; export const getPingHistogram = createAction('GET_PING_HISTOGRAM'); export const getPingHistogramSuccess = createAction('GET_PING_HISTOGRAM_SUCCESS'); export const getPingHistogramFail = createAction('GET_PING_HISTOGRAM_FAIL'); + +export const getPings = createAction('GET PINGS'); +export const getPingsSuccess = createAction('GET PINGS SUCCESS'); +export const getPingsFail = createAction('GET PINGS FAIL'); diff --git a/x-pack/legacy/plugins/uptime/public/state/api/monitor_status.ts b/x-pack/legacy/plugins/uptime/public/state/api/monitor_status.ts index f9e171adda3348..7c8ab3518b5a07 100644 --- a/x-pack/legacy/plugins/uptime/public/state/api/monitor_status.ts +++ b/x-pack/legacy/plugins/uptime/public/state/api/monitor_status.ts @@ -5,9 +5,9 @@ */ import { QueryParams } from '../actions/types'; -import { Ping } from '../../../common/graphql/types'; -import { apiService } from './utils'; +import { Ping } from '../../../common/runtime_types'; import { API_URLS } from '../../../common/constants'; +import { apiService } from './utils'; export const fetchMonitorStatus = async ({ monitorId, diff --git a/x-pack/legacy/plugins/uptime/public/state/api/ping.ts b/x-pack/legacy/plugins/uptime/public/state/api/ping.ts index df71cc8d67bd07..bbd3ddf399dcc6 100644 --- a/x-pack/legacy/plugins/uptime/public/state/api/ping.ts +++ b/x-pack/legacy/plugins/uptime/public/state/api/ping.ts @@ -5,10 +5,21 @@ */ import { APIFn } from './types'; -import { GetPingHistogramParams, HistogramResult } from '../../../common/types'; +import { + PingsResponseType, + PingsResponse, + GetPingsParams, + GetPingHistogramParams, + HistogramResult, +} from '../../../common/runtime_types'; import { apiService } from './utils'; import { API_URLS } from '../../../common/constants/rest_api'; +export const fetchPings: APIFn = async ({ + dateRange: { from, to }, + ...optional +}) => await apiService.get(API_URLS.PINGS, { from, to, ...optional }, PingsResponseType); + export const fetchPingHistogram: APIFn = async ({ monitorId, dateStart, @@ -19,9 +30,9 @@ export const fetchPingHistogram: APIFn const queryParams = { dateStart, dateEnd, - ...(monitorId && { monitorId }), - ...(statusFilter && { statusFilter }), - ...(filters && { filters }), + monitorId, + statusFilter, + filters, }; return await apiService.get(API_URLS.PING_HISTOGRAM, queryParams); diff --git a/x-pack/legacy/plugins/uptime/public/state/effects/fetch_effect.ts b/x-pack/legacy/plugins/uptime/public/state/effects/fetch_effect.ts index 49e497952ea44c..b0734cb5ccabbc 100644 --- a/x-pack/legacy/plugins/uptime/public/state/effects/fetch_effect.ts +++ b/x-pack/legacy/plugins/uptime/public/state/effects/fetch_effect.ts @@ -16,7 +16,7 @@ import { IHttpFetchError } from '../../../../../../../target/types/core/public/h * @param fail creates a failure action * @template T the action type expected by the fetch action * @template R the type that the API request should return on success - * @template S tye type of the success action + * @template S the type of the success action * @template F the type of the failure action */ export function fetchEffectFactory( diff --git a/x-pack/legacy/plugins/uptime/public/state/effects/index.ts b/x-pack/legacy/plugins/uptime/public/state/effects/index.ts index 8d457be1d1c783..8df11312b64550 100644 --- a/x-pack/legacy/plugins/uptime/public/state/effects/index.ts +++ b/x-pack/legacy/plugins/uptime/public/state/effects/index.ts @@ -11,7 +11,7 @@ import { fetchSnapshotCountEffect } from './snapshot'; import { fetchMonitorStatusEffect } from './monitor_status'; import { fetchDynamicSettingsEffect, setDynamicSettingsEffect } from './dynamic_settings'; import { fetchIndexPatternEffect } from './index_pattern'; -import { fetchPingHistogramEffect } from './ping'; +import { fetchPingsEffect, fetchPingHistogramEffect } from './ping'; import { fetchMonitorDurationEffect } from './monitor_duration'; import { fetchMLJobEffect } from './ml_anomaly'; import { fetchIndexStatusEffect } from './index_status'; @@ -24,6 +24,7 @@ export function* rootEffect() { yield fork(fetchDynamicSettingsEffect); yield fork(setDynamicSettingsEffect); yield fork(fetchIndexPatternEffect); + yield fork(fetchPingsEffect); yield fork(fetchPingHistogramEffect); yield fork(fetchMLJobEffect); yield fork(fetchMonitorDurationEffect); diff --git a/x-pack/legacy/plugins/uptime/public/state/effects/ping.ts b/x-pack/legacy/plugins/uptime/public/state/effects/ping.ts index acb9b31915fa99..dec67ed8cf9794 100644 --- a/x-pack/legacy/plugins/uptime/public/state/effects/ping.ts +++ b/x-pack/legacy/plugins/uptime/public/state/effects/ping.ts @@ -5,10 +5,21 @@ */ import { takeLatest } from 'redux-saga/effects'; -import { getPingHistogram, getPingHistogramSuccess, getPingHistogramFail } from '../actions'; -import { fetchPingHistogram } from '../api'; +import { + getPingHistogram, + getPingHistogramSuccess, + getPingHistogramFail, + getPings, + getPingsSuccess, + getPingsFail, +} from '../actions'; +import { fetchPingHistogram, fetchPings } from '../api'; import { fetchEffectFactory } from './fetch_effect'; +export function* fetchPingsEffect() { + yield takeLatest(String(getPings), fetchEffectFactory(fetchPings, getPingsSuccess, getPingsFail)); +} + export function* fetchPingHistogramEffect() { yield takeLatest( String(getPingHistogram), diff --git a/x-pack/legacy/plugins/uptime/public/state/reducers/index.ts b/x-pack/legacy/plugins/uptime/public/state/reducers/index.ts index 7bf8af5dd4d031..0a3ff35df0599f 100644 --- a/x-pack/legacy/plugins/uptime/public/state/reducers/index.ts +++ b/x-pack/legacy/plugins/uptime/public/state/reducers/index.ts @@ -13,6 +13,7 @@ import { monitorStatusReducer } from './monitor_status'; import { dynamicSettingsReducer } from './dynamic_settings'; import { indexPatternReducer } from './index_pattern'; import { pingReducer } from './ping'; +import { pingListReducer } from './ping_list'; import { monitorDurationReducer } from './monitor_duration'; import { indexStatusReducer } from './index_status'; import { mlJobsReducer } from './ml_anomaly'; @@ -26,6 +27,7 @@ export const rootReducer = combineReducers({ dynamicSettings: dynamicSettingsReducer, indexPattern: indexPatternReducer, ping: pingReducer, + pingList: pingListReducer, ml: mlJobsReducer, monitorDuration: monitorDurationReducer, indexStatus: indexStatusReducer, diff --git a/x-pack/legacy/plugins/uptime/public/state/reducers/monitor_status.ts b/x-pack/legacy/plugins/uptime/public/state/reducers/monitor_status.ts index 6cfaa9f8f59c1f..fa3e377b5ebf4f 100644 --- a/x-pack/legacy/plugins/uptime/public/state/reducers/monitor_status.ts +++ b/x-pack/legacy/plugins/uptime/public/state/reducers/monitor_status.ts @@ -9,7 +9,7 @@ import { getMonitorStatusActionSuccess, getMonitorStatusActionFail, } from '../actions'; -import { Ping } from '../../../common/graphql/types'; +import { Ping } from '../../../common/runtime_types'; import { QueryParams } from '../actions/types'; export interface MonitorStatusState { diff --git a/x-pack/legacy/plugins/uptime/public/state/reducers/ping.ts b/x-pack/legacy/plugins/uptime/public/state/reducers/ping.ts index 76775e6a0a3550..4c8715038ce360 100644 --- a/x-pack/legacy/plugins/uptime/public/state/reducers/ping.ts +++ b/x-pack/legacy/plugins/uptime/public/state/reducers/ping.ts @@ -6,7 +6,7 @@ import { handleActions, Action } from 'redux-actions'; import { getPingHistogram, getPingHistogramSuccess, getPingHistogramFail } from '../actions'; -import { HistogramResult } from '../../../common/types'; +import { HistogramResult } from '../../../common/runtime_types'; export interface PingState { pingHistogram: HistogramResult | null; diff --git a/x-pack/legacy/plugins/uptime/public/state/reducers/ping_list.ts b/x-pack/legacy/plugins/uptime/public/state/reducers/ping_list.ts new file mode 100644 index 00000000000000..e3ccb1e663edad --- /dev/null +++ b/x-pack/legacy/plugins/uptime/public/state/reducers/ping_list.ts @@ -0,0 +1,48 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { handleActions, Action } from 'redux-actions'; +import { PingsResponse } from '../../../common/runtime_types'; +import { getPings, getPingsSuccess, getPingsFail } from '../actions'; + +export interface PingListState { + pingList: PingsResponse; + error?: Error; + loading: boolean; +} + +const initialState: PingListState = { + pingList: { + total: 0, + locations: [], + pings: [], + }, + loading: false, +}; + +type PingListPayload = PingsResponse & Error; + +export const pingListReducer = handleActions( + { + [String(getPings)]: state => ({ + ...state, + loading: true, + }), + + [String(getPingsSuccess)]: (state, action: Action) => ({ + ...state, + pingList: { ...action.payload }, + loading: false, + }), + + [String(getPingsFail)]: (state, action: Action) => ({ + ...state, + error: action.payload, + loading: false, + }), + }, + initialState +); diff --git a/x-pack/legacy/plugins/uptime/public/state/selectors/__tests__/index.test.ts b/x-pack/legacy/plugins/uptime/public/state/selectors/__tests__/index.test.ts index 3b4547514a11ec..77902f347f6f93 100644 --- a/x-pack/legacy/plugins/uptime/public/state/selectors/__tests__/index.test.ts +++ b/x-pack/legacy/plugins/uptime/public/state/selectors/__tests__/index.test.ts @@ -58,6 +58,14 @@ describe('state selectors', () => { loading: false, errors: [], }, + pingList: { + loading: false, + pingList: { + total: 0, + locations: [], + pings: [], + }, + }, monitorDuration: { durationLines: null, loading: false, diff --git a/x-pack/legacy/plugins/uptime/public/state/selectors/index.ts b/x-pack/legacy/plugins/uptime/public/state/selectors/index.ts index 0fc3c7151cb3b8..37695e42743066 100644 --- a/x-pack/legacy/plugins/uptime/public/state/selectors/index.ts +++ b/x-pack/legacy/plugins/uptime/public/state/selectors/index.ts @@ -41,6 +41,11 @@ export const selectPingHistogram = ({ ping, ui }: AppState) => { }; }; +export const selectPingList = ({ pingList, ui: { lastRefresh } }: AppState) => ({ + pings: pingList, + lastRefresh, +}); + const mlCapabilitiesSelector = (state: AppState) => state.ml.mlCapabilities.data; export const hasMLFeatureAvailable = createSelector( diff --git a/x-pack/plugins/uptime/server/graphql/index.ts b/x-pack/plugins/uptime/server/graphql/index.ts index 49ba5583b417be..a88afd7ac769c8 100644 --- a/x-pack/plugins/uptime/server/graphql/index.ts +++ b/x-pack/plugins/uptime/server/graphql/index.ts @@ -5,14 +5,13 @@ */ import { createMonitorStatesResolvers, monitorStatesSchema } from './monitor_states'; -import { createPingsResolvers, pingsSchema } from './pings'; +import { pingsSchema } from './pings'; import { CreateUMGraphQLResolvers } from './types'; import { unsignedIntegerResolverFunctions, unsignedIntegerSchema } from './unsigned_int_scalar'; export { DEFAULT_GRAPHQL_PATH } from './constants'; export const resolvers: CreateUMGraphQLResolvers[] = [ createMonitorStatesResolvers, - createPingsResolvers, unsignedIntegerResolverFunctions, ]; export const typeDefs: any[] = [pingsSchema, unsignedIntegerSchema, monitorStatesSchema]; diff --git a/x-pack/plugins/uptime/server/graphql/monitor_states/schema.gql.ts b/x-pack/plugins/uptime/server/graphql/monitor_states/schema.gql.ts index 6ab564fdeb532f..040ad99ac0c640 100644 --- a/x-pack/plugins/uptime/server/graphql/monitor_states/schema.gql.ts +++ b/x-pack/plugins/uptime/server/graphql/monitor_states/schema.gql.ts @@ -169,7 +169,7 @@ export const monitorStatesSchema = gql` DESC } - extend type Query { + type Query { "Fetches the current state of Uptime monitors for the given parameters." getMonitorStates( dateRangeStart: String! diff --git a/x-pack/plugins/uptime/server/graphql/pings/index.ts b/x-pack/plugins/uptime/server/graphql/pings/index.ts index 57ec3242a7aa90..100ce29c398ec1 100644 --- a/x-pack/plugins/uptime/server/graphql/pings/index.ts +++ b/x-pack/plugins/uptime/server/graphql/pings/index.ts @@ -4,5 +4,4 @@ * you may not use this file except in compliance with the Elastic License. */ -export { createPingsResolvers } from './resolvers'; export { pingsSchema } from './schema.gql'; diff --git a/x-pack/plugins/uptime/server/graphql/pings/resolvers.ts b/x-pack/plugins/uptime/server/graphql/pings/resolvers.ts deleted file mode 100644 index 2bb1e13bc4b1f9..00000000000000 --- a/x-pack/plugins/uptime/server/graphql/pings/resolvers.ts +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import { UMResolver } from '../../../../../legacy/plugins/uptime/common/graphql/resolver_types'; -import { - AllPingsQueryArgs, - PingResults, -} from '../../../../../legacy/plugins/uptime/common/graphql/types'; -import { UMServerLibs } from '../../lib/lib'; -import { UMContext } from '../types'; -import { CreateUMGraphQLResolvers } from '../types'; -import { savedObjectsAdapter } from '../../lib/saved_objects'; - -export type UMAllPingsResolver = UMResolver< - PingResults | Promise, - any, - AllPingsQueryArgs, - UMContext ->; - -export interface UMPingResolver { - allPings: () => PingResults; -} - -export const createPingsResolvers: CreateUMGraphQLResolvers = ( - libs: UMServerLibs -): { - Query: { - allPings: UMAllPingsResolver; - }; -} => ({ - Query: { - async allPings( - _resolver, - { monitorId, sort, size, status, dateRangeStart, dateRangeEnd, location, page }, - { APICaller, savedObjectsClient } - ): Promise { - const dynamicSettings = await savedObjectsAdapter.getUptimeDynamicSettings( - savedObjectsClient - ); - - return await libs.requests.getPings({ - callES: APICaller, - dynamicSettings, - dateRangeStart, - dateRangeEnd, - monitorId, - status, - sort, - size, - location, - page, - }); - }, - }, -}); diff --git a/x-pack/plugins/uptime/server/graphql/pings/schema.gql.ts b/x-pack/plugins/uptime/server/graphql/pings/schema.gql.ts index 25767fb5441048..179bca53db1617 100644 --- a/x-pack/plugins/uptime/server/graphql/pings/schema.gql.ts +++ b/x-pack/plugins/uptime/server/graphql/pings/schema.gql.ts @@ -7,10 +7,6 @@ import gql from 'graphql-tag'; export const pingsSchema = gql` - schema { - query: Query - } - type PingResults { "Total number of matching pings" total: UnsignedInteger! @@ -20,28 +16,6 @@ export const pingsSchema = gql` pings: [Ping!]! } - type Query { - "Get a list of all recorded pings for all monitors" - allPings( - "Optional: the direction to sort by. Accepts 'asc' and 'desc'. Defaults to 'desc'." - sort: String - "Optional: the number of results to return." - size: Int - "Optional: the monitor ID filter." - monitorId: String - "Optional: the check status to filter by." - status: String - "The lower limit of the date range." - dateRangeStart: String! - "The upper limit of the date range." - dateRangeEnd: String! - "Optional: agent location to filter by." - location: String - "Optional: current page." - page: Int - ): PingResults! - } - type ContainerImage { name: String tag: String diff --git a/x-pack/plugins/uptime/server/lib/requests/__tests__/get_latest_monitor.test.ts b/x-pack/plugins/uptime/server/lib/requests/__tests__/get_latest_monitor.test.ts index 112c8e97d4c009..cf8414a3b0a68c 100644 --- a/x-pack/plugins/uptime/server/lib/requests/__tests__/get_latest_monitor.test.ts +++ b/x-pack/plugins/uptime/server/lib/requests/__tests__/get_latest_monitor.test.ts @@ -42,10 +42,16 @@ describe('getLatestMonitor', () => { hits: { hits: [ { + _id: 'fejwio32', _source: { - timestamp: 123456, + '@timestamp': '123456', monitor: { + duration: { + us: 12345, + }, id: 'testMonitor', + status: 'down', + type: 'http', }, }, }, @@ -64,7 +70,22 @@ describe('getLatestMonitor', () => { monitorId: 'testMonitor', }); - expect(result.timestamp).toBe(123456); + expect(result).toMatchInlineSnapshot(` + Object { + "@timestamp": "123456", + "docId": "fejwio32", + "monitor": Object { + "duration": Object { + "us": 12345, + }, + "id": "testMonitor", + "status": "down", + "type": "http", + }, + "timestamp": "123456", + } + `); + expect(result.timestamp).toBe('123456'); expect(result.monitor).not.toBeFalsy(); expect(result?.monitor?.id).toBe('testMonitor'); expect(mockEsClient).toHaveBeenCalledWith('search', expectedGetLatestSearchParams); diff --git a/x-pack/plugins/uptime/server/lib/requests/__tests__/get_pings.test.ts b/x-pack/plugins/uptime/server/lib/requests/__tests__/get_pings.test.ts index 9145ccca1b6d17..fcf773db23de67 100644 --- a/x-pack/plugins/uptime/server/lib/requests/__tests__/get_pings.test.ts +++ b/x-pack/plugins/uptime/server/lib/requests/__tests__/get_pings.test.ts @@ -17,16 +17,34 @@ describe('getAll', () => { { _source: { '@timestamp': '2018-10-30T18:51:59.792Z', + monitor: { + duration: { us: 2134 }, + id: 'foo', + status: 'up', + type: 'http', + }, }, }, { _source: { '@timestamp': '2018-10-30T18:53:59.792Z', + monitor: { + duration: { us: 2131 }, + id: 'foo', + status: 'up', + type: 'http', + }, }, }, { _source: { '@timestamp': '2018-10-30T18:55:59.792Z', + monitor: { + duration: { us: 2132 }, + id: 'foo', + status: 'up', + type: 'http', + }, }, }, ]; @@ -48,7 +66,7 @@ describe('getAll', () => { body: { query: { bool: { - filter: [{ range: { '@timestamp': { gte: 'now-1h', lte: 'now' } } }], + filter: [{ range: { timestamp: { gte: 'now-1h', lte: 'now' } } }], }, }, aggregations: { @@ -60,8 +78,7 @@ describe('getAll', () => { }, }, }, - sort: [{ '@timestamp': { order: 'desc' } }], - size: 12, + sort: [{ timestamp: { order: 'desc' } }], }, }; }); @@ -72,8 +89,7 @@ describe('getAll', () => { const result = await getPings({ callES: mockEsClient, dynamicSettings: defaultDynamicSettings, - dateRangeStart: 'now-1h', - dateRangeEnd: 'now', + dateRange: { from: 'now-1h', to: 'now' }, sort: 'asc', size: 12, }); @@ -95,15 +111,54 @@ describe('getAll', () => { await getPings({ callES: mockEsClient, dynamicSettings: defaultDynamicSettings, - dateRangeStart: 'now-1h', - dateRangeEnd: 'now', + dateRange: { from: 'now-1h', to: 'now' }, sort: 'asc', size: 12, }); - set(expectedGetAllParams, 'body.sort[0]', { '@timestamp': { order: 'asc' } }); + set(expectedGetAllParams, 'body.sort[0]', { timestamp: { order: 'asc' } }); expect(mockEsClient).toHaveBeenCalledTimes(1); - expect(mockEsClient).toHaveBeenCalledWith('search', expectedGetAllParams); + expect(mockEsClient.mock.calls[0]).toMatchInlineSnapshot(` + Array [ + "search", + Object { + "body": Object { + "aggregations": Object { + "locations": Object { + "terms": Object { + "field": "observer.geo.name", + "missing": "N/A", + "size": 1000, + }, + }, + }, + "query": Object { + "bool": Object { + "filter": Array [ + Object { + "range": Object { + "@timestamp": Object { + "gte": "now-1h", + "lte": "now", + }, + }, + }, + ], + }, + }, + "size": 12, + "sort": Array [ + Object { + "@timestamp": Object { + "order": "asc", + }, + }, + ], + }, + "index": "heartbeat-8*", + }, + ] + `); }); it('omits the sort param when no sort passed', async () => { @@ -112,12 +167,52 @@ describe('getAll', () => { await getPings({ callES: mockEsClient, dynamicSettings: defaultDynamicSettings, - dateRangeStart: 'now-1h', - dateRangeEnd: 'now', + dateRange: { from: 'now-1h', to: 'now' }, size: 12, }); - expect(mockEsClient).toHaveBeenCalledWith('search', expectedGetAllParams); + expect(mockEsClient).toHaveBeenCalledTimes(1); + expect(mockEsClient.mock.calls[0]).toMatchInlineSnapshot(` + Array [ + "search", + Object { + "body": Object { + "aggregations": Object { + "locations": Object { + "terms": Object { + "field": "observer.geo.name", + "missing": "N/A", + "size": 1000, + }, + }, + }, + "query": Object { + "bool": Object { + "filter": Array [ + Object { + "range": Object { + "@timestamp": Object { + "gte": "now-1h", + "lte": "now", + }, + }, + }, + ], + }, + }, + "size": 12, + "sort": Array [ + Object { + "@timestamp": Object { + "order": "desc", + }, + }, + ], + }, + "index": "heartbeat-8*", + }, + ] + `); }); it('omits the size param when no size passed', async () => { @@ -126,14 +221,52 @@ describe('getAll', () => { await getPings({ callES: mockEsClient, dynamicSettings: defaultDynamicSettings, - dateRangeStart: 'now-1h', - dateRangeEnd: 'now', + dateRange: { from: 'now-1h', to: 'now' }, sort: 'desc', }); - delete expectedGetAllParams.body.size; - set(expectedGetAllParams, 'body.sort[0].@timestamp.order', 'desc'); - expect(mockEsClient).toHaveBeenCalledWith('search', expectedGetAllParams); + expect(mockEsClient).toHaveBeenCalledTimes(1); + expect(mockEsClient.mock.calls[0]).toMatchInlineSnapshot(` + Array [ + "search", + Object { + "body": Object { + "aggregations": Object { + "locations": Object { + "terms": Object { + "field": "observer.geo.name", + "missing": "N/A", + "size": 1000, + }, + }, + }, + "query": Object { + "bool": Object { + "filter": Array [ + Object { + "range": Object { + "@timestamp": Object { + "gte": "now-1h", + "lte": "now", + }, + }, + }, + ], + }, + }, + "size": 25, + "sort": Array [ + Object { + "@timestamp": Object { + "order": "desc", + }, + }, + ], + }, + "index": "heartbeat-8*", + }, + ] + `); }); it('adds a filter for monitor ID', async () => { @@ -142,14 +275,57 @@ describe('getAll', () => { await getPings({ callES: mockEsClient, dynamicSettings: defaultDynamicSettings, - dateRangeStart: 'now-1h', - dateRangeEnd: 'now', + dateRange: { from: 'now-1h', to: 'now' }, monitorId: 'testmonitorid', }); - delete expectedGetAllParams.body.size; - expectedGetAllParams.body.query.bool.filter.push({ term: { 'monitor.id': 'testmonitorid' } }); - expect(mockEsClient).toHaveBeenCalledWith('search', expectedGetAllParams); + expect(mockEsClient).toHaveBeenCalledTimes(1); + expect(mockEsClient.mock.calls[0]).toMatchInlineSnapshot(` + Array [ + "search", + Object { + "body": Object { + "aggregations": Object { + "locations": Object { + "terms": Object { + "field": "observer.geo.name", + "missing": "N/A", + "size": 1000, + }, + }, + }, + "query": Object { + "bool": Object { + "filter": Array [ + Object { + "range": Object { + "@timestamp": Object { + "gte": "now-1h", + "lte": "now", + }, + }, + }, + Object { + "term": Object { + "monitor.id": "testmonitorid", + }, + }, + ], + }, + }, + "size": 25, + "sort": Array [ + Object { + "@timestamp": Object { + "order": "desc", + }, + }, + ], + }, + "index": "heartbeat-8*", + }, + ] + `); }); it('adds a filter for monitor status', async () => { @@ -158,13 +334,56 @@ describe('getAll', () => { await getPings({ callES: mockEsClient, dynamicSettings: defaultDynamicSettings, - dateRangeStart: 'now-1h', - dateRangeEnd: 'now', + dateRange: { from: 'now-1h', to: 'now' }, status: 'down', }); - delete expectedGetAllParams.body.size; - expectedGetAllParams.body.query.bool.filter.push({ term: { 'monitor.status': 'down' } }); - expect(mockEsClient).toHaveBeenCalledWith('search', expectedGetAllParams); + expect(mockEsClient).toHaveBeenCalledTimes(1); + expect(mockEsClient.mock.calls[0]).toMatchInlineSnapshot(` + Array [ + "search", + Object { + "body": Object { + "aggregations": Object { + "locations": Object { + "terms": Object { + "field": "observer.geo.name", + "missing": "N/A", + "size": 1000, + }, + }, + }, + "query": Object { + "bool": Object { + "filter": Array [ + Object { + "range": Object { + "@timestamp": Object { + "gte": "now-1h", + "lte": "now", + }, + }, + }, + Object { + "term": Object { + "monitor.status": "down", + }, + }, + ], + }, + }, + "size": 25, + "sort": Array [ + Object { + "@timestamp": Object { + "order": "desc", + }, + }, + ], + }, + "index": "heartbeat-8*", + }, + ] + `); }); }); diff --git a/x-pack/plugins/uptime/server/lib/requests/get_latest_monitor.ts b/x-pack/plugins/uptime/server/lib/requests/get_latest_monitor.ts index 299e3eb6ca3cf9..a8e9ccb875a08c 100644 --- a/x-pack/plugins/uptime/server/lib/requests/get_latest_monitor.ts +++ b/x-pack/plugins/uptime/server/lib/requests/get_latest_monitor.ts @@ -5,7 +5,7 @@ */ import { UMElasticsearchQueryFn } from '../adapters'; -import { Ping } from '../../../../../legacy/plugins/uptime/common/graphql/types'; +import { Ping } from '../../../../../legacy/plugins/uptime/common/runtime_types'; export interface GetLatestMonitorParams { /** @member dateRangeStart timestamp bounds */ @@ -53,11 +53,9 @@ export const getLatestMonitor: UMElasticsearchQueryFn = async ({ +export const getPings: UMElasticsearchQueryFn = async ({ callES, dynamicSettings, - dateRangeStart, - dateRangeEnd, + dateRange: { from, to }, + index, monitorId, status, sort, - size, + size: sizeParam, location, - page, }) => { + const size = sizeParam ?? DEFAULT_PAGE_SIZE; const sortParam = { sort: [{ '@timestamp': { order: sort ?? 'desc' } }] }; - const sizeParam = size ? { size } : undefined; - const filter: any[] = [{ range: { '@timestamp': { gte: dateRangeStart, lte: dateRangeEnd } } }]; + const filter: any[] = [{ range: { '@timestamp': { gte: from, lte: to } } }]; if (monitorId) { filter.push({ term: { 'monitor.id': monitorId } }); } @@ -71,7 +47,7 @@ export const getPings: UMElasticsearchQueryFn = asy ...queryContext, }, ...sortParam, - ...sizeParam, + size, aggregations: { locations: { terms: { @@ -85,8 +61,8 @@ export const getPings: UMElasticsearchQueryFn = asy }, }; - if (page) { - params.body.from = page * (size ?? 25); + if (index) { + params.body.from = index * size; } const { @@ -96,25 +72,22 @@ export const getPings: UMElasticsearchQueryFn = asy const locations = aggs?.locations ?? { buckets: [{ key: 'N/A', doc_count: 0 }] }; - const pings: Ping[] = hits.map(({ _id, _source }: any) => { - const timestamp = _source['@timestamp']; - + const pings: Ping[] = hits.map((doc: any) => { + const { _id, _source } = doc; // Calculate here the length of the content string in bytes, this is easier than in client JS, where // we don't have access to Buffer.byteLength. There are some hacky ways to do this in the // client but this is cleaner. - const httpBody: HttpBody | undefined = _source?.http?.response?.body; + const httpBody: HttpResponseBody | undefined = _source?.http?.response?.body; if (httpBody && httpBody.content) { httpBody.content_bytes = Buffer.byteLength(httpBody.content); } - return { id: _id, timestamp, ..._source }; + return { ..._source, timestamp: _source['@timestamp'], docId: _id }; }); - const results: PingResults = { + return { total: total.value, locations: locations.buckets.map((bucket: { key: string }) => bucket.key), pings, }; - - return results; }; diff --git a/x-pack/plugins/uptime/server/lib/requests/index.ts b/x-pack/plugins/uptime/server/lib/requests/index.ts index 445adc3c15a930..6317f665d377f4 100644 --- a/x-pack/plugins/uptime/server/lib/requests/index.ts +++ b/x-pack/plugins/uptime/server/lib/requests/index.ts @@ -13,7 +13,7 @@ export { getMonitorLocations, GetMonitorLocationsParams } from './get_monitor_lo export { getMonitorStates, GetMonitorStatesParams } from './get_monitor_states'; export { getMonitorStatus, GetMonitorStatusParams } from './get_monitor_status'; export * from './get_monitor_status'; -export { getPings, GetPingsParams } from './get_pings'; +export { getPings } from './get_pings'; export { getPingHistogram, GetPingHistogramParams } from './get_ping_histogram'; export { UptimeRequests } from './uptime_requests'; export { getSnapshotCount, GetSnapshotCountParams } from './get_snapshot_counts'; diff --git a/x-pack/plugins/uptime/server/lib/requests/types.ts b/x-pack/plugins/uptime/server/lib/requests/types.ts deleted file mode 100644 index 53a4e989e37893..00000000000000 --- a/x-pack/plugins/uptime/server/lib/requests/types.ts +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import { Ping, PingResults } from '../../../../../legacy/plugins/uptime/common/graphql/types'; -import { UMElasticsearchQueryFn } from '../adapters'; -import { - GetPingHistogramParams, - HistogramResult, -} from '../../../../../legacy/plugins/uptime/common/types'; - -export interface GetAllParams { - /** @member dateRangeStart timestamp bounds */ - dateRangeStart: string; - - /** @member dateRangeEnd timestamp bounds */ - dateRangeEnd: string; - - /** @member monitorId optional limit by monitorId */ - monitorId?: string | null; - - /** @member status optional limit by check statuses */ - status?: string | null; - - /** @member sort optional sort by timestamp */ - sort?: string | null; - - /** @member size optional limit query size */ - size?: number | null; - - /** @member location optional location value for use in filtering*/ - location?: string | null; -} - -export interface GetLatestMonitorDocsParams { - /** @member dateRangeStart timestamp bounds */ - dateStart?: string; - - /** @member dateRangeEnd timestamp bounds */ - dateEnd?: string; - - /** @member monitorId optional limit to monitorId */ - monitorId?: string | null; -} - -/** - * Count the number of documents in heartbeat indices - */ -export interface UMPingsAdapter { - getAll: UMElasticsearchQueryFn; - - // Get the monitor meta info regardless of timestamp - getMonitor: UMElasticsearchQueryFn; - - getLatestMonitorStatus: UMElasticsearchQueryFn; - - getPingHistogram: UMElasticsearchQueryFn; -} - -export interface HistogramQueryResult { - key: number; - key_as_string: string; - doc_count: number; - down: { - doc_count: number; - }; - up: { - doc_count: number; - }; -} diff --git a/x-pack/plugins/uptime/server/lib/requests/uptime_requests.ts b/x-pack/plugins/uptime/server/lib/requests/uptime_requests.ts index 9d3fa5aa08aedb..e9a7aa94dd3aa8 100644 --- a/x-pack/plugins/uptime/server/lib/requests/uptime_requests.ts +++ b/x-pack/plugins/uptime/server/lib/requests/uptime_requests.ts @@ -5,7 +5,12 @@ */ import { UMElasticsearchQueryFn } from '../adapters'; -import { Ping, PingResults } from '../../../../../legacy/plugins/uptime/common/graphql/types'; +import { + HistogramResult, + Ping, + PingsResponse as PingResults, + GetPingsParams, +} from '../../../../../legacy/plugins/uptime/common/runtime_types'; import { GetFilterBarParams, GetLatestMonitorParams, @@ -13,7 +18,6 @@ import { GetMonitorDetailsParams, GetMonitorLocationsParams, GetMonitorStatesParams, - GetPingsParams, GetPingHistogramParams, GetMonitorStatusParams, GetMonitorStatusResult, @@ -27,10 +31,7 @@ import { } from '../../../../../legacy/plugins/uptime/common/runtime_types'; import { GetMonitorStatesResult } from './get_monitor_states'; import { GetSnapshotCountParams } from './get_snapshot_counts'; -import { - HistogramResult, - MonitorDurationResult, -} from '../../../../../legacy/plugins/uptime/common/types'; +import { MonitorDurationResult } from '../../../../../legacy/plugins/uptime/common/types'; type ESQ = UMElasticsearchQueryFn; diff --git a/x-pack/plugins/uptime/server/rest_api/index.ts b/x-pack/plugins/uptime/server/rest_api/index.ts index c84ea71037953e..c0412e588fa93a 100644 --- a/x-pack/plugins/uptime/server/rest_api/index.ts +++ b/x-pack/plugins/uptime/server/rest_api/index.ts @@ -5,7 +5,7 @@ */ import { createGetOverviewFilters } from './overview_filters'; -import { createGetPingsRoute } from './pings'; +import { createGetPingHistogramRoute, createGetPingsRoute } from './pings'; import { createGetDynamicSettingsRoute, createPostDynamicSettingsRoute } from './dynamic_settings'; import { createLogPageViewRoute } from './telemetry'; import { createGetSnapshotCount } from './snapshot'; @@ -15,10 +15,8 @@ import { createGetMonitorLocationsRoute, createGetStatusBarRoute, } from './monitors'; -import { createGetPingHistogramRoute } from './pings/get_ping_histogram'; import { createGetMonitorDurationRoute } from './monitors/monitors_durations'; import { createGetIndexPatternRoute, createGetIndexStatusRoute } from './index_state'; - export * from './types'; export { createRouteWithAuth } from './create_route_with_auth'; export { uptimeRouteWrapper } from './uptime_route_wrapper'; diff --git a/x-pack/plugins/uptime/server/rest_api/pings/get_all.ts b/x-pack/plugins/uptime/server/rest_api/pings/get_all.ts deleted file mode 100644 index c76892103da6b7..00000000000000 --- a/x-pack/plugins/uptime/server/rest_api/pings/get_all.ts +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import { schema } from '@kbn/config-schema'; -import { UMServerLibs } from '../../lib/lib'; -import { UMRestApiRouteFactory } from '../types'; -import { API_URLS } from '../../../../../legacy/plugins/uptime/common/constants/rest_api'; - -export const createGetAllRoute: UMRestApiRouteFactory = (libs: UMServerLibs) => ({ - method: 'GET', - path: API_URLS.PINGS, - validate: { - query: schema.object({ - dateRangeStart: schema.string(), - dateRangeEnd: schema.string(), - location: schema.maybe(schema.string()), - monitorId: schema.maybe(schema.string()), - size: schema.maybe(schema.number()), - sort: schema.maybe(schema.string()), - status: schema.maybe(schema.string()), - }), - }, - handler: async ({ callES, dynamicSettings }, _context, request, response): Promise => { - const { dateRangeStart, dateRangeEnd, location, monitorId, size, sort, status } = request.query; - - const result = await libs.requests.getPings({ - callES, - dynamicSettings, - dateRangeStart, - dateRangeEnd, - monitorId, - status, - sort, - size, - location, - }); - - return response.ok({ - body: { - ...result, - }, - }); - }, -}); diff --git a/x-pack/plugins/uptime/server/rest_api/pings/get_pings.ts b/x-pack/plugins/uptime/server/rest_api/pings/get_pings.ts index cde9a8c4e47ead..80a887a7f64a9d 100644 --- a/x-pack/plugins/uptime/server/rest_api/pings/get_pings.ts +++ b/x-pack/plugins/uptime/server/rest_api/pings/get_pings.ts @@ -5,37 +5,41 @@ */ import { schema } from '@kbn/config-schema'; +import { isLeft } from 'fp-ts/lib/Either'; +import { PathReporter } from 'io-ts/lib/PathReporter'; import { UMServerLibs } from '../../lib/lib'; import { UMRestApiRouteFactory } from '../types'; import { API_URLS } from '../../../../../legacy/plugins/uptime/common/constants/rest_api'; +import { GetPingsParamsType } from '../../../../../legacy/plugins/uptime/common/runtime_types'; export const createGetPingsRoute: UMRestApiRouteFactory = (libs: UMServerLibs) => ({ method: 'GET', path: API_URLS.PINGS, validate: { query: schema.object({ - dateRangeStart: schema.string(), - dateRangeEnd: schema.string(), + from: schema.string(), + to: schema.string(), location: schema.maybe(schema.string()), monitorId: schema.maybe(schema.string()), + index: schema.maybe(schema.number()), size: schema.maybe(schema.number()), sort: schema.maybe(schema.string()), status: schema.maybe(schema.string()), }), }, handler: async ({ callES, dynamicSettings }, _context, request, response): Promise => { - const { dateRangeStart, dateRangeEnd, location, monitorId, size, sort, status } = request.query; + const { from, to, ...optional } = request.query; + const params = GetPingsParamsType.decode({ dateRange: { from, to }, ...optional }); + if (isLeft(params)) { + // eslint-disable-next-line no-console + console.error(new Error(PathReporter.report(params).join(';'))); + return response.badRequest({ body: { message: 'Received invalid request parameters.' } }); + } const result = await libs.requests.getPings({ callES, dynamicSettings, - dateRangeStart, - dateRangeEnd, - monitorId, - status, - sort, - size, - location, + ...params.right, }); return response.ok({ diff --git a/x-pack/plugins/uptime/server/rest_api/pings/index.ts b/x-pack/plugins/uptime/server/rest_api/pings/index.ts index abb7da26f994f0..a10ab435e4b0a3 100644 --- a/x-pack/plugins/uptime/server/rest_api/pings/index.ts +++ b/x-pack/plugins/uptime/server/rest_api/pings/index.ts @@ -5,3 +5,4 @@ */ export { createGetPingsRoute } from './get_pings'; +export { createGetPingHistogramRoute } from './get_ping_histogram'; diff --git a/x-pack/test/api_integration/apis/uptime/feature_controls.ts b/x-pack/test/api_integration/apis/uptime/feature_controls.ts index 4c3b7f97c9544f..8b82735fc38b05 100644 --- a/x-pack/test/api_integration/apis/uptime/feature_controls.ts +++ b/x-pack/test/api_integration/apis/uptime/feature_controls.ts @@ -40,7 +40,7 @@ export default function featureControlsTests({ getService }: FtrProviderContext) const executePingsRequest = async (username: string, password: string, spaceId?: string) => { const basePath = spaceId ? `/s/${spaceId}` : ''; - const url = `${basePath}${API_URLS.PINGS}?sort=desc&dateRangeStart=${PINGS_DATE_RANGE_START}&dateRangeEnd=${PINGS_DATE_RANGE_END}`; + const url = `${basePath}${API_URLS.PINGS}?sort=desc&from=${PINGS_DATE_RANGE_START}&to=${PINGS_DATE_RANGE_END}`; return await supertest .get(url) .auth(username, password) diff --git a/x-pack/test/api_integration/apis/uptime/get_all_pings.ts b/x-pack/test/api_integration/apis/uptime/get_all_pings.ts index 666986e7008b7c..0b3f5faccb044d 100644 --- a/x-pack/test/api_integration/apis/uptime/get_all_pings.ts +++ b/x-pack/test/api_integration/apis/uptime/get_all_pings.ts @@ -22,7 +22,7 @@ export default function({ getService }: FtrProviderContext) { it('should get all pings stored in index', async () => { const { body: apiResponse } = await supertest .get( - `/api/uptime/pings?sort=desc&dateRangeStart=${PINGS_DATE_RANGE_START}&dateRangeEnd=${PINGS_DATE_RANGE_END}` + `/api/uptime/pings?sort=desc&from=${PINGS_DATE_RANGE_START}&to=${PINGS_DATE_RANGE_END}` ) .expect(200); @@ -33,21 +33,19 @@ export default function({ getService }: FtrProviderContext) { it('should sort pings according to timestamp', async () => { const { body: apiResponse } = await supertest - .get( - `/api/uptime/pings?sort=asc&dateRangeStart=${PINGS_DATE_RANGE_START}&dateRangeEnd=${PINGS_DATE_RANGE_END}` - ) + .get(`/api/uptime/pings?sort=asc&from=${PINGS_DATE_RANGE_START}&to=${PINGS_DATE_RANGE_END}`) .expect(200); expect(apiResponse.total).to.be(2); expect(apiResponse.pings.length).to.be(2); - expect(apiResponse.pings[0].timestamp).to.be('2018-10-30T14:49:23.889Z'); - expect(apiResponse.pings[1].timestamp).to.be('2018-10-30T18:51:56.792Z'); + expect(apiResponse.pings[0]['@timestamp']).to.be('2018-10-30T14:49:23.889Z'); + expect(apiResponse.pings[1]['@timestamp']).to.be('2018-10-30T18:51:56.792Z'); }); it('should return results of n length', async () => { const { body: apiResponse } = await supertest .get( - `/api/uptime/pings?sort=desc&size=1&dateRangeStart=${PINGS_DATE_RANGE_START}&dateRangeEnd=${PINGS_DATE_RANGE_END}` + `/api/uptime/pings?sort=desc&size=1&from=${PINGS_DATE_RANGE_START}&to=${PINGS_DATE_RANGE_END}` ) .expect(200); @@ -57,10 +55,10 @@ export default function({ getService }: FtrProviderContext) { }); it('should miss pings outside of date range', async () => { - const dateRangeStart = moment('2002-01-01').valueOf(); - const dateRangeEnd = moment('2002-01-02').valueOf(); + const from = moment('2002-01-01').valueOf(); + const to = moment('2002-01-02').valueOf(); const { body: apiResponse } = await supertest - .get(`/api/uptime/pings?dateRangeStart=${dateRangeStart}&dateRangeEnd=${dateRangeEnd}`) + .get(`/api/uptime/pings?from=${from}&to=${to}`) .expect(200); expect(apiResponse.total).to.be(0); diff --git a/x-pack/test/api_integration/apis/uptime/graphql/fixtures/ping_list.json b/x-pack/test/api_integration/apis/uptime/graphql/fixtures/ping_list.json deleted file mode 100644 index 330ec83931a62b..00000000000000 --- a/x-pack/test/api_integration/apis/uptime/graphql/fixtures/ping_list.json +++ /dev/null @@ -1,320 +0,0 @@ -{ - "allPings": { - "total": 2000, - "locations": [ - "mpls" - ], - "pings": [ - { - "timestamp": "2019-09-11T03:40:34.410Z", - "http": { - "response": { - "status_code": 200, - "body": { - "bytes": 3, - "hash": "27badc983df1780b60c2b3fa9d3a19a00e46aac798451f0febdca52920faaddf", - "content": null, - "content_bytes": null - } - } - }, - "error": null, - "monitor": { - "duration": { - "us": 413 - }, - "id": "0074-up", - "ip": "127.0.0.1", - "name": "", - "scheme": null, - "status": "up", - "type": "http" - }, - "observer": { - "geo": { - "name": "mpls" - } - } - }, - { - "timestamp": "2019-09-11T03:40:34.406Z", - "http": { - "response": { - "status_code": 200, - "body": { - "bytes": 3, - "hash": "27badc983df1780b60c2b3fa9d3a19a00e46aac798451f0febdca52920faaddf", - "content": null, - "content_bytes": null - } - } - }, - "error": null, - "monitor": { - "duration": { - "us": 441 - }, - "id": "0073-up", - "ip": "127.0.0.1", - "name": "", - "scheme": null, - "status": "up", - "type": "http" - }, - "observer": { - "geo": { - "name": "mpls" - } - } - }, - { - "timestamp": "2019-09-11T03:40:34.406Z", - "http": { - "response": { - "status_code": 200, - "body": { - "bytes": 3, - "hash": "27badc983df1780b60c2b3fa9d3a19a00e46aac798451f0febdca52920faaddf", - "content": null, - "content_bytes": null - } - } - }, - "error": null, - "monitor": { - "duration": { - "us": 482 - }, - "id": "0099-up", - "ip": "127.0.0.1", - "name": "", - "scheme": null, - "status": "up", - "type": "http" - }, - "observer": { - "geo": { - "name": "mpls" - } - } - }, - { - "timestamp": "2019-09-11T03:40:34.406Z", - "http": { - "response": { - "status_code": 200, - "body": { - "bytes": 3, - "hash": "27badc983df1780b60c2b3fa9d3a19a00e46aac798451f0febdca52920faaddf", - "content": null, - "content_bytes": null - } - } - }, - "error": null, - "monitor": { - "duration": { - "us": 558 - }, - "id": "0098-up", - "ip": "127.0.0.1", - "name": "", - "scheme": null, - "status": "up", - "type": "http" - }, - "observer": { - "geo": { - "name": "mpls" - } - } - }, - { - "timestamp": "2019-09-11T03:40:34.406Z", - "http": { - "response": { - "status_code": 200, - "body": { - "bytes": 3, - "hash": "27badc983df1780b60c2b3fa9d3a19a00e46aac798451f0febdca52920faaddf", - "content": null, - "content_bytes": null - } - } - }, - "error": null, - "monitor": { - "duration": { - "us": 304 - }, - "id": "0075-intermittent", - "ip": "127.0.0.1", - "name": "", - "scheme": null, - "status": "up", - "type": "http" - }, - "observer": { - "geo": { - "name": "mpls" - } - } - }, - { - "timestamp": "2019-09-11T03:40:34.405Z", - "http": { - "response": { - "status_code": 200, - "body": { - "bytes": 3, - "hash": "27badc983df1780b60c2b3fa9d3a19a00e46aac798451f0febdca52920faaddf", - "content": null, - "content_bytes": null - } - } - }, - "error": null, - "monitor": { - "duration": { - "us": 487 - }, - "id": "0097-up", - "ip": "127.0.0.1", - "name": "", - "scheme": null, - "status": "up", - "type": "http" - }, - "observer": { - "geo": { - "name": "mpls" - } - } - }, - { - "timestamp": "2019-09-11T03:40:34.405Z", - "http": { - "response": { - "status_code": 200, - "body": { - "bytes": 3, - "hash": "27badc983df1780b60c2b3fa9d3a19a00e46aac798451f0febdca52920faaddf", - "content": null, - "content_bytes": null - } - } - }, - "error": null, - "monitor": { - "duration": { - "us": 602 - }, - "id": "0049-up", - "ip": "127.0.0.1", - "name": "", - "scheme": null, - "status": "up", - "type": "http" - }, - "observer": { - "geo": { - "name": "mpls" - } - } - }, - { - "timestamp": "2019-09-11T03:40:34.390Z", - "http": { - "response": { - "status_code": 200, - "body": { - "bytes": 3, - "hash": "27badc983df1780b60c2b3fa9d3a19a00e46aac798451f0febdca52920faaddf", - "content": null, - "content_bytes": null - } - } - }, - "error": null, - "monitor": { - "duration": { - "us": 365 - }, - "id": "0047-up", - "ip": "127.0.0.1", - "name": "", - "scheme": null, - "status": "up", - "type": "http" - }, - "observer": { - "geo": { - "name": "mpls" - } - } - }, - { - "timestamp": "2019-09-11T03:40:34.389Z", - "http": { - "response": { - "status_code": 200, - "body": { - "bytes": 3, - "hash": "27badc983df1780b60c2b3fa9d3a19a00e46aac798451f0febdca52920faaddf", - "content": null, - "content_bytes": null - } - } - }, - "error": null, - "monitor": { - "duration": { - "us": 870 - }, - "id": "0077-up", - "ip": "127.0.0.1", - "name": "", - "scheme": null, - "status": "up", - "type": "http" - }, - "observer": { - "geo": { - "name": "mpls" - } - } - }, - { - "timestamp": "2019-09-11T03:40:34.387Z", - "http": { - "response": { - "status_code": 200, - "body": { - "bytes": 3, - "hash": "27badc983df1780b60c2b3fa9d3a19a00e46aac798451f0febdca52920faaddf", - "content": null, - "content_bytes": null - } - } - }, - "error": null, - "monitor": { - "duration": { - "us": 2808 - }, - "id": "0076-up", - "ip": "127.0.0.1", - "name": "", - "scheme": null, - "status": "up", - "type": "http" - }, - "observer": { - "geo": { - "name": "mpls" - } - } - } - ] - } -} \ No newline at end of file diff --git a/x-pack/test/api_integration/apis/uptime/graphql/fixtures/ping_list_count.json b/x-pack/test/api_integration/apis/uptime/graphql/fixtures/ping_list_count.json deleted file mode 100644 index 3a619f517626ad..00000000000000 --- a/x-pack/test/api_integration/apis/uptime/graphql/fixtures/ping_list_count.json +++ /dev/null @@ -1,1569 +0,0 @@ -{ - "allPings": { - "total": 2000, - "locations": [ - "mpls" - ], - "pings": [ - { - "timestamp": "2019-09-11T03:40:34.410Z", - "http": { - "response": { - "status_code": 200, - "body": { - "bytes": 3, - "hash": "27badc983df1780b60c2b3fa9d3a19a00e46aac798451f0febdca52920faaddf", - "content": null, - "content_bytes": null - } - } - }, - "error": null, - "monitor": { - "duration": { - "us": 413 - }, - "id": "0074-up", - "ip": "127.0.0.1", - "name": "", - "scheme": null, - "status": "up", - "type": "http" - }, - "observer": { - "geo": { - "name": "mpls" - } - } - }, - { - "timestamp": "2019-09-11T03:40:34.406Z", - "http": { - "response": { - "status_code": 200, - "body": { - "bytes": 3, - "hash": "27badc983df1780b60c2b3fa9d3a19a00e46aac798451f0febdca52920faaddf", - "content": null, - "content_bytes": null - } - } - }, - "error": null, - "monitor": { - "duration": { - "us": 441 - }, - "id": "0073-up", - "ip": "127.0.0.1", - "name": "", - "scheme": null, - "status": "up", - "type": "http" - }, - "observer": { - "geo": { - "name": "mpls" - } - } - }, - { - "timestamp": "2019-09-11T03:40:34.406Z", - "http": { - "response": { - "status_code": 200, - "body": { - "bytes": 3, - "hash": "27badc983df1780b60c2b3fa9d3a19a00e46aac798451f0febdca52920faaddf", - "content": null, - "content_bytes": null - } - } - }, - "error": null, - "monitor": { - "duration": { - "us": 482 - }, - "id": "0099-up", - "ip": "127.0.0.1", - "name": "", - "scheme": null, - "status": "up", - "type": "http" - }, - "observer": { - "geo": { - "name": "mpls" - } - } - }, - { - "timestamp": "2019-09-11T03:40:34.406Z", - "http": { - "response": { - "status_code": 200, - "body": { - "bytes": 3, - "hash": "27badc983df1780b60c2b3fa9d3a19a00e46aac798451f0febdca52920faaddf", - "content": null, - "content_bytes": null - } - } - }, - "error": null, - "monitor": { - "duration": { - "us": 558 - }, - "id": "0098-up", - "ip": "127.0.0.1", - "name": "", - "scheme": null, - "status": "up", - "type": "http" - }, - "observer": { - "geo": { - "name": "mpls" - } - } - }, - { - "timestamp": "2019-09-11T03:40:34.406Z", - "http": { - "response": { - "status_code": 200, - "body": { - "bytes": 3, - "hash": "27badc983df1780b60c2b3fa9d3a19a00e46aac798451f0febdca52920faaddf", - "content": null, - "content_bytes": null - } - } - }, - "error": null, - "monitor": { - "duration": { - "us": 304 - }, - "id": "0075-intermittent", - "ip": "127.0.0.1", - "name": "", - "scheme": null, - "status": "up", - "type": "http" - }, - "observer": { - "geo": { - "name": "mpls" - } - } - }, - { - "timestamp": "2019-09-11T03:40:34.405Z", - "http": { - "response": { - "status_code": 200, - "body": { - "bytes": 3, - "hash": "27badc983df1780b60c2b3fa9d3a19a00e46aac798451f0febdca52920faaddf", - "content": null, - "content_bytes": null - } - } - }, - "error": null, - "monitor": { - "duration": { - "us": 487 - }, - "id": "0097-up", - "ip": "127.0.0.1", - "name": "", - "scheme": null, - "status": "up", - "type": "http" - }, - "observer": { - "geo": { - "name": "mpls" - } - } - }, - { - "timestamp": "2019-09-11T03:40:34.405Z", - "http": { - "response": { - "status_code": 200, - "body": { - "bytes": 3, - "hash": "27badc983df1780b60c2b3fa9d3a19a00e46aac798451f0febdca52920faaddf", - "content": null, - "content_bytes": null - } - } - }, - "error": null, - "monitor": { - "duration": { - "us": 602 - }, - "id": "0049-up", - "ip": "127.0.0.1", - "name": "", - "scheme": null, - "status": "up", - "type": "http" - }, - "observer": { - "geo": { - "name": "mpls" - } - } - }, - { - "timestamp": "2019-09-11T03:40:34.390Z", - "http": { - "response": { - "status_code": 200, - "body": { - "bytes": 3, - "hash": "27badc983df1780b60c2b3fa9d3a19a00e46aac798451f0febdca52920faaddf", - "content": null, - "content_bytes": null - } - } - }, - "error": null, - "monitor": { - "duration": { - "us": 365 - }, - "id": "0047-up", - "ip": "127.0.0.1", - "name": "", - "scheme": null, - "status": "up", - "type": "http" - }, - "observer": { - "geo": { - "name": "mpls" - } - } - }, - { - "timestamp": "2019-09-11T03:40:34.389Z", - "http": { - "response": { - "status_code": 200, - "body": { - "bytes": 3, - "hash": "27badc983df1780b60c2b3fa9d3a19a00e46aac798451f0febdca52920faaddf", - "content": null, - "content_bytes": null - } - } - }, - "error": null, - "monitor": { - "duration": { - "us": 870 - }, - "id": "0077-up", - "ip": "127.0.0.1", - "name": "", - "scheme": null, - "status": "up", - "type": "http" - }, - "observer": { - "geo": { - "name": "mpls" - } - } - }, - { - "timestamp": "2019-09-11T03:40:34.387Z", - "http": { - "response": { - "status_code": 200, - "body": { - "bytes": 3, - "hash": "27badc983df1780b60c2b3fa9d3a19a00e46aac798451f0febdca52920faaddf", - "content": null, - "content_bytes": null - } - } - }, - "error": null, - "monitor": { - "duration": { - "us": 2808 - }, - "id": "0076-up", - "ip": "127.0.0.1", - "name": "", - "scheme": null, - "status": "up", - "type": "http" - }, - "observer": { - "geo": { - "name": "mpls" - } - } - }, - { - "timestamp": "2019-09-11T03:40:34.386Z", - "http": { - "response": { - "status_code": 400, - "body": { - "bytes": 3, - "hash": "26d228663f13a88592a12d16cf9587caab0388b262d6d9f126ed62f9333aca94", - "content": "400", - "content_bytes": 3 - } - } - }, - "error": { - "message": "400 Bad Request", - "type": "validate" - }, - "monitor": { - "duration": { - "us": 4258 - }, - "id": "0050-down", - "ip": "127.0.0.1", - "name": "", - "scheme": null, - "status": "down", - "type": "http" - }, - "observer": { - "geo": { - "name": "mpls" - } - } - }, - { - "timestamp": "2019-09-11T03:40:34.386Z", - "http": { - "response": { - "status_code": 200, - "body": { - "bytes": 3, - "hash": "27badc983df1780b60c2b3fa9d3a19a00e46aac798451f0febdca52920faaddf", - "content": null, - "content_bytes": null - } - } - }, - "error": null, - "monitor": { - "duration": { - "us": 4784 - }, - "id": "0048-up", - "ip": "127.0.0.1", - "name": "", - "scheme": null, - "status": "up", - "type": "http" - }, - "observer": { - "geo": { - "name": "mpls" - } - } - }, - { - "timestamp": "2019-09-11T03:40:34.376Z", - "http": { - "response": { - "status_code": 200, - "body": { - "bytes": 3, - "hash": "27badc983df1780b60c2b3fa9d3a19a00e46aac798451f0febdca52920faaddf", - "content": null, - "content_bytes": null - } - } - }, - "error": null, - "monitor": { - "duration": { - "us": 14580 - }, - "id": "0072-up", - "ip": "127.0.0.1", - "name": "", - "scheme": null, - "status": "up", - "type": "http" - }, - "observer": { - "geo": { - "name": "mpls" - } - } - }, - { - "timestamp": "2019-09-11T03:40:34.376Z", - "http": { - "response": { - "status_code": 200, - "body": { - "bytes": 3, - "hash": "27badc983df1780b60c2b3fa9d3a19a00e46aac798451f0febdca52920faaddf", - "content": null, - "content_bytes": null - } - } - }, - "error": null, - "monitor": { - "duration": { - "us": 14679 - }, - "id": "0096-up", - "ip": "127.0.0.1", - "name": "", - "scheme": null, - "status": "up", - "type": "http" - }, - "observer": { - "geo": { - "name": "mpls" - } - } - }, - { - "timestamp": "2019-09-11T03:40:34.375Z", - "http": { - "response": { - "status_code": 200, - "body": { - "bytes": 3, - "hash": "27badc983df1780b60c2b3fa9d3a19a00e46aac798451f0febdca52920faaddf", - "content": null, - "content_bytes": null - } - } - }, - "error": null, - "monitor": { - "duration": { - "us": 15308 - }, - "id": "0092-up", - "ip": "127.0.0.1", - "name": "", - "scheme": null, - "status": "up", - "type": "http" - }, - "observer": { - "geo": { - "name": "mpls" - } - } - }, - { - "timestamp": "2019-09-11T03:40:34.375Z", - "http": { - "response": { - "status_code": 200, - "body": { - "bytes": 3, - "hash": "27badc983df1780b60c2b3fa9d3a19a00e46aac798451f0febdca52920faaddf", - "content": null, - "content_bytes": null - } - } - }, - "error": null, - "monitor": { - "duration": { - "us": 15183 - }, - "id": "0069-up", - "ip": "127.0.0.1", - "name": "", - "scheme": null, - "status": "up", - "type": "http" - }, - "observer": { - "geo": { - "name": "mpls" - } - } - }, - { - "timestamp": "2019-09-11T03:40:34.375Z", - "http": { - "response": { - "status_code": 200, - "body": { - "bytes": 3, - "hash": "27badc983df1780b60c2b3fa9d3a19a00e46aac798451f0febdca52920faaddf", - "content": null, - "content_bytes": null - } - } - }, - "error": null, - "monitor": { - "duration": { - "us": 15013 - }, - "id": "0093-up", - "ip": "127.0.0.1", - "name": "", - "scheme": null, - "status": "up", - "type": "http" - }, - "observer": { - "geo": { - "name": "mpls" - } - } - }, - { - "timestamp": "2019-09-11T03:40:34.375Z", - "http": { - "response": { - "status_code": 400, - "body": { - "bytes": 3, - "hash": "26d228663f13a88592a12d16cf9587caab0388b262d6d9f126ed62f9333aca94", - "content": "400", - "content_bytes": 3 - } - } - }, - "error": { - "message": "400 Bad Request", - "type": "validate" - }, - "monitor": { - "duration": { - "us": 15117 - }, - "id": "0070-down", - "ip": "127.0.0.1", - "name": "", - "scheme": null, - "status": "down", - "type": "http" - }, - "observer": { - "geo": { - "name": "mpls" - } - } - }, - { - "timestamp": "2019-09-11T03:40:34.375Z", - "http": { - "response": { - "status_code": 200, - "body": { - "bytes": 3, - "hash": "27badc983df1780b60c2b3fa9d3a19a00e46aac798451f0febdca52920faaddf", - "content": null, - "content_bytes": null - } - } - }, - "error": null, - "monitor": { - "duration": { - "us": 14875 - }, - "id": "0071-up", - "ip": "127.0.0.1", - "name": "", - "scheme": null, - "status": "up", - "type": "http" - }, - "observer": { - "geo": { - "name": "mpls" - } - } - }, - { - "timestamp": "2019-09-11T03:40:34.375Z", - "http": { - "response": { - "status_code": 200, - "body": { - "bytes": 3, - "hash": "27badc983df1780b60c2b3fa9d3a19a00e46aac798451f0febdca52920faaddf", - "content": null, - "content_bytes": null - } - } - }, - "error": null, - "monitor": { - "duration": { - "us": 14801 - }, - "id": "0095-up", - "ip": "127.0.0.1", - "name": "", - "scheme": null, - "status": "up", - "type": "http" - }, - "observer": { - "geo": { - "name": "mpls" - } - } - }, - { - "timestamp": "2019-09-11T03:40:34.375Z", - "http": { - "response": { - "status_code": 200, - "body": { - "bytes": 3, - "hash": "27badc983df1780b60c2b3fa9d3a19a00e46aac798451f0febdca52920faaddf", - "content": null, - "content_bytes": null - } - } - }, - "error": null, - "monitor": { - "duration": { - "us": 15065 - }, - "id": "0032-up", - "ip": "127.0.0.1", - "name": "", - "scheme": null, - "status": "up", - "type": "http" - }, - "observer": { - "geo": { - "name": "mpls" - } - } - }, - { - "timestamp": "2019-09-11T03:40:34.375Z", - "http": { - "response": { - "status_code": 200, - "body": { - "bytes": 3, - "hash": "27badc983df1780b60c2b3fa9d3a19a00e46aac798451f0febdca52920faaddf", - "content": null, - "content_bytes": null - } - } - }, - "error": null, - "monitor": { - "duration": { - "us": 14911 - }, - "id": "0094-up", - "ip": "127.0.0.1", - "name": "", - "scheme": null, - "status": "up", - "type": "http" - }, - "observer": { - "geo": { - "name": "mpls" - } - } - }, - { - "timestamp": "2019-09-11T03:40:34.374Z", - "http": { - "response": { - "status_code": 200, - "body": { - "bytes": 3, - "hash": "27badc983df1780b60c2b3fa9d3a19a00e46aac798451f0febdca52920faaddf", - "content": null, - "content_bytes": null - } - } - }, - "error": null, - "monitor": { - "duration": { - "us": 16135 - }, - "id": "0046-up", - "ip": "127.0.0.1", - "name": "", - "scheme": null, - "status": "up", - "type": "http" - }, - "observer": { - "geo": { - "name": "mpls" - } - } - }, - { - "timestamp": "2019-09-11T03:40:34.374Z", - "http": { - "response": { - "status_code": 200, - "body": { - "bytes": 3, - "hash": "27badc983df1780b60c2b3fa9d3a19a00e46aac798451f0febdca52920faaddf", - "content": null, - "content_bytes": null - } - } - }, - "error": null, - "monitor": { - "duration": { - "us": 15428 - }, - "id": "0091-up", - "ip": "127.0.0.1", - "name": "", - "scheme": null, - "status": "up", - "type": "http" - }, - "observer": { - "geo": { - "name": "mpls" - } - } - }, - { - "timestamp": "2019-09-11T03:40:34.374Z", - "http": { - "response": { - "status_code": 200, - "body": { - "bytes": 3, - "hash": "27badc983df1780b60c2b3fa9d3a19a00e46aac798451f0febdca52920faaddf", - "content": null, - "content_bytes": null - } - } - }, - "error": null, - "monitor": { - "duration": { - "us": 15499 - }, - "id": "0067-up", - "ip": "127.0.0.1", - "name": "", - "scheme": null, - "status": "up", - "type": "http" - }, - "observer": { - "geo": { - "name": "mpls" - } - } - }, - { - "timestamp": "2019-09-11T03:40:34.374Z", - "http": { - "response": { - "status_code": 200, - "body": { - "bytes": 3, - "hash": "27badc983df1780b60c2b3fa9d3a19a00e46aac798451f0febdca52920faaddf", - "content": null, - "content_bytes": null - } - } - }, - "error": null, - "monitor": { - "duration": { - "us": 15464 - }, - "id": "0068-up", - "ip": "127.0.0.1", - "name": "", - "scheme": null, - "status": "up", - "type": "http" - }, - "observer": { - "geo": { - "name": "mpls" - } - } - }, - { - "timestamp": "2019-09-11T03:40:34.374Z", - "http": { - "response": { - "status_code": 200, - "body": { - "bytes": 3, - "hash": "27badc983df1780b60c2b3fa9d3a19a00e46aac798451f0febdca52920faaddf", - "content": null, - "content_bytes": null - } - } - }, - "error": null, - "monitor": { - "duration": { - "us": 21736 - }, - "id": "0090-intermittent", - "ip": "127.0.0.1", - "name": "", - "scheme": null, - "status": "up", - "type": "http" - }, - "observer": { - "geo": { - "name": "mpls" - } - } - }, - { - "timestamp": "2019-09-11T03:40:34.374Z", - "http": { - "response": { - "status_code": 200, - "body": { - "bytes": 3, - "hash": "27badc983df1780b60c2b3fa9d3a19a00e46aac798451f0febdca52920faaddf", - "content": null, - "content_bytes": null - } - } - }, - "error": null, - "monitor": { - "duration": { - "us": 21874 - }, - "id": "0031-up", - "ip": "127.0.0.1", - "name": "", - "scheme": null, - "status": "up", - "type": "http" - }, - "observer": { - "geo": { - "name": "mpls" - } - } - }, - { - "timestamp": "2019-09-11T03:40:34.374Z", - "http": { - "response": { - "status_code": 200, - "body": { - "bytes": 3, - "hash": "27badc983df1780b60c2b3fa9d3a19a00e46aac798451f0febdca52920faaddf", - "content": null, - "content_bytes": null - } - } - }, - "error": null, - "monitor": { - "duration": { - "us": 36584 - }, - "id": "0066-up", - "ip": "127.0.0.1", - "name": "", - "scheme": null, - "status": "up", - "type": "http" - }, - "observer": { - "geo": { - "name": "mpls" - } - } - }, - { - "timestamp": "2019-09-11T03:40:34.373Z", - "http": { - "response": { - "status_code": 200, - "body": { - "bytes": 3, - "hash": "27badc983df1780b60c2b3fa9d3a19a00e46aac798451f0febdca52920faaddf", - "content": null, - "content_bytes": null - } - } - }, - "error": null, - "monitor": { - "duration": { - "us": 3148 - }, - "id": "0084-up", - "ip": "127.0.0.1", - "name": "", - "scheme": null, - "status": "up", - "type": "http" - }, - "observer": { - "geo": { - "name": "mpls" - } - } - }, - { - "timestamp": "2019-09-11T03:40:34.373Z", - "http": { - "response": { - "status_code": 200, - "body": { - "bytes": 3, - "hash": "27badc983df1780b60c2b3fa9d3a19a00e46aac798451f0febdca52920faaddf", - "content": null, - "content_bytes": null - } - } - }, - "error": null, - "monitor": { - "duration": { - "us": 13442 - }, - "id": "0083-up", - "ip": "127.0.0.1", - "name": "", - "scheme": null, - "status": "up", - "type": "http" - }, - "observer": { - "geo": { - "name": "mpls" - } - } - }, - { - "timestamp": "2019-09-11T03:40:34.373Z", - "http": { - "response": { - "status_code": 200, - "body": { - "bytes": 3, - "hash": "27badc983df1780b60c2b3fa9d3a19a00e46aac798451f0febdca52920faaddf", - "content": null, - "content_bytes": null - } - } - }, - "error": null, - "monitor": { - "duration": { - "us": 13666 - }, - "id": "0041-up", - "ip": "127.0.0.1", - "name": "", - "scheme": null, - "status": "up", - "type": "http" - }, - "observer": { - "geo": { - "name": "mpls" - } - } - }, - { - "timestamp": "2019-09-11T03:40:34.373Z", - "http": { - "response": { - "status_code": 200, - "body": { - "bytes": 3, - "hash": "27badc983df1780b60c2b3fa9d3a19a00e46aac798451f0febdca52920faaddf", - "content": null, - "content_bytes": null - } - } - }, - "error": null, - "monitor": { - "duration": { - "us": 16290 - }, - "id": "0045-intermittent", - "ip": "127.0.0.1", - "name": "", - "scheme": null, - "status": "up", - "type": "http" - }, - "observer": { - "geo": { - "name": "mpls" - } - } - }, - { - "timestamp": "2019-09-11T03:40:34.373Z", - "http": { - "response": { - "status_code": 200, - "body": { - "bytes": 3, - "hash": "27badc983df1780b60c2b3fa9d3a19a00e46aac798451f0febdca52920faaddf", - "content": null, - "content_bytes": null - } - } - }, - "error": null, - "monitor": { - "duration": { - "us": 17255 - }, - "id": "0042-up", - "ip": "127.0.0.1", - "name": "", - "scheme": null, - "status": "up", - "type": "http" - }, - "observer": { - "geo": { - "name": "mpls" - } - } - }, - { - "timestamp": "2019-09-11T03:40:34.373Z", - "http": { - "response": { - "status_code": 500, - "body": { - "bytes": 3, - "hash": "0604cd3138feed202ef293e062da2f4720f77a05d25ee036a7a01c9cfcdd1f0a", - "content": "500", - "content_bytes": 3 - } - } - }, - "error": { - "message": "500 Internal Server Error", - "type": "validate" - }, - "monitor": { - "duration": { - "us": 17146 - }, - "id": "0030-intermittent", - "ip": "127.0.0.1", - "name": "", - "scheme": null, - "status": "down", - "type": "http" - }, - "observer": { - "geo": { - "name": "mpls" - } - } - }, - { - "timestamp": "2019-09-11T03:40:34.373Z", - "http": { - "response": { - "status_code": 200, - "body": { - "bytes": 3, - "hash": "27badc983df1780b60c2b3fa9d3a19a00e46aac798451f0febdca52920faaddf", - "content": null, - "content_bytes": null - } - } - }, - "error": null, - "monitor": { - "duration": { - "us": 17770 - }, - "id": "0063-up", - "ip": "127.0.0.1", - "name": "", - "scheme": null, - "status": "up", - "type": "http" - }, - "observer": { - "geo": { - "name": "mpls" - } - } - }, - { - "timestamp": "2019-09-11T03:40:34.373Z", - "http": { - "response": { - "status_code": 200, - "body": { - "bytes": 3, - "hash": "27badc983df1780b60c2b3fa9d3a19a00e46aac798451f0febdca52920faaddf", - "content": null, - "content_bytes": null - } - } - }, - "error": null, - "monitor": { - "duration": { - "us": 18194 - }, - "id": "0061-up", - "ip": "127.0.0.1", - "name": "", - "scheme": null, - "status": "up", - "type": "http" - }, - "observer": { - "geo": { - "name": "mpls" - } - } - }, - { - "timestamp": "2019-09-11T03:40:34.373Z", - "http": { - "response": { - "status_code": 200, - "body": { - "bytes": 3, - "hash": "27badc983df1780b60c2b3fa9d3a19a00e46aac798451f0febdca52920faaddf", - "content": null, - "content_bytes": null - } - } - }, - "error": null, - "monitor": { - "duration": { - "us": 17587 - }, - "id": "0065-up", - "ip": "127.0.0.1", - "name": "", - "scheme": null, - "status": "up", - "type": "http" - }, - "observer": { - "geo": { - "name": "mpls" - } - } - }, - { - "timestamp": "2019-09-11T03:40:34.373Z", - "http": { - "response": { - "status_code": 200, - "body": { - "bytes": 3, - "hash": "27badc983df1780b60c2b3fa9d3a19a00e46aac798451f0febdca52920faaddf", - "content": null, - "content_bytes": null - } - } - }, - "error": null, - "monitor": { - "duration": { - "us": 22666 - }, - "id": "0062-up", - "ip": "127.0.0.1", - "name": "", - "scheme": null, - "status": "up", - "type": "http" - }, - "observer": { - "geo": { - "name": "mpls" - } - } - }, - { - "timestamp": "2019-09-11T03:40:34.373Z", - "http": { - "response": { - "status_code": 200, - "body": { - "bytes": 3, - "hash": "27badc983df1780b60c2b3fa9d3a19a00e46aac798451f0febdca52920faaddf", - "content": null, - "content_bytes": null - } - } - }, - "error": null, - "monitor": { - "duration": { - "us": 33311 - }, - "id": "0026-up", - "ip": "127.0.0.1", - "name": "", - "scheme": null, - "status": "up", - "type": "http" - }, - "observer": { - "geo": { - "name": "mpls" - } - } - }, - { - "timestamp": "2019-09-11T03:40:34.373Z", - "http": { - "response": { - "status_code": 200, - "body": { - "bytes": 3, - "hash": "27badc983df1780b60c2b3fa9d3a19a00e46aac798451f0febdca52920faaddf", - "content": null, - "content_bytes": null - } - } - }, - "error": null, - "monitor": { - "duration": { - "us": 33506 - }, - "id": "0085-up", - "ip": "127.0.0.1", - "name": "", - "scheme": null, - "status": "up", - "type": "http" - }, - "observer": { - "geo": { - "name": "mpls" - } - } - }, - { - "timestamp": "2019-09-11T03:40:34.373Z", - "http": { - "response": { - "status_code": 200, - "body": { - "bytes": 3, - "hash": "27badc983df1780b60c2b3fa9d3a19a00e46aac798451f0febdca52920faaddf", - "content": null, - "content_bytes": null - } - } - }, - "error": null, - "monitor": { - "duration": { - "us": 33974 - }, - "id": "0025-up", - "ip": "127.0.0.1", - "name": "", - "scheme": null, - "status": "up", - "type": "http" - }, - "observer": { - "geo": { - "name": "mpls" - } - } - }, - { - "timestamp": "2019-09-11T03:40:34.373Z", - "http": { - "response": { - "status_code": 200, - "body": { - "bytes": 3, - "hash": "27badc983df1780b60c2b3fa9d3a19a00e46aac798451f0febdca52920faaddf", - "content": null, - "content_bytes": null - } - } - }, - "error": null, - "monitor": { - "duration": { - "us": 33693 - }, - "id": "0088-up", - "ip": "127.0.0.1", - "name": "", - "scheme": null, - "status": "up", - "type": "http" - }, - "observer": { - "geo": { - "name": "mpls" - } - } - }, - { - "timestamp": "2019-09-11T03:40:34.373Z", - "http": { - "response": { - "status_code": 200, - "body": { - "bytes": 3, - "hash": "27badc983df1780b60c2b3fa9d3a19a00e46aac798451f0febdca52920faaddf", - "content": null, - "content_bytes": null - } - } - }, - "error": null, - "monitor": { - "duration": { - "us": 33833 - }, - "id": "0089-up", - "ip": "127.0.0.1", - "name": "", - "scheme": null, - "status": "up", - "type": "http" - }, - "observer": { - "geo": { - "name": "mpls" - } - } - }, - { - "timestamp": "2019-09-11T03:40:34.373Z", - "http": { - "response": { - "status_code": 200, - "body": { - "bytes": 3, - "hash": "27badc983df1780b60c2b3fa9d3a19a00e46aac798451f0febdca52920faaddf", - "content": null, - "content_bytes": null - } - } - }, - "error": null, - "monitor": { - "duration": { - "us": 34600 - }, - "id": "0087-up", - "ip": "127.0.0.1", - "name": "", - "scheme": null, - "status": "up", - "type": "http" - }, - "observer": { - "geo": { - "name": "mpls" - } - } - }, - { - "timestamp": "2019-09-11T03:40:34.373Z", - "http": { - "response": { - "status_code": 200, - "body": { - "bytes": 3, - "hash": "27badc983df1780b60c2b3fa9d3a19a00e46aac798451f0febdca52920faaddf", - "content": null, - "content_bytes": null - } - } - }, - "error": null, - "monitor": { - "duration": { - "us": 35573 - }, - "id": "0028-up", - "ip": "127.0.0.1", - "name": "", - "scheme": null, - "status": "up", - "type": "http" - }, - "observer": { - "geo": { - "name": "mpls" - } - } - }, - { - "timestamp": "2019-09-11T03:40:34.373Z", - "http": { - "response": { - "status_code": 200, - "body": { - "bytes": 3, - "hash": "27badc983df1780b60c2b3fa9d3a19a00e46aac798451f0febdca52920faaddf", - "content": null, - "content_bytes": null - } - } - }, - "error": null, - "monitor": { - "duration": { - "us": 35830 - }, - "id": "0086-up", - "ip": "127.0.0.1", - "name": "", - "scheme": null, - "status": "up", - "type": "http" - }, - "observer": { - "geo": { - "name": "mpls" - } - } - }, - { - "timestamp": "2019-09-11T03:40:34.373Z", - "http": { - "response": { - "status_code": 200, - "body": { - "bytes": 3, - "hash": "27badc983df1780b60c2b3fa9d3a19a00e46aac798451f0febdca52920faaddf", - "content": null, - "content_bytes": null - } - } - }, - "error": null, - "monitor": { - "duration": { - "us": 35698 - }, - "id": "0064-up", - "ip": "127.0.0.1", - "name": "", - "scheme": null, - "status": "up", - "type": "http" - }, - "observer": { - "geo": { - "name": "mpls" - } - } - }, - { - "timestamp": "2019-09-11T03:40:34.373Z", - "http": { - "response": { - "status_code": 200, - "body": { - "bytes": 3, - "hash": "27badc983df1780b60c2b3fa9d3a19a00e46aac798451f0febdca52920faaddf", - "content": null, - "content_bytes": null - } - } - }, - "error": null, - "monitor": { - "duration": { - "us": 35594 - }, - "id": "0029-up", - "ip": "127.0.0.1", - "name": "", - "scheme": null, - "status": "up", - "type": "http" - }, - "observer": { - "geo": { - "name": "mpls" - } - } - }, - { - "timestamp": "2019-09-11T03:40:34.373Z", - "http": { - "response": { - "status_code": 200, - "body": { - "bytes": 3, - "hash": "27badc983df1780b60c2b3fa9d3a19a00e46aac798451f0febdca52920faaddf", - "content": null, - "content_bytes": null - } - } - }, - "error": null, - "monitor": { - "duration": { - "us": 35652 - }, - "id": "0044-up", - "ip": "127.0.0.1", - "name": "", - "scheme": null, - "status": "up", - "type": "http" - }, - "observer": { - "geo": { - "name": "mpls" - } - } - } - ] - } -} \ No newline at end of file diff --git a/x-pack/test/api_integration/apis/uptime/graphql/fixtures/ping_list_monitor_id.json b/x-pack/test/api_integration/apis/uptime/graphql/fixtures/ping_list_monitor_id.json deleted file mode 100644 index 5826fd9f3f540d..00000000000000 --- a/x-pack/test/api_integration/apis/uptime/graphql/fixtures/ping_list_monitor_id.json +++ /dev/null @@ -1,475 +0,0 @@ -{ - "allPings": { - "total": 20, - "locations": [ - "mpls" - ], - "pings": [ - { - "timestamp": "2019-09-11T03:40:34.371Z", - "http": { - "response": { - "status_code": 200, - "body": { - "bytes": 3, - "hash": "27badc983df1780b60c2b3fa9d3a19a00e46aac798451f0febdca52920faaddf", - "content": null, - "content_bytes": null - } - } - }, - "error": null, - "monitor": { - "duration": { - "us": 35534 - }, - "id": "0001-up", - "ip": "127.0.0.1", - "name": "", - "scheme": null, - "status": "up", - "type": "http" - }, - "observer": { - "geo": { - "name": "mpls" - } - } - }, - { - "timestamp": "2019-09-11T03:40:04.370Z", - "http": { - "response": { - "status_code": 200, - "body": { - "bytes": 3, - "hash": "27badc983df1780b60c2b3fa9d3a19a00e46aac798451f0febdca52920faaddf", - "content": null, - "content_bytes": null - } - } - }, - "error": null, - "monitor": { - "duration": { - "us": 3080 - }, - "id": "0001-up", - "ip": "127.0.0.1", - "name": "", - "scheme": null, - "status": "up", - "type": "http" - }, - "observer": { - "geo": { - "name": "mpls" - } - } - }, - { - "timestamp": "2019-09-11T03:39:34.370Z", - "http": { - "response": { - "status_code": 200, - "body": { - "bytes": 3, - "hash": "27badc983df1780b60c2b3fa9d3a19a00e46aac798451f0febdca52920faaddf", - "content": null, - "content_bytes": null - } - } - }, - "error": null, - "monitor": { - "duration": { - "us": 7810 - }, - "id": "0001-up", - "ip": "127.0.0.1", - "name": "", - "scheme": null, - "status": "up", - "type": "http" - }, - "observer": { - "geo": { - "name": "mpls" - } - } - }, - { - "timestamp": "2019-09-11T03:39:04.371Z", - "http": { - "response": { - "status_code": 200, - "body": { - "bytes": 3, - "hash": "27badc983df1780b60c2b3fa9d3a19a00e46aac798451f0febdca52920faaddf", - "content": null, - "content_bytes": null - } - } - }, - "error": null, - "monitor": { - "duration": { - "us": 1575 - }, - "id": "0001-up", - "ip": "127.0.0.1", - "name": "", - "scheme": null, - "status": "up", - "type": "http" - }, - "observer": { - "geo": { - "name": "mpls" - } - } - }, - { - "timestamp": "2019-09-11T03:38:34.370Z", - "http": { - "response": { - "status_code": 200, - "body": { - "bytes": 3, - "hash": "27badc983df1780b60c2b3fa9d3a19a00e46aac798451f0febdca52920faaddf", - "content": null, - "content_bytes": null - } - } - }, - "error": null, - "monitor": { - "duration": { - "us": 1787 - }, - "id": "0001-up", - "ip": "127.0.0.1", - "name": "", - "scheme": null, - "status": "up", - "type": "http" - }, - "observer": { - "geo": { - "name": "mpls" - } - } - }, - { - "timestamp": "2019-09-11T03:38:04.370Z", - "http": { - "response": { - "status_code": 200, - "body": { - "bytes": 3, - "hash": "27badc983df1780b60c2b3fa9d3a19a00e46aac798451f0febdca52920faaddf", - "content": null, - "content_bytes": null - } - } - }, - "error": null, - "monitor": { - "duration": { - "us": 654 - }, - "id": "0001-up", - "ip": "127.0.0.1", - "name": "", - "scheme": null, - "status": "up", - "type": "http" - }, - "observer": { - "geo": { - "name": "mpls" - } - } - }, - { - "timestamp": "2019-09-11T03:37:34.370Z", - "http": { - "response": { - "status_code": 200, - "body": { - "bytes": 3, - "hash": "27badc983df1780b60c2b3fa9d3a19a00e46aac798451f0febdca52920faaddf", - "content": null, - "content_bytes": null - } - } - }, - "error": null, - "monitor": { - "duration": { - "us": 15915 - }, - "id": "0001-up", - "ip": "127.0.0.1", - "name": "", - "scheme": null, - "status": "up", - "type": "http" - }, - "observer": { - "geo": { - "name": "mpls" - } - } - }, - { - "timestamp": "2019-09-11T03:37:04.370Z", - "http": { - "response": { - "status_code": 200, - "body": { - "bytes": 3, - "hash": "27badc983df1780b60c2b3fa9d3a19a00e46aac798451f0febdca52920faaddf", - "content": null, - "content_bytes": null - } - } - }, - "error": null, - "monitor": { - "duration": { - "us": 2679 - }, - "id": "0001-up", - "ip": "127.0.0.1", - "name": "", - "scheme": null, - "status": "up", - "type": "http" - }, - "observer": { - "geo": { - "name": "mpls" - } - } - }, - { - "timestamp": "2019-09-11T03:36:34.371Z", - "http": { - "response": { - "status_code": 200, - "body": { - "bytes": 3, - "hash": "27badc983df1780b60c2b3fa9d3a19a00e46aac798451f0febdca52920faaddf", - "content": null, - "content_bytes": null - } - } - }, - "error": null, - "monitor": { - "duration": { - "us": 2104 - }, - "id": "0001-up", - "ip": "127.0.0.1", - "name": "", - "scheme": null, - "status": "up", - "type": "http" - }, - "observer": { - "geo": { - "name": "mpls" - } - } - }, - { - "timestamp": "2019-09-11T03:36:04.370Z", - "http": { - "response": { - "status_code": 200, - "body": { - "bytes": 3, - "hash": "27badc983df1780b60c2b3fa9d3a19a00e46aac798451f0febdca52920faaddf", - "content": null, - "content_bytes": null - } - } - }, - "error": null, - "monitor": { - "duration": { - "us": 5759 - }, - "id": "0001-up", - "ip": "127.0.0.1", - "name": "", - "scheme": null, - "status": "up", - "type": "http" - }, - "observer": { - "geo": { - "name": "mpls" - } - } - }, - { - "timestamp": "2019-09-11T03:35:34.373Z", - "http": { - "response": { - "status_code": 200, - "body": { - "bytes": 3, - "hash": "27badc983df1780b60c2b3fa9d3a19a00e46aac798451f0febdca52920faaddf", - "content": null, - "content_bytes": null - } - } - }, - "error": null, - "monitor": { - "duration": { - "us": 7166 - }, - "id": "0001-up", - "ip": "127.0.0.1", - "name": "", - "scheme": null, - "status": "up", - "type": "http" - }, - "observer": { - "geo": { - "name": "mpls" - } - } - }, - { - "timestamp": "2019-09-11T03:35:04.371Z", - "http": { - "response": { - "status_code": 200, - "body": { - "bytes": 3, - "hash": "27badc983df1780b60c2b3fa9d3a19a00e46aac798451f0febdca52920faaddf", - "content": null, - "content_bytes": null - } - } - }, - "error": null, - "monitor": { - "duration": { - "us": 26830 - }, - "id": "0001-up", - "ip": "127.0.0.1", - "name": "", - "scheme": null, - "status": "up", - "type": "http" - }, - "observer": { - "geo": { - "name": "mpls" - } - } - }, - { - "timestamp": "2019-09-11T03:34:34.371Z", - "http": { - "response": { - "status_code": 200, - "body": { - "bytes": 3, - "hash": "27badc983df1780b60c2b3fa9d3a19a00e46aac798451f0febdca52920faaddf", - "content": null, - "content_bytes": null - } - } - }, - "error": null, - "monitor": { - "duration": { - "us": 993 - }, - "id": "0001-up", - "ip": "127.0.0.1", - "name": "", - "scheme": null, - "status": "up", - "type": "http" - }, - "observer": { - "geo": { - "name": "mpls" - } - } - }, - { - "timestamp": "2019-09-11T03:34:04.381Z", - "http": { - "response": { - "status_code": 200, - "body": { - "bytes": 3, - "hash": "27badc983df1780b60c2b3fa9d3a19a00e46aac798451f0febdca52920faaddf", - "content": null, - "content_bytes": null - } - } - }, - "error": null, - "monitor": { - "duration": { - "us": 3880 - }, - "id": "0001-up", - "ip": "127.0.0.1", - "name": "", - "scheme": null, - "status": "up", - "type": "http" - }, - "observer": { - "geo": { - "name": "mpls" - } - } - }, - { - "timestamp": "2019-09-11T03:33:34.371Z", - "http": { - "response": { - "status_code": 200, - "body": { - "bytes": 3, - "hash": "27badc983df1780b60c2b3fa9d3a19a00e46aac798451f0febdca52920faaddf", - "content": null, - "content_bytes": null - } - } - }, - "error": null, - "monitor": { - "duration": { - "us": 1604 - }, - "id": "0001-up", - "ip": "127.0.0.1", - "name": "", - "scheme": null, - "status": "up", - "type": "http" - }, - "observer": { - "geo": { - "name": "mpls" - } - } - } - ] - } -} \ No newline at end of file diff --git a/x-pack/test/api_integration/apis/uptime/graphql/fixtures/ping_list_sort.json b/x-pack/test/api_integration/apis/uptime/graphql/fixtures/ping_list_sort.json deleted file mode 100644 index b9b8deae2e564f..00000000000000 --- a/x-pack/test/api_integration/apis/uptime/graphql/fixtures/ping_list_sort.json +++ /dev/null @@ -1,165 +0,0 @@ -{ - "allPings": { - "total": 20, - "locations": [ - "mpls" - ], - "pings": [ - { - "timestamp": "2019-09-11T03:31:04.380Z", - "http": { - "response": { - "status_code": 200, - "body": { - "bytes": 3, - "hash": "27badc983df1780b60c2b3fa9d3a19a00e46aac798451f0febdca52920faaddf", - "content": null, - "content_bytes": null - } - } - }, - "error": null, - "monitor": { - "duration": { - "us": 56940 - }, - "id": "0001-up", - "ip": "127.0.0.1", - "name": "", - "scheme": null, - "status": "up", - "type": "http" - }, - "observer": { - "geo": { - "name": "mpls" - } - } - }, - { - "timestamp": "2019-09-11T03:31:34.366Z", - "http": { - "response": { - "status_code": 200, - "body": { - "bytes": 3, - "hash": "27badc983df1780b60c2b3fa9d3a19a00e46aac798451f0febdca52920faaddf", - "content": null, - "content_bytes": null - } - } - }, - "error": null, - "monitor": { - "duration": { - "us": 9861 - }, - "id": "0001-up", - "ip": "127.0.0.1", - "name": "", - "scheme": null, - "status": "up", - "type": "http" - }, - "observer": { - "geo": { - "name": "mpls" - } - } - }, - { - "timestamp": "2019-09-11T03:32:04.372Z", - "http": { - "response": { - "status_code": 200, - "body": { - "bytes": 3, - "hash": "27badc983df1780b60c2b3fa9d3a19a00e46aac798451f0febdca52920faaddf", - "content": null, - "content_bytes": null - } - } - }, - "error": null, - "monitor": { - "duration": { - "us": 2924 - }, - "id": "0001-up", - "ip": "127.0.0.1", - "name": "", - "scheme": null, - "status": "up", - "type": "http" - }, - "observer": { - "geo": { - "name": "mpls" - } - } - }, - { - "timestamp": "2019-09-11T03:32:34.375Z", - "http": { - "response": { - "status_code": 200, - "body": { - "bytes": 3, - "hash": "27badc983df1780b60c2b3fa9d3a19a00e46aac798451f0febdca52920faaddf", - "content": null, - "content_bytes": null - } - } - }, - "error": null, - "monitor": { - "duration": { - "us": 21665 - }, - "id": "0001-up", - "ip": "127.0.0.1", - "name": "", - "scheme": null, - "status": "up", - "type": "http" - }, - "observer": { - "geo": { - "name": "mpls" - } - } - }, - { - "timestamp": "2019-09-11T03:33:04.370Z", - "http": { - "response": { - "status_code": 200, - "body": { - "bytes": 3, - "hash": "27badc983df1780b60c2b3fa9d3a19a00e46aac798451f0febdca52920faaddf", - "content": null, - "content_bytes": null - } - } - }, - "error": null, - "monitor": { - "duration": { - "us": 2128 - }, - "id": "0001-up", - "ip": "127.0.0.1", - "name": "", - "scheme": null, - "status": "up", - "type": "http" - }, - "observer": { - "geo": { - "name": "mpls" - } - } - } - ] - } -} \ No newline at end of file diff --git a/x-pack/test/api_integration/apis/uptime/graphql/index.ts b/x-pack/test/api_integration/apis/uptime/graphql/index.ts index 2e0b5e2eea2a5f..862cce47f257a5 100644 --- a/x-pack/test/api_integration/apis/uptime/graphql/index.ts +++ b/x-pack/test/api_integration/apis/uptime/graphql/index.ts @@ -13,6 +13,5 @@ export default function({ loadTestFile }: FtrProviderContext) { // verifying the pre-loaded documents are returned in a way that // matches the snapshots contained in './fixtures' loadTestFile(require.resolve('./monitor_states')); - loadTestFile(require.resolve('./ping_list')); }); } diff --git a/x-pack/test/api_integration/apis/uptime/graphql/ping_list.ts b/x-pack/test/api_integration/apis/uptime/graphql/ping_list.ts deleted file mode 100644 index c84b9c382acddc..00000000000000 --- a/x-pack/test/api_integration/apis/uptime/graphql/ping_list.ts +++ /dev/null @@ -1,116 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import expect from '@kbn/expect'; -import { pingsQueryString } from '../../../../../legacy/plugins/uptime/public/queries'; -import { expectFixtureEql } from './helpers/expect_fixture_eql'; -import { Ping, PingResults } from '../../../../../legacy/plugins/uptime/common/graphql/types'; - -const expectPingFixtureEql = (data: { allPings: PingResults }, fixtureName: string) => { - expectFixtureEql(data, fixtureName, d => d.allPings.pings.forEach((p: Ping) => delete p.id)); -}; - -export default function({ getService }: any) { - describe('pingList query', () => { - before('load heartbeat data', () => getService('esArchiver').load('uptime/full_heartbeat')); - after('unload heartbeat index', () => getService('esArchiver').unload('uptime/full_heartbeat')); - - const supertest = getService('supertest'); - - it('returns a list of pings for the given date range and default size', async () => { - const getPingsQuery = { - operationName: 'PingList', - query: pingsQueryString, - variables: { - dateRangeStart: '2019-01-28T17:40:08.078Z', - dateRangeEnd: '2025-01-28T19:00:16.078Z', - }, - }; - const { - body: { data }, - } = await supertest - .post('/api/uptime/graphql') - .set('kbn-xsrf', 'foo') - .send({ ...getPingsQuery }); - const { - allPings: { pings }, - } = data; - expect(pings).length(10); - - expectPingFixtureEql(data, 'ping_list'); - }); - - it('returns a list of pings for the date range and given size', async () => { - const SIZE = 50; - const getPingsQuery = { - operationName: 'PingList', - query: pingsQueryString, - variables: { - dateRangeStart: '2019-01-28T17:40:08.078Z', - dateRangeEnd: '2025-01-28T19:00:16.078Z', - size: SIZE, - }, - }; - const { - body: { data }, - } = await supertest - .post('/api/uptime/graphql') - .set('kbn-xsrf', 'foo') - .send({ ...getPingsQuery }); - const { - allPings: { pings }, - } = data; - expect(pings).length(SIZE); - expectPingFixtureEql(data, 'ping_list_count'); - }); - - it('returns a list of pings for a monitor ID', async () => { - const SIZE = 15; - const MONITOR_ID = '0001-up'; - const getPingsQuery = { - operationName: 'PingList', - query: pingsQueryString, - variables: { - dateRangeStart: '2019-01-28T17:40:08.078Z', - dateRangeEnd: '2025-01-28T19:00:16.078Z', - monitorId: MONITOR_ID, - size: SIZE, - }, - }; - const { - body: { data }, - } = await supertest - .post('/api/uptime/graphql') - .set('kbn-xsrf', 'foo') - .send({ ...getPingsQuery }); - expectPingFixtureEql(data, 'ping_list_monitor_id'); - }); - - it('returns a list of pings sorted ascending', async () => { - const SIZE = 5; - const MONITOR_ID = '0001-up'; - const getPingsQuery = { - operationName: 'PingList', - query: pingsQueryString, - variables: { - dateRangeStart: '2019-01-28T17:40:08.078Z', - dateRangeEnd: '2025-01-28T19:00:16.078Z', - monitorId: MONITOR_ID, - size: SIZE, - sort: 'asc', - }, - }; - const { - body: { data }, - } = await supertest - .post('/api/uptime/graphql') - .set('kbn-xsrf', 'foo') - .send({ ...getPingsQuery }); - - expectPingFixtureEql(data, 'ping_list_sort'); - }); - }); -} diff --git a/x-pack/test/api_integration/apis/uptime/index.ts b/x-pack/test/api_integration/apis/uptime/index.ts index a21db08d58c4d4..8def64b71a110d 100644 --- a/x-pack/test/api_integration/apis/uptime/index.ts +++ b/x-pack/test/api_integration/apis/uptime/index.ts @@ -10,11 +10,12 @@ export default function({ getService, loadTestFile }: FtrProviderContext) { const es = getService('legacyEs'); describe('uptime', () => { - before(() => - es.indices.delete({ - index: 'heartbeat*', - ignore: [404], - }) + before( + async () => + await es.indices.delete({ + index: 'heartbeat*', + ignore: [404], + }) ); loadTestFile(require.resolve('./feature_controls')); diff --git a/x-pack/test/api_integration/apis/uptime/rest/fixtures/monitor_latest_status.json b/x-pack/test/api_integration/apis/uptime/rest/fixtures/monitor_latest_status.json index 2e5854f4d98665..6a832ad8536f7f 100644 --- a/x-pack/test/api_integration/apis/uptime/rest/fixtures/monitor_latest_status.json +++ b/x-pack/test/api_integration/apis/uptime/rest/fixtures/monitor_latest_status.json @@ -1,16 +1,11 @@ { - "timestamp": "2019-09-11T03:40:34.371Z", "observer": { - "geo": { - "name": "mpls", - "location": "37.926868, -78.024902" - }, + "geo": { "name": "mpls", "location": "37.926868, -78.024902" }, "hostname": "avc-x1x" }, + "@timestamp": "2019-09-11T03:40:34.371Z", "monitor": { - "duration": { - "us": 24627 - }, + "duration": { "us": 24627 }, "ip": "127.0.0.1", "name": "", "check_group": "d76f0762-d445-11e9-88e3-3e80641b9c71", @@ -25,5 +20,7 @@ "domain": "localhost", "query": "r=200x1", "full": "http://localhost:5678/pattern?r=200x1" - } + }, + "docId": "h5toHm0B0I9WX_CznN_V", + "timestamp": "2019-09-11T03:40:34.371Z" } diff --git a/x-pack/test/api_integration/apis/uptime/rest/index.ts b/x-pack/test/api_integration/apis/uptime/rest/index.ts index 9b0cd61c224628..3f8df81856f5c9 100644 --- a/x-pack/test/api_integration/apis/uptime/rest/index.ts +++ b/x-pack/test/api_integration/apis/uptime/rest/index.ts @@ -45,10 +45,11 @@ export default function({ getService, loadTestFile }: FtrProviderContext) { loadTestFile(require.resolve('./telemetry_collectors')); }); describe('with real-world data', () => { - before('load heartbeat data', async () => await esArchiver.load('uptime/full_heartbeat')); - after('unload', async () => await esArchiver.unload('uptime/full_heartbeat')); + beforeEach('load heartbeat data', async () => await esArchiver.load('uptime/full_heartbeat')); + afterEach('unload', async () => await esArchiver.unload('uptime/full_heartbeat')); loadTestFile(require.resolve('./monitor_latest_status')); loadTestFile(require.resolve('./ping_histogram')); + loadTestFile(require.resolve('./ping_list')); loadTestFile(require.resolve('./monitor_duration')); loadTestFile(require.resolve('./doc_count')); }); diff --git a/x-pack/test/api_integration/apis/uptime/rest/ping_list.ts b/x-pack/test/api_integration/apis/uptime/rest/ping_list.ts new file mode 100644 index 00000000000000..a261763d5991f9 --- /dev/null +++ b/x-pack/test/api_integration/apis/uptime/rest/ping_list.ts @@ -0,0 +1,178 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import expect from '@kbn/expect'; +import { isLeft } from 'fp-ts/lib/Either'; +import { PathReporter } from 'io-ts/lib/PathReporter'; +import { PingsResponseType } from '../../../../../legacy/plugins/uptime/common/runtime_types'; +import { FtrProviderContext } from '../../../ftr_provider_context'; + +function decodePingsResponseData(response: any) { + const decoded = PingsResponseType.decode(response); + if (isLeft(decoded)) { + throw Error(JSON.stringify(PathReporter.report(decoded), null, 2)); + } + return decoded.right; +} + +export default function({ getService }: FtrProviderContext) { + const supertest = getService('supertest'); + describe('pingList query', () => { + before('load heartbeat data', () => getService('esArchiver').load('uptime/full_heartbeat')); + after('unload heartbeat index', () => getService('esArchiver').unload('uptime/full_heartbeat')); + + it('returns a list of pings for the given date range and default size', async () => { + const from = '2019-01-28T17:40:08.078Z'; + const to = '2025-01-28T19:00:16.078Z'; + + const apiResponse = await supertest.get(`/api/uptime/pings?from=${from}&to=${to}&size=10`); + + const { total, locations, pings } = decodePingsResponseData(apiResponse.body); + + expect(total).to.be(2000); + expect(locations).to.eql(['mpls']); + expect(pings).length(10); + expect(pings.map(({ monitor: { id } }) => id)).to.eql([ + '0074-up', + '0073-up', + '0099-up', + '0098-up', + '0075-intermittent', + '0097-up', + '0049-up', + '0047-up', + '0077-up', + '0076-up', + ]); + }); + + it('returns a list of pings for the date range and given size', async () => { + const from = '2019-01-28T17:40:08.078Z'; + const to = '2025-01-28T19:00:16.078Z'; + const size = 50; + + const apiResponse = await supertest.get( + `/api/uptime/pings?from=${from}&to=${to}&size=${size}` + ); + + const { total, locations, pings } = decodePingsResponseData(apiResponse.body); + + expect(total).to.be(2000); + expect(locations).to.eql(['mpls']); + expect(pings).length(50); + expect(pings.map(({ monitor: { id } }) => id)).to.eql([ + '0074-up', + '0073-up', + '0099-up', + '0098-up', + '0075-intermittent', + '0097-up', + '0049-up', + '0047-up', + '0077-up', + '0076-up', + '0050-down', + '0048-up', + '0072-up', + '0096-up', + '0092-up', + '0069-up', + '0093-up', + '0070-down', + '0071-up', + '0095-up', + '0032-up', + '0094-up', + '0046-up', + '0091-up', + '0067-up', + '0068-up', + '0090-intermittent', + '0031-up', + '0066-up', + '0084-up', + '0083-up', + '0041-up', + '0045-intermittent', + '0042-up', + '0030-intermittent', + '0063-up', + '0061-up', + '0065-up', + '0062-up', + '0026-up', + '0085-up', + '0025-up', + '0088-up', + '0089-up', + '0087-up', + '0028-up', + '0086-up', + '0064-up', + '0029-up', + '0044-up', + ]); + }); + + it('returns a list of pings for a monitor ID', async () => { + const from = '2019-01-28T17:40:08.078Z'; + const to = '2025-01-28T19:00:16.078Z'; + const monitorId = '0001-up'; + const size = 15; + + const apiResponse = await supertest.get( + `/api/uptime/pings?from=${from}&to=${to}&monitorId=${monitorId}&size=${size}` + ); + + const { total, locations, pings } = decodePingsResponseData(apiResponse.body); + + expect(total).to.be(20); + expect(locations).to.eql(['mpls']); + pings.forEach(({ monitor: { id } }) => expect(id).to.eql('0001-up')); + expect(pings.map(({ timestamp }) => timestamp)).to.eql([ + '2019-09-11T03:40:34.371Z', + '2019-09-11T03:40:04.370Z', + '2019-09-11T03:39:34.370Z', + '2019-09-11T03:39:04.371Z', + '2019-09-11T03:38:34.370Z', + '2019-09-11T03:38:04.370Z', + '2019-09-11T03:37:34.370Z', + '2019-09-11T03:37:04.370Z', + '2019-09-11T03:36:34.371Z', + '2019-09-11T03:36:04.370Z', + '2019-09-11T03:35:34.373Z', + '2019-09-11T03:35:04.371Z', + '2019-09-11T03:34:34.371Z', + '2019-09-11T03:34:04.381Z', + '2019-09-11T03:33:34.371Z', + ]); + }); + + it('returns a list of pings sorted ascending', async () => { + const from = '2019-01-28T17:40:08.078Z'; + const to = '2025-01-28T19:00:16.078Z'; + const monitorId = '0001-up'; + const size = 5; + const sort = 'asc'; + + const apiResponse = await supertest.get( + `/api/uptime/pings?from=${from}&to=${to}&monitorId=${monitorId}&size=${size}&sort=${sort}` + ); + + const { total, locations, pings } = decodePingsResponseData(apiResponse.body); + + expect(total).to.be(20); + expect(locations).to.eql(['mpls']); + expect(pings.map(({ timestamp }) => timestamp)).to.eql([ + '2019-09-11T03:31:04.380Z', + '2019-09-11T03:31:34.366Z', + '2019-09-11T03:32:04.372Z', + '2019-09-11T03:32:34.375Z', + '2019-09-11T03:33:04.370Z', + ]); + }); + }); +} diff --git a/x-pack/test/functional/apps/uptime/monitor.ts b/x-pack/test/functional/apps/uptime/monitor.ts index 90ad1836c69d31..388d660f21eb3a 100644 --- a/x-pack/test/functional/apps/uptime/monitor.ts +++ b/x-pack/test/functional/apps/uptime/monitor.ts @@ -23,8 +23,33 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { await uptimeService.navigation.goToUptime(); }); - it('loads and displays uptime data based on date range', async () => { - await uptime.loadDataAndGoToMonitorPage(dateStart, dateEnd, monitorId); + after(async () => { + await esArchiver.unload(archive); + }); + + describe('navigation to monitor page', () => { + before(async () => { + await uptime.loadDataAndGoToMonitorPage(dateStart, dateEnd, monitorId); + }); + + it('displays ping data as expected', async () => { + await uptime.checkPingListInteractions( + [ + 'XZtoHm0B0I9WX_CznN-6', + '7ZtoHm0B0I9WX_CzJ96M', + 'pptnHm0B0I9WX_Czst5X', + 'I5tnHm0B0I9WX_CzPd46', + 'y5tmHm0B0I9WX_Czx93x', + 'XZtmHm0B0I9WX_CzUt3H', + '-JtlHm0B0I9WX_Cz3dyX', + 'k5tlHm0B0I9WX_CzaNxm', + 'NZtkHm0B0I9WX_Cz89w9', + 'zJtkHm0B0I9WX_CzftsN', + ], + 'mpls', + 'up' + ); + }); }); }); }; diff --git a/x-pack/test/functional/page_objects/uptime_page.ts b/x-pack/test/functional/page_objects/uptime_page.ts index 7157bbfb3811b4..0ebcb5c87deeec 100644 --- a/x-pack/test/functional/page_objects/uptime_page.ts +++ b/x-pack/test/functional/page_objects/uptime_page.ts @@ -9,7 +9,7 @@ import { FtrProviderContext } from '../ftr_provider_context'; export function UptimePageProvider({ getPageObjects, getService }: FtrProviderContext) { const pageObjects = getPageObjects(['common', 'timePicker']); - const { common: commonService, navigation, alerts } = getService('uptime'); + const { alerts, common: commonService, monitor, navigation } = getService('uptime'); const retry = getService('retry'); return new (class UptimePage { @@ -137,6 +137,20 @@ export function UptimePageProvider({ getPageObjects, getService }: FtrProviderCo return commonService.clickPageSizeSelectPopoverItem(size); } + public async checkPingListInteractions( + timestamps: string[], + location?: string, + status?: string + ): Promise { + if (location) { + await monitor.setPingListLocation(location); + } + if (status) { + await monitor.setPingListStatus(status); + } + return monitor.checkForPingListTimestamps(timestamps); + } + public async resetFilters() { await this.inputFilterQuery(''); await commonService.resetStatusFilter(); diff --git a/x-pack/test/functional/services/uptime/monitor.ts b/x-pack/test/functional/services/uptime/monitor.ts index 3bdec4b6749d42..a3e3d953e2eb76 100644 --- a/x-pack/test/functional/services/uptime/monitor.ts +++ b/x-pack/test/functional/services/uptime/monitor.ts @@ -27,5 +27,22 @@ export function UptimeMonitorProvider({ getService }: FtrProviderContext) { await find.descendantExistsByCssSelector('canvas.mapboxgl-canvas', mapPanel); }); }, + async setPingListLocation(location: string) { + await testSubjects.click('xpack.uptime.pingList.locationSelect', 5000); + return testSubjects.click(`xpack.uptime.pingList.locationOptions.${location}`, 5000); + }, + async setPingListStatus(status: string) { + await testSubjects.click('xpack.uptime.pingList.statusSelect', 5000); + return testSubjects.click(`xpack.uptime.pingList.statusOptions.${status}`, 5000); + }, + async checkForPingListTimestamps(timestamps: string[]): Promise { + return retry.tryForTime(10000, async () => { + await Promise.all( + timestamps.map(timestamp => + testSubjects.existOrFail(`xpack.uptime.pingList.ping-${timestamp}`) + ) + ); + }); + }, }; } From b38c98a730f4962910e29acf7d8847346ab67e6d Mon Sep 17 00:00:00 2001 From: Alison Goryachev Date: Tue, 14 Apr 2020 09:13:20 -0400 Subject: [PATCH 12/12] =?UTF-8?q?[Remote=20clusters]=20guard=20against=20u?= =?UTF-8?q?sageCollection=20plugin=20if=20unav=E2=80=A6=20(#63284)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../public/application/services/ui_metric.ts | 21 ++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/x-pack/plugins/remote_clusters/public/application/services/ui_metric.ts b/x-pack/plugins/remote_clusters/public/application/services/ui_metric.ts index 91354155cacb05..4fc3c438e76d6c 100644 --- a/x-pack/plugins/remote_clusters/public/application/services/ui_metric.ts +++ b/x-pack/plugins/remote_clusters/public/application/services/ui_metric.ts @@ -3,17 +3,24 @@ * or more contributor license agreements. Licensed under the Elastic License; * you may not use this file except in compliance with the Elastic License. */ - +import { UiStatsMetricType, METRIC_TYPE } from '@kbn/analytics'; import { UsageCollectionSetup } from 'src/plugins/usage_collection/public'; -import { UiStatsMetricType } from '@kbn/analytics'; import { UIM_APP_NAME } from '../constants'; -export let trackUiMetric: (metricType: UiStatsMetricType, eventName: string) => void; -export let METRIC_TYPE: UsageCollectionSetup['METRIC_TYPE']; +export { METRIC_TYPE }; + +export let usageCollection: UsageCollectionSetup | undefined; + +export function init(_usageCollection: UsageCollectionSetup): void { + usageCollection = _usageCollection; +} -export function init(usageCollection: UsageCollectionSetup): void { - trackUiMetric = usageCollection.reportUiStats.bind(usageCollection, UIM_APP_NAME); - METRIC_TYPE = usageCollection.METRIC_TYPE; +export function trackUiMetric(metricType: UiStatsMetricType, name: string) { + if (!usageCollection) { + return; + } + const { reportUiStats } = usageCollection; + reportUiStats(UIM_APP_NAME, metricType, name); } /**