diff --git a/.ci/Jenkinsfile_baseline_capture b/.ci/Jenkinsfile_baseline_capture index 6993dc9e087f97..672f5127a97964 100644 --- a/.ci/Jenkinsfile_baseline_capture +++ b/.ci/Jenkinsfile_baseline_capture @@ -3,40 +3,48 @@ library 'kibana-pipeline-library' kibanaLibrary.load() -kibanaPipeline(timeoutMinutes: 120) { +kibanaPipeline(timeoutMinutes: 210) { githubCommitStatus.trackBuild(params.commit, 'kibana-ci-baseline') { ciStats.trackBuild { - catchError { - withEnv([ - 'CI_PARALLEL_PROCESS_NUMBER=1' - ]) { - parallel([ - 'oss-baseline': { - workers.ci(name: 'oss-baseline', size: 'l', ramDisk: true, runErrorReporter: false, bootstrapped: false) { - // bootstrap ourselves, but with the env needed to upload the ts refs cache - withGcpServiceAccount.fromVaultSecret('secret/kibana-issues/dev/ci-artifacts-key', 'value') { - withEnv([ - 'BUILD_TS_REFS_CACHE_ENABLE=true', - 'BUILD_TS_REFS_CACHE_CAPTURE=true' - ]) { - kibanaPipeline.doSetup() - } - } + catchErrors { + slackNotifications.onFailure( + title: "*<${env.BUILD_URL}|[${params.branch}] Baseline Capture Failure>*", + message: "[${params.branch}/${params.commit}] Baseline Capture Failure", + ) { + retryable.enable(2) - kibanaPipeline.functionalTestProcess('oss-baseline', './test/scripts/jenkins_baseline.sh')() + catchErrors { + workers.ci( + name: 'baseline-worker', + size: 'xl', + ramDisk: true, + runErrorReporter: false, + bootstrapped: false + ) { + withGcpServiceAccount.fromVaultSecret('secret/kibana-issues/dev/ci-artifacts-key', 'value') { + withEnv([ + 'BUILD_TS_REFS_CACHE_ENABLE=true', + 'BUILD_TS_REFS_CACHE_CAPTURE=true', + 'DISABLE_BOOTSTRAP_VALIDATIONS=true', + ]) { + kibanaPipeline.doSetup() + } } - }, - 'xpack-baseline': { - workers.ci(name: 'xpack-baseline', size: 'l', ramDisk: true, runErrorReporter: false) { - kibanaPipeline.functionalTestProcess('xpack-baseline', './test/scripts/jenkins_xpack_baseline.sh')() + + kibanaPipeline.withCiTaskQueue([parallel: 2]) { + catchErrors { + tasks([ + kibanaPipeline.functionalTestProcess('oss-baseline', './test/scripts/jenkins_baseline.sh'), + kibanaPipeline.functionalTestProcess('xpack-baseline', './test/scripts/jenkins_xpack_baseline.sh'), + ]) + } } - }, - ]) + } + } } } - - kibanaPipeline.sendMail() - slackNotifications.onFailure() } + + kibanaPipeline.sendMail() } } diff --git a/docs/action-type-template.asciidoc b/docs/action-type-template.asciidoc new file mode 100644 index 00000000000000..5b61c259563ad2 --- /dev/null +++ b/docs/action-type-template.asciidoc @@ -0,0 +1,73 @@ +[[-action-type]] +=== action +++++ + +++++ + +Include a short description of the action type. + +[float] +[[-connector-configuration]] +==== Connector configuration + + connectors have the following configuration properties. + +//// +List of user-facing connector configurations. This should align with the fields available in the Create connector flyout form for this action type. +//// + +Property1:: A short description of this property. +Property2:: A short description of this property with format hints. This can be specified in `this specific format`. + +[float] +[[Preconfigured--configuration]] +==== Preconfigured action type + +//// +Example preconfigured format for this action type +//// + +[source,text] +-- + my-: + name: preconfigured--action-type + actionTypeId: . + config: + property1: value1 + property2: value2 + secrets: + property3: value3 +-- + +[float] +[[-connector-config-properties]] +//// +List of properties from the ConfigSchema and SecretsSchema for this action type. +//// +Config defines information for the action type. + +`property1`:: A short description of this property. +`property2`:: A short descriptionn of this property. + +Secrets defines sensitive information for the action type. + +`property3`:: A short descriptionn of this property. + +[float] +[[-action-configuration]] +==== Action configuration + + actions have the following configuration properties. + +//// +List of user-facing action configurations. This should align with the fields available in the Action section of the Create/Update alert flyout. +//// + +Property1:: A short description of this property. +Property2:: A short description of this property with format hints. This can be specified in `this specific format`. + +//// +Optional - additional configuration details here +[[configuring-]] +==== Configure +//// diff --git a/docs/alert-type-template.asciidoc b/docs/alert-type-template.asciidoc new file mode 100644 index 00000000000000..292ed00d05496f --- /dev/null +++ b/docs/alert-type-template.asciidoc @@ -0,0 +1,39 @@ +[[alert-type-]] +=== + +Include a short description of the alert type. + +[float] +==== Create the alert + +Fill in the <>, then select **. + +[float] +==== Define the conditions + +Define properties to detect the condition. + +//// +Optional, include a screenshot +[role="screenshot"] +image::user/alerting/images/alert-types--conditions.png[Conditions for alert type] +//// + +Condition1:: This is a condition the user must define. +Condition2:: This is another condition the user must define. + +[float] +==== Add action variables + +<> to run when the alert condition is met. The following variables are specific to the alert. You can also specify <>. + +`context.variableA`:: A short description of the context variable defined by the alert type. +`context.variableB`:: A short description of the context variable defined by the alert type with an example. Example: `this is what variableB outputs`. + +//// +Optional, include a step-by-step example for creating this alert +[float] +==== Example + +In this section, you will use the {kib} <> to setup and tune the conditions on an alert. For this example, we want to detect when . +//// \ No newline at end of file diff --git a/docs/developer/plugin-list.asciidoc b/docs/developer/plugin-list.asciidoc index a2068b5b53b6dd..7cedd56badb71c 100644 --- a/docs/developer/plugin-list.asciidoc +++ b/docs/developer/plugin-list.asciidoc @@ -29,6 +29,8 @@ as uiSettings within the code. |{kib-repo}blob/{branch}/src/plugins/apm_oss/README.asciidoc[apmOss] +|undefined + |{kib-repo}blob/{branch}/src/plugins/bfetch/README.md[bfetch] |bfetch allows to batch HTTP requests and streams responses back. diff --git a/docs/management/advanced-options.asciidoc b/docs/management/advanced-options.asciidoc index c7d5242da69de4..3ee7a0471eec13 100644 --- a/docs/management/advanced-options.asciidoc +++ b/docs/management/advanced-options.asciidoc @@ -83,6 +83,10 @@ specific dashboard, application, or saved object as they enter each space. [[fields-popularlimit]]`fields:popularLimit`:: The top N most popular fields to show. +[[fileupload-maxfilesize]]`fileUpload:maxFileSize`:: +Sets the file size limit when importing files. The default +value is `100MB`. The highest supported value for this setting is `1GB`. + [[filtereditor-suggestvalues]]`filterEditor:suggestValues`:: Set this property to `false` to prevent the filter editor from suggesting values for fields. @@ -257,7 +261,7 @@ Hides the "Time" column in *Discover* and in all saved searches on dashboards. Highlights results in *Discover* and saved searches on dashboards. Highlighting slows requests when working on big documents. -[[doctable-legacy]]`doc_table:legacy`:: +[[doctable-legacy]]`doc_table:legacy`:: Controls the way the document table looks and works. Set this property to `true` to revert to the legacy implementation. [[discover-searchFieldsFromSource]]`discover:searchFieldsFromSource`:: @@ -281,10 +285,6 @@ must contain `from` and `to` values (see {ref}/common-options.html#date-math[accepted formats]). It is ignored unless `ml:anomalyDetection:results:enableTimeDefaults` is enabled. -[[ml-filedatavisualizermaxfilesize]]`ml:fileDataVisualizerMaxFileSize`:: -Sets the file size limit when importing data in the {data-viz}. The default -value is `100MB`. The highest supported value for this setting is `1GB`. - [float] [[kibana-notification-settings]] diff --git a/docs/user/alerting/action-types/email.asciidoc b/docs/user/alerting/action-types/email.asciidoc index 0c238da1b39e38..3813eccd048d9d 100644 --- a/docs/user/alerting/action-types/email.asciidoc +++ b/docs/user/alerting/action-types/email.asciidoc @@ -1,6 +1,9 @@ [role="xpack"] [[email-action-type]] === Email action +++++ +Email +++++ The email action type uses the SMTP protocol to send mail message, using an integration of https://nodemailer.com/[Nodemailer]. Email message text is sent as both plain text and html text. @@ -10,14 +13,15 @@ NOTE: For emails to have a footer with a link back to {kib}, set the <"` format. See the https://nodemailer.com/message/addresses/[Nodemailer address documentation] for more information. Host:: Host name of the service provider. If you are using the <> setting, make sure this hostname is added to the allowed hosts. Port:: The port to connect to on the service provider. Secure:: If true, the connection will use TLS when connecting to the service provider. Refer to the https://nodemailer.com/smtp/#tls-options[Nodemailer TLS documentation] for more information. If not true, the connection will initially connect over TCP, then attempt to switch to TLS via the SMTP STARTTLS command. -User:: Username for login type authentication. +Require authentication:: If true, a username and password for login type authentication must be provided. +Username:: Username for login type authentication. Password:: Password for login type authentication. [float] @@ -39,56 +43,33 @@ Password:: Password for login type authentication. password: passwordkeystorevalue -- -[[email-connector-config-properties]] -**`config`** defines the action type specific to the configuration and contains the following properties: +Config defines information for the action type. -[cols="2*<"] -|=== +`service`:: The name of a https://nodemailer.com/smtp/well-known/[well-known email service provider]. If `service` is provided, `host`, `port`, and `secure` properties are ignored. For more information on the `gmail` service value, see the https://nodemailer.com/usage/using-gmail/[Nodemailer Gmail documentation]. +`from`:: An email address that corresponds to *Sender*. +`host`:: A string that corresponds to *Host*. +`port`:: A number that corresponds to *Port*. +`secure`:: A boolean that corresponds to *Secure*. +`hasAuth`:: A boolean that corresponds to *Requires authentication*. If `true`, this connector will require values for `user` and `password` inside the secrets configuration. Defaults to `true`. -| `service` -| The name of a https://nodemailer.com/smtp/well-known/[well-known email service provider]. If `service` is provided, `host`, `port`, and `secure` properties are ignored. For more information on the `gmail` service value, see the (https://nodemailer.com/usage/using-gmail/)[Nodemailer Gmail documentation]. +Secrets defines sensitive information for the action type. -| `from` -| An email address that corresponds to *Sender*. +`user`:: A string that corresponds to *Username*. Required if `hasAuth` is set to `true`. +`password`:: A string that corresponds to *Password*. Should be stored in the <>. Required if `hasAuth` is set to `true`. -| `host` -| A string that corresponds to *Host*. - -| `port` -| A number that corresponds to *Port*. - -| `secure` -| A boolean that corresponds to *Secure*. - -| `hasAuth` -| If `true`, this connector will require values for `user` and `password` inside the secrets configuration. Defaults to `true`. - -|=== - -**`secrets`** defines sensitive information for the action type and contains the following properties: - -[cols="2*<"] -|=== - -| `user` -| A string that corresponds to *User*. Required if `hasAuth` is set to `true`. - -| `password` -| A string that corresponds to *Password*. Should be stored in the <>. Required if `hasAuth` is set to `true`. - -|=== +[float] [[email-action-configuration]] ==== Action configuration -Email actions have the following configuration properties: +Email actions have the following configuration properties. -To, CC, BCC:: Each is a list of addresses. Addresses can be specified in `user@host-name` format, or in `name ` format. One of To, CC, or BCC must contain an entry. +To, CC, BCC:: Each item is a list of addresses. Addresses can be specified in `user@host-name` format, or in `name ` format. One of To, CC, or BCC must contain an entry. Subject:: The subject line of the email. Message:: The message text of the email. Markdown format is supported. [[configuring-email]] -==== Configuring email accounts +==== Configuring email accounts for well-known services The email action can send email using many popular SMTP email services. diff --git a/docs/user/alerting/action-types/index.asciidoc b/docs/user/alerting/action-types/index.asciidoc index 7ecc1cdb4f74e8..a57048243d7577 100644 --- a/docs/user/alerting/action-types/index.asciidoc +++ b/docs/user/alerting/action-types/index.asciidoc @@ -1,6 +1,9 @@ [role="xpack"] [[index-action-type]] === Index action +++++ +Index +++++ The index action type will index a document into {es}. See also the {ref}/indices-create-index.html[create index API]. @@ -8,7 +11,7 @@ The index action type will index a document into {es}. See also the {ref}/indice [[index-connector-configuration]] ==== Connector configuration -Index connectors have the following configuration properties: +Index connectors have the following configuration properties. Name:: The name of the connector. The name is used to identify a connector in the management UI connector listing, or in the connector list when configuring an action. Index:: The {es} index to be written to. @@ -30,32 +33,24 @@ Execution time field:: This field will be automatically set to the time the ale executionTimeField: somedate -- -[[index-connector-config-properties]] -**`config`** defines the action type specific to the configuration and contains the following properties: - -[cols="2*<"] -|=== - -|`index` -| A string that corresponds to *Index*. - -|`refresh` -| A boolean that corresponds to *Refresh*. Defaults to `false`. - -|`executionTimeField` -| A string that corresponds to *Execution time field*. - -|=== +Config defines information for the action type. +`index`:: A string that corresponds to *Index*. +`refresh`:: A boolean that corresponds to *Refresh*. Defaults to `false`. +`executionTimeField`:: A string that corresponds to *Execution time field*. [float] [[index-action-configuration]] ==== Action configuration -Index actions have the following properties: +Index actions have the following properties. Document:: The document to index in JSON format. +[float] +[[index-action-example]] +==== Example + Example of the index document for Index Threshold alert: [source,text] diff --git a/docs/user/alerting/action-types/jira.asciidoc b/docs/user/alerting/action-types/jira.asciidoc index 0740cf7838b15a..a1941b4b302834 100644 --- a/docs/user/alerting/action-types/jira.asciidoc +++ b/docs/user/alerting/action-types/jira.asciidoc @@ -1,6 +1,9 @@ [role="xpack"] [[jira-action-type]] === Jira action +++++ +Jira +++++ The Jira action type uses the https://developer.atlassian.com/cloud/jira/platform/rest/v2/[REST API v2] to create Jira issues. @@ -8,7 +11,7 @@ The Jira action type uses the https://developer.atlassian.com/cloud/jira/platfor [[jira-connector-configuration]] ==== Connector configuration -Jira connectors have the following configuration properties: +Jira connectors have the following configuration properties. Name:: The name of the connector. The name is used to identify a connector in the **Stack Management** UI connector listing, and in the connector list when configuring an action. URL:: Jira instance URL. @@ -33,78 +36,31 @@ API token (or password):: Jira API authentication token (or password) for HTTP apiToken: tokenkeystorevalue -- -[[jira-connector-config-properties]] -**`config`** defines the action type specific to the configuration and contains the following properties: +Config defines information for the action type. -[cols="2*<"] -|=== +`apiUrl`:: An address that corresponds to *URL*. +`projectKey`:: A key that corresponds to *Project Key*. -| `apiUrl` -| An address that corresponds to *URL*. +Secrets defines sensitive information for the action type. -| `projectKey` -| A key that corresponds to *Project Key*. - -|=== - -**`secrets`** defines sensitive information for the action type and contains the following properties: - -[cols="2*<"] -|=== - -| `email` -| A string that corresponds to *Email*. - -| `apiToken` -| A string that corresponds to *API Token*. Should be stored in the <>. - -|=== +`email`:: A string that corresponds to *Email*. +`apiToken`:: A string that corresponds to *API Token*. Should be stored in the <>. +[float] [[jira-action-configuration]] ==== Action configuration -Jira actions have the following configuration properties: - -Subaction:: The subaction to perform: `pushToService`, `getIncident`, `issueTypes`, `fieldsByIssueType`, `issues`, `issue`, or `getFields`. -Subaction params:: The parameters of the subaction. - -==== `pushToService` subaction configuration - -Incident:: A Jira incident has the following properties: -* `summary` - The title of the issue. -* `description` - A description of the issue. -* `externalId` - The ID of the issue in Jira. If present, the issue is updated. Otherwise, a new issue is created. -* `issueType` - The ID of the issue type in Jira. -* `priority` - The priority level in Jira. Example: `Medium`. -* `labels` - An array of labels. Labels cannot contain spaces. -* `parent` - The parent issue ID or key. Only for subtask issue types. -Comments:: A comment in the form of `{ commentId: string, version: string, comment: string }`. - -==== `getIncident` subaction configuration - -External ID:: The ID of the issue in Jira. - -==== `issueTypes` subaction configuration - -The `issueTypes` subaction has no parameters. Provide an empty object `{}`. - -==== `fieldsByIssueType` subaction configuration - -ID:: The ID of the issue in Jira. - -==== `issues` subaction configuration - -Title:: The title to search for. - -==== `issue` subaction configuration - -ID:: The ID of the issue in Jira. - -==== `getFields` subaction configuration +Jira actions have the following configuration properties. -The `getFields` subaction has no parameters. Provide an empty object `{}`. +Issue type:: The type of the issue. +Priority:: The priority of the incident. +Labels:: The labels for the incident. +Title:: A title for the issue, used for searching the contents of the knowledge base. +Description:: The details about the incident. +Parent:: The ID or key of the parent issue. Only for `Subtask` issue types. +Additional comments:: Additional information for the client, such as how to troubleshoot the issue. [[configuring-jira]] -==== Configuring and testing Jira +==== Configure Jira Jira offers free https://www.atlassian.com/software/jira/free[Instances], which you can use to test incidents. diff --git a/docs/user/alerting/action-types/pagerduty.asciidoc b/docs/user/alerting/action-types/pagerduty.asciidoc index cadf8e0b16a44d..f74b5773b37197 100644 --- a/docs/user/alerting/action-types/pagerduty.asciidoc +++ b/docs/user/alerting/action-types/pagerduty.asciidoc @@ -1,49 +1,72 @@ [role="xpack"] [[pagerduty-action-type]] === PagerDuty action +++++ +PagerDuty +++++ The PagerDuty action type uses the https://v2.developer.pagerduty.com/docs/events-api-v2[v2 Events API] to trigger, acknowledge, and resolve PagerDuty alerts. -* <> -* <> -* <> - [float] -[[pagerduty-benefits]] -==== PagerDuty + Elastic integration benefits +[[pagerduty-connector-configuration]] +==== Connector configuration -By integrating PagerDuty with alerts, you can: +PagerDuty connectors have the following configuration properties. -* Route your alerts to the right PagerDuty responder within your team, based on your structure, escalation policies, and workflows. -* Automatically generate incidents of different types and severity based on each alert’s context. -* Tailor the incident data to match your needs by easily passing the alerting context from Kibana to PagerDuty. +Name:: The name of the connector. The name is used to identify a connector in the management UI connector listing, or in the connector list when configuring an action. +API URL:: An optional PagerDuty event URL. Defaults to `https://events.pagerduty.com/v2/enqueue`. If you are using the <> setting, make sure the hostname is added to the allowed hosts. +Integration Key:: A 32 character PagerDuty Integration Key for an integration on a service, also referred to as the routing key. [float] -[[pagerduty-how-it-works]] -===== How it works +[[Preconfigured-pagerduty-configuration]] +==== Preconfigured action type + +[source,text] +-- + my-pagerduty: + name: preconfigured-pagerduty-action-type + actionTypeId: .pagerduty + config: + apiUrl: https://test.host + secrets: + routingKey: testroutingkey +-- + +Config defines information for the action type. + +`apiURL`:: A URL string that corresponds to *API URL*. -{kib} allows you to create alerts to notify you of a significant move -in your dataset. -You can create alerts for all your Observability, Security, and Elastic Stack use cases. -Alerts will trigger a new incident on the corresponding PagerDuty service. +Secrets defines sensitive information for the action type. + +`routingKey`:: A string that corresponds to *Integration Key*. [float] -===== Requirements +[[pagerduty-action-configuration]] +==== Action configuration -In the `kibana.yml` configuration file, you must add the <>. -This is required to encrypt parameters that must be secured, for example PagerDuty’s integration key. +PagerDuty actions have the following properties. -If you have security enabled: +Severity:: The perceived severity of on the affected system. This can be one of `Critical`, `Error`, `Warning` or `Info`(default). +Event action:: One of `Trigger` (default), `Resolve`, or `Acknowledge`. See https://v2.developer.pagerduty.com/docs/events-api-v2#event-action[event action] for more details. +Dedup Key:: All actions sharing this key will be associated with the same PagerDuty alert. This value is used to correlate trigger and resolution. This value is *optional*, and if not set, defaults to `:`. The maximum length is *255* characters. See https://v2.developer.pagerduty.com/docs/events-api-v2#alert-de-duplication[alert deduplication] for details. +Timestamp:: An *optional* https://v2.developer.pagerduty.com/v2/docs/types#datetime[ISO-8601 format date-time], indicating the time the event was detected or generated. +Component:: An *optional* value indicating the component of the source machine that is responsible for the event, for example `mysql` or `eth0`. +Group:: An *optional* value indicating the logical grouping of components of a service, for example `app-stack`. +Source:: An *optional* value indicating the affected system, preferably a hostname or fully qualified domain name. Defaults to the {kib} saved object id of the action. +Summary:: An *optional* text summary of the event, defaults to `No summary provided`. The maximum length is 1024 characters. +Class:: An *optional* value indicating the class/type of the event, for example `ping failure` or `cpu load`. -* You must have -application privileges to access Metrics, APM, Uptime, or Security. -* If you are using a self-managed deployment with security, you must have -Transport Security Layer (TLS) enabled for communication <>. -Alerts uses API keys to secure background alert checks and actions, -and API keys require {ref}/configuring-tls.html#tls-http[TLS on the HTTP interface]. +For more details on these properties, see https://v2.developer.pagerduty.com/v2/docs/send-an-event-events-api-v2[PagerDuty v2 event parameters]. -Although not a requirement, to harden the integrations security you might want to -review the <> that are available to you. +[float] +[[pagerduty-benefits]] +==== Configure PagerDuty + +By integrating PagerDuty with alerts, you can: + +* Route your alerts to the right PagerDuty responder within your team, based on your structure, escalation policies, and workflows. +* Automatically generate incidents of different types and severity based on each alert’s context. +* Tailor the incident data to match your needs by easily passing the alerting context from Kibana to PagerDuty. [float] [[pagerduty-support]] @@ -111,80 +134,3 @@ To see the available context variables, click on the *Add alert variable* icon n to each corresponding field. For more details on these parameters, see the <> and the PagerDuty https://v2.developer.pagerduty.com/v2/docs/send-an-event-events-api-v2[API v2 documentation]. - - -[float] -[[pagerduty-uninstall]] -===== How to uninstall -To remove a PagerDuty connector from an alert, simply remove it -from the *Actions* section of that alert, using the remove (x) icon. -This will disable the integration for the particular alert. - -To delete the connector entirely, open the main menu, then click *Stack Management > Alerts and Actions*. -Select the *Connectors* tab, and then click on the delete icon. -This is an irreversible action and impacts all alerts that use this connector. - - -[float] -[[pagerduty-connector-configuration]] -==== Connector configuration - -PagerDuty connectors have the following configuration properties: - -Name:: The name of the connector. The name is used to identify a connector in the management UI connector listing, or in the connector list when configuring an action. -API URL:: An optional PagerDuty event URL. Defaults to `https://events.pagerduty.com/v2/enqueue`. If you are using the <> setting, make sure the hostname is added to the allowed hosts. -Integration Key:: A 32 character PagerDuty Integration Key for an integration on a service, also referred to as the routing key. - -[float] -[[Preconfigured-pagerduty-configuration]] -==== Preconfigured action type - -[source,text] --- - my-pagerduty: - name: preconfigured-pagerduty-action-type - actionTypeId: .pagerduty - config: - apiUrl: https://test.host - secrets: - routingKey: testroutingkey --- - -[[pagerduty-connector-config-properties]] -**`config`** defines the action type specific to the configuration and contains the following properties: - -[cols="2*<"] -|=== - -|`apiURL` -| A URL string that corresponds to *API URL*. - -|=== - -**`secrets`** defines sensitive information for the action type and contains the following properties: - -[cols="2*<"] -|=== - -|`routingKey` -| A string that corresponds to *Integration Key*. - -|=== - -[float] -[[pagerduty-action-configuration]] -==== Action configuration - -PagerDuty actions have the following properties: - -Severity:: The perceived severity of on the affected system. This can be one of `Critical`, `Error`, `Warning` or `Info`(default). -Event action:: One of `Trigger` (default), `Resolve`, or `Acknowledge`. See https://v2.developer.pagerduty.com/docs/events-api-v2#event-action[event action] for more details. -Dedup Key:: All actions sharing this key will be associated with the same PagerDuty alert. This value is used to correlate trigger and resolution. This value is *optional*, and if not set, defaults to `:`. The maximum length is *255* characters. See https://v2.developer.pagerduty.com/docs/events-api-v2#alert-de-duplication[alert deduplication] for details. -Timestamp:: An *optional* https://v2.developer.pagerduty.com/v2/docs/types#datetime[ISO-8601 format date-time], indicating the time the event was detected or generated. -Component:: An *optional* value indicating the component of the source machine that is responsible for the event, for example `mysql` or `eth0`. -Group:: An *optional* value indicating the logical grouping of components of a service, for example `app-stack`. -Source:: An *optional* value indicating the affected system, preferably a hostname or fully qualified domain name. Defaults to the {kib} saved object id of the action. -Summary:: An *optional* text summary of the event, defaults to `No summary provided`. The maximum length is 1024 characters. -Class:: An *optional* value indicating the class/type of the event, for example `ping failure` or `cpu load`. - -For more details on these properties, see https://v2.developer.pagerduty.com/v2/docs/send-an-event-events-api-v2[PagerDuty v2 event parameters]. diff --git a/docs/user/alerting/action-types/resilient.asciidoc b/docs/user/alerting/action-types/resilient.asciidoc index dfa95e2deec008..296156875ceb69 100644 --- a/docs/user/alerting/action-types/resilient.asciidoc +++ b/docs/user/alerting/action-types/resilient.asciidoc @@ -1,6 +1,9 @@ [role="xpack"] [[resilient-action-type]] === IBM Resilient action +++++ +IBM Resilient +++++ The IBM Resilient action type uses the https://developer.ibm.com/security/resilient/rest/[RESILIENT REST v2] to create IBM Resilient incidents. @@ -8,7 +11,7 @@ The IBM Resilient action type uses the https://developer.ibm.com/security/resili [[resilient-connector-configuration]] ==== Connector configuration -IBM Resilient connectors have the following configuration properties: +IBM Resilient connectors have the following configuration properties. Name:: The name of the connector. The name is used to identify a connector in the **Stack Management** UI connector listing, and in the connector list when configuring an action. URL:: IBM Resilient instance URL. @@ -33,64 +36,29 @@ API key secret:: The authentication key secret for HTTP Basic authentication. apiKeySecret: tokenkeystorevalue -- -[[resilient-connector-config-properties]] -**`config`** defines the action type specific to the configuration and contains the following properties: +Config defines information for the action type. -[cols="2*<"] -|=== +`apiUrl`:: An address that corresponds to *URL*. +`orgId`:: An ID that corresponds to *Organization ID*. -| `apiUrl` -| An address that corresponds to *URL*. +Secrets defines sensitive information for the action type. -| `orgId` -| An ID that corresponds to *Organization ID*. - -|=== - -**`secrets`** defines sensitive information for the action type and contains the following properties: - -[cols="2*<"] -|=== - -| `apiKeyId` -| A string that corresponds to *API key ID*. - -| `apiKeySecret` -| A string that corresponds to *API Key secret*. Should be stored in the <>. - -|=== +`apiKeyId`:: A string that corresponds to *API key ID*. +`apiKeySecret`:: A string that corresponds to *API Key secret*. Should be stored in the <>. +[float] [[resilient-action-configuration]] ==== Action configuration -IBM Resilient actions have the following configuration properties: - -Subaction:: The subaction to perform: `pushToService`, `getFields`, `incidentTypes`, or `severity`. -Subaction params:: The parameters of the subaction. - -==== `pushToService` subaction configuration - -Incident:: The IBM resilient incident has the following properties: -* `name` - A name for the issue, used for searching the contents of the knowledge base. -* `description` - The details about the incident. -* `externalId` - The ID of the incident in IBM Resilient. If present, the incident is updated. Otherwise, a new incident is created. -* `incidentTypes` - An array with the IDs of IBM Resilient incident types. -* `severityCode` - The IBM Resilient ID of the severity code. -Comments:: A comment in the form of `{ commentId: string, version: string, comment: string }`. - -===== `getFields` subaction configuration - -The `getFields` subaction has not parameters. Provide an empty object `{}`. - -===== `incidentTypes` subaction configuration - -The `incidentTypes` subaction has no parameters. Provide an empty object `{}`. - -===== `severity` subaction configuration +IBM Resilient actions have the following configuration properties. -The `severity` subaction has no parameters. Provide an empty object `{}`. +Incident types:: The type of the incident. +Severity code:: The severity of the incident. +Name:: A name for the issue, used for searching the contents of the knowledge base. +Description:: The details about the incident. +Additional comments:: Additional information for the client, such as how to troubleshoot the issue. [[configuring-resilient]] -==== Configuring and testing IBM Resilient +==== Configure IBM Resilient IBM Resilient offers https://www.ibm.com/security/intelligent-orchestration/resilient[Instances], which you can use to test incidents. diff --git a/docs/user/alerting/action-types/server-log.asciidoc b/docs/user/alerting/action-types/server-log.asciidoc index 276f64e7786bd9..7849a70a239c36 100644 --- a/docs/user/alerting/action-types/server-log.asciidoc +++ b/docs/user/alerting/action-types/server-log.asciidoc @@ -1,6 +1,9 @@ [role="xpack"] [[server-log-action-type]] === Server log action +++++ +Server log +++++ This action type writes an entry to the {kib} server log. @@ -8,7 +11,7 @@ This action type writes an entry to the {kib} server log. [[server-log-connector-configuration]] ==== Connector configuration -Server log connectors have the following configuration properties: +Server log connectors have the following configuration properties. Name:: The name of the connector. The name is used to identify a connector in the management UI connector listing, or in the connector list when configuring an action. @@ -27,7 +30,7 @@ Name:: The name of the connector. The name is used to identify a connector [[server-log-action-configuration]] ==== Action configuration -Server log actions have the following properties: +Server log actions have the following properties. Message:: The message to log. Level:: The log level of the message: `trace`, `debug`, `info`, `warn`, `error` or `fatal`. Defaults to `info`. diff --git a/docs/user/alerting/action-types/servicenow.asciidoc b/docs/user/alerting/action-types/servicenow.asciidoc index d1ee1b9357737d..f002c39416f1ad 100644 --- a/docs/user/alerting/action-types/servicenow.asciidoc +++ b/docs/user/alerting/action-types/servicenow.asciidoc @@ -1,6 +1,9 @@ [role="xpack"] [[servicenow-action-type]] === ServiceNow action +++++ +ServiceNow +++++ The ServiceNow action type uses the https://developer.servicenow.com/app.do#!/rest_api_doc?v=orlando&id=c_TableAPI[V2 Table API] to create ServiceNow incidents. @@ -8,7 +11,7 @@ The ServiceNow action type uses the https://developer.servicenow.com/app.do#!/re [[servicenow-connector-configuration]] ==== Connector configuration -ServiceNow connectors have the following configuration properties: +ServiceNow connectors have the following configuration properties. Name:: The name of the connector. The name is used to identify a connector in the **Stack Management** UI connector listing, and in the connector list when configuring an action. URL:: ServiceNow instance URL. @@ -31,64 +34,29 @@ Password:: Password for HTTP Basic authentication. password: passwordkeystorevalue -- -[[servicenow-connector-config-properties]] -**`config`** defines the action type specific to the configuration and contains the following properties: +Config defines information for the action type. -[cols="2*<"] -|=== +`apiUrl`:: An address that corresponds to *URL*. -| `apiUrl` -| An address that corresponds to *URL*. +Secrets defines sensitive information for the action type. -|=== - -**`secrets`** defines sensitive information for the action type and contains the following properties: - -[cols="2*<"] -|=== - -| `username` -| A string that corresponds to *Username*. - -| `password` -| A string that corresponds to *Password*. Should be stored in the <>. - -|=== +`username`:: A string that corresponds to *Username*. +`password`:: A string that corresponds to *Password*. Should be stored in the <>. +[float] [[servicenow-action-configuration]] ==== Action configuration -ServiceNow actions have the following configuration properties: - -Subaction:: The subaction to perform: `pushToService`, `getFields`, `getIncident`, or `getChoices`. -Subaction params:: The parameters of the subaction. - -==== `pushToService` subaction configuration - -Incident:: The ServiceNow incident has the following properties: -* `short_description` - A short description for the incident, used for searching the contents of the knowledge base. -* `description` - The details about the incident. -* `externalId` - The ID of the incident in ServiceNow. If present, the incident is updated. Otherwise, a new incident is created. -* `severity` - The severity of the incident. -* `urgency` - The extent to which the incident resolution can delay. -* `impact` - The effect an incident has on business. Can be measured by the number of affected users or by how critical it is to the business in question. -* `category` - The name of the category in ServiceNow. -* `subcategory` - The name of the subcategory in ServiceNow. -Comments:: A comment in the form of `{ commentId: string, version: string, comment: string }`. - -===== `getFields` subaction configuration - -The `getFields` subaction has no parameters. Provide an empty object `{}`. - -===== `getIncident` subaction configuration - -External ID:: The ID of the incident in ServiceNow. - -===== `getChoices` subaction configuration +ServiceNow actions have the following configuration properties. -Fields:: An array of fields. Example: `[priority, category, impact]`. +Urgency:: The extent to which the incident resolution can delay. +Severity:: The severity of the incident. +Impact:: The effect an incident has on business. Can be measured by the number of affected users or by how critical it is to the business in question. +Short description:: A short description for the incident, used for searching the contents of the knowledge base. +Description:: The details about the incident. +Additional comments:: Additional information for the client, such as how to troubleshoot the issue. [[configuring-servicenow]] -==== Configuring and testing ServiceNow +==== Configure ServiceNow ServiceNow offers free https://developer.servicenow.com/dev.do#!/guides/madrid/now-platform/pdi-guide/obtaining-a-pdi[Personal Developer Instances], which you can use to test incidents. diff --git a/docs/user/alerting/action-types/slack.asciidoc b/docs/user/alerting/action-types/slack.asciidoc index 62589697533562..6f7d1b3e11d318 100644 --- a/docs/user/alerting/action-types/slack.asciidoc +++ b/docs/user/alerting/action-types/slack.asciidoc @@ -1,6 +1,9 @@ [role="xpack"] [[slack-action-type]] === Slack action +++++ +Slack +++++ The Slack action type uses https://api.slack.com/incoming-webhooks[Slack Incoming Webhooks]. @@ -8,7 +11,7 @@ The Slack action type uses https://api.slack.com/incoming-webhooks[Slack Incomin [[slack-connector-configuration]] ==== Connector configuration -Slack connectors have the following configuration properties: +Slack connectors have the following configuration properties. Name:: The name of the connector. The name is used to identify a connector in the management UI connector listing, or in the connector list when configuring an action. Webhook URL:: The URL of the incoming webhook. See https://api.slack.com/messaging/webhooks#getting_started[Slack Incoming Webhooks] for instructions on generating this URL. If you are using the <> setting, make sure the hostname is added to the allowed hosts. @@ -26,29 +29,20 @@ Webhook URL:: The URL of the incoming webhook. See https://api.slack.com/messa webhookUrl: 'https://hooks.slack.com/services/abcd/efgh/ijklmnopqrstuvwxyz' -- -**`secrets`** defines sensitive information for the action type and contains the following properties: +Secrets defines sensitive information for the action type. -[cols="2*<"] -|=== - -| `webhookUrl` -| A string that corresponds to *Webhook URL*. - -|=== +`webhookUrl`:: A string that corresponds to *Webhook URL*. [float] [[slack-action-configuration]] ==== Action configuration -Slack actions have the following properties: +Slack actions have the following properties. Message:: The message text, converted to the `text` field in the Webhook JSON payload. Currently only the text field is supported. Markdown, images, and other advanced formatting are not yet supported. [[configuring-slack]] -==== Configuring Slack Accounts - -You configure the accounts Slack action type can use to communicate with Slack in the -connector form. +==== Configure a Slack account You need a https://api.slack.com/incoming-webhooks[Slack webhook URL] to configure a Slack account. To create a webhook diff --git a/docs/user/alerting/action-types/teams.asciidoc b/docs/user/alerting/action-types/teams.asciidoc index 7f4a29dc86fc52..294b5474e390a4 100644 --- a/docs/user/alerting/action-types/teams.asciidoc +++ b/docs/user/alerting/action-types/teams.asciidoc @@ -1,6 +1,9 @@ [role="xpack"] [[teams-action-type]] === Microsoft Teams action +++++ +Microsoft Teams +++++ The Microsoft Teams action type uses https://docs.microsoft.com/en-us/microsoftteams/platform/webhooks-and-connectors/how-to/add-incoming-webhook[Incoming Webhooks]. @@ -8,7 +11,7 @@ The Microsoft Teams action type uses https://docs.microsoft.com/en-us/microsoftt [[teams-connector-configuration]] ==== Connector configuration -Microsoft Teams connectors have the following configuration properties: +Microsoft Teams connectors have the following configuration properties. Name:: The name of the connector. The name is used to identify a connector in the management UI connector listing, or in the connector list when configuring an action. Webhook URL:: The URL of the incoming webhook. See https://docs.microsoft.com/en-us/microsoftteams/platform/webhooks-and-connectors/how-to/add-incoming-webhook#add-an-incoming-webhook-to-a-teams-channel[Add Incoming Webhooks] for instructions on generating this URL. If you are using the <> setting, make sure the hostname is added to the allowed hosts. @@ -26,28 +29,20 @@ Webhook URL:: The URL of the incoming webhook. See https://docs.microsoft.com/ webhookUrl: 'https://outlook.office.com/webhook/abcd@0123456/IncomingWebhook/abcdefgh/ijklmnopqrstuvwxyz' -- -[[teams-connector-config-properties]] -**`secrets`** defines sensitive information for the action type and contains the following properties: - -[cols="2*<"] -|=== - -| `webhookUrl` -| A string that corresponds to *Webhook URL*. - -|=== +Secrets defines sensitive information for the action type. +`webhookUrl`:: A string that corresponds to *Webhook URL*. [float] [[teams-action-configuration]] ==== Action configuration -Microsoft Teams actions have the following properties: +Microsoft Teams actions have the following properties. Message:: The message text, converted to the `text` field in the Webhook JSON payload. Currently only the text field is supported. Markdown, images, and other advanced formatting are not yet supported. [[configuring-teams]] -==== Configuring Microsoft Teams Accounts +==== Configure a Microsoft Teams account You need a https://docs.microsoft.com/en-us/microsoftteams/platform/webhooks-and-connectors/how-to/add-incoming-webhook[Microsoft Teams webhook URL] to configure a Microsoft Teams action. To create a webhook diff --git a/docs/user/alerting/action-types/webhook.asciidoc b/docs/user/alerting/action-types/webhook.asciidoc index efe1077707ef09..381d6e72bf9c0c 100644 --- a/docs/user/alerting/action-types/webhook.asciidoc +++ b/docs/user/alerting/action-types/webhook.asciidoc @@ -1,6 +1,9 @@ [role="xpack"] [[webhook-action-type]] === Webhook action +++++ +Webhook +++++ The Webhook action type uses https://github.com/axios/axios[axios] to send a POST or PUT request to a web service. @@ -8,13 +11,14 @@ The Webhook action type uses https://github.com/axios/axios[axios] to send a POS [[webhook-connector-configuration]] ==== Connector configuration -Webhook connectors have the following configuration properties: +Webhook connectors have the following configuration properties. Name:: The name of the connector. The name is used to identify a connector in the management UI connector listing, or in the connector list when configuring an action. URL:: The request URL. If you are using the <> setting, make sure the hostname is added to the allowed hosts. Method:: HTTP request method, either `POST`(default) or `PUT`. Headers:: A set of key-value pairs sent as headers with the request -User:: Username for HTTP basic authentication. +Require authentication:: If true, a username and password for login type authentication must be provided. +Username:: Username for HTTP basic authentication. Password:: Password for HTTP basic authentication. [float] @@ -36,45 +40,23 @@ Password:: Password for HTTP basic authentication. password: passwordkeystorevalue -- -[[webhook-connector-config-properties]] -**`config`** defines the action type specific to the configuration and contains the following properties: +Config defines information for the action type. -[cols="2*<"] -|=== +`url`:: A URL string that corresponds to *URL*. +`method`:: A string that corresponds to *Method*. +`headers`:: A record that corresponds to *Headers*. +`hasAuth`:: A boolean that corresponds to *Requires authentication*. If `true`, this connector will require values for `user` and `password` inside the secrets configuration. Defaults to `true`. -|`url` -| A URL string that corresponds to *URL*. - -|`method` -| A string that corresponds to *Method*. - -|`headers` -|A record that corresponds to *Headers*. - -| `hasAuth` -| If `true`, this connector will require values for `user` and `password` inside the secrets configuration. Defaults to `true`. - -|=== - -**`secrets`** defines sensitive information for the action type and contains the following properties: - -[cols="2*<"] -|=== - -|`user` -|A string that corresponds to *User*. Required if `hasAuth` is set to `true`. - -|`password` -|A string that corresponds to *Password*. Should be stored in the <>. Required if `hasAuth` is set to `true`. - -|=== +Secrets defines sensitive information for the action type. +`user`:: A string that corresponds to *User*. Required if `hasAuth` is set to `true`. +`password`:: A string that corresponds to *Password*. Should be stored in the <>. Required if `hasAuth` is set to `true`. [float] [[webhook-action-configuration]] ==== Action configuration -Webhook actions have the following properties: +Webhook actions have the following properties. Body:: A JSON payload sent to the request URL. For example: + diff --git a/docs/user/alerting/alert-types.asciidoc b/docs/user/alerting/alert-types.asciidoc index 5afce8fa6cd93b..9eac084bd03c40 100644 --- a/docs/user/alerting/alert-types.asciidoc +++ b/docs/user/alerting/alert-types.asciidoc @@ -10,14 +10,13 @@ Kibana provides two types of alerts: [float] ==== Standard stack alerts -Users require the `all` privilege to access to the *Stack Alerts* feature and create and edit alerts. . -See <> for more information. - {kib} provides two stack alerts: * <> * <> +Users require the `all` privilege to access the *Stack Alerts* feature and create and edit alerts. +See <> for more information. [float] ==== Domain-specific alerts diff --git a/docs/user/alerting/defining-alerts.asciidoc b/docs/user/alerting/defining-alerts.asciidoc index 8c8e25cea407a0..27f3a6c7309cb0 100644 --- a/docs/user/alerting/defining-alerts.asciidoc +++ b/docs/user/alerting/defining-alerts.asciidoc @@ -5,9 +5,9 @@ {kib} alerts can be created in a variety of apps including <>, <>, <>, <>, <> and from <> UI. While alerting details may differ from app to app, they share a common interface for defining and configuring alerts that this section describes in more detail. [float] -=== Alert flyout +=== Create an alert -When an alert is created in an app, the app will display a flyout panel with three main sections to configure: +When you create an alert, you must define the alert details, conditions, and actions. . <> . <> @@ -19,7 +19,7 @@ image::images/alert-flyout-sections.png[The three sections of an alert definitio [[defining-alerts-general-details]] === General alert details -All alerts share the following four properties in common: +All alerts share the following four properties. [role="screenshot"] image::images/alert-flyout-general-details.png[alt='All alerts have name, tags, check every, and notify properties in common'] @@ -69,6 +69,7 @@ Each action type exposes different properties. For example an email action allow image::images/alert-flyout-action-details.png[UI for defining an email action] [float] +[[defining-alerts-actions-variables]] ==== Action variables Using the https://mustache.github.io/[Mustache] template syntax `{{variable name}}`, you can pass alert values at the time a condition is detected to an action. You can access the list of available variables using the "add variable" button. Although available variables differ by alert type, all alert types pass the following variables: @@ -105,6 +106,6 @@ Actions are not required on alerts. You can run an alert without actions to unde ============================================== [float] -=== Managing alerts +=== Manage alerts To modify an alert after it was created, including muting or disabling it, use the <>. diff --git a/docs/user/alerting/images/alert-flyout-alert-type-selection.png b/docs/user/alerting/images/alert-flyout-alert-type-selection.png index 4e5c49975160f3..6ebbe4213ba7d3 100644 Binary files a/docs/user/alerting/images/alert-flyout-alert-type-selection.png and b/docs/user/alerting/images/alert-flyout-alert-type-selection.png differ diff --git a/docs/user/alerting/images/slack-copy-webhook-url.png b/docs/user/alerting/images/slack-copy-webhook-url.png index 0acc9488e22a33..805f5719980dab 100644 Binary files a/docs/user/alerting/images/slack-copy-webhook-url.png and b/docs/user/alerting/images/slack-copy-webhook-url.png differ diff --git a/docs/user/alerting/stack-alerts/es-query.asciidoc b/docs/user/alerting/stack-alerts/es-query.asciidoc index 9f4a882328b9f7..d25b7267ed18ff 100644 --- a/docs/user/alerting/stack-alerts/es-query.asciidoc +++ b/docs/user/alerting/stack-alerts/es-query.asciidoc @@ -2,24 +2,20 @@ [[alert-type-es-query]] === ES query -The ES query alert type is designed to run a user-configured {es} query over indices, compare the number of matches to a configured threshold, and schedule -actions to run when the threshold condition is met. +The ES query alert type runs a user-configured {es} query, compares the number of matches to a configured threshold, and schedules actions to run when the threshold condition is met. [float] -==== Creating the alert +==== Create the alert -An ES query alert can be created from the *Create* button in the <>. Fill in the <>, then select *ES query*. - -[role="screenshot"] -image::user/alerting/images/alert-types-es-query-select.png[Choosing an ES query alert type] +Fill in the <>, then select *ES query*. [float] -==== Defining the conditions +==== Define the conditions -The ES query alert has 5 clauses that define the condition to detect. +Define properties to detect the condition. [role="screenshot"] -image::user/alerting/images/alert-types-es-query-conditions.png[Four clauses define the condition to detect] +image::user/alerting/images/alert-types-es-query-conditions.png[Five clauses define the condition to detect] Index:: This clause requires an *index or index pattern* and a *time field* that will be used for the *time window*. Size:: This clause specifies the number of documents to pass to the configured actions when the the threshold condition is met. @@ -29,9 +25,9 @@ Threshold:: This clause defines a threshold value and a comparison operator (`i Time window:: This clause determines how far back to search for documents, using the *time field* set in the *index* clause. Generally this value should be set to a value higher than the *check every* value in the <>, to avoid gaps in detection. [float] -==== Action variables +==== Add action variables -When the ES query alert condition is met, the following variables are available to use inside each action: +<> to run when the alert condition is met. The following variables are specific to the ES query alert. You can also specify <>. `context.title`:: A preconstructed title for the alert. Example: `alert term match alert query matched`. `context.message`:: A preconstructed message for the alert. Example: + @@ -45,22 +41,23 @@ When the ES query alert condition is met, the following variables are available `context.value`:: The value of the alert that met the condition. `context.conditions`:: A description of the condition. Example: `count greater than 4`. `context.hits`:: The most recent ES documents that matched the query. Using the https://mustache.github.io/[Mustache] template array syntax, you can iterate over these hits to get values from the ES documents into your actions. - ++ [role="screenshot"] image::images/alert-types-es-query-example-action-variable.png[Iterate over hits using Mustache template syntax] + [float] -==== Testing your query +==== Test your query Use the *Test query* feature to verify that your query DSL is valid. -When your query is valid:: Valid queries will be executed against the configured *index* using the configured *time window*. The number of documents that +* Valid queries are executed against the configured *index* using the configured *time window*. The number of documents that match the query will be displayed. - ++ [role="screenshot"] image::user/alerting/images/alert-types-es-query-valid.png[Test ES query returns number of matches when valid] -When your query is invalid:: An error message is shown if the query is invalid. - +* An error message is shown if the query is invalid. ++ [role="screenshot"] image::user/alerting/images/alert-types-es-query-invalid.png[Test ES query shows error when invalid] \ No newline at end of file diff --git a/docs/user/alerting/stack-alerts/index-threshold.asciidoc b/docs/user/alerting/stack-alerts/index-threshold.asciidoc index 6b45f69401c4aa..89ca8e3087f12a 100644 --- a/docs/user/alerting/stack-alerts/index-threshold.asciidoc +++ b/docs/user/alerting/stack-alerts/index-threshold.asciidoc @@ -2,20 +2,17 @@ [[alert-type-index-threshold]] === Index threshold -The index threshold alert type is designed to run an {es} query over indices, aggregating field values from documents, comparing them to threshold values, and scheduling actions to run when the thresholds are met. +The index threshold alert type runs an {es} query. It aggregates field values from documents, compares them to threshold values, and schedules actions to run when the thresholds are met. [float] -==== Creating the alert +==== Create the alert -An index threshold alert can be created from the *Create* button in the <>. Fill in the <>, then select *Index Threshold*. - -[role="screenshot"] -image::user/alerting/images/alert-types-index-threshold-select.png[Choosing an index threshold alert type] +Fill in the <>, then select *Index Threshold*. [float] -==== Defining the conditions +==== Define the conditions -The index threshold has 5 clauses that define the condition to detect. +Define properties to detect the condition. [role="screenshot"] image::user/alerting/images/alert-types-index-threshold-conditions.png[Five clauses define the condition to detect] @@ -32,9 +29,9 @@ If data is available and all clauses have been defined, a preview chart will ren image::user/alerting/images/alert-types-index-threshold-preview.png[Five clauses define the condition to detect] [float] -==== Action variables +==== Add action variables -When the index threshold alert condition is met, the following variables are available to use inside each action: +<> to run when the alert condition is met. The following variables are specific to the index threshold alert. You can also specify <>. `context.title`:: A preconstructed title for the alert. Example: `alert kibana sites - high egress met threshold`. `context.message`:: A preconstructed message for the alert. Example: + @@ -51,68 +48,53 @@ When the index threshold alert condition is met, the following variables are ava [float] ==== Example -In this section, you will use the {kib} <> to setup and tune the conditions on an index threshold alert. For this example, we want to detect when any of our top three sites have served more than 420,000 bytes over a 24 hour period. +In this example, you will use the {kib} <> to set up and tune the conditions on an index threshold alert. For this example, you want to detect when any of the top four sites serve more than 420,000 bytes over a 24 hour period. -From the <>, create a new alert, and fill in the <>. This alert will be checked every 4 hours, and will not execute actions more than once per day. Choose the index threshold alert type. +. Open the main menu, then click **Stack Management > Alerts and Actions**. +. Create a new alert that is checked every four hours and executes actions when the alert status changes. ++ [role="screenshot"] image::user/alerting/images/alert-types-index-threshold-select.png[Choosing an index threshold alert type] -Click on each clause to open a control that helps you set the value: - -[float] -==== Index clause -The index clause control will list and allow you to search for available indices. Choose *kibana_sample_data_logs* +. Select the **Index threshold** alert type. +. Click *Index*, and set *Indices to query* to *kibana_sample_data_logs*. ++ [role="screenshot"] image::user/alerting/images/alert-types-index-threshold-example-index.png[Choosing an index] -Once an index is selected, the list of time fields for that index will be available to select. Choose *@timestamp*. - +. Set the *Time field* to *@timestamp*. ++ [role="screenshot"] image::user/alerting/images/alert-types-index-threshold-example-timefield.png[Choosing a time field] -[float] -==== When clause - -We want to detect the number of bytes served during the time window, so we select `sum` as the aggregation, and `bytes` as the field to aggregate. - +. To detect the number of bytes served during the time window, click *When* and select `sum` as the aggregation, and bytes as the field to aggregate. ++ [role="screenshot"] image::user/alerting/images/alert-types-index-threshold-example-aggregation.png[Choosing the aggregation] -[float] -==== Over/Grouped over clause - -We want to alert on the three sites that have the most traffic, so we'll group the sum of bytes by the `host.keyword` field and take the top 3 values. - +. To detect the four sites that have the most traffic, click *Over* and select `top`, enter `4`, and select `host.keyword` as the field. ++ [role="screenshot"] image::user/alerting/images/alert-types-index-threshold-example-grouping.png[Choosing the groups] -[float] -==== Threshold clause - -We want to alert when any site exceeds 420,000 bytes over a 24 hour period, so we'll set the threshold to 420,000 and use the `is above` comparison. - +. To alert when any of the top four sites exceeds 420,000 bytes over a 24 hour period, select `is above` and enter `420000`. ++ [role="screenshot"] image::user/alerting/images/alert-types-index-threshold-example-threshold.png[Setting the threshold] -[float] -==== Time window clause - -Finally, set the time window to 24 hours to complete the alert configuration. - +. Finally, click *For the last*, enter `24` and select `hours` to complete the alert configuration. ++ [role="screenshot"] image::user/alerting/images/alert-types-index-threshold-example-window.png[Setting the time window] -The preview chart will render showing the 24 hour sum of bytes at 4 hours intervals (the *check every* interval) for the past 120 hours (the last 30 intervals). - +. The preview chart will render showing the 24 hour sum of bytes at 4 hours intervals (the *check every* interval) for the past 120 hours (the last 30 intervals). ++ [role="screenshot"] image::user/alerting/images/alert-types-index-threshold-example-preview.png[Setting the time window] -[float] -==== Comparing time windows - -You can interactively change the time window and observe the effect it has on the chart. Compare a 24 window to a 12 hour window. Notice the variability in the sum of bytes, due to different traffic levels during the day compared to at night. This variability would result in noisy alerts, so the 24 hour window is better. The preview chart can help you find the right values for your alert. - +. Change the time window and observe the effect it has on the chart. Compare a 24 window to a 12 hour window. Notice the variability in the sum of bytes, due to different traffic levels during the day compared to at night. This variability would result in noisy alerts, so the 24 hour window is better. The preview chart can help you find the right values for your alert. ++ [role="screenshot"] image::user/alerting/images/alert-types-index-threshold-example-comparison.png[Comparing two time windows] \ No newline at end of file diff --git a/docs/user/ml/index.asciidoc b/docs/user/ml/index.asciidoc index fa15e0652e2ab2..3c463da842faa5 100644 --- a/docs/user/ml/index.asciidoc +++ b/docs/user/ml/index.asciidoc @@ -20,10 +20,10 @@ image::user/ml/images/ml-data-visualizer-sample.jpg[{data-viz} for sample flight experimental[] You can also upload a CSV, NDJSON, or log file. The *{data-viz}* identifies the file format and field mappings. You can then optionally import that data into an {es} index. To change the default file size limit, see -<>. +<>. If {stack-security-features} are enabled, users must have the necessary -privileges to use {ml-features}. Refer to +privileges to use {ml-features}. Refer to {ml-docs}/setup.html#setup-privileges[Set up {ml-features}]. NOTE: There are limitations in {ml-features} that affect {kib}. For more information, refer to {ml-docs}/ml-limitations.html[Machine learning]. @@ -40,15 +40,15 @@ false positives. {anomaly-detect-cap} runs in and scales with {es}, and includes an intuitive UI on the {kib} *Machine Learning* page for creating {anomaly-jobs} and understanding results. -If you have a license that includes the {ml-features}, you can +If you have a license that includes the {ml-features}, you can create {anomaly-jobs} and manage jobs and {dfeeds} from the *Job Management* -pane: +pane: [role="screenshot"] image::user/ml/images/ml-job-management.png[Job Management] -You can use the *Settings* pane to create and edit -{ml-docs}/ml-calendars.html[calendars] and the filters that are used in +You can use the *Settings* pane to create and edit +{ml-docs}/ml-calendars.html[calendars] and the filters that are used in {ml-docs}/ml-rules.html[custom rules]: [role="screenshot"] @@ -69,13 +69,13 @@ occurring in your operational environment at that time: image::user/ml/images/ml-annotations-list.png[Single Metric Viewer with annotations] In some circumstances, annotations are also added automatically. For example, if -the {anomaly-job} detects that there is missing data, it annotates the affected -time period. For more information, see -{ml-docs}/ml-delayed-data-detection.html[Handling delayed data]. The +the {anomaly-job} detects that there is missing data, it annotates the affected +time period. For more information, see +{ml-docs}/ml-delayed-data-detection.html[Handling delayed data]. The *Job Management* pane shows the full list of annotations for each job. -NOTE: The {kib} {ml-features} use pop-ups. You must configure your web -browser so that it does not block pop-up windows or create an exception for your +NOTE: The {kib} {ml-features} use pop-ups. You must configure your web +browser so that it does not block pop-up windows or create an exception for your {kib} URL. For more information about the {anomaly-detect} feature, see @@ -89,7 +89,7 @@ experimental[] The Elastic {ml} {dfanalytics} feature enables you to analyze your data using {classification}, {oldetection}, and {regression} algorithms and generate new -indices that contain the results alongside your source data. +indices that contain the results alongside your source data. If you have a license that includes the {ml-features}, you can create {dfanalytics-jobs} and view their results on the *Data Frame Analytics* page in @@ -98,5 +98,5 @@ If you have a license that includes the {ml-features}, you can create [role="screenshot"] image::user/ml/images/outliers.png[{oldetection-cap} results in {kib}] -For more information about the {dfanalytics} feature, see -{ml-docs}/ml-dfanalytics.html[{ml-cap} {dfanalytics}]. \ No newline at end of file +For more information about the {dfanalytics} feature, see +{ml-docs}/ml-dfanalytics.html[{ml-cap} {dfanalytics}]. diff --git a/package.json b/package.json index 3dde0c6a17fb51..d1d2bc56724274 100644 --- a/package.json +++ b/package.json @@ -347,7 +347,7 @@ "@cypress/webpack-preprocessor": "^5.5.0", "@elastic/apm-rum": "^5.6.1", "@elastic/apm-rum-react": "^1.2.5", - "@elastic/charts": "25.0.1", + "@elastic/charts": "25.1.0", "@elastic/eslint-config-kibana": "link:packages/elastic-eslint-config-kibana", "@elastic/eslint-plugin-eui": "0.0.2", "@elastic/github-checks-reporter": "0.0.20b3", diff --git a/packages/kbn-dev-utils/src/plugin_list/generate_plugin_list.ts b/packages/kbn-dev-utils/src/plugin_list/generate_plugin_list.ts index faf6dd289cc287..127e2a9904a4fc 100644 --- a/packages/kbn-dev-utils/src/plugin_list/generate_plugin_list.ts +++ b/packages/kbn-dev-utils/src/plugin_list/generate_plugin_list.ts @@ -28,10 +28,11 @@ function* printPlugins(plugins: Plugins, includes: string[]) { yield `|{kib-repo}blob/{branch}/${path}[${plugin.id}]`; } - if (!plugin.relativeReadmePath || plugin.readmeSnippet) { - yield plugin.readmeSnippet ? `|${plugin.readmeSnippet}` : '|WARNING: Missing README.'; - yield ''; - } + yield plugin.relativeReadmePath === undefined + ? '|WARNING: Missing README.' + : `|${plugin.readmeSnippet}`; + + yield ''; } } diff --git a/packages/kbn-legacy-logging/src/utils/get_payload_size.test.ts b/packages/kbn-legacy-logging/src/utils/get_payload_size.test.ts index 3bb97e57ca0a3c..01d2cf29758db9 100644 --- a/packages/kbn-legacy-logging/src/utils/get_payload_size.test.ts +++ b/packages/kbn-legacy-logging/src/utils/get_payload_size.test.ts @@ -6,9 +6,10 @@ * Side Public License, v 1. */ -import { createGunzip } from 'zlib'; import mockFs from 'mock-fs'; import { createReadStream } from 'fs'; +import { PassThrough } from 'stream'; +import { createGzip, createGunzip } from 'zlib'; import { getResponsePayloadBytes } from './get_payload_size'; @@ -27,38 +28,74 @@ describe('getPayloadSize', () => { }); }); - describe('handles fs streams', () => { + describe('handles streams', () => { afterEach(() => mockFs.restore()); - test('with ascii characters', async () => { - mockFs({ 'test.txt': 'heya' }); - const readStream = createReadStream('test.txt'); - - let data = ''; - for await (const chunk of readStream) { - data += chunk; - } - - const result = getResponsePayloadBytes(readStream); - expect(result).toBe(Buffer.byteLength(data)); - }); - - test('with special characters', async () => { - mockFs({ 'test.txt': '¡hola!' }); - const readStream = createReadStream('test.txt'); - - let data = ''; - for await (const chunk of readStream) { - data += chunk; - } - - const result = getResponsePayloadBytes(readStream); - expect(result).toBe(Buffer.byteLength(data)); + test('ignores streams that are not fs or zlib streams', async () => { + const result = getResponsePayloadBytes(new PassThrough()); + expect(result).toBe(undefined); }); - test('ignores streams that are not instances of ReadStream', async () => { - const result = getResponsePayloadBytes(createGunzip()); - expect(result).toBe(undefined); + describe('fs streams', () => { + test('with ascii characters', async () => { + mockFs({ 'test.txt': 'heya' }); + const readStream = createReadStream('test.txt'); + + let data = ''; + for await (const chunk of readStream) { + data += chunk; + } + + const result = getResponsePayloadBytes(readStream); + expect(result).toBe(Buffer.byteLength(data)); + }); + + test('with special characters', async () => { + mockFs({ 'test.txt': '¡hola!' }); + const readStream = createReadStream('test.txt'); + + let data = ''; + for await (const chunk of readStream) { + data += chunk; + } + + const result = getResponsePayloadBytes(readStream); + expect(result).toBe(Buffer.byteLength(data)); + }); + + describe('zlib streams', () => { + test('with ascii characters', async () => { + mockFs({ 'test.txt': 'heya' }); + const readStream = createReadStream('test.txt'); + const source = readStream.pipe(createGzip()).pipe(createGunzip()); + + let data = ''; + for await (const chunk of source) { + data += chunk; + } + + const result = getResponsePayloadBytes(source); + + expect(data).toBe('heya'); + expect(result).toBe(source.bytesWritten); + }); + + test('with special characters', async () => { + mockFs({ 'test.txt': '¡hola!' }); + const readStream = createReadStream('test.txt'); + const source = readStream.pipe(createGzip()).pipe(createGunzip()); + + let data = ''; + for await (const chunk of source) { + data += chunk; + } + + const result = getResponsePayloadBytes(source); + + expect(data).toBe('¡hola!'); + expect(result).toBe(source.bytesWritten); + }); + }); }); }); @@ -79,8 +116,17 @@ describe('getPayloadSize', () => { expect(result).toBe(JSON.stringify(payload).length); }); + test('when source is array object', () => { + const payload = [{ message: 'hey' }, { message: 'ya' }]; + const result = getResponsePayloadBytes(payload); + expect(result).toBe(JSON.stringify(payload).length); + }); + test('returns undefined when source is not plain object', () => { - const result = getResponsePayloadBytes([1, 2, 3]); + class TestClass { + constructor() {} + } + const result = getResponsePayloadBytes(new TestClass()); expect(result).toBe(undefined); }); }); diff --git a/packages/kbn-legacy-logging/src/utils/get_payload_size.ts b/packages/kbn-legacy-logging/src/utils/get_payload_size.ts index c7aeb0e8cac2bb..acc517c74c2d46 100644 --- a/packages/kbn-legacy-logging/src/utils/get_payload_size.ts +++ b/packages/kbn-legacy-logging/src/utils/get_payload_size.ts @@ -8,11 +8,15 @@ import { isPlainObject } from 'lodash'; import { ReadStream } from 'fs'; +import { Zlib } from 'zlib'; import type { ResponseObject } from '@hapi/hapi'; const isBuffer = (obj: unknown): obj is Buffer => Buffer.isBuffer(obj); const isFsReadStream = (obj: unknown): obj is ReadStream => typeof obj === 'object' && obj !== null && 'bytesRead' in obj && obj instanceof ReadStream; +const isZlibStream = (obj: unknown): obj is Zlib => { + return typeof obj === 'object' && obj !== null && 'bytesWritten' in obj; +}; const isString = (obj: unknown): obj is string => typeof obj === 'string'; /** @@ -51,11 +55,15 @@ export function getResponsePayloadBytes( return payload.bytesRead; } + if (isZlibStream(payload)) { + return payload.bytesWritten; + } + if (isString(payload)) { return Buffer.byteLength(payload); } - if (isPlainObject(payload)) { + if (isPlainObject(payload) || Array.isArray(payload)) { return Buffer.byteLength(JSON.stringify(payload)); } diff --git a/packages/kbn-optimizer/src/cli.ts b/packages/kbn-optimizer/src/cli.ts index 8fb906aa4603e8..8f82f34646e607 100644 --- a/packages/kbn-optimizer/src/cli.ts +++ b/packages/kbn-optimizer/src/cli.ts @@ -12,164 +12,190 @@ import Path from 'path'; import { REPO_ROOT } from '@kbn/utils'; import { lastValueFrom } from '@kbn/std'; -import { run, createFlagError } from '@kbn/dev-utils'; +import { run, createFlagError, Flags } from '@kbn/dev-utils'; import { logOptimizerState } from './log_optimizer_state'; import { OptimizerConfig } from './optimizer'; import { runOptimizer } from './run_optimizer'; import { validateLimitsForAllBundles, updateBundleLimits } from './limits'; -run( - async ({ log, flags }) => { - const watch = flags.watch ?? false; - if (typeof watch !== 'boolean') { - throw createFlagError('expected --watch to have no value'); +function getLimitsPath(flags: Flags, defaultPath: string) { + if (flags.limits) { + if (typeof flags.limits !== 'string') { + throw createFlagError('expected --limits to be a string'); } - const oss = flags.oss ?? false; - if (typeof oss !== 'boolean') { - throw createFlagError('expected --oss to have no value'); - } - - const cache = flags.cache ?? true; - if (typeof cache !== 'boolean') { - throw createFlagError('expected --cache to have no value'); - } - - const includeCoreBundle = flags.core ?? true; - if (typeof includeCoreBundle !== 'boolean') { - throw createFlagError('expected --core to have no value'); - } - - const dist = flags.dist ?? false; - if (typeof dist !== 'boolean') { - throw createFlagError('expected --dist to have no value'); - } - - const examples = flags.examples ?? false; - if (typeof examples !== 'boolean') { - throw createFlagError('expected --no-examples to have no value'); - } - - const profileWebpack = flags.profile ?? false; - if (typeof profileWebpack !== 'boolean') { - throw createFlagError('expected --profile to have no value'); - } - - const inspectWorkers = flags['inspect-workers'] ?? false; - if (typeof inspectWorkers !== 'boolean') { - throw createFlagError('expected --no-inspect-workers to have no value'); - } - - const maxWorkerCount = flags.workers ? Number.parseInt(String(flags.workers), 10) : undefined; - if (maxWorkerCount !== undefined && (!Number.isFinite(maxWorkerCount) || maxWorkerCount < 1)) { - throw createFlagError('expected --workers to be a number greater than 0'); - } - - const extraPluginScanDirs = ([] as string[]) - .concat((flags['scan-dir'] as string | string[]) || []) - .map((p) => Path.resolve(p)); - if (!extraPluginScanDirs.every((s) => typeof s === 'string')) { - throw createFlagError('expected --scan-dir to be a string'); - } - - const reportStats = flags['report-stats'] ?? false; - if (typeof reportStats !== 'boolean') { - throw createFlagError('expected --report-stats to have no value'); - } - - const filter = typeof flags.filter === 'string' ? [flags.filter] : flags.filter; - if (!Array.isArray(filter) || !filter.every((f) => typeof f === 'string')) { - throw createFlagError('expected --filter to be one or more strings'); - } - - const focus = typeof flags.focus === 'string' ? [flags.focus] : flags.focus; - if (!Array.isArray(focus) || !focus.every((f) => typeof f === 'string')) { - throw createFlagError('expected --focus to be one or more strings'); - } + return Path.resolve(flags.limits); + } - const validateLimits = flags['validate-limits'] ?? false; - if (typeof validateLimits !== 'boolean') { - throw createFlagError('expected --validate-limits to have no value'); - } + if (process.env.KBN_OPTIMIZER_LIMITS_PATH) { + return Path.resolve(process.env.KBN_OPTIMIZER_LIMITS_PATH); + } - const updateLimits = flags['update-limits'] ?? false; - if (typeof updateLimits !== 'boolean') { - throw createFlagError('expected --update-limits to have no value'); - } + return defaultPath; +} + +export function runKbnOptimizerCli(options: { defaultLimitsPath: string }) { + run( + async ({ log, flags }) => { + const watch = flags.watch ?? false; + if (typeof watch !== 'boolean') { + throw createFlagError('expected --watch to have no value'); + } + + const oss = flags.oss ?? false; + if (typeof oss !== 'boolean') { + throw createFlagError('expected --oss to have no value'); + } + + const cache = flags.cache ?? true; + if (typeof cache !== 'boolean') { + throw createFlagError('expected --cache to have no value'); + } + + const includeCoreBundle = flags.core ?? true; + if (typeof includeCoreBundle !== 'boolean') { + throw createFlagError('expected --core to have no value'); + } + + const dist = flags.dist ?? false; + if (typeof dist !== 'boolean') { + throw createFlagError('expected --dist to have no value'); + } + + const examples = flags.examples ?? false; + if (typeof examples !== 'boolean') { + throw createFlagError('expected --no-examples to have no value'); + } + + const profileWebpack = flags.profile ?? false; + if (typeof profileWebpack !== 'boolean') { + throw createFlagError('expected --profile to have no value'); + } + + const inspectWorkers = flags['inspect-workers'] ?? false; + if (typeof inspectWorkers !== 'boolean') { + throw createFlagError('expected --no-inspect-workers to have no value'); + } + + const maxWorkerCount = flags.workers ? Number.parseInt(String(flags.workers), 10) : undefined; + if ( + maxWorkerCount !== undefined && + (!Number.isFinite(maxWorkerCount) || maxWorkerCount < 1) + ) { + throw createFlagError('expected --workers to be a number greater than 0'); + } + + const extraPluginScanDirs = ([] as string[]) + .concat((flags['scan-dir'] as string | string[]) || []) + .map((p) => Path.resolve(p)); + if (!extraPluginScanDirs.every((s) => typeof s === 'string')) { + throw createFlagError('expected --scan-dir to be a string'); + } + + const reportStats = flags['report-stats'] ?? false; + if (typeof reportStats !== 'boolean') { + throw createFlagError('expected --report-stats to have no value'); + } + + const filter = typeof flags.filter === 'string' ? [flags.filter] : flags.filter; + if (!Array.isArray(filter) || !filter.every((f) => typeof f === 'string')) { + throw createFlagError('expected --filter to be one or more strings'); + } + + const focus = typeof flags.focus === 'string' ? [flags.focus] : flags.focus; + if (!Array.isArray(focus) || !focus.every((f) => typeof f === 'string')) { + throw createFlagError('expected --focus to be one or more strings'); + } + + const limitsPath = getLimitsPath(flags, options.defaultLimitsPath); + + const validateLimits = flags['validate-limits'] ?? false; + if (typeof validateLimits !== 'boolean') { + throw createFlagError('expected --validate-limits to have no value'); + } + + const updateLimits = flags['update-limits'] ?? false; + if (typeof updateLimits !== 'boolean') { + throw createFlagError('expected --update-limits to have no value'); + } + + const config = OptimizerConfig.create({ + repoRoot: REPO_ROOT, + watch, + maxWorkerCount, + oss: oss && !(validateLimits || updateLimits), + dist: dist || updateLimits, + cache, + examples: examples && !(validateLimits || updateLimits), + profileWebpack, + extraPluginScanDirs, + inspectWorkers, + includeCoreBundle, + filter, + focus, + limitsPath, + }); - const config = OptimizerConfig.create({ - repoRoot: REPO_ROOT, - watch, - maxWorkerCount, - oss: oss && !(validateLimits || updateLimits), - dist: dist || updateLimits, - cache, - examples: examples && !(validateLimits || updateLimits), - profileWebpack, - extraPluginScanDirs, - inspectWorkers, - includeCoreBundle, - filter, - focus, - }); - - if (validateLimits) { - validateLimitsForAllBundles(log, config); - return; - } + if (validateLimits) { + validateLimitsForAllBundles(log, config, limitsPath); + return; + } - const update$ = runOptimizer(config); + const update$ = runOptimizer(config); - await lastValueFrom(update$.pipe(logOptimizerState(log, config))); + await lastValueFrom(update$.pipe(logOptimizerState(log, config))); - if (updateLimits) { - updateBundleLimits({ - log, - config, - dropMissing: !(focus || filter), - }); - } - }, - { - flags: { - boolean: [ - 'core', - 'watch', - 'oss', - 'examples', - 'dist', - 'cache', - 'profile', - 'inspect-workers', - 'validate-limits', - 'update-limits', - ], - string: ['workers', 'scan-dir', 'filter'], - default: { - core: true, - examples: true, - cache: true, - 'inspect-workers': true, - filter: [], - focus: [], - }, - help: ` - --watch run the optimizer in watch mode - --workers max number of workers to use - --oss only build oss plugins - --profile profile the webpack builds and write stats.json files to build outputs - --no-core disable generating the core bundle - --no-cache disable the cache - --focus just like --filter, except dependencies are automatically included, --filter applies to result - --filter comma-separated list of bundle id filters, results from multiple flags are merged, * and ! are supported - --no-examples don't build the example plugins - --dist create bundles that are suitable for inclusion in the Kibana distributable, enabled when running with --update-limits - --scan-dir add a directory to the list of directories scanned for plugins (specify as many times as necessary) - --no-inspect-workers when inspecting the parent process, don't inspect the workers - --validate-limits validate the limits.yml config to ensure that there are limits defined for every bundle - --update-limits run a build and rewrite the limits file to include the current bundle sizes +5kb - `, + if (updateLimits) { + updateBundleLimits({ + log, + config, + dropMissing: !(focus || filter), + limitsPath, + }); + } }, - } -); + { + flags: { + boolean: [ + 'core', + 'watch', + 'oss', + 'examples', + 'dist', + 'cache', + 'profile', + 'inspect-workers', + 'validate-limits', + 'update-limits', + ], + string: ['workers', 'scan-dir', 'filter', 'limits'], + default: { + core: true, + examples: true, + cache: true, + 'inspect-workers': true, + filter: [], + focus: [], + }, + help: ` + --watch run the optimizer in watch mode + --workers max number of workers to use + --oss only build oss plugins + --profile profile the webpack builds and write stats.json files to build outputs + --no-core disable generating the core bundle + --no-cache disable the cache + --focus just like --filter, except dependencies are automatically included, --filter applies to result + --filter comma-separated list of bundle id filters, results from multiple flags are merged, * and ! are supported + --no-examples don't build the example plugins + --dist create bundles that are suitable for inclusion in the Kibana distributable, enabled when running with --update-limits + --scan-dir add a directory to the list of directories scanned for plugins (specify as many times as necessary) + --no-inspect-workers when inspecting the parent process, don't inspect the workers + --limits path to a limits.yml file to read, defaults to $KBN_OPTIMIZER_LIMITS_PATH or source file + --validate-limits validate the limits.yml config to ensure that there are limits defined for every bundle + --update-limits run a build and rewrite the limits file to include the current bundle sizes +5kb + `, + }, + } + ); +} diff --git a/packages/kbn-optimizer/src/index.ts b/packages/kbn-optimizer/src/index.ts index 551d2ffacfcfbf..8d6e89008bc681 100644 --- a/packages/kbn-optimizer/src/index.ts +++ b/packages/kbn-optimizer/src/index.ts @@ -11,3 +11,4 @@ export * from './run_optimizer'; export * from './log_optimizer_state'; export * from './node'; export * from './limits'; +export * from './cli'; diff --git a/packages/kbn-optimizer/src/limits.ts b/packages/kbn-optimizer/src/limits.ts index 292314a4608e40..077fe38ddc7f69 100644 --- a/packages/kbn-optimizer/src/limits.ts +++ b/packages/kbn-optimizer/src/limits.ts @@ -15,15 +15,14 @@ import { createFailError, ToolingLog, CiStatsMetrics } from '@kbn/dev-utils'; import { OptimizerConfig, Limits } from './optimizer'; -const LIMITS_PATH = require.resolve('../limits.yml'); const DEFAULT_BUDGET = 15000; const diff = (a: T[], b: T[]): T[] => a.filter((item) => !b.includes(item)); -export function readLimits(): Limits { +export function readLimits(path: string): Limits { let yaml; try { - yaml = Fs.readFileSync(LIMITS_PATH, 'utf8'); + yaml = Fs.readFileSync(path, 'utf8'); } catch (error) { if (error.code !== 'ENOENT') { throw error; @@ -33,8 +32,12 @@ export function readLimits(): Limits { return yaml ? Yaml.safeLoad(yaml) : {}; } -export function validateLimitsForAllBundles(log: ToolingLog, config: OptimizerConfig) { - const limitBundleIds = Object.keys(readLimits().pageLoadAssetSize || {}); +export function validateLimitsForAllBundles( + log: ToolingLog, + config: OptimizerConfig, + limitsPath: string +) { + const limitBundleIds = Object.keys(readLimits(limitsPath).pageLoadAssetSize || {}); const configBundleIds = config.bundles.map((b) => b.id); const missingBundleIds = diff(configBundleIds, limitBundleIds); @@ -73,10 +76,16 @@ interface UpdateBundleLimitsOptions { log: ToolingLog; config: OptimizerConfig; dropMissing: boolean; + limitsPath: string; } -export function updateBundleLimits({ log, config, dropMissing }: UpdateBundleLimitsOptions) { - const limits = readLimits(); +export function updateBundleLimits({ + log, + config, + dropMissing, + limitsPath, +}: UpdateBundleLimitsOptions) { + const limits = readLimits(limitsPath); const metrics: CiStatsMetrics = config.bundles .map((bundle) => JSON.parse(Fs.readFileSync(Path.resolve(bundle.outputDir, 'metrics.json'), 'utf-8')) @@ -102,6 +111,6 @@ export function updateBundleLimits({ log, config, dropMissing }: UpdateBundleLim pageLoadAssetSize, }; - Fs.writeFileSync(LIMITS_PATH, Yaml.safeDump(newLimits)); - log.success(`wrote updated limits to ${LIMITS_PATH}`); + Fs.writeFileSync(limitsPath, Yaml.safeDump(newLimits)); + log.success(`wrote updated limits to ${limitsPath}`); } diff --git a/packages/kbn-optimizer/src/optimizer/optimizer_config.test.ts b/packages/kbn-optimizer/src/optimizer/optimizer_config.test.ts index c60d6719cdea78..c546a0c6cf9928 100644 --- a/packages/kbn-optimizer/src/optimizer/optimizer_config.test.ts +++ b/packages/kbn-optimizer/src/optimizer/optimizer_config.test.ts @@ -427,6 +427,7 @@ describe('OptimizerConfig::create()', () => { it('passes parsed options to findKibanaPlatformPlugins, getBundles, and assignBundlesToWorkers', () => { const config = OptimizerConfig.create({ repoRoot: REPO_ROOT, + limitsPath: '/foo/limits.yml', }); expect(config).toMatchInlineSnapshot(` diff --git a/packages/kbn-optimizer/src/optimizer/optimizer_config.ts b/packages/kbn-optimizer/src/optimizer/optimizer_config.ts index ed521d32a0a297..9110b6db27e927 100644 --- a/packages/kbn-optimizer/src/optimizer/optimizer_config.ts +++ b/packages/kbn-optimizer/src/optimizer/optimizer_config.ts @@ -115,6 +115,9 @@ interface Options { * - "k7light" */ themes?: ThemeTag | '*' | ThemeTag[]; + + /** path to a limits.yml file that should be used to inform ci-stats of metric limits */ + limitsPath?: string; } export interface ParsedOptions { @@ -211,7 +214,7 @@ export class OptimizerConfig { } static create(inputOptions: Options) { - const limits = readLimits(); + const limits = inputOptions.limitsPath ? readLimits(inputOptions.limitsPath) : {}; const options = OptimizerConfig.parseOptions(inputOptions); const plugins = findKibanaPlatformPlugins(options.pluginScanDirs, options.pluginPaths); const bundles = [ diff --git a/packages/kbn-pm/dist/index.js b/packages/kbn-pm/dist/index.js index e390b1fc9e4b35..739bf9d4b67238 100644 --- a/packages/kbn-pm/dist/index.js +++ b/packages/kbn-pm/dist/index.js @@ -59860,7 +59860,7 @@ __webpack_require__.r(__webpack_exports__); /* harmony import */ var path__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(4); /* harmony import */ var path__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(path__WEBPACK_IMPORTED_MODULE_2__); /* harmony import */ var _build_non_bazel_production_projects__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(746); -/* harmony import */ var _utils_bazel_run__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(375); +/* harmony import */ var _utils_bazel__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(371); /* harmony import */ var _utils_fs__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(131); /* harmony import */ var _utils_log__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(246); /* harmony import */ var _utils_package_json__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(251); @@ -59889,7 +59889,7 @@ async function buildBazelProductionProjects({ const projects = await Object(_utils_projects__WEBPACK_IMPORTED_MODULE_8__["getBazelProjectsOnly"])(await Object(_build_non_bazel_production_projects__WEBPACK_IMPORTED_MODULE_3__["getProductionProjects"])(kibanaRoot, onlyOSS)); const projectNames = [...projects.values()].map(project => project.name); _utils_log__WEBPACK_IMPORTED_MODULE_6__["log"].info(`Preparing Bazel projects production build for [${projectNames.join(', ')}]`); - await Object(_utils_bazel_run__WEBPACK_IMPORTED_MODULE_4__["runBazel"])(['build', '//packages:build']); + await Object(_utils_bazel__WEBPACK_IMPORTED_MODULE_4__["runBazel"])(['build', '//packages:build']); _utils_log__WEBPACK_IMPORTED_MODULE_6__["log"].info(`All Bazel projects production builds for [${projectNames.join(', ')}] are complete}]`); for (const project of projects.values()) { @@ -59913,9 +59913,8 @@ async function copyToBuild(project, kibanaRoot, buildRoot) { // We want the package to have the same relative location within the build const relativeProjectPath = Object(path__WEBPACK_IMPORTED_MODULE_2__["relative"])(kibanaRoot, project.path); const buildProjectPath = Object(path__WEBPACK_IMPORTED_MODULE_2__["resolve"])(buildRoot, relativeProjectPath); - const bazelFilesToExclude = ['!*.sh.runfiles*', '!*.params', '!*_mappings.json', '!*_options.optionsvalid.d.ts', '!*_loader.js', '!*_require_patch.js', '!*.sh']; - await cpy__WEBPACK_IMPORTED_MODULE_0___default()(['**/*', '!node_modules/**', ...bazelFilesToExclude], buildProjectPath, { - cwd: Object(path__WEBPACK_IMPORTED_MODULE_2__["join"])(kibanaRoot, 'bazel', 'bin', 'packages', Object(path__WEBPACK_IMPORTED_MODULE_2__["basename"])(buildProjectPath)), + await cpy__WEBPACK_IMPORTED_MODULE_0___default()(['**/*'], buildProjectPath, { + cwd: Object(path__WEBPACK_IMPORTED_MODULE_2__["join"])(kibanaRoot, 'bazel', 'bin', 'packages', Object(path__WEBPACK_IMPORTED_MODULE_2__["basename"])(buildProjectPath), 'npm_module'), dot: true, onlyFiles: true, parents: true @@ -59937,7 +59936,7 @@ async function applyCorrectPermissions(project, kibanaRoot, buildRoot) { const buildProjectPath = Object(path__WEBPACK_IMPORTED_MODULE_2__["resolve"])(buildRoot, relativeProjectPath); const allPluginPaths = await globby__WEBPACK_IMPORTED_MODULE_1___default()([`**/*`], { onlyFiles: false, - cwd: Object(path__WEBPACK_IMPORTED_MODULE_2__["join"])(kibanaRoot, 'bazel', 'bin', 'packages', Object(path__WEBPACK_IMPORTED_MODULE_2__["basename"])(buildProjectPath)), + cwd: Object(path__WEBPACK_IMPORTED_MODULE_2__["join"])(kibanaRoot, 'bazel', 'bin', 'packages', Object(path__WEBPACK_IMPORTED_MODULE_2__["basename"])(buildProjectPath), 'npm_module'), dot: true }); diff --git a/packages/kbn-pm/src/production/build_bazel_production_projects.ts b/packages/kbn-pm/src/production/build_bazel_production_projects.ts index 1034253c5e0dc3..313622d44276a4 100644 --- a/packages/kbn-pm/src/production/build_bazel_production_projects.ts +++ b/packages/kbn-pm/src/production/build_bazel_production_projects.ts @@ -11,7 +11,7 @@ import globby from 'globby'; import { basename, join, relative, resolve } from 'path'; import { getProductionProjects } from './build_non_bazel_production_projects'; -import { runBazel } from '../utils/bazel/run'; +import { runBazel } from '../utils/bazel'; import { chmod, isFile, isDirectory } from '../utils/fs'; import { log } from '../utils/log'; import { @@ -60,18 +60,9 @@ async function copyToBuild(project: Project, kibanaRoot: string, buildRoot: stri // We want the package to have the same relative location within the build const relativeProjectPath = relative(kibanaRoot, project.path); const buildProjectPath = resolve(buildRoot, relativeProjectPath); - const bazelFilesToExclude = [ - '!*.sh.runfiles*', - '!*.params', - '!*_mappings.json', - '!*_options.optionsvalid.d.ts', - '!*_loader.js', - '!*_require_patch.js', - '!*.sh', - ]; - await copy(['**/*', '!node_modules/**', ...bazelFilesToExclude], buildProjectPath, { - cwd: join(kibanaRoot, 'bazel', 'bin', 'packages', basename(buildProjectPath)), + await copy(['**/*'], buildProjectPath, { + cwd: join(kibanaRoot, 'bazel', 'bin', 'packages', basename(buildProjectPath), 'npm_module'), dot: true, onlyFiles: true, parents: true, @@ -97,7 +88,7 @@ async function applyCorrectPermissions(project: Project, kibanaRoot: string, bui const buildProjectPath = resolve(buildRoot, relativeProjectPath); const allPluginPaths = await globby([`**/*`], { onlyFiles: false, - cwd: join(kibanaRoot, 'bazel', 'bin', 'packages', basename(buildProjectPath)), + cwd: join(kibanaRoot, 'bazel', 'bin', 'packages', basename(buildProjectPath), 'npm_module'), dot: true, }); diff --git a/packages/kbn-storybook/lib/default_config.ts b/packages/kbn-storybook/lib/default_config.ts index 1b049761a3a985..e194c9789daab8 100644 --- a/packages/kbn-storybook/lib/default_config.ts +++ b/packages/kbn-storybook/lib/default_config.ts @@ -19,6 +19,9 @@ export const defaultConfig: StorybookConfig = { config.parallelism = 4; config.cache = true; } + + config.node = { fs: 'empty' }; + return config; }, }; diff --git a/packages/kbn-telemetry-tools/src/tools/__fixture__/all_extracted_collectors.ts b/packages/kbn-telemetry-tools/src/tools/__fixture__/all_extracted_collectors.ts index 28cfd3560874c5..37bdd327f945b5 100644 --- a/packages/kbn-telemetry-tools/src/tools/__fixture__/all_extracted_collectors.ts +++ b/packages/kbn-telemetry-tools/src/tools/__fixture__/all_extracted_collectors.ts @@ -13,6 +13,7 @@ import { parsedIndexedInterfaceWithNoMatchingSchema } from './parsed_indexed_int import { parsedNestedCollector } from './parsed_nested_collector'; import { parsedSchemaDefinedWithSpreadsCollector } from './parsed_schema_defined_with_spreads_collector'; import { parsedWorkingCollector } from './parsed_working_collector'; +import { parsedCollectorWithDescription } from './parsed_working_collector_with_description'; import { ParsedUsageCollection } from '../ts_parser'; export const allExtractedCollectors: ParsedUsageCollection[] = [ @@ -22,5 +23,6 @@ export const allExtractedCollectors: ParsedUsageCollection[] = [ parsedIndexedInterfaceWithNoMatchingSchema, parsedNestedCollector, parsedSchemaDefinedWithSpreadsCollector, + parsedCollectorWithDescription, parsedWorkingCollector, ]; diff --git a/packages/kbn-telemetry-tools/src/tools/__fixture__/mock_schema_with_descriptions.json b/packages/kbn-telemetry-tools/src/tools/__fixture__/mock_schema_with_descriptions.json new file mode 100644 index 00000000000000..77321327b38942 --- /dev/null +++ b/packages/kbn-telemetry-tools/src/tools/__fixture__/mock_schema_with_descriptions.json @@ -0,0 +1,57 @@ +{ + "properties": { + "my_working_collector_with_description": { + "properties": { + "flat": { + "type": "keyword", + "_meta": { + "description": "A flat keyword string" + } + }, + "my_index_signature_prop": { + "properties": { + "avg": { + "type": "float" + }, + "count": { + "type": "long" + }, + "max": { + "type": "long" + }, + "min": { + "type": "long" + } + } + }, + "my_str": { + "type": "text" + }, + "my_objects": { + "properties": { + "total": { + "type": "long" + }, + "type": { + "type": "boolean" + } + } + }, + "my_array": { + "type": "array", + "items": { + "properties": { + "total": { + "type": "long" + }, + "type": { + "type": "boolean" + } + } + } + }, + "my_str_array": { "type": "array", "items": { "type": "keyword" } } + } + } + } +} diff --git a/packages/kbn-telemetry-tools/src/tools/__fixture__/parsed_working_collector_with_description.ts b/packages/kbn-telemetry-tools/src/tools/__fixture__/parsed_working_collector_with_description.ts new file mode 100644 index 00000000000000..a2f9379eec7ac2 --- /dev/null +++ b/packages/kbn-telemetry-tools/src/tools/__fixture__/parsed_working_collector_with_description.ts @@ -0,0 +1,109 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { SyntaxKind } from 'typescript'; +import { ParsedUsageCollection } from '../ts_parser'; + +export const parsedCollectorWithDescription: ParsedUsageCollection = [ + 'src/fixtures/telemetry_collectors/working_collector_with_description.ts', + { + collectorName: 'my_working_collector_with_description', + schema: { + value: { + flat: { + type: 'keyword', + _meta: { + description: 'A flat keyword string', + }, + }, + my_str: { + type: 'text', + }, + my_index_signature_prop: { + avg: { + type: 'float', + }, + count: { + type: 'long', + }, + max: { + type: 'long', + }, + min: { + type: 'long', + }, + }, + my_objects: { + total: { + type: 'long', + }, + type: { + type: 'boolean', + }, + }, + my_array: { + type: 'array', + items: { + total: { + type: 'long', + }, + type: { type: 'boolean' }, + }, + }, + my_str_array: { type: 'array', items: { type: 'keyword' } }, + }, + }, + fetch: { + typeName: 'Usage', + typeDescriptor: { + flat: { + kind: SyntaxKind.StringKeyword, + type: 'StringKeyword', + }, + my_str: { + kind: SyntaxKind.StringKeyword, + type: 'StringKeyword', + }, + my_index_signature_prop: { + '@@INDEX@@': { + kind: SyntaxKind.NumberKeyword, + type: 'NumberKeyword', + }, + }, + my_objects: { + total: { + kind: SyntaxKind.NumberKeyword, + type: 'NumberKeyword', + }, + type: { + kind: SyntaxKind.BooleanKeyword, + type: 'BooleanKeyword', + }, + }, + my_array: { + items: { + total: { + kind: SyntaxKind.NumberKeyword, + type: 'NumberKeyword', + }, + type: { + kind: SyntaxKind.BooleanKeyword, + type: 'BooleanKeyword', + }, + }, + }, + my_str_array: { + items: { + kind: SyntaxKind.StringKeyword, + type: 'StringKeyword', + }, + }, + }, + }, + }, +]; diff --git a/packages/kbn-telemetry-tools/src/tools/extract_collectors.test.ts b/packages/kbn-telemetry-tools/src/tools/extract_collectors.test.ts index 378518a13c7ac2..5106ac7855fc6c 100644 --- a/packages/kbn-telemetry-tools/src/tools/extract_collectors.test.ts +++ b/packages/kbn-telemetry-tools/src/tools/extract_collectors.test.ts @@ -24,7 +24,7 @@ describe('extractCollectors', () => { const programPaths = await getProgramPaths(configs[0]); const results = [...extractCollectors(programPaths, tsConfig)]; - expect(results).toHaveLength(8); + expect(results).toHaveLength(9); expect(results).toStrictEqual(allExtractedCollectors); }); }); diff --git a/packages/kbn-telemetry-tools/src/tools/manage_schema.test.ts b/packages/kbn-telemetry-tools/src/tools/manage_schema.test.ts index b39e243d787728..80e58c49928b6b 100644 --- a/packages/kbn-telemetry-tools/src/tools/manage_schema.test.ts +++ b/packages/kbn-telemetry-tools/src/tools/manage_schema.test.ts @@ -8,6 +8,7 @@ import { generateMapping } from './manage_schema'; import { parsedWorkingCollector } from './__fixture__/parsed_working_collector'; +import { parsedCollectorWithDescription } from './__fixture__/parsed_working_collector_with_description'; import * as path from 'path'; import { readFile } from 'fs'; import { promisify } from 'util'; @@ -25,4 +26,9 @@ describe('generateMapping', () => { const result = generateMapping([parsedWorkingCollector]); expect(result).toEqual(mockSchema); }); + it('generates a mapping file that includes _meta.description fields', async () => { + const mockSchema = await parseJsonFile('mock_schema_with_descriptions.json'); + const result = generateMapping([parsedCollectorWithDescription]); + expect(result).toEqual(mockSchema); + }); }); diff --git a/scripts/build_kibana_platform_plugins.js b/scripts/build_kibana_platform_plugins.js index b562183dd19f5a..809e21bc652d0a 100644 --- a/scripts/build_kibana_platform_plugins.js +++ b/scripts/build_kibana_platform_plugins.js @@ -6,4 +6,6 @@ * Side Public License, v 1. */ -require('@kbn/optimizer/target/cli'); +require('@kbn/optimizer').runKbnOptimizerCli({ + defaultLimitsPath: require.resolve('../packages/kbn-optimizer/limits.yml'), +}); diff --git a/src/core/public/core_app/status/lib/load_status.ts b/src/core/public/core_app/status/lib/load_status.ts index d8d2bd3fec5175..3c31da4c5397f0 100644 --- a/src/core/public/core_app/status/lib/load_status.ts +++ b/src/core/public/core_app/status/lib/load_status.ts @@ -57,7 +57,7 @@ function formatMetrics({ metrics }: StatusResponse): Metric[] { defaultMessage: 'Load', }), value: [metrics.os.load['1m'], metrics.os.load['5m'], metrics.os.load['15m']], - type: 'time', + type: 'float', }, { name: i18n.translate('core.statusPage.metricsTiles.columns.resTimeAvgHeader', { diff --git a/src/core/public/doc_links/doc_links_service.ts b/src/core/public/doc_links/doc_links_service.ts index 7792e25e54d01e..e985b5cd61e79a 100644 --- a/src/core/public/doc_links/doc_links_service.ts +++ b/src/core/public/doc_links/doc_links_service.ts @@ -187,15 +187,17 @@ export class DocLinksService { guide: `${ELASTIC_WEBSITE_URL}guide/en/kibana/${DOC_LINK_VERSION}/managing-alerts-and-actions.html`, actionTypes: `${ELASTIC_WEBSITE_URL}guide/en/kibana/${DOC_LINK_VERSION}/action-types.html`, emailAction: `${ELASTIC_WEBSITE_URL}guide/en/kibana/${DOC_LINK_VERSION}/email-action-type.html`, + emailActionConfig: `${ELASTIC_WEBSITE_URL}guide/en/kibana/${DOC_LINK_VERSION}/email-action-type.html#configuring-email`, generalSettings: `${ELASTIC_WEBSITE_URL}guide/en/kibana/${DOC_LINK_VERSION}/alert-action-settings-kb.html#general-alert-action-settings`, indexAction: `${ELASTIC_WEBSITE_URL}guide/en/kibana/${DOC_LINK_VERSION}/index-action-type.html`, - indexThreshold: `${ELASTIC_WEBSITE_URL}guide/en/kibana/${DOC_LINK_VERSION}/alert-types.html#alert-type-index-threshold`, + esQuery: `${ELASTIC_WEBSITE_URL}guide/en/kibana/${DOC_LINK_VERSION}/alert-type-es-query.html`, + indexThreshold: `${ELASTIC_WEBSITE_URL}guide/en/kibana/${DOC_LINK_VERSION}/alert-type-index-threshold.html#index-action-configuration`, pagerDutyAction: `${ELASTIC_WEBSITE_URL}guide/en/kibana/${DOC_LINK_VERSION}/pagerduty-action-type.html`, preconfiguredConnectors: `${ELASTIC_WEBSITE_URL}guide/en/kibana/${DOC_LINK_VERSION}/pre-configured-action-types-and-connectors.html`, - serviceNowAction: `${ELASTIC_WEBSITE_URL}guide/en/kibana/${DOC_LINK_VERSION}/servicenow-action-type.html`, + serviceNowAction: `${ELASTIC_WEBSITE_URL}guide/en/kibana/${DOC_LINK_VERSION}/servicenow-action-type.html#configuring-servicenow`, setupPrerequisites: `${ELASTIC_WEBSITE_URL}guide/en/kibana/${DOC_LINK_VERSION}/alerting-getting-started.html#alerting-setup-prerequisites`, - slackAction: `${ELASTIC_WEBSITE_URL}guide/en/kibana/${DOC_LINK_VERSION}/slack-action-type.html`, - teamsAction: `${ELASTIC_WEBSITE_URL}guide/en/kibana/${DOC_LINK_VERSION}/teams-action-type.html`, + slackAction: `${ELASTIC_WEBSITE_URL}guide/en/kibana/${DOC_LINK_VERSION}/slack-action-type.html#configuring-slack`, + teamsAction: `${ELASTIC_WEBSITE_URL}guide/en/kibana/${DOC_LINK_VERSION}/teams-action-type.html#configuring-teams`, }, maps: { guide: `${ELASTIC_WEBSITE_URL}guide/en/kibana/${DOC_LINK_VERSION}/maps.html`, diff --git a/src/core/server/http/logging/get_payload_size.test.ts b/src/core/server/http/logging/get_payload_size.test.ts index dba5c7be30f3b0..30cb547dd98b77 100644 --- a/src/core/server/http/logging/get_payload_size.test.ts +++ b/src/core/server/http/logging/get_payload_size.test.ts @@ -6,12 +6,13 @@ * Side Public License, v 1. */ -import { createGunzip } from 'zlib'; import type { Request } from '@hapi/hapi'; import Boom from '@hapi/boom'; import mockFs from 'mock-fs'; import { createReadStream } from 'fs'; +import { PassThrough } from 'stream'; +import { createGunzip, createGzip } from 'zlib'; import { loggerMock, MockedLogger } from '../../logging/logger.mock'; @@ -55,59 +56,107 @@ describe('getPayloadSize', () => { }); }); - describe('handles fs streams', () => { + describe('handles streams', () => { afterEach(() => mockFs.restore()); - test('with ascii characters', async () => { - mockFs({ 'test.txt': 'heya' }); - const source = createReadStream('test.txt'); - - let data = ''; - for await (const chunk of source) { - data += chunk; - } - + test('ignores streams that are not fs or zlib streams', async () => { const result = getResponsePayloadBytes( { variety: 'stream', - source, + source: new PassThrough(), } as Response, logger ); - expect(result).toBe(Buffer.byteLength(data)); + expect(result).toBe(undefined); }); - test('with special characters', async () => { - mockFs({ 'test.txt': '¡hola!' }); - const source = createReadStream('test.txt'); + describe('fs streams', () => { + test('with ascii characters', async () => { + mockFs({ 'test.txt': 'heya' }); + const source = createReadStream('test.txt'); - let data = ''; - for await (const chunk of source) { - data += chunk; - } + let data = ''; + for await (const chunk of source) { + data += chunk; + } - const result = getResponsePayloadBytes( - { - variety: 'stream', - source, - } as Response, - logger - ); + const result = getResponsePayloadBytes( + { + variety: 'stream', + source, + } as Response, + logger + ); + + expect(result).toBe(Buffer.byteLength(data)); + }); + + test('with special characters', async () => { + mockFs({ 'test.txt': '¡hola!' }); + const source = createReadStream('test.txt'); + + let data = ''; + for await (const chunk of source) { + data += chunk; + } + + const result = getResponsePayloadBytes( + { + variety: 'stream', + source, + } as Response, + logger + ); - expect(result).toBe(Buffer.byteLength(data)); + expect(result).toBe(Buffer.byteLength(data)); + }); }); - test('ignores streams that are not instances of ReadStream', async () => { - const result = getResponsePayloadBytes( - { - variety: 'stream', - source: createGunzip(), - } as Response, - logger - ); + describe('zlib streams', () => { + test('with ascii characters', async () => { + mockFs({ 'test.txt': 'heya' }); + const readStream = createReadStream('test.txt'); + const source = readStream.pipe(createGzip()).pipe(createGunzip()); - expect(result).toBe(undefined); + let data = ''; + for await (const chunk of source) { + data += chunk; + } + + const result = getResponsePayloadBytes( + { + variety: 'stream', + source, + } as Response, + logger + ); + + expect(data).toBe('heya'); + expect(result).toBe(source.bytesWritten); + }); + + test('with special characters', async () => { + mockFs({ 'test.txt': '¡hola!' }); + const readStream = createReadStream('test.txt'); + const source = readStream.pipe(createGzip()).pipe(createGunzip()); + + let data = ''; + for await (const chunk of source) { + data += chunk; + } + + const result = getResponsePayloadBytes( + { + variety: 'stream', + source, + } as Response, + logger + ); + + expect(data).toBe('¡hola!'); + expect(result).toBe(source.bytesWritten); + }); }); }); @@ -134,7 +183,7 @@ describe('getPayloadSize', () => { expect(result).toBe(7); }); - test('when source is object', () => { + test('when source is plain object', () => { const payload = { message: 'heya' }; const result = getResponsePayloadBytes( { @@ -146,11 +195,26 @@ describe('getPayloadSize', () => { expect(result).toBe(JSON.stringify(payload).length); }); + test('when source is array object', () => { + const payload = [{ message: 'hey' }, { message: 'ya' }]; + const result = getResponsePayloadBytes( + { + variety: 'plain', + source: payload, + } as Response, + logger + ); + expect(result).toBe(JSON.stringify(payload).length); + }); + test('returns undefined when source is not a plain object', () => { + class TestClass { + constructor() {} + } const result = getResponsePayloadBytes( { variety: 'plain', - source: [1, 2, 3], + source: new TestClass(), } as Response, logger ); diff --git a/src/core/server/http/logging/get_payload_size.ts b/src/core/server/http/logging/get_payload_size.ts index 8e6dea13e1fa17..2797b4ba9f490e 100644 --- a/src/core/server/http/logging/get_payload_size.ts +++ b/src/core/server/http/logging/get_payload_size.ts @@ -8,25 +8,23 @@ import { isPlainObject } from 'lodash'; import { ReadStream } from 'fs'; +import { Zlib } from 'zlib'; import { isBoom } from '@hapi/boom'; import type { Request } from '@hapi/hapi'; import { Logger } from '../../logging'; type Response = Request['response']; -const isBuffer = (src: unknown, res: Response): src is Buffer => { - return !isBoom(res) && res.variety === 'buffer' && res.source === src; +const isBuffer = (src: unknown, variety: string): src is Buffer => + variety === 'buffer' && Buffer.isBuffer(src); +const isFsReadStream = (src: unknown, variety: string): src is ReadStream => { + return variety === 'stream' && src instanceof ReadStream; }; -const isFsReadStream = (src: unknown, res: Response): src is ReadStream => { - return ( - !isBoom(res) && - res.variety === 'stream' && - res.source === src && - res.source instanceof ReadStream - ); +const isZlibStream = (src: unknown, variety: string): src is Zlib => { + return variety === 'stream' && typeof src === 'object' && src !== null && 'bytesWritten' in src; }; -const isString = (src: unknown, res: Response): src is string => - !isBoom(res) && res.variety === 'plain' && typeof src === 'string'; +const isString = (src: unknown, variety: string): src is string => + variety === 'plain' && typeof src === 'string'; /** * Attempts to determine the size (in bytes) of a Hapi response @@ -57,19 +55,26 @@ export function getResponsePayloadBytes(response: Response, log: Logger): number return Buffer.byteLength(JSON.stringify(response.output.payload)); } - if (isBuffer(response.source, response)) { + if (isBuffer(response.source, response.variety)) { return response.source.byteLength; } - if (isFsReadStream(response.source, response)) { + if (isFsReadStream(response.source, response.variety)) { return response.source.bytesRead; } - if (isString(response.source, response)) { + if (isZlibStream(response.source, response.variety)) { + return response.source.bytesWritten; + } + + if (isString(response.source, response.variety)) { return Buffer.byteLength(response.source); } - if (response.variety === 'plain' && isPlainObject(response.source)) { + if ( + response.variety === 'plain' && + (isPlainObject(response.source) || Array.isArray(response.source)) + ) { return Buffer.byteLength(JSON.stringify(response.source)); } } catch (e) { diff --git a/src/core/server/ui_settings/saved_objects/migrations.test.ts b/src/core/server/ui_settings/saved_objects/migrations.test.ts index ea5b4133b49c30..7b53f4e21dd9bd 100644 --- a/src/core/server/ui_settings/saved_objects/migrations.test.ts +++ b/src/core/server/ui_settings/saved_objects/migrations.test.ts @@ -44,3 +44,37 @@ describe('ui_settings 7.9.0 migrations', () => { }); }); }); + +describe('ui_settings 7.13.0 migrations', () => { + const migration = migrations['7.13.0']; + + test('returns doc on empty object', () => { + expect(migration({} as SavedObjectUnsanitizedDoc)).toEqual({ + references: [], + }); + }); + test('properly renames ml:fileDataVisualizerMaxFileSize to fileUpload:maxFileSize', () => { + const doc = { + type: 'config', + id: '8.0.0', + attributes: { + buildNum: 9007199254740991, + 'ml:fileDataVisualizerMaxFileSize': '250MB', + }, + references: [], + updated_at: '2020-06-09T20:18:20.349Z', + migrationVersion: {}, + }; + expect(migration(doc)).toEqual({ + type: 'config', + id: '8.0.0', + attributes: { + buildNum: 9007199254740991, + 'fileUpload:maxFileSize': '250MB', + }, + references: [], + updated_at: '2020-06-09T20:18:20.349Z', + migrationVersion: {}, + }); + }); +}); diff --git a/src/core/server/ui_settings/saved_objects/migrations.ts b/src/core/server/ui_settings/saved_objects/migrations.ts index 7ea5573076ba02..b5dc13fcdae3b2 100644 --- a/src/core/server/ui_settings/saved_objects/migrations.ts +++ b/src/core/server/ui_settings/saved_objects/migrations.ts @@ -28,4 +28,23 @@ export const migrations = { }), references: doc.references || [], }), + '7.13.0': (doc: SavedObjectUnsanitizedDoc): SavedObjectSanitizedDoc => ({ + ...doc, + ...(doc.attributes && { + attributes: Object.keys(doc.attributes).reduce( + (acc, key) => + key === 'ml:fileDataVisualizerMaxFileSize' + ? { + ...acc, + ['fileUpload:maxFileSize']: doc.attributes[key], + } + : { + ...acc, + [key]: doc.attributes[key], + }, + {} + ), + }), + references: doc.references || [], + }), }; diff --git a/src/dev/bazel_workspace_status.js b/src/dev/bazel_workspace_status.js index fe60f9176d243e..3c3ef1574cd8e8 100644 --- a/src/dev/bazel_workspace_status.js +++ b/src/dev/bazel_workspace_status.js @@ -43,25 +43,23 @@ // Commit SHA const commitSHACmdResult = await runCmd('git', ['rev-parse', 'HEAD']); - if (commitSHACmdResult.exitCode !== 0) { - process.exit(1); - } - console.log(`COMMIT_SHA ${commitSHACmdResult.stdout}`); + if (commitSHACmdResult.exitCode === 0) { + console.log(`COMMIT_SHA ${commitSHACmdResult.stdout}`); - // Git branch - const gitBranchCmdResult = await runCmd('git', ['rev-parse', '--abbrev-ref', 'HEAD']); - if (gitBranchCmdResult.exitCode !== 0) { - process.exit(1); - } - console.log(`GIT_BRANCH ${gitBranchCmdResult.stdout}`); + // Branch + const gitBranchCmdResult = await runCmd('git', ['rev-parse', '--abbrev-ref', 'HEAD']); + if (gitBranchCmdResult.exitCode === 0) { + console.log(`GIT_BRANCH ${gitBranchCmdResult.stdout}`); + } - // Tree status - const treeStatusCmdResult = await runCmd('git', ['diff-index', '--quiet', 'HEAD', '--']); - const treeStatusVarStr = 'GIT_TREE_STATUS'; - if (treeStatusCmdResult.exitCode === 0) { - console.log(`${treeStatusVarStr} Clean`); - } else { - console.log(`${treeStatusVarStr} Modified`); + // Tree status + const treeStatusCmdResult = await runCmd('git', ['diff-index', '--quiet', 'HEAD', '--']); + const treeStatusVarStr = 'GIT_TREE_STATUS'; + if (treeStatusCmdResult.exitCode === 0) { + console.log(`${treeStatusVarStr} Clean`); + } else { + console.log(`${treeStatusVarStr} Modified`); + } } // Host @@ -72,9 +70,8 @@ return !cpu.model.includes('Intel') || index % 2 === 1; }).length; - if (hostCmdResult.exitCode !== 0) { - process.exit(1); + if (hostCmdResult.exitCode === 0) { + console.log(`HOST ${hostStr}-${coresStr}`); } - console.log(`HOST ${hostStr}-${coresStr}`); } })(); diff --git a/src/dev/build/tasks/build_kibana_platform_plugins.ts b/src/dev/build/tasks/build_kibana_platform_plugins.ts index d2d2d3275270b8..dfac3edf9847bd 100644 --- a/src/dev/build/tasks/build_kibana_platform_plugins.ts +++ b/src/dev/build/tasks/build_kibana_platform_plugins.ts @@ -27,6 +27,7 @@ export const BuildKibanaPlatformPlugins: Task = { watch: false, dist: true, includeCoreBundle: true, + limitsPath: Path.resolve(REPO_ROOT, 'packages/kbn-optimizer/limits.yml'), }); await lastValueFrom(runOptimizer(config).pipe(logOptimizerState(log, config))); diff --git a/src/dev/ci_setup/bootstrap_validations.sh b/src/dev/ci_setup/bootstrap_validations.sh new file mode 100644 index 00000000000000..939269952dea11 --- /dev/null +++ b/src/dev/ci_setup/bootstrap_validations.sh @@ -0,0 +1,64 @@ +#!/usr/bin/env bash + +set -e + +### +### verify no git modifications caused by bootstrap +### +if [[ $DISABLE_BOOTSTRAP_VALIDATIONS != "true" ]]; then + GIT_CHANGES="$(git ls-files --modified)" + if [ "$GIT_CHANGES" ]; then + echo -e "\n${RED}ERROR: 'yarn kbn bootstrap' caused changes to the following files:${C_RESET}\n" + echo -e "$GIT_CHANGES\n" + exit 1 + fi +fi + + +### +### rebuild kbn-pm distributable to ensure it's not out of date +### +echo " -- building kbn-pm distributable" +yarn kbn run build -i @kbn/pm + +### +### verify no git modifications +### +GIT_CHANGES="$(git ls-files --modified)" +if [ "$GIT_CHANGES" ]; then + echo -e "\n${RED}ERROR: 'yarn kbn run build -i @kbn/pm' caused changes to the following files:${C_RESET}\n" + echo -e "$GIT_CHANGES\n" + exit 1 +fi + +### +### rebuild plugin list to ensure it's not out of date +### +echo " -- building plugin list docs" +node scripts/build_plugin_list_docs + +### +### verify no git modifications +### +GIT_CHANGES="$(git ls-files --modified)" +if [ "$GIT_CHANGES" ]; then + echo -e "\n${RED}ERROR: 'node scripts/build_plugin_list_docs' caused changes to the following files:${C_RESET}\n" + echo -e "$GIT_CHANGES\n" + exit 1 +fi + +### +### rebuild plugin api docs to ensure it's not out of date +### +echo " -- building api docs" +node scripts/build_api_docs + +### +### verify no api changes +### +GIT_CHANGES="$(git ls-files --modified)" +if [ "$GIT_CHANGES" ]; then + echo -e "\n${RED}ERROR: 'node scripts/build_api_docs' caused changes to the following files:${C_RESET}\n" + echo -e "$GIT_CHANGES\n" + exit 1 +fi diff --git a/src/dev/ci_setup/setup.sh b/src/dev/ci_setup/setup.sh index b685b32038f8e3..3c08b336f16286 100755 --- a/src/dev/ci_setup/setup.sh +++ b/src/dev/ci_setup/setup.sh @@ -40,66 +40,12 @@ if [[ "$BUILD_TS_REFS_CACHE_CAPTURE" == "true" ]]; then cd "$KIBANA_DIR" fi +if [[ "$DISABLE_BOOTSTRAP_VALIDATIONS" != "true" ]]; then + source "$KIBANA_DIR/src/dev/ci_setup/bootstrap_validations.sh" +fi + ### ### Download es snapshots ### echo " -- downloading es snapshot" node scripts/es snapshot --download-only; - -### -### verify no git modifications -### -GIT_CHANGES="$(git ls-files --modified)" -if [ "$GIT_CHANGES" ]; then - echo -e "\n${RED}ERROR: 'yarn kbn bootstrap' caused changes to the following files:${C_RESET}\n" - echo -e "$GIT_CHANGES\n" - exit 1 -fi - -### -### rebuild kbn-pm distributable to ensure it's not out of date -### -echo " -- building kbn-pm distributable" -yarn kbn run build -i @kbn/pm - -### -### verify no git modifications -### -GIT_CHANGES="$(git ls-files --modified)" -if [ "$GIT_CHANGES" ]; then - echo -e "\n${RED}ERROR: 'yarn kbn run build -i @kbn/pm' caused changes to the following files:${C_RESET}\n" - echo -e "$GIT_CHANGES\n" - exit 1 -fi - -### -### rebuild plugin list to ensure it's not out of date -### -echo " -- building plugin list docs" -node scripts/build_plugin_list_docs - -### -### verify no git modifications -### -GIT_CHANGES="$(git ls-files --modified)" -if [ "$GIT_CHANGES" ]; then - echo -e "\n${RED}ERROR: 'node scripts/build_plugin_list_docs' caused changes to the following files:${C_RESET}\n" - echo -e "$GIT_CHANGES\n" - exit 1 -fi - -### -### rebuild plugin api docs to ensure it's not out of date -### -echo " -- building api docs" -node scripts/build_api_docs - -### -### verify no api changes -### -GIT_CHANGES="$(git ls-files --modified)" -if [ "$GIT_CHANGES" ]; then - echo -e "\n${RED}ERROR: 'node scripts/build_api_docs' caused changes to the following files:${C_RESET}\n" - echo -e "$GIT_CHANGES\n" - exit 1 -fi \ No newline at end of file diff --git a/src/fixtures/telemetry_collectors/working_collector_with_description.ts b/src/fixtures/telemetry_collectors/working_collector_with_description.ts new file mode 100644 index 00000000000000..433993df06886a --- /dev/null +++ b/src/fixtures/telemetry_collectors/working_collector_with_description.ts @@ -0,0 +1,102 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { CollectorSet } from '../../plugins/usage_collection/server/collector'; +import { loggerMock } from '../../core/server/logging/logger.mock'; + +const { makeUsageCollector } = new CollectorSet({ + logger: loggerMock.create(), + maximumWaitTimeForAllCollectorsInS: 0, +}); + +interface MyObject { + total: number; + type: boolean; +} + +interface Usage { + flat?: string; + my_str?: string; + my_objects: MyObject; + my_array?: MyObject[]; + my_str_array?: string[]; + my_index_signature_prop?: { + [key: string]: number; + }; +} + +const SOME_NUMBER: number = 123; + +export const myCollector = makeUsageCollector({ + type: 'my_working_collector_with_description', + isReady: () => true, + fetch() { + const testString = '123'; + // query ES and get some data + + // summarize the data into a model + // return the modeled object that includes whatever you want to track + try { + return { + flat: 'hello', + my_str: testString, + my_objects: { + total: SOME_NUMBER, + type: true, + }, + my_array: [ + { + total: SOME_NUMBER, + type: true, + }, + ], + my_str_array: ['hello', 'world'], + }; + } catch (err) { + return { + my_objects: { + total: 0, + type: true, + }, + }; + } + }, + schema: { + flat: { + type: 'keyword', + _meta: { + description: 'A flat keyword string', + }, + }, + my_str: { + type: 'text', + }, + my_objects: { + total: { + type: 'long', + }, + type: { type: 'boolean' }, + }, + my_array: { + type: 'array', + items: { + total: { + type: 'long', + }, + type: { type: 'boolean' }, + }, + }, + my_str_array: { type: 'array', items: { type: 'keyword' } }, + my_index_signature_prop: { + count: { type: 'long' }, + avg: { type: 'float' }, + max: { type: 'long' }, + min: { type: 'long' }, + }, + }, +}); diff --git a/src/plugins/discover/public/application/components/top_nav/open_search_panel.tsx b/src/plugins/discover/public/application/components/top_nav/open_search_panel.tsx index 8c5f44b97f4b30..f6881d1856566a 100644 --- a/src/plugins/discover/public/application/components/top_nav/open_search_panel.tsx +++ b/src/plugins/discover/public/application/components/top_nav/open_search_panel.tsx @@ -59,7 +59,7 @@ export function OpenSearchPanel(props: OpenSearchPanelProps) { savedObjectMetaData={[ { type: SEARCH_OBJECT_TYPE, - getIconForSavedObject: () => 'search', + getIconForSavedObject: () => 'discoverApp', name: i18n.translate('discover.savedSearch.savedObjectName', { defaultMessage: 'Saved search', }), diff --git a/src/plugins/discover/public/application/embeddable/search_embeddable_factory.ts b/src/plugins/discover/public/application/embeddable/search_embeddable_factory.ts index 043869f99bb350..77da138d118dd0 100644 --- a/src/plugins/discover/public/application/embeddable/search_embeddable_factory.ts +++ b/src/plugins/discover/public/application/embeddable/search_embeddable_factory.ts @@ -36,7 +36,7 @@ export class SearchEmbeddableFactory defaultMessage: 'Saved search', }), type: 'search', - getIconForSavedObject: () => 'search', + getIconForSavedObject: () => 'discoverApp', }; constructor( diff --git a/src/plugins/kibana_usage_collection/README.md b/src/plugins/kibana_usage_collection/README.md index 85d362cf0a9b1e..9ad2bd987e1f49 100644 --- a/src/plugins/kibana_usage_collection/README.md +++ b/src/plugins/kibana_usage_collection/README.md @@ -3,9 +3,16 @@ This plugin registers the basic usage collectors from Kibana: - [Application Usage](./server/collectors/application_usage/README.md) -- UI Metrics -- Ops stats -- Number of Saved Objects per type -- [User-changed UI Settings](./server/collectors/management/README.md) -- CSP configuration - Core Metrics +- CSP configuration +- Kibana: Number of Saved Objects per type +- Localization data +- [User-changed UI Settings](./server/collectors/management/README.md) +- Ops stats +- UI Counts +- UI Metrics + + + + + diff --git a/src/plugins/kibana_usage_collection/server/collectors/application_usage/README.md b/src/plugins/kibana_usage_collection/server/collectors/application_usage/README.md index c66074b792bd0f..1f7344a8012277 100644 --- a/src/plugins/kibana_usage_collection/server/collectors/application_usage/README.md +++ b/src/plugins/kibana_usage_collection/server/collectors/application_usage/README.md @@ -10,7 +10,7 @@ To track a sub view inside your application (ie a flyout, a tab, form step, etc) #### For a React Component -For tracking an application view rendered using react the simplest way is to wrap your component with the `TrackApplicationView` Higher order component: +For tracking an application view rendered using react the simplest way is to wrap your component with the `TrackApplicationView` Higher order component exposed from the `usageCollection` plugin. You will need to add the plugin to plugin's `kibana.json` file as an item in the `optionalPlugins` and `requiredBundles` declarations: kibana.json ```json @@ -26,6 +26,7 @@ kibana.json At the application level, the application must be wrapped by the `ApplicationUsageTrackingProvider` provided in the `usageCollection`'s setup contract. +For example: ```typescript jsx class MyPlugin implements Plugin { ... @@ -69,7 +70,6 @@ const MyTrackedComponent = () => { Application Usage will automatically track the active minutes on screen and clicks for both the application and the `MyComponent` component whenever it is mounted on the screen. Application Usage pauses counting screen minutes whenever the user is tabbed to another browser window. The prop `viewId` is used as a unique identifier for your plugin. The Application Id is automatically attached to the tracked usage, based on the ID used when registering your app via `core.application.register`. - ## Application Usage Telemetry Data This collector reports the number of general clicks and minutes on screen for each registered application in Kibana. @@ -126,4 +126,4 @@ In order to keep the count of the events, this collector uses 3 Saved Objects: All the types use the shared fields `appId: 'keyword'`, `viewId: 'keyword'`, `numberOfClicks: 'long'` and `minutesOnScreen: 'float'`, but they are currently not added in the mappings because we don't use them for search purposes, and we need to be thoughtful with the number of mapped fields in the SavedObjects index ([#43673](https://github.com/elastic/kibana/issues/43673)). `application_usage_transactional` and `application_usage_daily` also store `timestamp: { type: 'date' }`. -Rollups uses `appId` in the savedObject id for the default view. For other views `viewId` is concatenated. This keeps backwards compatiblity with previously stored documents on the clusters without requiring any form of migration. \ No newline at end of file +Rollups uses `appId` in the savedObject id for the default view. For other views `viewId` is concatenated. This keeps backwards compatiblity with previously stored documents on the clusters without requiring any form of migration. diff --git a/src/plugins/kibana_usage_collection/server/collectors/application_usage/schema.ts b/src/plugins/kibana_usage_collection/server/collectors/application_usage/schema.ts index 136abc9049053b..062d751ef454c7 100644 --- a/src/plugins/kibana_usage_collection/server/collectors/application_usage/schema.ts +++ b/src/plugins/kibana_usage_collection/server/collectors/application_usage/schema.ts @@ -10,29 +10,106 @@ import { MakeSchemaFrom } from 'src/plugins/usage_collection/server'; import { ApplicationUsageTelemetryReport } from './telemetry_application_usage_collector'; const commonSchema: MakeSchemaFrom = { - appId: { type: 'keyword' }, - viewId: { type: 'keyword' }, - clicks_total: { type: 'long' }, - clicks_7_days: { type: 'long' }, - clicks_30_days: { type: 'long' }, - clicks_90_days: { type: 'long' }, - minutes_on_screen_total: { type: 'float' }, - minutes_on_screen_7_days: { type: 'float' }, - minutes_on_screen_30_days: { type: 'float' }, - minutes_on_screen_90_days: { type: 'float' }, + appId: { type: 'keyword', _meta: { description: 'The application being tracked' } }, + viewId: { type: 'keyword', _meta: { description: 'Always `main`' } }, + clicks_total: { + type: 'long', + _meta: { + description: 'General number of clicks in the application since we started counting them', + }, + }, + clicks_7_days: { + type: 'long', + _meta: { description: 'General number of clicks in the application over the last 7 days' }, + }, + clicks_30_days: { + type: 'long', + _meta: { description: 'General number of clicks in the application over the last 30 days' }, + }, + clicks_90_days: { + type: 'long', + _meta: { description: 'General number of clicks in the application over the last 90 days' }, + }, + minutes_on_screen_total: { + type: 'float', + _meta: { + description: + 'Minutes the application is active and on-screen since we started counting them.', + }, + }, + minutes_on_screen_7_days: { + type: 'float', + _meta: { description: 'Minutes the application is active and on-screen over the last 7 days' }, + }, + minutes_on_screen_30_days: { + type: 'float', + _meta: { description: 'Minutes the application is active and on-screen over the last 30 days' }, + }, + minutes_on_screen_90_days: { + type: 'float', + _meta: { description: 'Minutes the application is active and on-screen over the last 90 days' }, + }, views: { type: 'array', items: { - appId: { type: 'keyword' }, - viewId: { type: 'keyword' }, - clicks_total: { type: 'long' }, - clicks_7_days: { type: 'long' }, - clicks_30_days: { type: 'long' }, - clicks_90_days: { type: 'long' }, - minutes_on_screen_total: { type: 'float' }, - minutes_on_screen_7_days: { type: 'float' }, - minutes_on_screen_30_days: { type: 'float' }, - minutes_on_screen_90_days: { type: 'float' }, + appId: { type: 'keyword', _meta: { description: 'The application being tracked' } }, + viewId: { type: 'keyword', _meta: { description: 'The application view being tracked' } }, + clicks_total: { + type: 'long', + _meta: { + description: + 'General number of clicks in the application sub view since we started counting them', + }, + }, + clicks_7_days: { + type: 'long', + _meta: { + description: + 'General number of clicks in the active application sub view over the last 7 days', + }, + }, + clicks_30_days: { + type: 'long', + _meta: { + description: + 'General number of clicks in the active application sub view over the last 30 days', + }, + }, + clicks_90_days: { + type: 'long', + _meta: { + description: + 'General number of clicks in the active application sub view over the last 90 days', + }, + }, + minutes_on_screen_total: { + type: 'float', + _meta: { + description: + 'Minutes the application sub view is active and on-screen since we started counting them.', + }, + }, + minutes_on_screen_7_days: { + type: 'float', + _meta: { + description: + 'Minutes the application is active and on-screen active application sub view over the last 7 days', + }, + }, + minutes_on_screen_30_days: { + type: 'float', + _meta: { + description: + 'Minutes the application is active and on-screen active application sub view over the last 30 days', + }, + }, + minutes_on_screen_90_days: { + type: 'float', + _meta: { + description: + 'Minutes the application is active and on-screen active application sub view over the last 90 days', + }, + }, }, }, }; diff --git a/src/plugins/kibana_usage_collection/server/collectors/core/core_usage_collector.ts b/src/plugins/kibana_usage_collection/server/collectors/core/core_usage_collector.ts index 4a1848586114a2..70ac2302dc3b4b 100644 --- a/src/plugins/kibana_usage_collection/server/collectors/core/core_usage_collector.ts +++ b/src/plugins/kibana_usage_collection/server/collectors/core/core_usage_collector.ts @@ -19,76 +19,276 @@ export function getCoreUsageCollector( schema: { config: { elasticsearch: { - sniffOnStart: { type: 'boolean' }, - sniffIntervalMs: { type: 'long' }, - sniffOnConnectionFault: { type: 'boolean' }, - numberOfHostsConfigured: { type: 'long' }, - requestHeadersWhitelistConfigured: { type: 'boolean' }, - customHeadersConfigured: { type: 'boolean' }, - shardTimeoutMs: { type: 'long' }, - requestTimeoutMs: { type: 'long' }, - pingTimeoutMs: { type: 'long' }, - logQueries: { type: 'boolean' }, + sniffOnStart: { + type: 'boolean', + _meta: { + description: + 'Indicates if an attempt should be made to find other Elasticsearch nodes on startup.', + }, + }, + sniffIntervalMs: { + type: 'long', + _meta: { + description: + 'Time in milliseconds between requests to check Elasticsearch for an updated list of nodes.', + }, + }, + sniffOnConnectionFault: { + type: 'boolean', + _meta: { + description: + 'Indicates if the list of Elasticsearch nodes should be updated immediately following a connection fault.', + }, + }, + numberOfHostsConfigured: { + type: 'long', + _meta: { + description: 'Number of Elasticsearch instances configured to use for queries.', + }, + }, + requestHeadersWhitelistConfigured: { + type: 'boolean', + _meta: { + description: + 'Indicates if Kibana client-side headers to send to Elasticsearch is different to the default value.', + }, + }, + customHeadersConfigured: { + type: 'boolean', + _meta: { description: 'Indicates if any custom headers have been configured.' }, + }, + shardTimeoutMs: { + type: 'long', + _meta: { + description: + 'Time in milliseconds for Elasticsearch to wait for responses from shards.', + }, + }, + requestTimeoutMs: { + type: 'long', + _meta: { + description: + 'Time in milliseconds to wait for responses from the back end or Elasticsearch.', + }, + }, + pingTimeoutMs: { + type: 'long', + _meta: { + description: 'Time in milliseconds to wait for Elasticsearch to respond to pings.', + }, + }, + logQueries: { + type: 'boolean', + _meta: { description: 'Indicates if queries sent to Elasticsearch should be logged.' }, + }, ssl: { - verificationMode: { type: 'keyword' }, - certificateAuthoritiesConfigured: { type: 'boolean' }, - certificateConfigured: { type: 'boolean' }, - keyConfigured: { type: 'boolean' }, - keystoreConfigured: { type: 'boolean' }, - truststoreConfigured: { type: 'boolean' }, - alwaysPresentCertificate: { type: 'boolean' }, + verificationMode: { + type: 'keyword', + _meta: { + description: + 'The verification of the server certificate that Kibana receives when making an outbound SSL or TLS connection to Elasticsearch', + }, + }, + certificateAuthoritiesConfigured: { + type: 'boolean', + _meta: { + description: + 'Indicates if any PEM-encoded X.509 certificate authority certificates are configured.', + }, + }, + certificateConfigured: { + type: 'boolean', + _meta: { description: 'Indicates if a certificate authority is configured.' }, + }, + keyConfigured: { + type: 'boolean', + _meta: { description: 'Indicates if a certificate key is configured.' }, + }, + keystoreConfigured: { + type: 'boolean', + _meta: { description: 'Indicates if a keystore is configured.' }, + }, + truststoreConfigured: { + type: 'boolean', + _meta: { description: 'Indicates if a path to a PKCS#12 trust store is configured.' }, + }, + alwaysPresentCertificate: { + type: 'boolean', + _meta: { + description: + 'Indicates if a client certificate is presented when requested by Elasticsearch.', + }, + }, + }, + apiVersion: { + type: 'keyword', + _meta: { description: 'Version of the Elasticsearch API used.' }, + }, + healthCheckDelayMs: { + type: 'long', + _meta: { + description: + 'The interval in miliseconds between health check requests Kibana sends to the Elasticsearch.', + }, }, - apiVersion: { type: 'keyword' }, - healthCheckDelayMs: { type: 'long' }, }, http: { - basePathConfigured: { type: 'boolean' }, - maxPayloadInBytes: { type: 'long' }, - rewriteBasePath: { type: 'boolean' }, - keepaliveTimeout: { type: 'long' }, - socketTimeout: { type: 'long' }, + basePathConfigured: { + type: 'boolean', + _meta: { description: 'Indicates if a base path has been configured.' }, + }, + maxPayloadInBytes: { + type: 'long', + _meta: { description: 'Maximum payload size in bytes that is allowed.' }, + }, + rewriteBasePath: { + type: 'boolean', + _meta: { description: 'Indicates if the base path should be rewritten.' }, + }, + keepaliveTimeout: { + type: 'long', + _meta: { description: 'How long to keep sockets alive globally in milliseconds.' }, + }, + socketTimeout: { + type: 'long', + _meta: { + description: 'How long to wait before closing inactive sockets in milliseconds.', + }, + }, compression: { - enabled: { type: 'boolean' }, - referrerWhitelistConfigured: { type: 'boolean' }, + enabled: { + type: 'boolean', + _meta: { description: 'Indicates if HTTP response compression is enabled.' }, + }, + referrerWhitelistConfigured: { + type: 'boolean', + _meta: { description: 'Indicates if any responses should be compressed.' }, + }, }, xsrf: { - disableProtection: { type: 'boolean' }, - allowlistConfigured: { type: 'boolean' }, + disableProtection: { + type: 'boolean', + _meta: { description: 'Indicates if protection against xsrf should be disabled.' }, + }, + allowlistConfigured: { + type: 'boolean', + _meta: { description: 'Indicates if any http headers have been whitelisted.' }, + }, }, requestId: { - allowFromAnyIp: { type: 'boolean' }, - ipAllowlistConfigured: { type: 'boolean' }, + allowFromAnyIp: { + type: 'boolean', + _meta: { description: 'Indicates if any http headers have been whitelisted.' }, + }, + ipAllowlistConfigured: { + type: 'boolean', + _meta: { description: 'Indicates if a list of specific IPs has been configured.' }, + }, }, ssl: { - certificateAuthoritiesConfigured: { type: 'boolean' }, - certificateConfigured: { type: 'boolean' }, - cipherSuites: { type: 'array', items: { type: 'keyword' } }, - keyConfigured: { type: 'boolean' }, - keystoreConfigured: { type: 'boolean' }, - truststoreConfigured: { type: 'boolean' }, - redirectHttpFromPortConfigured: { type: 'boolean' }, - supportedProtocols: { type: 'array', items: { type: 'keyword' } }, - clientAuthentication: { type: 'keyword' }, + certificateAuthoritiesConfigured: { + type: 'boolean', + _meta: { + description: 'Indicates if ssl certificate authorities have been configured.', + }, + }, + certificateConfigured: { + type: 'boolean', + _meta: { description: 'Indicates if an ssl certificate is configured.' }, + }, + cipherSuites: { + type: 'array', + items: { + type: 'keyword', + _meta: { description: 'The keyword of the cipher suite used.' }, + }, + }, + keyConfigured: { + type: 'boolean', + _meta: { description: 'Indicates if an ssl key has been configured.' }, + }, + keystoreConfigured: { + type: 'boolean', + _meta: { description: 'Indicates if an ssl keystore has been configured.' }, + }, + truststoreConfigured: { + type: 'boolean', + _meta: { description: 'Indicates if a path to a PKCS#12 trust store is configured.' }, + }, + redirectHttpFromPortConfigured: { + type: 'boolean', + _meta: { + description: + 'Indicates if a port to redirect all http requests has been configured.', + }, + }, + supportedProtocols: { + type: 'array', + items: { + type: 'keyword', + _meta: { description: 'The version of a supported protocol used.' }, + }, + }, + clientAuthentication: { + type: 'keyword', + _meta: { + description: + 'The behavior in Kibana for requesting a certificate from client connections.', + }, + }, }, }, logging: { - appendersTypesUsed: { type: 'array', items: { type: 'keyword' } }, - loggersConfiguredCount: { type: 'long' }, + appendersTypesUsed: { + type: 'array', + items: { + type: 'keyword', + _meta: { description: 'The type of logging appender confgured.' }, + }, + }, + loggersConfiguredCount: { + type: 'long', + _meta: { description: 'The total number of logging appenders configured.' }, + }, }, savedObjects: { - customIndex: { type: 'boolean' }, - maxImportPayloadBytes: { type: 'long' }, - maxImportExportSizeBytes: { type: 'long' }, + customIndex: { + type: 'boolean', + _meta: { + description: + 'Indicates if the saved objects index is different to the standard internal .kibana index.', + }, + }, + maxImportPayloadBytes: { + type: 'long', + _meta: { + description: + 'Maximum size of the payload in bytes of saved objects that can be imported.', + }, + }, + maxImportExportSizeBytes: { + type: 'long', + _meta: { + description: + 'Maximum size in bytes of saved object that can be imported or exported.', + }, + }, }, }, environment: { memory: { - heapSizeLimit: { type: 'long' }, - heapTotalBytes: { type: 'long' }, - heapUsedBytes: { type: 'long' }, + heapSizeLimit: { type: 'long', _meta: { description: 'Host memory heap size limit.' } }, + heapTotalBytes: { + type: 'long', + _meta: { description: 'Total memory heap size of host that is available in bytes.' }, + }, + heapUsedBytes: { + type: 'long', + _meta: { description: 'Total memory heap size of host that is used in bytes.' }, + }, }, }, services: { @@ -96,117 +296,576 @@ export function getCoreUsageCollector( indices: { type: 'array', items: { - docsCount: { type: 'long' }, - docsDeleted: { type: 'long' }, - alias: { type: 'keyword' }, - primaryStoreSizeBytes: { type: 'long' }, - storeSizeBytes: { type: 'long' }, + docsCount: { + type: 'long', + _meta: { + description: + 'The number of documents in the index, including hidden nested documents.', + }, + }, + docsDeleted: { + type: 'long', + _meta: { + description: + 'The number of deleted documents in the index, including hidden nested documents.', + }, + }, + alias: { + type: 'keyword', + _meta: { + description: + 'The alias used to map customized saved object index names to standard index names (.kibana or .kibana_task_manager).', + }, + }, + primaryStoreSizeBytes: { + type: 'long', + _meta: { description: 'The size in bytes of the index, for primaries only.' }, + }, + storeSizeBytes: { + type: 'long', + _meta: { + description: 'The size in bytes of the index, for primaries and replicas.', + }, + }, }, }, }, }, // Saved Objects Client APIs - 'apiCalls.savedObjectsBulkCreate.total': { type: 'long' }, - 'apiCalls.savedObjectsBulkCreate.namespace.default.total': { type: 'long' }, - 'apiCalls.savedObjectsBulkCreate.namespace.default.kibanaRequest.yes': { type: 'long' }, - 'apiCalls.savedObjectsBulkCreate.namespace.default.kibanaRequest.no': { type: 'long' }, - 'apiCalls.savedObjectsBulkCreate.namespace.custom.total': { type: 'long' }, - 'apiCalls.savedObjectsBulkCreate.namespace.custom.kibanaRequest.yes': { type: 'long' }, - 'apiCalls.savedObjectsBulkCreate.namespace.custom.kibanaRequest.no': { type: 'long' }, - 'apiCalls.savedObjectsBulkGet.total': { type: 'long' }, - 'apiCalls.savedObjectsBulkGet.namespace.default.total': { type: 'long' }, - 'apiCalls.savedObjectsBulkGet.namespace.default.kibanaRequest.yes': { type: 'long' }, - 'apiCalls.savedObjectsBulkGet.namespace.default.kibanaRequest.no': { type: 'long' }, - 'apiCalls.savedObjectsBulkGet.namespace.custom.total': { type: 'long' }, - 'apiCalls.savedObjectsBulkGet.namespace.custom.kibanaRequest.yes': { type: 'long' }, - 'apiCalls.savedObjectsBulkGet.namespace.custom.kibanaRequest.no': { type: 'long' }, - 'apiCalls.savedObjectsBulkUpdate.total': { type: 'long' }, - 'apiCalls.savedObjectsBulkUpdate.namespace.default.total': { type: 'long' }, - 'apiCalls.savedObjectsBulkUpdate.namespace.default.kibanaRequest.yes': { type: 'long' }, - 'apiCalls.savedObjectsBulkUpdate.namespace.default.kibanaRequest.no': { type: 'long' }, - 'apiCalls.savedObjectsBulkUpdate.namespace.custom.total': { type: 'long' }, - 'apiCalls.savedObjectsBulkUpdate.namespace.custom.kibanaRequest.yes': { type: 'long' }, - 'apiCalls.savedObjectsBulkUpdate.namespace.custom.kibanaRequest.no': { type: 'long' }, - 'apiCalls.savedObjectsCreate.total': { type: 'long' }, - 'apiCalls.savedObjectsCreate.namespace.default.total': { type: 'long' }, - 'apiCalls.savedObjectsCreate.namespace.default.kibanaRequest.yes': { type: 'long' }, - 'apiCalls.savedObjectsCreate.namespace.default.kibanaRequest.no': { type: 'long' }, - 'apiCalls.savedObjectsCreate.namespace.custom.total': { type: 'long' }, - 'apiCalls.savedObjectsCreate.namespace.custom.kibanaRequest.yes': { type: 'long' }, - 'apiCalls.savedObjectsCreate.namespace.custom.kibanaRequest.no': { type: 'long' }, - 'apiCalls.savedObjectsDelete.total': { type: 'long' }, - 'apiCalls.savedObjectsDelete.namespace.default.total': { type: 'long' }, - 'apiCalls.savedObjectsDelete.namespace.default.kibanaRequest.yes': { type: 'long' }, - 'apiCalls.savedObjectsDelete.namespace.default.kibanaRequest.no': { type: 'long' }, - 'apiCalls.savedObjectsDelete.namespace.custom.total': { type: 'long' }, - 'apiCalls.savedObjectsDelete.namespace.custom.kibanaRequest.yes': { type: 'long' }, - 'apiCalls.savedObjectsDelete.namespace.custom.kibanaRequest.no': { type: 'long' }, - 'apiCalls.savedObjectsFind.total': { type: 'long' }, - 'apiCalls.savedObjectsFind.namespace.default.total': { type: 'long' }, - 'apiCalls.savedObjectsFind.namespace.default.kibanaRequest.yes': { type: 'long' }, - 'apiCalls.savedObjectsFind.namespace.default.kibanaRequest.no': { type: 'long' }, - 'apiCalls.savedObjectsFind.namespace.custom.total': { type: 'long' }, - 'apiCalls.savedObjectsFind.namespace.custom.kibanaRequest.yes': { type: 'long' }, - 'apiCalls.savedObjectsFind.namespace.custom.kibanaRequest.no': { type: 'long' }, - 'apiCalls.savedObjectsGet.total': { type: 'long' }, - 'apiCalls.savedObjectsGet.namespace.default.total': { type: 'long' }, - 'apiCalls.savedObjectsGet.namespace.default.kibanaRequest.yes': { type: 'long' }, - 'apiCalls.savedObjectsGet.namespace.default.kibanaRequest.no': { type: 'long' }, - 'apiCalls.savedObjectsGet.namespace.custom.total': { type: 'long' }, - 'apiCalls.savedObjectsGet.namespace.custom.kibanaRequest.yes': { type: 'long' }, - 'apiCalls.savedObjectsGet.namespace.custom.kibanaRequest.no': { type: 'long' }, - 'apiCalls.savedObjectsResolve.total': { type: 'long' }, - 'apiCalls.savedObjectsResolve.namespace.default.total': { type: 'long' }, - 'apiCalls.savedObjectsResolve.namespace.default.kibanaRequest.yes': { type: 'long' }, - 'apiCalls.savedObjectsResolve.namespace.default.kibanaRequest.no': { type: 'long' }, - 'apiCalls.savedObjectsResolve.namespace.custom.total': { type: 'long' }, - 'apiCalls.savedObjectsResolve.namespace.custom.kibanaRequest.yes': { type: 'long' }, - 'apiCalls.savedObjectsResolve.namespace.custom.kibanaRequest.no': { type: 'long' }, - 'apiCalls.savedObjectsUpdate.total': { type: 'long' }, - 'apiCalls.savedObjectsUpdate.namespace.default.total': { type: 'long' }, - 'apiCalls.savedObjectsUpdate.namespace.default.kibanaRequest.yes': { type: 'long' }, - 'apiCalls.savedObjectsUpdate.namespace.default.kibanaRequest.no': { type: 'long' }, - 'apiCalls.savedObjectsUpdate.namespace.custom.total': { type: 'long' }, - 'apiCalls.savedObjectsUpdate.namespace.custom.kibanaRequest.yes': { type: 'long' }, - 'apiCalls.savedObjectsUpdate.namespace.custom.kibanaRequest.no': { type: 'long' }, + 'apiCalls.savedObjectsBulkCreate.total': { + type: 'long', + _meta: { description: 'How many times this API has been called.' }, + }, + 'apiCalls.savedObjectsBulkCreate.namespace.default.total': { + type: 'long', + _meta: { description: 'How many times this API has been called in the Default space.' }, + }, + 'apiCalls.savedObjectsBulkCreate.namespace.default.kibanaRequest.yes': { + type: 'long', + _meta: { + description: + 'How many times this API has been called by the Kibana client in the Default space.', + }, + }, + 'apiCalls.savedObjectsBulkCreate.namespace.default.kibanaRequest.no': { + type: 'long', + _meta: { + description: + 'How many times this API has been called by a non-Kibana client in the Default space.', + }, + }, + 'apiCalls.savedObjectsBulkCreate.namespace.custom.total': { + type: 'long', + _meta: { description: 'How many times this API has been called in a custom space.' }, + }, + 'apiCalls.savedObjectsBulkCreate.namespace.custom.kibanaRequest.yes': { + type: 'long', + _meta: { + description: + 'How many times this API has been called by the Kibana client in a custom space.', + }, + }, + 'apiCalls.savedObjectsBulkCreate.namespace.custom.kibanaRequest.no': { + type: 'long', + _meta: { + description: + 'How many times this API has been called by a non-Kibana client in a custom space.', + }, + }, + 'apiCalls.savedObjectsBulkGet.total': { + type: 'long', + _meta: { description: 'How many times this API has been called.' }, + }, + 'apiCalls.savedObjectsBulkGet.namespace.default.total': { + type: 'long', + _meta: { description: 'How many times this API has been called in the Default space.' }, + }, + 'apiCalls.savedObjectsBulkGet.namespace.default.kibanaRequest.yes': { + type: 'long', + _meta: { + description: + 'How many times this API has been called by the Kibana client in the Default space.', + }, + }, + 'apiCalls.savedObjectsBulkGet.namespace.default.kibanaRequest.no': { + type: 'long', + _meta: { + description: + 'How many times this API has been called by a non-Kibana client in the Default space.', + }, + }, + 'apiCalls.savedObjectsBulkGet.namespace.custom.total': { + type: 'long', + _meta: { description: 'How many times this API has been called in a custom space.' }, + }, + 'apiCalls.savedObjectsBulkGet.namespace.custom.kibanaRequest.yes': { + type: 'long', + _meta: { + description: + 'How many times this API has been called by the Kibana client in a custom space.', + }, + }, + 'apiCalls.savedObjectsBulkGet.namespace.custom.kibanaRequest.no': { + type: 'long', + _meta: { + description: + 'How many times this API has been called by a non-Kibana client in a custom space.', + }, + }, + 'apiCalls.savedObjectsBulkUpdate.total': { + type: 'long', + _meta: { description: 'How many times this API has been called.' }, + }, + 'apiCalls.savedObjectsBulkUpdate.namespace.default.total': { + type: 'long', + _meta: { description: 'How many times this API has been called in the Default space.' }, + }, + 'apiCalls.savedObjectsBulkUpdate.namespace.default.kibanaRequest.yes': { + type: 'long', + _meta: { + description: + 'How many times this API has been called by the Kibana client in the Default space.', + }, + }, + 'apiCalls.savedObjectsBulkUpdate.namespace.default.kibanaRequest.no': { + type: 'long', + _meta: { + description: + 'How many times this API has been called by a non-Kibana client in the Default space.', + }, + }, + 'apiCalls.savedObjectsBulkUpdate.namespace.custom.total': { + type: 'long', + _meta: { description: 'How many times this API has been called in a custom space.' }, + }, + 'apiCalls.savedObjectsBulkUpdate.namespace.custom.kibanaRequest.yes': { + type: 'long', + _meta: { + description: + 'How many times this API has been called by the Kibana client in a custom space.', + }, + }, + 'apiCalls.savedObjectsBulkUpdate.namespace.custom.kibanaRequest.no': { + type: 'long', + _meta: { + description: + 'How many times this API has been called by a non-Kibana client in a custom space.', + }, + }, + 'apiCalls.savedObjectsCreate.total': { + type: 'long', + _meta: { description: 'How many times this API has been called.' }, + }, + 'apiCalls.savedObjectsCreate.namespace.default.total': { + type: 'long', + _meta: { description: 'How many times this API has been called in the Default space.' }, + }, + 'apiCalls.savedObjectsCreate.namespace.default.kibanaRequest.yes': { + type: 'long', + _meta: { + description: + 'How many times this API has been called by the Kibana client in the Default space.', + }, + }, + 'apiCalls.savedObjectsCreate.namespace.default.kibanaRequest.no': { + type: 'long', + _meta: { + description: + 'How many times this API has been called by a non-Kibana client in the Default space.', + }, + }, + 'apiCalls.savedObjectsCreate.namespace.custom.total': { + type: 'long', + _meta: { description: 'How many times this API has been called in a custom space.' }, + }, + 'apiCalls.savedObjectsCreate.namespace.custom.kibanaRequest.yes': { + type: 'long', + _meta: { + description: + 'How many times this API has been called by the Kibana client in a custom space.', + }, + }, + 'apiCalls.savedObjectsCreate.namespace.custom.kibanaRequest.no': { + type: 'long', + _meta: { + description: + 'How many times this API has been called by a non-Kibana client in a custom space.', + }, + }, + 'apiCalls.savedObjectsDelete.total': { + type: 'long', + _meta: { description: 'How many times this API has been called.' }, + }, + 'apiCalls.savedObjectsDelete.namespace.default.total': { + type: 'long', + _meta: { description: 'How many times this API has been called in the Default space.' }, + }, + 'apiCalls.savedObjectsDelete.namespace.default.kibanaRequest.yes': { + type: 'long', + _meta: { + description: + 'How many times this API has been called by the Kibana client in the Default space.', + }, + }, + 'apiCalls.savedObjectsDelete.namespace.default.kibanaRequest.no': { + type: 'long', + _meta: { + description: + 'How many times this API has been called by a non-Kibana client in the Default space.', + }, + }, + 'apiCalls.savedObjectsDelete.namespace.custom.total': { + type: 'long', + _meta: { description: 'How many times this API has been called in a custom space.' }, + }, + 'apiCalls.savedObjectsDelete.namespace.custom.kibanaRequest.yes': { + type: 'long', + _meta: { + description: + 'How many times this API has been called by the Kibana client in a custom space.', + }, + }, + 'apiCalls.savedObjectsDelete.namespace.custom.kibanaRequest.no': { + type: 'long', + _meta: { + description: + 'How many times this API has been called by a non-Kibana client in a custom space.', + }, + }, + 'apiCalls.savedObjectsFind.total': { + type: 'long', + _meta: { description: 'How many times this API has been called.' }, + }, + 'apiCalls.savedObjectsFind.namespace.default.total': { + type: 'long', + _meta: { description: 'How many times this API has been called in the Default space.' }, + }, + 'apiCalls.savedObjectsFind.namespace.default.kibanaRequest.yes': { + type: 'long', + _meta: { + description: + 'How many times this API has been called by the Kibana client in the Default space.', + }, + }, + 'apiCalls.savedObjectsFind.namespace.default.kibanaRequest.no': { + type: 'long', + _meta: { + description: + 'How many times this API has been called by a non-Kibana client in the Default space.', + }, + }, + 'apiCalls.savedObjectsFind.namespace.custom.total': { + type: 'long', + _meta: { description: 'How many times this API has been called in a custom space.' }, + }, + 'apiCalls.savedObjectsFind.namespace.custom.kibanaRequest.yes': { + type: 'long', + _meta: { + description: + 'How many times this API has been called by the Kibana client in a custom space.', + }, + }, + 'apiCalls.savedObjectsFind.namespace.custom.kibanaRequest.no': { + type: 'long', + _meta: { + description: + 'How many times this API has been called by a non-Kibana client in a custom space.', + }, + }, + 'apiCalls.savedObjectsGet.total': { + type: 'long', + _meta: { description: 'How many times this API has been called.' }, + }, + 'apiCalls.savedObjectsGet.namespace.default.total': { + type: 'long', + _meta: { description: 'How many times this API has been called in the Default space.' }, + }, + 'apiCalls.savedObjectsGet.namespace.default.kibanaRequest.yes': { + type: 'long', + _meta: { + description: + 'How many times this API has been called by the Kibana client in the Default space.', + }, + }, + 'apiCalls.savedObjectsGet.namespace.default.kibanaRequest.no': { + type: 'long', + _meta: { + description: + 'How many times this API has been called by a non-Kibana client in the Default space.', + }, + }, + 'apiCalls.savedObjectsGet.namespace.custom.total': { + type: 'long', + _meta: { description: 'How many times this API has been called in a custom space.' }, + }, + 'apiCalls.savedObjectsGet.namespace.custom.kibanaRequest.yes': { + type: 'long', + _meta: { + description: + 'How many times this API has been called by the Kibana client in a custom space.', + }, + }, + 'apiCalls.savedObjectsGet.namespace.custom.kibanaRequest.no': { + type: 'long', + _meta: { + description: + 'How many times this API has been called by a non-Kibana client in a custom space.', + }, + }, + 'apiCalls.savedObjectsResolve.total': { + type: 'long', + _meta: { description: 'How many times this API has been called.' }, + }, + 'apiCalls.savedObjectsResolve.namespace.default.total': { + type: 'long', + _meta: { description: 'How many times this API has been called in the Default space.' }, + }, + 'apiCalls.savedObjectsResolve.namespace.default.kibanaRequest.yes': { + type: 'long', + _meta: { + description: + 'How many times this API has been called by the Kibana client in the Default space.', + }, + }, + 'apiCalls.savedObjectsResolve.namespace.default.kibanaRequest.no': { + type: 'long', + _meta: { + description: + 'How many times this API has been called by a non-Kibana client in the Default space.', + }, + }, + 'apiCalls.savedObjectsResolve.namespace.custom.total': { + type: 'long', + _meta: { description: 'How many times this API has been called in a custom space.' }, + }, + 'apiCalls.savedObjectsResolve.namespace.custom.kibanaRequest.yes': { + type: 'long', + _meta: { + description: + 'How many times this API has been called by the Kibana client in a custom space.', + }, + }, + 'apiCalls.savedObjectsResolve.namespace.custom.kibanaRequest.no': { + type: 'long', + _meta: { + description: + 'How many times this API has been called by a non-Kibana client in a custom space.', + }, + }, + 'apiCalls.savedObjectsUpdate.total': { + type: 'long', + _meta: { description: 'How many times this API has been called.' }, + }, + 'apiCalls.savedObjectsUpdate.namespace.default.total': { + type: 'long', + _meta: { description: 'How many times this API has been called in the Default space.' }, + }, + 'apiCalls.savedObjectsUpdate.namespace.default.kibanaRequest.yes': { + type: 'long', + _meta: { + description: + 'How many times this API has been called by the Kibana client in the Default space.', + }, + }, + 'apiCalls.savedObjectsUpdate.namespace.default.kibanaRequest.no': { + type: 'long', + _meta: { + description: + 'How many times this API has been called by a non-Kibana client in the Default space.', + }, + }, + 'apiCalls.savedObjectsUpdate.namespace.custom.total': { + type: 'long', + _meta: { description: 'How many times this API has been called in a custom space.' }, + }, + 'apiCalls.savedObjectsUpdate.namespace.custom.kibanaRequest.yes': { + type: 'long', + _meta: { + description: + 'How many times this API has been called by the Kibana client in a custom space.', + }, + }, + 'apiCalls.savedObjectsUpdate.namespace.custom.kibanaRequest.no': { + type: 'long', + _meta: { + description: + 'How many times this API has been called by a non-Kibana client in a custom space.', + }, + }, // Saved Objects Management APIs - 'apiCalls.savedObjectsImport.total': { type: 'long' }, - 'apiCalls.savedObjectsImport.namespace.default.total': { type: 'long' }, - 'apiCalls.savedObjectsImport.namespace.default.kibanaRequest.yes': { type: 'long' }, - 'apiCalls.savedObjectsImport.namespace.default.kibanaRequest.no': { type: 'long' }, - 'apiCalls.savedObjectsImport.namespace.custom.total': { type: 'long' }, - 'apiCalls.savedObjectsImport.namespace.custom.kibanaRequest.yes': { type: 'long' }, - 'apiCalls.savedObjectsImport.namespace.custom.kibanaRequest.no': { type: 'long' }, - 'apiCalls.savedObjectsImport.createNewCopiesEnabled.yes': { type: 'long' }, - 'apiCalls.savedObjectsImport.createNewCopiesEnabled.no': { type: 'long' }, - 'apiCalls.savedObjectsImport.overwriteEnabled.yes': { type: 'long' }, - 'apiCalls.savedObjectsImport.overwriteEnabled.no': { type: 'long' }, - 'apiCalls.savedObjectsResolveImportErrors.total': { type: 'long' }, - 'apiCalls.savedObjectsResolveImportErrors.namespace.default.total': { type: 'long' }, + 'apiCalls.savedObjectsImport.total': { + type: 'long', + _meta: { description: 'How many times this API has been called.' }, + }, + 'apiCalls.savedObjectsImport.namespace.default.total': { + type: 'long', + _meta: { description: 'How many times this API has been called in the Default space.' }, + }, + 'apiCalls.savedObjectsImport.namespace.default.kibanaRequest.yes': { + type: 'long', + _meta: { + description: + 'How many times this API has been called by the Kibana client in the Default space.', + }, + }, + 'apiCalls.savedObjectsImport.namespace.default.kibanaRequest.no': { + type: 'long', + _meta: { + description: + 'How many times this API has been called by a non-Kibana client in the Default space.', + }, + }, + 'apiCalls.savedObjectsImport.namespace.custom.total': { + type: 'long', + _meta: { description: 'How many times this API has been called in a custom space.' }, + }, + 'apiCalls.savedObjectsImport.namespace.custom.kibanaRequest.yes': { + type: 'long', + _meta: { + description: + 'How many times this API has been called by the Kibana client in a custom space.', + }, + }, + 'apiCalls.savedObjectsImport.namespace.custom.kibanaRequest.no': { + type: 'long', + _meta: { + description: + 'How many times this API has been called by a non-Kibana client in a custom space.', + }, + }, + 'apiCalls.savedObjectsImport.createNewCopiesEnabled.yes': { + type: 'long', + _meta: { + description: + 'How many times this API has been called with the `createNewCopiesEnabled` option.', + }, + }, + 'apiCalls.savedObjectsImport.createNewCopiesEnabled.no': { + type: 'long', + _meta: { + description: + 'How many times this API has been called without the `createNewCopiesEnabled` option.', + }, + }, + 'apiCalls.savedObjectsImport.overwriteEnabled.yes': { + type: 'long', + _meta: { + description: 'How many times this API has been called with the `overwrite` option.', + }, + }, + 'apiCalls.savedObjectsImport.overwriteEnabled.no': { + type: 'long', + _meta: { + description: 'How many times this API has been called without the `overwrite` option.', + }, + }, + 'apiCalls.savedObjectsResolveImportErrors.total': { + type: 'long', + _meta: { description: 'How many times this API has been called.' }, + }, + 'apiCalls.savedObjectsResolveImportErrors.namespace.default.total': { + type: 'long', + _meta: { description: 'How many times this API has been called in the Default space.' }, + }, 'apiCalls.savedObjectsResolveImportErrors.namespace.default.kibanaRequest.yes': { type: 'long', + _meta: { + description: + 'How many times this API has been called by the Kibana client in the Default space.', + }, }, 'apiCalls.savedObjectsResolveImportErrors.namespace.default.kibanaRequest.no': { type: 'long', + _meta: { + description: + 'How many times this API has been called by a non-Kibana client in the Default space.', + }, + }, + 'apiCalls.savedObjectsResolveImportErrors.namespace.custom.total': { + type: 'long', + _meta: { description: 'How many times this API has been called in a custom space.' }, }, - 'apiCalls.savedObjectsResolveImportErrors.namespace.custom.total': { type: 'long' }, 'apiCalls.savedObjectsResolveImportErrors.namespace.custom.kibanaRequest.yes': { type: 'long', + _meta: { + description: + 'How many times this API has been called by the Kibana client in a custom space.', + }, }, 'apiCalls.savedObjectsResolveImportErrors.namespace.custom.kibanaRequest.no': { type: 'long', + _meta: { + description: + 'How many times this API has been called by a non-Kibana client in a custom space.', + }, + }, + 'apiCalls.savedObjectsResolveImportErrors.createNewCopiesEnabled.yes': { + type: 'long', + _meta: { + description: + 'How many times this API has been called with the `createNewCopiesEnabled` option.', + }, + }, + 'apiCalls.savedObjectsResolveImportErrors.createNewCopiesEnabled.no': { + type: 'long', + _meta: { + description: + 'How many times this API has been called without the `createNewCopiesEnabled` option.', + }, + }, + 'apiCalls.savedObjectsExport.total': { + type: 'long', + _meta: { description: 'How many times this API has been called.' }, + }, + 'apiCalls.savedObjectsExport.namespace.default.total': { + type: 'long', + _meta: { description: 'How many times this API has been called in the Default space.' }, + }, + 'apiCalls.savedObjectsExport.namespace.default.kibanaRequest.yes': { + type: 'long', + _meta: { + description: + 'How many times this API has been called by the Kibana client in the Default space.', + }, + }, + 'apiCalls.savedObjectsExport.namespace.default.kibanaRequest.no': { + type: 'long', + _meta: { + description: + 'How many times this API has been called by a non-Kibana client in the Default space.', + }, + }, + 'apiCalls.savedObjectsExport.namespace.custom.total': { + type: 'long', + _meta: { description: 'How many times this API has been called in a custom space.' }, + }, + 'apiCalls.savedObjectsExport.namespace.custom.kibanaRequest.yes': { + type: 'long', + _meta: { + description: + 'How many times this API has been called by the Kibana client in a custom space.', + }, + }, + 'apiCalls.savedObjectsExport.namespace.custom.kibanaRequest.no': { + type: 'long', + _meta: { + description: + 'How many times this API has been called by a non-Kibana client in a custom space.', + }, + }, + 'apiCalls.savedObjectsExport.allTypesSelected.yes': { + type: 'long', + _meta: { + description: + 'How many times this API has been called with the `createNewCopiesEnabled` option.', + }, + }, + 'apiCalls.savedObjectsExport.allTypesSelected.no': { + type: 'long', + _meta: { + description: 'How many times this API has been called without all types selected.', + }, }, - 'apiCalls.savedObjectsResolveImportErrors.createNewCopiesEnabled.yes': { type: 'long' }, - 'apiCalls.savedObjectsResolveImportErrors.createNewCopiesEnabled.no': { type: 'long' }, - 'apiCalls.savedObjectsExport.total': { type: 'long' }, - 'apiCalls.savedObjectsExport.namespace.default.total': { type: 'long' }, - 'apiCalls.savedObjectsExport.namespace.default.kibanaRequest.yes': { type: 'long' }, - 'apiCalls.savedObjectsExport.namespace.default.kibanaRequest.no': { type: 'long' }, - 'apiCalls.savedObjectsExport.namespace.custom.total': { type: 'long' }, - 'apiCalls.savedObjectsExport.namespace.custom.kibanaRequest.yes': { type: 'long' }, - 'apiCalls.savedObjectsExport.namespace.custom.kibanaRequest.no': { type: 'long' }, - 'apiCalls.savedObjectsExport.allTypesSelected.yes': { type: 'long' }, - 'apiCalls.savedObjectsExport.allTypesSelected.no': { type: 'long' }, }, fetch() { return getCoreUsageDataService().getCoreUsageData(); diff --git a/src/plugins/kibana_usage_collection/server/collectors/csp/csp_collector.ts b/src/plugins/kibana_usage_collection/server/collectors/csp/csp_collector.ts index 8119fe394b60c3..fa0cd55cd3072f 100644 --- a/src/plugins/kibana_usage_collection/server/collectors/csp/csp_collector.ts +++ b/src/plugins/kibana_usage_collection/server/collectors/csp/csp_collector.ts @@ -34,12 +34,15 @@ export function createCspCollector(http: HttpServiceSetup): UsageCollectorOption schema: { strict: { type: 'boolean', + _meta: { description: 'Indicates if strict mode should be used.' }, }, warnLegacyBrowsers: { type: 'boolean', + _meta: { description: 'Indicates if legacy browser versions should be warned.' }, }, rulesChangedFromDefault: { type: 'boolean', + _meta: { description: 'Indicates if the rules have been changed from the default.' }, }, }, }; diff --git a/src/plugins/kibana_usage_collection/server/collectors/kibana/kibana_usage_collector.ts b/src/plugins/kibana_usage_collection/server/collectors/kibana/kibana_usage_collector.ts index 8c1fe31e963d08..d9f4718cdb4755 100644 --- a/src/plugins/kibana_usage_collection/server/collectors/kibana/kibana_usage_collector.ts +++ b/src/plugins/kibana_usage_collection/server/collectors/kibana/kibana_usage_collector.ts @@ -24,13 +24,37 @@ export function getKibanaUsageCollector( type: 'kibana', isReady: () => true, schema: { - index: { type: 'keyword' }, - dashboard: { total: { type: 'long' } }, - visualization: { total: { type: 'long' } }, - search: { total: { type: 'long' } }, - index_pattern: { total: { type: 'long' } }, - graph_workspace: { total: { type: 'long' } }, - timelion_sheet: { total: { type: 'long' } }, + index: { type: 'keyword', _meta: { description: 'The index storing the saved objects' } }, + dashboard: { + total: { type: 'long', _meta: { description: 'Total number of dashboard saved objects' } }, + }, + visualization: { + total: { + type: 'long', + _meta: { description: 'Total number of visualization saved objects' }, + }, + }, + search: { + total: { type: 'long', _meta: { description: 'Total number of search saved objects' } }, + }, + index_pattern: { + total: { + type: 'long', + _meta: { description: 'Total number of index_pattern saved objects' }, + }, + }, + graph_workspace: { + total: { + type: 'long', + _meta: { description: 'Total number of graph_workspace saved objects' }, + }, + }, + timelion_sheet: { + total: { + type: 'long', + _meta: { description: 'Total number of timelion_sheet saved objects' }, + }, + }, }, async fetch({ esClient }) { const { diff --git a/src/plugins/kibana_usage_collection/server/collectors/localization/telemetry_localization_collector.ts b/src/plugins/kibana_usage_collection/server/collectors/localization/telemetry_localization_collector.ts index 6ad2fd9270bc74..34ab4a5be7d28d 100644 --- a/src/plugins/kibana_usage_collection/server/collectors/localization/telemetry_localization_collector.ts +++ b/src/plugins/kibana_usage_collection/server/collectors/localization/telemetry_localization_collector.ts @@ -53,9 +53,27 @@ export function registerLocalizationUsageCollector( isReady: () => true, fetch: createCollectorFetch(i18n), schema: { - locale: { type: 'keyword' }, - integrities: { DYNAMIC_KEY: { type: 'text' } }, - labelsCount: { type: 'long' }, + locale: { + type: 'keyword', + _meta: { + description: 'The default locale set on the Kibana system', + }, + }, + integrities: { + DYNAMIC_KEY: { + type: 'text', + _meta: { + description: + 'Translation file hash. If the hash is different it indicates that a custom translation file is used', + }, + }, + }, + labelsCount: { + type: 'long', + _meta: { + description: 'The number of translated labels', + }, + }, }, }); diff --git a/src/plugins/kibana_usage_collection/server/collectors/management/schema.ts b/src/plugins/kibana_usage_collection/server/collectors/management/schema.ts index d632c3ad61a800..f166e4fcebfa33 100644 --- a/src/plugins/kibana_usage_collection/server/collectors/management/schema.ts +++ b/src/plugins/kibana_usage_collection/server/collectors/management/schema.ts @@ -11,120 +11,405 @@ import { UsageStats } from './types'; export const stackManagementSchema: MakeSchemaFrom = { // sensitive - 'timelion:quandl.key': { type: 'keyword' }, - 'securitySolution:defaultIndex': { type: 'keyword' }, - 'securitySolution:newsFeedUrl': { type: 'keyword' }, - 'xpackReporting:customPdfLogo': { type: 'keyword' }, - 'notifications:banner': { type: 'keyword' }, - 'timelion:graphite.url': { type: 'keyword' }, - 'xpackDashboardMode:roles': { type: 'keyword' }, - 'securitySolution:ipReputationLinks': { type: 'keyword' }, + 'timelion:quandl.key': { + type: 'keyword', + _meta: { description: 'Default value of the setting was changed.' }, + }, + 'securitySolution:defaultIndex': { + type: 'keyword', + _meta: { description: 'Default value of the setting was changed.' }, + }, + 'securitySolution:newsFeedUrl': { + type: 'keyword', + _meta: { description: 'Default value of the setting was changed.' }, + }, + 'xpackReporting:customPdfLogo': { + type: 'keyword', + _meta: { description: 'Default value of the setting was changed.' }, + }, + 'notifications:banner': { + type: 'keyword', + _meta: { description: 'Default value of the setting was changed.' }, + }, + 'timelion:graphite.url': { + type: 'keyword', + _meta: { description: 'Default value of the setting changed.' }, + }, + 'xpackDashboardMode:roles': { + type: 'keyword', + _meta: { description: 'Default value of the setting was changed.' }, + }, + 'securitySolution:ipReputationLinks': { + type: 'keyword', + _meta: { description: 'Default value of the setting was changed.' }, + }, // non-sensitive - 'visualize:enableLabs': { type: 'boolean' }, - 'visualization:heatmap:maxBuckets': { type: 'long' }, - 'visualization:colorMapping': { type: 'text' }, - 'visualization:regionmap:showWarnings': { type: 'boolean' }, - 'visualization:dimmingOpacity': { type: 'float' }, - 'visualization:tileMap:maxPrecision': { type: 'long' }, - 'csv:separator': { type: 'keyword' }, - 'visualization:tileMap:WMSdefaults': { type: 'text' }, - 'timelion:target_buckets': { type: 'long' }, - 'timelion:max_buckets': { type: 'long' }, - 'timelion:es.timefield': { type: 'keyword' }, - 'timelion:min_interval': { type: 'keyword' }, - 'timelion:default_rows': { type: 'long' }, - 'timelion:default_columns': { type: 'long' }, - 'timelion:es.default_index': { type: 'keyword' }, - 'timelion:showTutorial': { type: 'boolean' }, - 'securitySolution:timeDefaults': { type: 'keyword' }, - 'securitySolution:defaultAnomalyScore': { type: 'long' }, - 'securitySolution:refreshIntervalDefaults': { type: 'keyword' }, - 'securitySolution:enableNewsFeed': { type: 'boolean' }, - 'search:includeFrozen': { type: 'boolean' }, - 'courier:maxConcurrentShardRequests': { type: 'long' }, - 'courier:batchSearches': { type: 'boolean' }, - 'courier:setRequestPreference': { type: 'keyword' }, - 'courier:customRequestPreference': { type: 'keyword' }, - 'courier:ignoreFilterIfFieldNotInIndex': { type: 'boolean' }, - 'rollups:enableIndexPatterns': { type: 'boolean' }, - 'notifications:lifetime:warning': { type: 'long' }, - 'notifications:lifetime:banner': { type: 'long' }, - 'notifications:lifetime:info': { type: 'long' }, - 'notifications:lifetime:error': { type: 'long' }, - 'doc_table:highlight': { type: 'boolean' }, - 'discover:searchOnPageLoad': { type: 'boolean' }, + 'visualize:enableLabs': { + type: 'boolean', + _meta: { description: 'Non-default value of setting.' }, + }, + 'visualization:heatmap:maxBuckets': { + type: 'long', + _meta: { description: 'Non-default value of setting.' }, + }, + 'visualization:colorMapping': { + type: 'text', + _meta: { description: 'Non-default value of setting.' }, + }, + 'visualization:regionmap:showWarnings': { + type: 'boolean', + _meta: { description: 'Non-default value of setting.' }, + }, + 'visualization:dimmingOpacity': { + type: 'float', + _meta: { description: 'Non-default value of setting.' }, + }, + 'visualization:tileMap:maxPrecision': { + type: 'long', + _meta: { description: 'Non-default value of setting.' }, + }, + 'csv:separator': { + type: 'keyword', + _meta: { description: 'Non-default value of setting.' }, + }, + 'visualization:tileMap:WMSdefaults': { + type: 'text', + _meta: { description: 'Non-default value of setting.' }, + }, + 'timelion:target_buckets': { + type: 'long', + _meta: { description: 'Non-default value of setting.' }, + }, + 'timelion:max_buckets': { + type: 'long', + _meta: { description: 'Non-default value of setting.' }, + }, + 'timelion:es.timefield': { + type: 'keyword', + _meta: { description: 'Non-default value of setting.' }, + }, + 'timelion:min_interval': { + type: 'keyword', + _meta: { description: 'Non-default value of setting.' }, + }, + 'timelion:default_rows': { + type: 'long', + _meta: { description: 'Non-default value of setting.' }, + }, + 'timelion:default_columns': { + type: 'long', + _meta: { description: 'Non-default value of setting.' }, + }, + 'timelion:es.default_index': { + type: 'keyword', + _meta: { description: 'Non-default value of setting.' }, + }, + 'timelion:showTutorial': { + type: 'boolean', + _meta: { description: 'Non-default value of setting.' }, + }, + 'securitySolution:timeDefaults': { + type: 'keyword', + _meta: { description: 'Non-default value of setting.' }, + }, + 'securitySolution:defaultAnomalyScore': { + type: 'long', + _meta: { description: 'Non-default value of setting.' }, + }, + 'securitySolution:refreshIntervalDefaults': { + type: 'keyword', + _meta: { description: 'Non-default value of setting.' }, + }, + 'securitySolution:enableNewsFeed': { + type: 'boolean', + _meta: { description: 'Non-default value of setting.' }, + }, + 'search:includeFrozen': { + type: 'boolean', + _meta: { description: 'Non-default value of setting.' }, + }, + 'courier:maxConcurrentShardRequests': { + type: 'long', + _meta: { description: 'Non-default value of setting.' }, + }, + 'courier:batchSearches': { + type: 'boolean', + _meta: { description: 'Non-default value of setting.' }, + }, + 'courier:setRequestPreference': { + type: 'keyword', + _meta: { description: 'Non-default value of setting.' }, + }, + 'courier:customRequestPreference': { + type: 'keyword', + _meta: { description: 'Non-default value of setting.' }, + }, + 'courier:ignoreFilterIfFieldNotInIndex': { + type: 'boolean', + _meta: { description: 'Non-default value of setting.' }, + }, + 'rollups:enableIndexPatterns': { + type: 'boolean', + _meta: { description: 'Non-default value of setting.' }, + }, + 'notifications:lifetime:warning': { + type: 'long', + _meta: { description: 'Non-default value of setting.' }, + }, + 'notifications:lifetime:banner': { + type: 'long', + _meta: { description: 'Non-default value of setting.' }, + }, + 'notifications:lifetime:info': { + type: 'long', + _meta: { description: 'Non-default value of setting.' }, + }, + 'notifications:lifetime:error': { + type: 'long', + _meta: { description: 'Non-default value of setting.' }, + }, + 'doc_table:highlight': { + type: 'boolean', + _meta: { description: 'Non-default value of setting.' }, + }, + 'discover:searchOnPageLoad': { + type: 'boolean', + _meta: { description: 'Non-default value of setting.' }, + }, // eslint-disable-next-line @typescript-eslint/naming-convention - 'doc_table:hideTimeColumn': { type: 'boolean' }, - 'discover:sampleSize': { type: 'long' }, + 'doc_table:hideTimeColumn': { + type: 'boolean', + _meta: { description: 'Non-default value of setting.' }, + }, + 'discover:sampleSize': { + type: 'long', + _meta: { description: 'Non-default value of setting.' }, + }, defaultColumns: { type: 'array', items: { type: 'keyword', + _meta: { description: 'Non-default value of setting.' }, }, }, - 'context:defaultSize': { type: 'long' }, - 'discover:aggs:terms:size': { type: 'long' }, + 'context:defaultSize': { + type: 'long', + _meta: { description: 'Non-default value of setting.' }, + }, + 'discover:aggs:terms:size': { + type: 'long', + _meta: { description: 'Non-default value of setting.' }, + }, 'context:tieBreakerFields': { type: 'array', items: { type: 'keyword', + _meta: { description: 'Non-default value of setting.' }, }, }, - 'discover:sort:defaultOrder': { type: 'keyword' }, - 'context:step': { type: 'long' }, - 'accessibility:disableAnimations': { type: 'boolean' }, - 'ml:fileDataVisualizerMaxFileSize': { type: 'keyword' }, - 'ml:anomalyDetection:results:enableTimeDefaults': { type: 'boolean' }, - 'ml:anomalyDetection:results:timeDefaults': { type: 'keyword' }, - 'truncate:maxHeight': { type: 'long' }, - 'timepicker:timeDefaults': { type: 'keyword' }, - 'timepicker:refreshIntervalDefaults': { type: 'keyword' }, - 'timepicker:quickRanges': { type: 'keyword' }, - 'theme:version': { type: 'keyword' }, - 'theme:darkMode': { type: 'boolean' }, - 'state:storeInSessionStorage': { type: 'boolean' }, - 'savedObjects:perPage': { type: 'long' }, - 'search:queryLanguage': { type: 'keyword' }, - 'shortDots:enable': { type: 'boolean' }, - 'sort:options': { type: 'keyword' }, - 'savedObjects:listingLimit': { type: 'long' }, - 'query:queryString:options': { type: 'keyword' }, - 'metrics:max_buckets': { type: 'long' }, - 'query:allowLeadingWildcards': { type: 'boolean' }, + 'discover:sort:defaultOrder': { + type: 'keyword', + _meta: { description: 'Non-default value of setting.' }, + }, + 'context:step': { type: 'long', _meta: { description: 'Non-default value of setting.' } }, + 'accessibility:disableAnimations': { + type: 'boolean', + _meta: { description: 'Non-default value of setting.' }, + }, + 'fileUpload:maxFileSize': { + type: 'keyword', + _meta: { description: 'Non-default value of setting.' }, + }, + 'ml:anomalyDetection:results:enableTimeDefaults': { + type: 'boolean', + _meta: { description: 'Non-default value of setting.' }, + }, + 'ml:anomalyDetection:results:timeDefaults': { + type: 'keyword', + _meta: { description: 'Non-default value of setting.' }, + }, + 'truncate:maxHeight': { + type: 'long', + _meta: { description: 'Non-default value of setting.' }, + }, + 'timepicker:timeDefaults': { + type: 'keyword', + _meta: { description: 'Non-default value of setting.' }, + }, + 'timepicker:refreshIntervalDefaults': { + type: 'keyword', + _meta: { description: 'Non-default value of setting.' }, + }, + 'timepicker:quickRanges': { + type: 'keyword', + _meta: { description: 'Non-default value of setting.' }, + }, + 'theme:version': { + type: 'keyword', + _meta: { description: 'Non-default value of setting.' }, + }, + 'theme:darkMode': { + type: 'boolean', + _meta: { description: 'Non-default value of setting.' }, + }, + 'state:storeInSessionStorage': { + type: 'boolean', + _meta: { description: 'Non-default value of setting.' }, + }, + 'savedObjects:perPage': { + type: 'long', + _meta: { description: 'Non-default value of setting.' }, + }, + 'search:queryLanguage': { + type: 'keyword', + _meta: { description: 'Non-default value of setting.' }, + }, + 'shortDots:enable': { + type: 'boolean', + _meta: { description: 'Non-default value of setting.' }, + }, + 'sort:options': { + type: 'keyword', + _meta: { description: 'Non-default value of setting.' }, + }, + 'savedObjects:listingLimit': { + type: 'long', + _meta: { description: 'Non-default value of setting.' }, + }, + 'query:queryString:options': { + type: 'keyword', + _meta: { description: 'Non-default value of setting.' }, + }, + 'metrics:max_buckets': { + type: 'long', + _meta: { description: 'Non-default value of setting.' }, + }, + 'query:allowLeadingWildcards': { + type: 'boolean', + _meta: { description: 'Non-default value of setting.' }, + }, metaFields: { type: 'array', items: { type: 'keyword', + _meta: { description: 'Non-default value of setting.' }, }, }, - 'indexPattern:placeholder': { type: 'keyword' }, - 'histogram:barTarget': { type: 'long' }, - 'histogram:maxBars': { type: 'long' }, - 'format:number:defaultLocale': { type: 'keyword' }, - 'format:percent:defaultPattern': { type: 'keyword' }, - 'format:number:defaultPattern': { type: 'keyword' }, - 'history:limit': { type: 'long' }, - 'format:defaultTypeMap': { type: 'keyword' }, - 'format:currency:defaultPattern': { type: 'keyword' }, - defaultIndex: { type: 'keyword' }, - 'format:bytes:defaultPattern': { type: 'keyword' }, - 'filters:pinnedByDefault': { type: 'boolean' }, - 'filterEditor:suggestValues': { type: 'boolean' }, - 'fields:popularLimit': { type: 'long' }, - dateNanosFormat: { type: 'keyword' }, - defaultRoute: { type: 'keyword' }, - 'dateFormat:tz': { type: 'keyword' }, - 'dateFormat:scaled': { type: 'keyword' }, - 'csv:quoteValues': { type: 'boolean' }, - 'dateFormat:dow': { type: 'keyword' }, - dateFormat: { type: 'keyword' }, - 'autocomplete:useTimeRange': { type: 'boolean' }, - 'search:timeout': { type: 'long' }, - 'visualization:visualize:legacyChartsLibrary': { type: 'boolean' }, - 'doc_table:legacy': { type: 'boolean' }, - 'discover:modifyColumnsOnSwitch': { type: 'boolean' }, - 'discover:searchFieldsFromSource': { type: 'boolean' }, - 'securitySolution:rulesTableRefresh': { type: 'text' }, - 'apm:enableSignificantTerms': { type: 'boolean' }, - 'apm:enableServiceOverview': { type: 'boolean' }, + 'indexPattern:placeholder': { + type: 'keyword', + _meta: { description: 'Non-default value of setting.' }, + }, + 'histogram:barTarget': { + type: 'long', + _meta: { description: 'Non-default value of setting.' }, + }, + 'histogram:maxBars': { + type: 'long', + _meta: { description: 'Non-default value of setting.' }, + }, + 'format:number:defaultLocale': { + type: 'keyword', + _meta: { description: 'Non-default value of setting.' }, + }, + 'format:percent:defaultPattern': { + type: 'keyword', + _meta: { description: 'Non-default value of setting.' }, + }, + 'format:number:defaultPattern': { + type: 'keyword', + _meta: { description: 'Non-default value of setting.' }, + }, + 'history:limit': { + type: 'long', + _meta: { description: 'Non-default value of setting.' }, + }, + 'format:defaultTypeMap': { + type: 'keyword', + _meta: { description: 'Non-default value of setting.' }, + }, + 'format:currency:defaultPattern': { + type: 'keyword', + _meta: { description: 'Non-default value of setting.' }, + }, + defaultIndex: { + type: 'keyword', + _meta: { description: 'Non-default value of setting.' }, + }, + 'format:bytes:defaultPattern': { + type: 'keyword', + _meta: { description: 'Non-default value of setting.' }, + }, + 'filters:pinnedByDefault': { + type: 'boolean', + _meta: { description: 'Non-default value of setting.' }, + }, + 'filterEditor:suggestValues': { + type: 'boolean', + _meta: { description: 'Non-default value of setting.' }, + }, + 'fields:popularLimit': { + type: 'long', + _meta: { description: 'Non-default value of setting.' }, + }, + dateNanosFormat: { + type: 'keyword', + _meta: { description: 'Non-default value of setting.' }, + }, + defaultRoute: { + type: 'keyword', + _meta: { description: 'Non-default value of setting.' }, + }, + 'dateFormat:tz': { + type: 'keyword', + _meta: { description: 'Non-default value of setting.' }, + }, + 'dateFormat:scaled': { + type: 'keyword', + _meta: { description: 'Non-default value of setting.' }, + }, + 'csv:quoteValues': { + type: 'boolean', + _meta: { description: 'Non-default value of setting.' }, + }, + 'dateFormat:dow': { + type: 'keyword', + _meta: { description: 'Non-default value of setting.' }, + }, + dateFormat: { type: 'keyword', _meta: { description: 'Non-default value of setting.' } }, + 'autocomplete:useTimeRange': { + type: 'boolean', + _meta: { description: 'Non-default value of setting.' }, + }, + 'search:timeout': { + type: 'long', + _meta: { description: 'Non-default value of setting.' }, + }, + 'visualization:visualize:legacyChartsLibrary': { + type: 'boolean', + _meta: { description: 'Non-default value of setting.' }, + }, + 'doc_table:legacy': { + type: 'boolean', + _meta: { description: 'Non-default value of setting.' }, + }, + 'discover:modifyColumnsOnSwitch': { + type: 'boolean', + _meta: { description: 'Non-default value of setting.' }, + }, + 'discover:searchFieldsFromSource': { + type: 'boolean', + _meta: { description: 'Non-default value of setting.' }, + }, + 'securitySolution:rulesTableRefresh': { + type: 'text', + _meta: { description: 'Non-default value of setting.' }, + }, + 'apm:enableSignificantTerms': { + type: 'boolean', + _meta: { description: 'Non-default value of setting.' }, + }, + 'apm:enableServiceOverview': { + type: 'boolean', + _meta: { description: 'Non-default value of setting.' }, + }, }; diff --git a/src/plugins/kibana_usage_collection/server/collectors/management/telemetry_management_collector.ts b/src/plugins/kibana_usage_collection/server/collectors/management/telemetry_management_collector.ts index df53c770603cc8..cba5140997f3f5 100644 --- a/src/plugins/kibana_usage_collection/server/collectors/management/telemetry_management_collector.ts +++ b/src/plugins/kibana_usage_collection/server/collectors/management/telemetry_management_collector.ts @@ -8,9 +8,9 @@ import { IUiSettingsClient } from 'kibana/server'; import { UsageCollectionSetup } from 'src/plugins/usage_collection/server'; -import { stackManagementSchema } from './schema'; import { UsageStats } from './types'; import { REDACTED_KEYWORD } from '../../../common/constants'; +import { stackManagementSchema } from './schema'; export function createCollectorFetch(getUiSettingsClient: () => IUiSettingsClient | undefined) { return async function fetchUsageStats(): Promise { @@ -27,7 +27,6 @@ export function createCollectorFetch(getUiSettingsClient: () => IUiSettingsClien obj[key] = sensitive ? REDACTED_KEYWORD : userValue; return obj; }, {}); - return modifiedEntries; }; } diff --git a/src/plugins/kibana_usage_collection/server/collectors/management/types.ts b/src/plugins/kibana_usage_collection/server/collectors/management/types.ts index 698e7e7115295c..8bbc14e0678d39 100644 --- a/src/plugins/kibana_usage_collection/server/collectors/management/types.ts +++ b/src/plugins/kibana_usage_collection/server/collectors/management/types.ts @@ -73,7 +73,7 @@ export interface UsageStats { 'discover:sort:defaultOrder': string; 'context:step': number; 'accessibility:disableAnimations': boolean; - 'ml:fileDataVisualizerMaxFileSize': string; + 'fileUpload:maxFileSize': string; 'ml:anomalyDetection:results:enableTimeDefaults': boolean; 'ml:anomalyDetection:results:timeDefaults': string; 'truncate:maxHeight': number; diff --git a/src/plugins/kibana_usage_collection/server/collectors/ops_stats/ops_stats_collector.ts b/src/plugins/kibana_usage_collection/server/collectors/ops_stats/ops_stats_collector.ts index 91ab77d202dbd9..7959b67b4f4686 100644 --- a/src/plugins/kibana_usage_collection/server/collectors/ops_stats/ops_stats_collector.ts +++ b/src/plugins/kibana_usage_collection/server/collectors/ops_stats/ops_stats_collector.ts @@ -12,7 +12,6 @@ import moment from 'moment'; import { OpsMetrics } from 'kibana/server'; import { UsageCollectionSetup } from 'src/plugins/usage_collection/server'; import { KIBANA_STATS_TYPE } from '../../../common/constants'; - interface OpsStatsMetrics extends Omit { timestamp: string; response_times: { diff --git a/src/plugins/kibana_usage_collection/server/collectors/ui_counters/register_ui_counters_collector.ts b/src/plugins/kibana_usage_collection/server/collectors/ui_counters/register_ui_counters_collector.ts index c754649b34eb13..dc3fac73820949 100644 --- a/src/plugins/kibana_usage_collection/server/collectors/ui_counters/register_ui_counters_collector.ts +++ b/src/plugins/kibana_usage_collection/server/collectors/ui_counters/register_ui_counters_collector.ts @@ -52,12 +52,27 @@ export function registerUiCountersUsageCollector(usageCollection: UsageCollectio dailyEvents: { type: 'array', items: { - appName: { type: 'keyword' }, - eventName: { type: 'keyword' }, - lastUpdatedAt: { type: 'date' }, - fromTimestamp: { type: 'date' }, - counterType: { type: 'keyword' }, - total: { type: 'integer' }, + appName: { + type: 'keyword', + _meta: { description: 'Name of the app reporting ui counts.' }, + }, + eventName: { + type: 'keyword', + _meta: { description: 'Name of the event that happened.' }, + }, + lastUpdatedAt: { + type: 'date', + _meta: { description: 'Time at which the metric was last updated.' }, + }, + fromTimestamp: { + type: 'date', + _meta: { description: 'Time at which the metric was captured.' }, + }, + counterType: { type: 'keyword', _meta: { description: 'The type of counter used.' } }, + total: { + type: 'integer', + _meta: { description: 'The total number of times the event happened.' }, + }, }, }, }, diff --git a/src/plugins/kibana_usage_collection/server/collectors/ui_metric/schema.ts b/src/plugins/kibana_usage_collection/server/collectors/ui_metric/schema.ts index 6affbf4f54fa95..b64c23a2af2898 100644 --- a/src/plugins/kibana_usage_collection/server/collectors/ui_metric/schema.ts +++ b/src/plugins/kibana_usage_collection/server/collectors/ui_metric/schema.ts @@ -12,8 +12,8 @@ import { UIMetricUsage } from './telemetry_ui_metric_collector'; const commonSchema: MakeSchemaFrom[string] = { type: 'array', items: { - key: { type: 'keyword' }, - value: { type: 'long' }, + key: { type: 'keyword', _meta: { description: 'The event that is tracked' } }, + value: { type: 'long', _meta: { description: 'The value of the event' } }, }, }; diff --git a/src/plugins/telemetry/schema/oss_plugins.json b/src/plugins/telemetry/schema/oss_plugins.json index 566d10182b5444..f7795dbf9b2f8e 100644 --- a/src/plugins/telemetry/schema/oss_plugins.json +++ b/src/plugins/telemetry/schema/oss_plugins.json @@ -83,68 +83,128 @@ "dashboards": { "properties": { "appId": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "The application being tracked" + } }, "viewId": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "Always `main`" + } }, "clicks_total": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the application since we started counting them" + } }, "clicks_7_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the application over the last 7 days" + } }, "clicks_30_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the application over the last 30 days" + } }, "clicks_90_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the application over the last 90 days" + } }, "minutes_on_screen_total": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen since we started counting them." + } }, "minutes_on_screen_7_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen over the last 7 days" + } }, "minutes_on_screen_30_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen over the last 30 days" + } }, "minutes_on_screen_90_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen over the last 90 days" + } }, "views": { "type": "array", "items": { "properties": { "appId": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "The application being tracked" + } }, "viewId": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "The application view being tracked" + } }, "clicks_total": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the application sub view since we started counting them" + } }, "clicks_7_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the active application sub view over the last 7 days" + } }, "clicks_30_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the active application sub view over the last 30 days" + } }, "clicks_90_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the active application sub view over the last 90 days" + } }, "minutes_on_screen_total": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application sub view is active and on-screen since we started counting them." + } }, "minutes_on_screen_7_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen active application sub view over the last 7 days" + } }, "minutes_on_screen_30_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen active application sub view over the last 30 days" + } }, "minutes_on_screen_90_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen active application sub view over the last 90 days" + } } } } @@ -154,68 +214,128 @@ "dev_tools": { "properties": { "appId": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "The application being tracked" + } }, "viewId": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "Always `main`" + } }, "clicks_total": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the application since we started counting them" + } }, "clicks_7_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the application over the last 7 days" + } }, "clicks_30_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the application over the last 30 days" + } }, "clicks_90_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the application over the last 90 days" + } }, "minutes_on_screen_total": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen since we started counting them." + } }, "minutes_on_screen_7_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen over the last 7 days" + } }, "minutes_on_screen_30_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen over the last 30 days" + } }, "minutes_on_screen_90_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen over the last 90 days" + } }, "views": { "type": "array", "items": { "properties": { "appId": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "The application being tracked" + } }, "viewId": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "The application view being tracked" + } }, "clicks_total": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the application sub view since we started counting them" + } }, "clicks_7_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the active application sub view over the last 7 days" + } }, "clicks_30_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the active application sub view over the last 30 days" + } }, "clicks_90_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the active application sub view over the last 90 days" + } }, "minutes_on_screen_total": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application sub view is active and on-screen since we started counting them." + } }, "minutes_on_screen_7_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen active application sub view over the last 7 days" + } }, "minutes_on_screen_30_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen active application sub view over the last 30 days" + } }, "minutes_on_screen_90_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen active application sub view over the last 90 days" + } } } } @@ -225,68 +345,128 @@ "discover": { "properties": { "appId": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "The application being tracked" + } }, "viewId": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "Always `main`" + } }, "clicks_total": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the application since we started counting them" + } }, "clicks_7_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the application over the last 7 days" + } }, "clicks_30_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the application over the last 30 days" + } }, "clicks_90_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the application over the last 90 days" + } }, "minutes_on_screen_total": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen since we started counting them." + } }, "minutes_on_screen_7_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen over the last 7 days" + } }, "minutes_on_screen_30_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen over the last 30 days" + } }, "minutes_on_screen_90_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen over the last 90 days" + } }, "views": { "type": "array", "items": { "properties": { "appId": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "The application being tracked" + } }, "viewId": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "The application view being tracked" + } }, "clicks_total": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the application sub view since we started counting them" + } }, "clicks_7_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the active application sub view over the last 7 days" + } }, "clicks_30_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the active application sub view over the last 30 days" + } }, "clicks_90_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the active application sub view over the last 90 days" + } }, "minutes_on_screen_total": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application sub view is active and on-screen since we started counting them." + } }, "minutes_on_screen_7_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen active application sub view over the last 7 days" + } }, "minutes_on_screen_30_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen active application sub view over the last 30 days" + } }, "minutes_on_screen_90_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen active application sub view over the last 90 days" + } } } } @@ -296,68 +476,128 @@ "home": { "properties": { "appId": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "The application being tracked" + } }, "viewId": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "Always `main`" + } }, "clicks_total": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the application since we started counting them" + } }, "clicks_7_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the application over the last 7 days" + } }, "clicks_30_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the application over the last 30 days" + } }, "clicks_90_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the application over the last 90 days" + } }, "minutes_on_screen_total": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen since we started counting them." + } }, "minutes_on_screen_7_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen over the last 7 days" + } }, "minutes_on_screen_30_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen over the last 30 days" + } }, "minutes_on_screen_90_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen over the last 90 days" + } }, "views": { "type": "array", "items": { "properties": { "appId": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "The application being tracked" + } }, "viewId": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "The application view being tracked" + } }, "clicks_total": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the application sub view since we started counting them" + } }, "clicks_7_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the active application sub view over the last 7 days" + } }, "clicks_30_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the active application sub view over the last 30 days" + } }, "clicks_90_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the active application sub view over the last 90 days" + } }, "minutes_on_screen_total": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application sub view is active and on-screen since we started counting them." + } }, "minutes_on_screen_7_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen active application sub view over the last 7 days" + } }, "minutes_on_screen_30_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen active application sub view over the last 30 days" + } }, "minutes_on_screen_90_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen active application sub view over the last 90 days" + } } } } @@ -367,68 +607,128 @@ "kibana": { "properties": { "appId": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "The application being tracked" + } }, "viewId": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "Always `main`" + } }, "clicks_total": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the application since we started counting them" + } }, "clicks_7_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the application over the last 7 days" + } }, "clicks_30_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the application over the last 30 days" + } }, "clicks_90_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the application over the last 90 days" + } }, "minutes_on_screen_total": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen since we started counting them." + } }, "minutes_on_screen_7_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen over the last 7 days" + } }, "minutes_on_screen_30_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen over the last 30 days" + } }, "minutes_on_screen_90_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen over the last 90 days" + } }, "views": { "type": "array", "items": { "properties": { "appId": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "The application being tracked" + } }, "viewId": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "The application view being tracked" + } }, "clicks_total": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the application sub view since we started counting them" + } }, "clicks_7_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the active application sub view over the last 7 days" + } }, "clicks_30_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the active application sub view over the last 30 days" + } }, "clicks_90_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the active application sub view over the last 90 days" + } }, "minutes_on_screen_total": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application sub view is active and on-screen since we started counting them." + } }, "minutes_on_screen_7_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen active application sub view over the last 7 days" + } }, "minutes_on_screen_30_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen active application sub view over the last 30 days" + } }, "minutes_on_screen_90_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen active application sub view over the last 90 days" + } } } } @@ -438,68 +738,128 @@ "management": { "properties": { "appId": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "The application being tracked" + } }, "viewId": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "Always `main`" + } }, "clicks_total": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the application since we started counting them" + } }, "clicks_7_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the application over the last 7 days" + } }, "clicks_30_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the application over the last 30 days" + } }, "clicks_90_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the application over the last 90 days" + } }, "minutes_on_screen_total": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen since we started counting them." + } }, "minutes_on_screen_7_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen over the last 7 days" + } }, "minutes_on_screen_30_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen over the last 30 days" + } }, "minutes_on_screen_90_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen over the last 90 days" + } }, "views": { "type": "array", "items": { "properties": { "appId": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "The application being tracked" + } }, "viewId": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "The application view being tracked" + } }, "clicks_total": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the application sub view since we started counting them" + } }, "clicks_7_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the active application sub view over the last 7 days" + } }, "clicks_30_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the active application sub view over the last 30 days" + } }, "clicks_90_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the active application sub view over the last 90 days" + } }, "minutes_on_screen_total": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application sub view is active and on-screen since we started counting them." + } }, "minutes_on_screen_7_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen active application sub view over the last 7 days" + } }, "minutes_on_screen_30_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen active application sub view over the last 30 days" + } }, "minutes_on_screen_90_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen active application sub view over the last 90 days" + } } } } @@ -509,68 +869,128 @@ "short_url_redirect": { "properties": { "appId": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "The application being tracked" + } }, "viewId": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "Always `main`" + } }, "clicks_total": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the application since we started counting them" + } }, "clicks_7_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the application over the last 7 days" + } }, "clicks_30_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the application over the last 30 days" + } }, "clicks_90_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the application over the last 90 days" + } }, "minutes_on_screen_total": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen since we started counting them." + } }, "minutes_on_screen_7_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen over the last 7 days" + } }, "minutes_on_screen_30_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen over the last 30 days" + } }, "minutes_on_screen_90_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen over the last 90 days" + } }, "views": { "type": "array", "items": { "properties": { "appId": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "The application being tracked" + } }, "viewId": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "The application view being tracked" + } }, "clicks_total": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the application sub view since we started counting them" + } }, "clicks_7_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the active application sub view over the last 7 days" + } }, "clicks_30_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the active application sub view over the last 30 days" + } }, "clicks_90_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the active application sub view over the last 90 days" + } }, "minutes_on_screen_total": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application sub view is active and on-screen since we started counting them." + } }, "minutes_on_screen_7_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen active application sub view over the last 7 days" + } }, "minutes_on_screen_30_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen active application sub view over the last 30 days" + } }, "minutes_on_screen_90_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen active application sub view over the last 90 days" + } } } } @@ -580,68 +1000,128 @@ "timelion": { "properties": { "appId": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "The application being tracked" + } }, "viewId": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "Always `main`" + } }, "clicks_total": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the application since we started counting them" + } }, "clicks_7_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the application over the last 7 days" + } }, "clicks_30_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the application over the last 30 days" + } }, "clicks_90_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the application over the last 90 days" + } }, "minutes_on_screen_total": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen since we started counting them." + } }, "minutes_on_screen_7_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen over the last 7 days" + } }, "minutes_on_screen_30_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen over the last 30 days" + } }, "minutes_on_screen_90_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen over the last 90 days" + } }, "views": { "type": "array", "items": { "properties": { "appId": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "The application being tracked" + } }, "viewId": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "The application view being tracked" + } }, "clicks_total": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the application sub view since we started counting them" + } }, "clicks_7_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the active application sub view over the last 7 days" + } }, "clicks_30_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the active application sub view over the last 30 days" + } }, "clicks_90_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the active application sub view over the last 90 days" + } }, "minutes_on_screen_total": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application sub view is active and on-screen since we started counting them." + } }, "minutes_on_screen_7_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen active application sub view over the last 7 days" + } }, "minutes_on_screen_30_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen active application sub view over the last 30 days" + } }, "minutes_on_screen_90_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen active application sub view over the last 90 days" + } } } } @@ -651,68 +1131,128 @@ "visualize": { "properties": { "appId": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "The application being tracked" + } }, "viewId": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "Always `main`" + } }, "clicks_total": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the application since we started counting them" + } }, "clicks_7_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the application over the last 7 days" + } }, "clicks_30_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the application over the last 30 days" + } }, "clicks_90_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the application over the last 90 days" + } }, "minutes_on_screen_total": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen since we started counting them." + } }, "minutes_on_screen_7_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen over the last 7 days" + } }, "minutes_on_screen_30_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen over the last 30 days" + } }, "minutes_on_screen_90_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen over the last 90 days" + } }, "views": { "type": "array", "items": { "properties": { "appId": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "The application being tracked" + } }, "viewId": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "The application view being tracked" + } }, "clicks_total": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the application sub view since we started counting them" + } }, "clicks_7_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the active application sub view over the last 7 days" + } }, "clicks_30_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the active application sub view over the last 30 days" + } }, "clicks_90_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the active application sub view over the last 90 days" + } }, "minutes_on_screen_total": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application sub view is active and on-screen since we started counting them." + } }, "minutes_on_screen_7_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen active application sub view over the last 7 days" + } }, "minutes_on_screen_30_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen active application sub view over the last 30 days" + } }, "minutes_on_screen_90_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen active application sub view over the last 90 days" + } } } } @@ -722,68 +1262,128 @@ "error": { "properties": { "appId": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "The application being tracked" + } }, "viewId": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "Always `main`" + } }, "clicks_total": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the application since we started counting them" + } }, "clicks_7_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the application over the last 7 days" + } }, "clicks_30_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the application over the last 30 days" + } }, "clicks_90_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the application over the last 90 days" + } }, "minutes_on_screen_total": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen since we started counting them." + } }, "minutes_on_screen_7_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen over the last 7 days" + } }, "minutes_on_screen_30_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen over the last 30 days" + } }, "minutes_on_screen_90_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen over the last 90 days" + } }, "views": { "type": "array", "items": { "properties": { "appId": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "The application being tracked" + } }, "viewId": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "The application view being tracked" + } }, "clicks_total": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the application sub view since we started counting them" + } }, "clicks_7_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the active application sub view over the last 7 days" + } }, "clicks_30_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the active application sub view over the last 30 days" + } }, "clicks_90_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the active application sub view over the last 90 days" + } }, "minutes_on_screen_total": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application sub view is active and on-screen since we started counting them." + } }, "minutes_on_screen_7_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen active application sub view over the last 7 days" + } }, "minutes_on_screen_30_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen active application sub view over the last 30 days" + } }, "minutes_on_screen_90_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen active application sub view over the last 90 days" + } } } } @@ -793,68 +1393,128 @@ "status": { "properties": { "appId": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "The application being tracked" + } }, "viewId": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "Always `main`" + } }, "clicks_total": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the application since we started counting them" + } }, "clicks_7_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the application over the last 7 days" + } }, "clicks_30_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the application over the last 30 days" + } }, "clicks_90_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the application over the last 90 days" + } }, "minutes_on_screen_total": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen since we started counting them." + } }, "minutes_on_screen_7_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen over the last 7 days" + } }, "minutes_on_screen_30_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen over the last 30 days" + } }, "minutes_on_screen_90_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen over the last 90 days" + } }, "views": { "type": "array", "items": { "properties": { "appId": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "The application being tracked" + } }, "viewId": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "The application view being tracked" + } }, "clicks_total": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the application sub view since we started counting them" + } }, "clicks_7_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the active application sub view over the last 7 days" + } }, "clicks_30_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the active application sub view over the last 30 days" + } }, "clicks_90_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the active application sub view over the last 90 days" + } }, "minutes_on_screen_total": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application sub view is active and on-screen since we started counting them." + } }, "minutes_on_screen_7_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen active application sub view over the last 7 days" + } }, "minutes_on_screen_30_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen active application sub view over the last 30 days" + } }, "minutes_on_screen_90_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen active application sub view over the last 90 days" + } } } } @@ -864,68 +1524,128 @@ "kibanaOverview": { "properties": { "appId": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "The application being tracked" + } }, "viewId": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "Always `main`" + } }, "clicks_total": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the application since we started counting them" + } }, "clicks_7_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the application over the last 7 days" + } }, "clicks_30_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the application over the last 30 days" + } }, "clicks_90_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the application over the last 90 days" + } }, "minutes_on_screen_total": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen since we started counting them." + } }, "minutes_on_screen_7_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen over the last 7 days" + } }, "minutes_on_screen_30_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen over the last 30 days" + } }, "minutes_on_screen_90_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen over the last 90 days" + } }, "views": { "type": "array", "items": { "properties": { "appId": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "The application being tracked" + } }, "viewId": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "The application view being tracked" + } }, "clicks_total": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the application sub view since we started counting them" + } }, "clicks_7_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the active application sub view over the last 7 days" + } }, "clicks_30_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the active application sub view over the last 30 days" + } }, "clicks_90_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the active application sub view over the last 90 days" + } }, "minutes_on_screen_total": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application sub view is active and on-screen since we started counting them." + } }, "minutes_on_screen_7_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen active application sub view over the last 7 days" + } }, "minutes_on_screen_30_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen active application sub view over the last 30 days" + } }, "minutes_on_screen_90_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen active application sub view over the last 90 days" + } } } } @@ -935,68 +1655,128 @@ "apm": { "properties": { "appId": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "The application being tracked" + } }, "viewId": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "Always `main`" + } }, "clicks_total": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the application since we started counting them" + } }, "clicks_7_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the application over the last 7 days" + } }, "clicks_30_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the application over the last 30 days" + } }, "clicks_90_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the application over the last 90 days" + } }, "minutes_on_screen_total": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen since we started counting them." + } }, "minutes_on_screen_7_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen over the last 7 days" + } }, "minutes_on_screen_30_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen over the last 30 days" + } }, "minutes_on_screen_90_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen over the last 90 days" + } }, "views": { "type": "array", "items": { "properties": { "appId": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "The application being tracked" + } }, "viewId": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "The application view being tracked" + } }, "clicks_total": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the application sub view since we started counting them" + } }, "clicks_7_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the active application sub view over the last 7 days" + } }, "clicks_30_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the active application sub view over the last 30 days" + } }, "clicks_90_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the active application sub view over the last 90 days" + } }, "minutes_on_screen_total": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application sub view is active and on-screen since we started counting them." + } }, "minutes_on_screen_7_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen active application sub view over the last 7 days" + } }, "minutes_on_screen_30_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen active application sub view over the last 30 days" + } }, "minutes_on_screen_90_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen active application sub view over the last 90 days" + } } } } @@ -1006,68 +1786,128 @@ "canvas": { "properties": { "appId": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "The application being tracked" + } }, "viewId": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "Always `main`" + } }, "clicks_total": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the application since we started counting them" + } }, "clicks_7_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the application over the last 7 days" + } }, "clicks_30_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the application over the last 30 days" + } }, "clicks_90_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the application over the last 90 days" + } }, "minutes_on_screen_total": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen since we started counting them." + } }, "minutes_on_screen_7_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen over the last 7 days" + } }, "minutes_on_screen_30_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen over the last 30 days" + } }, "minutes_on_screen_90_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen over the last 90 days" + } }, "views": { "type": "array", "items": { "properties": { "appId": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "The application being tracked" + } }, "viewId": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "The application view being tracked" + } }, "clicks_total": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the application sub view since we started counting them" + } }, "clicks_7_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the active application sub view over the last 7 days" + } }, "clicks_30_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the active application sub view over the last 30 days" + } }, "clicks_90_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the active application sub view over the last 90 days" + } }, "minutes_on_screen_total": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application sub view is active and on-screen since we started counting them." + } }, "minutes_on_screen_7_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen active application sub view over the last 7 days" + } }, "minutes_on_screen_30_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen active application sub view over the last 30 days" + } }, "minutes_on_screen_90_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen active application sub view over the last 90 days" + } } } } @@ -1077,68 +1917,128 @@ "dashboard_mode": { "properties": { "appId": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "The application being tracked" + } }, "viewId": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "Always `main`" + } }, "clicks_total": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the application since we started counting them" + } }, "clicks_7_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the application over the last 7 days" + } }, "clicks_30_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the application over the last 30 days" + } }, "clicks_90_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the application over the last 90 days" + } }, "minutes_on_screen_total": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen since we started counting them." + } }, "minutes_on_screen_7_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen over the last 7 days" + } }, "minutes_on_screen_30_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen over the last 30 days" + } }, "minutes_on_screen_90_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen over the last 90 days" + } }, "views": { "type": "array", "items": { "properties": { "appId": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "The application being tracked" + } }, "viewId": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "The application view being tracked" + } }, "clicks_total": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the application sub view since we started counting them" + } }, "clicks_7_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the active application sub view over the last 7 days" + } }, "clicks_30_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the active application sub view over the last 30 days" + } }, "clicks_90_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the active application sub view over the last 90 days" + } }, "minutes_on_screen_total": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application sub view is active and on-screen since we started counting them." + } }, "minutes_on_screen_7_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen active application sub view over the last 7 days" + } }, "minutes_on_screen_30_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen active application sub view over the last 30 days" + } }, "minutes_on_screen_90_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen active application sub view over the last 90 days" + } } } } @@ -1148,68 +2048,128 @@ "enterpriseSearch": { "properties": { "appId": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "The application being tracked" + } }, "viewId": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "Always `main`" + } }, "clicks_total": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the application since we started counting them" + } }, "clicks_7_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the application over the last 7 days" + } }, "clicks_30_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the application over the last 30 days" + } }, "clicks_90_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the application over the last 90 days" + } }, "minutes_on_screen_total": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen since we started counting them." + } }, "minutes_on_screen_7_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen over the last 7 days" + } }, "minutes_on_screen_30_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen over the last 30 days" + } }, "minutes_on_screen_90_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen over the last 90 days" + } }, "views": { "type": "array", "items": { "properties": { "appId": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "The application being tracked" + } }, "viewId": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "The application view being tracked" + } }, "clicks_total": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the application sub view since we started counting them" + } }, "clicks_7_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the active application sub view over the last 7 days" + } }, "clicks_30_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the active application sub view over the last 30 days" + } }, "clicks_90_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the active application sub view over the last 90 days" + } }, "minutes_on_screen_total": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application sub view is active and on-screen since we started counting them." + } }, "minutes_on_screen_7_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen active application sub view over the last 7 days" + } }, "minutes_on_screen_30_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen active application sub view over the last 30 days" + } }, "minutes_on_screen_90_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen active application sub view over the last 90 days" + } } } } @@ -1219,68 +2179,128 @@ "appSearch": { "properties": { "appId": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "The application being tracked" + } }, "viewId": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "Always `main`" + } }, "clicks_total": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the application since we started counting them" + } }, "clicks_7_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the application over the last 7 days" + } }, "clicks_30_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the application over the last 30 days" + } }, "clicks_90_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the application over the last 90 days" + } }, "minutes_on_screen_total": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen since we started counting them." + } }, "minutes_on_screen_7_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen over the last 7 days" + } }, "minutes_on_screen_30_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen over the last 30 days" + } }, "minutes_on_screen_90_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen over the last 90 days" + } }, "views": { "type": "array", "items": { "properties": { "appId": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "The application being tracked" + } }, "viewId": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "The application view being tracked" + } }, "clicks_total": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the application sub view since we started counting them" + } }, "clicks_7_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the active application sub view over the last 7 days" + } }, "clicks_30_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the active application sub view over the last 30 days" + } }, "clicks_90_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the active application sub view over the last 90 days" + } }, "minutes_on_screen_total": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application sub view is active and on-screen since we started counting them." + } }, "minutes_on_screen_7_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen active application sub view over the last 7 days" + } }, "minutes_on_screen_30_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen active application sub view over the last 30 days" + } }, "minutes_on_screen_90_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen active application sub view over the last 90 days" + } } } } @@ -1290,68 +2310,128 @@ "workplaceSearch": { "properties": { "appId": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "The application being tracked" + } }, "viewId": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "Always `main`" + } }, "clicks_total": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the application since we started counting them" + } }, "clicks_7_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the application over the last 7 days" + } }, "clicks_30_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the application over the last 30 days" + } }, "clicks_90_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the application over the last 90 days" + } }, "minutes_on_screen_total": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen since we started counting them." + } }, "minutes_on_screen_7_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen over the last 7 days" + } }, "minutes_on_screen_30_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen over the last 30 days" + } }, "minutes_on_screen_90_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen over the last 90 days" + } }, "views": { "type": "array", "items": { "properties": { "appId": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "The application being tracked" + } }, "viewId": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "The application view being tracked" + } }, "clicks_total": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the application sub view since we started counting them" + } }, "clicks_7_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the active application sub view over the last 7 days" + } }, "clicks_30_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the active application sub view over the last 30 days" + } }, "clicks_90_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the active application sub view over the last 90 days" + } }, "minutes_on_screen_total": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application sub view is active and on-screen since we started counting them." + } }, "minutes_on_screen_7_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen active application sub view over the last 7 days" + } }, "minutes_on_screen_30_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen active application sub view over the last 30 days" + } }, "minutes_on_screen_90_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen active application sub view over the last 90 days" + } } } } @@ -1361,68 +2441,128 @@ "graph": { "properties": { "appId": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "The application being tracked" + } }, "viewId": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "Always `main`" + } }, "clicks_total": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the application since we started counting them" + } }, "clicks_7_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the application over the last 7 days" + } }, "clicks_30_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the application over the last 30 days" + } }, "clicks_90_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the application over the last 90 days" + } }, "minutes_on_screen_total": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen since we started counting them." + } }, "minutes_on_screen_7_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen over the last 7 days" + } }, "minutes_on_screen_30_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen over the last 30 days" + } }, "minutes_on_screen_90_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen over the last 90 days" + } }, "views": { "type": "array", "items": { "properties": { "appId": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "The application being tracked" + } }, "viewId": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "The application view being tracked" + } }, "clicks_total": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the application sub view since we started counting them" + } }, "clicks_7_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the active application sub view over the last 7 days" + } }, "clicks_30_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the active application sub view over the last 30 days" + } }, "clicks_90_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the active application sub view over the last 90 days" + } }, "minutes_on_screen_total": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application sub view is active and on-screen since we started counting them." + } }, "minutes_on_screen_7_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen active application sub view over the last 7 days" + } }, "minutes_on_screen_30_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen active application sub view over the last 30 days" + } }, "minutes_on_screen_90_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen active application sub view over the last 90 days" + } } } } @@ -1432,68 +2572,128 @@ "logs": { "properties": { "appId": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "The application being tracked" + } }, "viewId": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "Always `main`" + } }, "clicks_total": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the application since we started counting them" + } }, "clicks_7_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the application over the last 7 days" + } }, "clicks_30_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the application over the last 30 days" + } }, "clicks_90_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the application over the last 90 days" + } }, "minutes_on_screen_total": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen since we started counting them." + } }, "minutes_on_screen_7_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen over the last 7 days" + } }, "minutes_on_screen_30_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen over the last 30 days" + } }, "minutes_on_screen_90_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen over the last 90 days" + } }, "views": { "type": "array", "items": { "properties": { "appId": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "The application being tracked" + } }, "viewId": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "The application view being tracked" + } }, "clicks_total": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the application sub view since we started counting them" + } }, "clicks_7_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the active application sub view over the last 7 days" + } }, "clicks_30_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the active application sub view over the last 30 days" + } }, "clicks_90_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the active application sub view over the last 90 days" + } }, "minutes_on_screen_total": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application sub view is active and on-screen since we started counting them." + } }, "minutes_on_screen_7_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen active application sub view over the last 7 days" + } }, "minutes_on_screen_30_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen active application sub view over the last 30 days" + } }, "minutes_on_screen_90_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen active application sub view over the last 90 days" + } } } } @@ -1503,68 +2703,128 @@ "metrics": { "properties": { "appId": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "The application being tracked" + } }, "viewId": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "Always `main`" + } }, "clicks_total": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the application since we started counting them" + } }, "clicks_7_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the application over the last 7 days" + } }, "clicks_30_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the application over the last 30 days" + } }, "clicks_90_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the application over the last 90 days" + } }, "minutes_on_screen_total": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen since we started counting them." + } }, "minutes_on_screen_7_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen over the last 7 days" + } }, "minutes_on_screen_30_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen over the last 30 days" + } }, "minutes_on_screen_90_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen over the last 90 days" + } }, "views": { "type": "array", "items": { "properties": { "appId": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "The application being tracked" + } }, "viewId": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "The application view being tracked" + } }, "clicks_total": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the application sub view since we started counting them" + } }, "clicks_7_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the active application sub view over the last 7 days" + } }, "clicks_30_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the active application sub view over the last 30 days" + } }, "clicks_90_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the active application sub view over the last 90 days" + } }, "minutes_on_screen_total": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application sub view is active and on-screen since we started counting them." + } }, "minutes_on_screen_7_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen active application sub view over the last 7 days" + } }, "minutes_on_screen_30_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen active application sub view over the last 30 days" + } }, "minutes_on_screen_90_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen active application sub view over the last 90 days" + } } } } @@ -1574,68 +2834,128 @@ "infra": { "properties": { "appId": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "The application being tracked" + } }, "viewId": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "Always `main`" + } }, "clicks_total": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the application since we started counting them" + } }, "clicks_7_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the application over the last 7 days" + } }, "clicks_30_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the application over the last 30 days" + } }, "clicks_90_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the application over the last 90 days" + } }, "minutes_on_screen_total": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen since we started counting them." + } }, "minutes_on_screen_7_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen over the last 7 days" + } }, "minutes_on_screen_30_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen over the last 30 days" + } }, "minutes_on_screen_90_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen over the last 90 days" + } }, "views": { "type": "array", "items": { "properties": { "appId": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "The application being tracked" + } }, "viewId": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "The application view being tracked" + } }, "clicks_total": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the application sub view since we started counting them" + } }, "clicks_7_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the active application sub view over the last 7 days" + } }, "clicks_30_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the active application sub view over the last 30 days" + } }, "clicks_90_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the active application sub view over the last 90 days" + } }, "minutes_on_screen_total": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application sub view is active and on-screen since we started counting them." + } }, "minutes_on_screen_7_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen active application sub view over the last 7 days" + } }, "minutes_on_screen_30_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen active application sub view over the last 30 days" + } }, "minutes_on_screen_90_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen active application sub view over the last 90 days" + } } } } @@ -1645,68 +2965,128 @@ "fleet": { "properties": { "appId": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "The application being tracked" + } }, "viewId": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "Always `main`" + } }, "clicks_total": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the application since we started counting them" + } }, "clicks_7_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the application over the last 7 days" + } }, "clicks_30_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the application over the last 30 days" + } }, "clicks_90_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the application over the last 90 days" + } }, "minutes_on_screen_total": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen since we started counting them." + } }, "minutes_on_screen_7_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen over the last 7 days" + } }, "minutes_on_screen_30_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen over the last 30 days" + } }, "minutes_on_screen_90_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen over the last 90 days" + } }, "views": { "type": "array", "items": { "properties": { "appId": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "The application being tracked" + } }, "viewId": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "The application view being tracked" + } }, "clicks_total": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the application sub view since we started counting them" + } }, "clicks_7_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the active application sub view over the last 7 days" + } }, "clicks_30_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the active application sub view over the last 30 days" + } }, "clicks_90_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the active application sub view over the last 90 days" + } }, "minutes_on_screen_total": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application sub view is active and on-screen since we started counting them." + } }, "minutes_on_screen_7_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen active application sub view over the last 7 days" + } }, "minutes_on_screen_30_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen active application sub view over the last 30 days" + } }, "minutes_on_screen_90_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen active application sub view over the last 90 days" + } } } } @@ -1716,68 +3096,128 @@ "ingestManager": { "properties": { "appId": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "The application being tracked" + } }, "viewId": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "Always `main`" + } }, "clicks_total": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the application since we started counting them" + } }, "clicks_7_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the application over the last 7 days" + } }, "clicks_30_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the application over the last 30 days" + } }, "clicks_90_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the application over the last 90 days" + } }, "minutes_on_screen_total": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen since we started counting them." + } }, "minutes_on_screen_7_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen over the last 7 days" + } }, "minutes_on_screen_30_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen over the last 30 days" + } }, "minutes_on_screen_90_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen over the last 90 days" + } }, "views": { "type": "array", "items": { "properties": { "appId": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "The application being tracked" + } }, "viewId": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "The application view being tracked" + } }, "clicks_total": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the application sub view since we started counting them" + } }, "clicks_7_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the active application sub view over the last 7 days" + } }, "clicks_30_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the active application sub view over the last 30 days" + } }, "clicks_90_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the active application sub view over the last 90 days" + } }, "minutes_on_screen_total": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application sub view is active and on-screen since we started counting them." + } }, "minutes_on_screen_7_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen active application sub view over the last 7 days" + } }, "minutes_on_screen_30_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen active application sub view over the last 30 days" + } }, "minutes_on_screen_90_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen active application sub view over the last 90 days" + } } } } @@ -1787,68 +3227,128 @@ "lens": { "properties": { "appId": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "The application being tracked" + } }, "viewId": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "Always `main`" + } }, "clicks_total": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the application since we started counting them" + } }, "clicks_7_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the application over the last 7 days" + } }, "clicks_30_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the application over the last 30 days" + } }, "clicks_90_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the application over the last 90 days" + } }, "minutes_on_screen_total": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen since we started counting them." + } }, "minutes_on_screen_7_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen over the last 7 days" + } }, "minutes_on_screen_30_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen over the last 30 days" + } }, "minutes_on_screen_90_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen over the last 90 days" + } }, "views": { "type": "array", "items": { "properties": { "appId": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "The application being tracked" + } }, "viewId": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "The application view being tracked" + } }, "clicks_total": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the application sub view since we started counting them" + } }, "clicks_7_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the active application sub view over the last 7 days" + } }, "clicks_30_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the active application sub view over the last 30 days" + } }, "clicks_90_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the active application sub view over the last 90 days" + } }, "minutes_on_screen_total": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application sub view is active and on-screen since we started counting them." + } }, "minutes_on_screen_7_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen active application sub view over the last 7 days" + } }, "minutes_on_screen_30_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen active application sub view over the last 30 days" + } }, "minutes_on_screen_90_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen active application sub view over the last 90 days" + } } } } @@ -1858,68 +3358,128 @@ "maps": { "properties": { "appId": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "The application being tracked" + } }, "viewId": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "Always `main`" + } }, "clicks_total": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the application since we started counting them" + } }, "clicks_7_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the application over the last 7 days" + } }, "clicks_30_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the application over the last 30 days" + } }, "clicks_90_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the application over the last 90 days" + } }, "minutes_on_screen_total": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen since we started counting them." + } }, "minutes_on_screen_7_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen over the last 7 days" + } }, "minutes_on_screen_30_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen over the last 30 days" + } }, "minutes_on_screen_90_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen over the last 90 days" + } }, "views": { "type": "array", "items": { "properties": { "appId": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "The application being tracked" + } }, "viewId": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "The application view being tracked" + } }, "clicks_total": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the application sub view since we started counting them" + } }, "clicks_7_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the active application sub view over the last 7 days" + } }, "clicks_30_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the active application sub view over the last 30 days" + } }, "clicks_90_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the active application sub view over the last 90 days" + } }, "minutes_on_screen_total": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application sub view is active and on-screen since we started counting them." + } }, "minutes_on_screen_7_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen active application sub view over the last 7 days" + } }, "minutes_on_screen_30_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen active application sub view over the last 30 days" + } }, "minutes_on_screen_90_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen active application sub view over the last 90 days" + } } } } @@ -1929,68 +3489,128 @@ "ml": { "properties": { "appId": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "The application being tracked" + } }, "viewId": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "Always `main`" + } }, "clicks_total": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the application since we started counting them" + } }, "clicks_7_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the application over the last 7 days" + } }, "clicks_30_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the application over the last 30 days" + } }, "clicks_90_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the application over the last 90 days" + } }, "minutes_on_screen_total": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen since we started counting them." + } }, "minutes_on_screen_7_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen over the last 7 days" + } }, "minutes_on_screen_30_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen over the last 30 days" + } }, "minutes_on_screen_90_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen over the last 90 days" + } }, "views": { "type": "array", "items": { "properties": { "appId": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "The application being tracked" + } }, "viewId": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "The application view being tracked" + } }, "clicks_total": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the application sub view since we started counting them" + } }, "clicks_7_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the active application sub view over the last 7 days" + } }, "clicks_30_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the active application sub view over the last 30 days" + } }, "clicks_90_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the active application sub view over the last 90 days" + } }, "minutes_on_screen_total": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application sub view is active and on-screen since we started counting them." + } }, "minutes_on_screen_7_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen active application sub view over the last 7 days" + } }, "minutes_on_screen_30_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen active application sub view over the last 30 days" + } }, "minutes_on_screen_90_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen active application sub view over the last 90 days" + } } } } @@ -2000,68 +3620,128 @@ "monitoring": { "properties": { "appId": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "The application being tracked" + } }, "viewId": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "Always `main`" + } }, "clicks_total": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the application since we started counting them" + } }, "clicks_7_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the application over the last 7 days" + } }, "clicks_30_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the application over the last 30 days" + } }, "clicks_90_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the application over the last 90 days" + } }, "minutes_on_screen_total": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen since we started counting them." + } }, "minutes_on_screen_7_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen over the last 7 days" + } }, "minutes_on_screen_30_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen over the last 30 days" + } }, "minutes_on_screen_90_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen over the last 90 days" + } }, "views": { "type": "array", "items": { "properties": { "appId": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "The application being tracked" + } }, "viewId": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "The application view being tracked" + } }, "clicks_total": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the application sub view since we started counting them" + } }, "clicks_7_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the active application sub view over the last 7 days" + } }, "clicks_30_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the active application sub view over the last 30 days" + } }, "clicks_90_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the active application sub view over the last 90 days" + } }, "minutes_on_screen_total": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application sub view is active and on-screen since we started counting them." + } }, "minutes_on_screen_7_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen active application sub view over the last 7 days" + } }, "minutes_on_screen_30_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen active application sub view over the last 30 days" + } }, "minutes_on_screen_90_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen active application sub view over the last 90 days" + } } } } @@ -2071,68 +3751,128 @@ "observability-overview": { "properties": { "appId": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "The application being tracked" + } }, "viewId": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "Always `main`" + } }, "clicks_total": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the application since we started counting them" + } }, "clicks_7_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the application over the last 7 days" + } }, "clicks_30_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the application over the last 30 days" + } }, "clicks_90_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the application over the last 90 days" + } }, "minutes_on_screen_total": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen since we started counting them." + } }, "minutes_on_screen_7_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen over the last 7 days" + } }, "minutes_on_screen_30_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen over the last 30 days" + } }, "minutes_on_screen_90_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen over the last 90 days" + } }, "views": { "type": "array", "items": { "properties": { "appId": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "The application being tracked" + } }, "viewId": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "The application view being tracked" + } }, "clicks_total": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the application sub view since we started counting them" + } }, "clicks_7_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the active application sub view over the last 7 days" + } }, "clicks_30_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the active application sub view over the last 30 days" + } }, "clicks_90_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the active application sub view over the last 90 days" + } }, "minutes_on_screen_total": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application sub view is active and on-screen since we started counting them." + } }, "minutes_on_screen_7_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen active application sub view over the last 7 days" + } }, "minutes_on_screen_30_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen active application sub view over the last 30 days" + } }, "minutes_on_screen_90_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen active application sub view over the last 90 days" + } } } } @@ -2142,68 +3882,128 @@ "security_account": { "properties": { "appId": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "The application being tracked" + } }, "viewId": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "Always `main`" + } }, "clicks_total": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the application since we started counting them" + } }, "clicks_7_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the application over the last 7 days" + } }, "clicks_30_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the application over the last 30 days" + } }, "clicks_90_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the application over the last 90 days" + } }, "minutes_on_screen_total": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen since we started counting them." + } }, "minutes_on_screen_7_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen over the last 7 days" + } }, "minutes_on_screen_30_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen over the last 30 days" + } }, "minutes_on_screen_90_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen over the last 90 days" + } }, "views": { "type": "array", "items": { "properties": { "appId": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "The application being tracked" + } }, "viewId": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "The application view being tracked" + } }, "clicks_total": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the application sub view since we started counting them" + } }, "clicks_7_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the active application sub view over the last 7 days" + } }, "clicks_30_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the active application sub view over the last 30 days" + } }, "clicks_90_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the active application sub view over the last 90 days" + } }, "minutes_on_screen_total": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application sub view is active and on-screen since we started counting them." + } }, "minutes_on_screen_7_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen active application sub view over the last 7 days" + } }, "minutes_on_screen_30_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen active application sub view over the last 30 days" + } }, "minutes_on_screen_90_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen active application sub view over the last 90 days" + } } } } @@ -2213,68 +4013,128 @@ "security_access_agreement": { "properties": { "appId": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "The application being tracked" + } }, "viewId": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "Always `main`" + } }, "clicks_total": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the application since we started counting them" + } }, "clicks_7_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the application over the last 7 days" + } }, "clicks_30_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the application over the last 30 days" + } }, "clicks_90_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the application over the last 90 days" + } }, "minutes_on_screen_total": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen since we started counting them." + } }, "minutes_on_screen_7_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen over the last 7 days" + } }, "minutes_on_screen_30_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen over the last 30 days" + } }, "minutes_on_screen_90_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen over the last 90 days" + } }, "views": { "type": "array", "items": { "properties": { "appId": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "The application being tracked" + } }, "viewId": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "The application view being tracked" + } }, "clicks_total": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the application sub view since we started counting them" + } }, "clicks_7_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the active application sub view over the last 7 days" + } }, "clicks_30_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the active application sub view over the last 30 days" + } }, "clicks_90_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the active application sub view over the last 90 days" + } }, "minutes_on_screen_total": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application sub view is active and on-screen since we started counting them." + } }, "minutes_on_screen_7_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen active application sub view over the last 7 days" + } }, "minutes_on_screen_30_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen active application sub view over the last 30 days" + } }, "minutes_on_screen_90_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen active application sub view over the last 90 days" + } } } } @@ -2284,68 +4144,128 @@ "security_capture_url": { "properties": { "appId": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "The application being tracked" + } }, "viewId": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "Always `main`" + } }, "clicks_total": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the application since we started counting them" + } }, "clicks_7_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the application over the last 7 days" + } }, "clicks_30_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the application over the last 30 days" + } }, "clicks_90_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the application over the last 90 days" + } }, "minutes_on_screen_total": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen since we started counting them." + } }, "minutes_on_screen_7_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen over the last 7 days" + } }, "minutes_on_screen_30_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen over the last 30 days" + } }, "minutes_on_screen_90_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen over the last 90 days" + } }, "views": { "type": "array", "items": { "properties": { "appId": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "The application being tracked" + } }, "viewId": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "The application view being tracked" + } }, "clicks_total": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the application sub view since we started counting them" + } }, "clicks_7_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the active application sub view over the last 7 days" + } }, "clicks_30_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the active application sub view over the last 30 days" + } }, "clicks_90_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the active application sub view over the last 90 days" + } }, "minutes_on_screen_total": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application sub view is active and on-screen since we started counting them." + } }, "minutes_on_screen_7_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen active application sub view over the last 7 days" + } }, "minutes_on_screen_30_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen active application sub view over the last 30 days" + } }, "minutes_on_screen_90_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen active application sub view over the last 90 days" + } } } } @@ -2355,68 +4275,128 @@ "security_logged_out": { "properties": { "appId": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "The application being tracked" + } }, "viewId": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "Always `main`" + } }, "clicks_total": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the application since we started counting them" + } }, "clicks_7_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the application over the last 7 days" + } }, "clicks_30_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the application over the last 30 days" + } }, "clicks_90_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the application over the last 90 days" + } }, "minutes_on_screen_total": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen since we started counting them." + } }, "minutes_on_screen_7_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen over the last 7 days" + } }, "minutes_on_screen_30_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen over the last 30 days" + } }, "minutes_on_screen_90_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen over the last 90 days" + } }, "views": { "type": "array", "items": { "properties": { "appId": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "The application being tracked" + } }, "viewId": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "The application view being tracked" + } }, "clicks_total": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the application sub view since we started counting them" + } }, "clicks_7_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the active application sub view over the last 7 days" + } }, "clicks_30_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the active application sub view over the last 30 days" + } }, "clicks_90_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the active application sub view over the last 90 days" + } }, "minutes_on_screen_total": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application sub view is active and on-screen since we started counting them." + } }, "minutes_on_screen_7_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen active application sub view over the last 7 days" + } }, "minutes_on_screen_30_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen active application sub view over the last 30 days" + } }, "minutes_on_screen_90_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen active application sub view over the last 90 days" + } } } } @@ -2426,68 +4406,128 @@ "security_login": { "properties": { "appId": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "The application being tracked" + } }, "viewId": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "Always `main`" + } }, "clicks_total": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the application since we started counting them" + } }, "clicks_7_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the application over the last 7 days" + } }, "clicks_30_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the application over the last 30 days" + } }, "clicks_90_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the application over the last 90 days" + } }, "minutes_on_screen_total": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen since we started counting them." + } }, "minutes_on_screen_7_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen over the last 7 days" + } }, "minutes_on_screen_30_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen over the last 30 days" + } }, "minutes_on_screen_90_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen over the last 90 days" + } }, "views": { "type": "array", "items": { "properties": { "appId": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "The application being tracked" + } }, "viewId": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "The application view being tracked" + } }, "clicks_total": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the application sub view since we started counting them" + } }, "clicks_7_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the active application sub view over the last 7 days" + } }, "clicks_30_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the active application sub view over the last 30 days" + } }, "clicks_90_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the active application sub view over the last 90 days" + } }, "minutes_on_screen_total": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application sub view is active and on-screen since we started counting them." + } }, "minutes_on_screen_7_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen active application sub view over the last 7 days" + } }, "minutes_on_screen_30_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen active application sub view over the last 30 days" + } }, "minutes_on_screen_90_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen active application sub view over the last 90 days" + } } } } @@ -2497,68 +4537,128 @@ "security_logout": { "properties": { "appId": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "The application being tracked" + } }, "viewId": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "Always `main`" + } }, "clicks_total": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the application since we started counting them" + } }, "clicks_7_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the application over the last 7 days" + } }, "clicks_30_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the application over the last 30 days" + } }, "clicks_90_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the application over the last 90 days" + } }, "minutes_on_screen_total": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen since we started counting them." + } }, "minutes_on_screen_7_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen over the last 7 days" + } }, "minutes_on_screen_30_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen over the last 30 days" + } }, "minutes_on_screen_90_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen over the last 90 days" + } }, "views": { "type": "array", "items": { "properties": { "appId": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "The application being tracked" + } }, "viewId": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "The application view being tracked" + } }, "clicks_total": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the application sub view since we started counting them" + } }, "clicks_7_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the active application sub view over the last 7 days" + } }, "clicks_30_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the active application sub view over the last 30 days" + } }, "clicks_90_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the active application sub view over the last 90 days" + } }, "minutes_on_screen_total": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application sub view is active and on-screen since we started counting them." + } }, "minutes_on_screen_7_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen active application sub view over the last 7 days" + } }, "minutes_on_screen_30_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen active application sub view over the last 30 days" + } }, "minutes_on_screen_90_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen active application sub view over the last 90 days" + } } } } @@ -2568,68 +4668,128 @@ "security_overwritten_session": { "properties": { "appId": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "The application being tracked" + } }, "viewId": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "Always `main`" + } }, "clicks_total": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the application since we started counting them" + } }, "clicks_7_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the application over the last 7 days" + } }, "clicks_30_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the application over the last 30 days" + } }, "clicks_90_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the application over the last 90 days" + } }, "minutes_on_screen_total": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen since we started counting them." + } }, "minutes_on_screen_7_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen over the last 7 days" + } }, "minutes_on_screen_30_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen over the last 30 days" + } }, "minutes_on_screen_90_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen over the last 90 days" + } }, "views": { "type": "array", "items": { "properties": { "appId": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "The application being tracked" + } }, "viewId": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "The application view being tracked" + } }, "clicks_total": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the application sub view since we started counting them" + } }, "clicks_7_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the active application sub view over the last 7 days" + } }, "clicks_30_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the active application sub view over the last 30 days" + } }, "clicks_90_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the active application sub view over the last 90 days" + } }, "minutes_on_screen_total": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application sub view is active and on-screen since we started counting them." + } }, "minutes_on_screen_7_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen active application sub view over the last 7 days" + } }, "minutes_on_screen_30_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen active application sub view over the last 30 days" + } }, "minutes_on_screen_90_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen active application sub view over the last 90 days" + } } } } @@ -2639,68 +4799,128 @@ "securitySolution": { "properties": { "appId": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "The application being tracked" + } }, "viewId": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "Always `main`" + } }, "clicks_total": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the application since we started counting them" + } }, "clicks_7_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the application over the last 7 days" + } }, "clicks_30_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the application over the last 30 days" + } }, "clicks_90_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the application over the last 90 days" + } }, "minutes_on_screen_total": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen since we started counting them." + } }, "minutes_on_screen_7_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen over the last 7 days" + } }, "minutes_on_screen_30_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen over the last 30 days" + } }, "minutes_on_screen_90_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen over the last 90 days" + } }, "views": { "type": "array", "items": { "properties": { "appId": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "The application being tracked" + } }, "viewId": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "The application view being tracked" + } }, "clicks_total": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the application sub view since we started counting them" + } }, "clicks_7_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the active application sub view over the last 7 days" + } }, "clicks_30_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the active application sub view over the last 30 days" + } }, "clicks_90_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the active application sub view over the last 90 days" + } }, "minutes_on_screen_total": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application sub view is active and on-screen since we started counting them." + } }, "minutes_on_screen_7_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen active application sub view over the last 7 days" + } }, "minutes_on_screen_30_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen active application sub view over the last 30 days" + } }, "minutes_on_screen_90_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen active application sub view over the last 90 days" + } } } } @@ -2710,68 +4930,128 @@ "securitySolution:overview": { "properties": { "appId": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "The application being tracked" + } }, "viewId": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "Always `main`" + } }, "clicks_total": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the application since we started counting them" + } }, "clicks_7_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the application over the last 7 days" + } }, "clicks_30_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the application over the last 30 days" + } }, "clicks_90_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the application over the last 90 days" + } }, "minutes_on_screen_total": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen since we started counting them." + } }, "minutes_on_screen_7_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen over the last 7 days" + } }, "minutes_on_screen_30_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen over the last 30 days" + } }, "minutes_on_screen_90_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen over the last 90 days" + } }, "views": { "type": "array", "items": { "properties": { "appId": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "The application being tracked" + } }, "viewId": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "The application view being tracked" + } }, "clicks_total": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the application sub view since we started counting them" + } }, "clicks_7_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the active application sub view over the last 7 days" + } }, "clicks_30_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the active application sub view over the last 30 days" + } }, "clicks_90_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the active application sub view over the last 90 days" + } }, "minutes_on_screen_total": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application sub view is active and on-screen since we started counting them." + } }, "minutes_on_screen_7_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen active application sub view over the last 7 days" + } }, "minutes_on_screen_30_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen active application sub view over the last 30 days" + } }, "minutes_on_screen_90_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen active application sub view over the last 90 days" + } } } } @@ -2781,68 +5061,128 @@ "securitySolution:detections": { "properties": { "appId": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "The application being tracked" + } }, "viewId": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "Always `main`" + } }, "clicks_total": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the application since we started counting them" + } }, "clicks_7_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the application over the last 7 days" + } }, "clicks_30_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the application over the last 30 days" + } }, "clicks_90_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the application over the last 90 days" + } }, "minutes_on_screen_total": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen since we started counting them." + } }, "minutes_on_screen_7_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen over the last 7 days" + } }, "minutes_on_screen_30_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen over the last 30 days" + } }, "minutes_on_screen_90_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen over the last 90 days" + } }, "views": { "type": "array", "items": { "properties": { "appId": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "The application being tracked" + } }, "viewId": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "The application view being tracked" + } }, "clicks_total": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the application sub view since we started counting them" + } }, "clicks_7_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the active application sub view over the last 7 days" + } }, "clicks_30_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the active application sub view over the last 30 days" + } }, "clicks_90_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the active application sub view over the last 90 days" + } }, "minutes_on_screen_total": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application sub view is active and on-screen since we started counting them." + } }, "minutes_on_screen_7_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen active application sub view over the last 7 days" + } }, "minutes_on_screen_30_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen active application sub view over the last 30 days" + } }, "minutes_on_screen_90_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen active application sub view over the last 90 days" + } } } } @@ -2852,68 +5192,128 @@ "securitySolution:hosts": { "properties": { "appId": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "The application being tracked" + } }, "viewId": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "Always `main`" + } }, "clicks_total": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the application since we started counting them" + } }, "clicks_7_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the application over the last 7 days" + } }, "clicks_30_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the application over the last 30 days" + } }, "clicks_90_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the application over the last 90 days" + } }, "minutes_on_screen_total": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen since we started counting them." + } }, "minutes_on_screen_7_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen over the last 7 days" + } }, "minutes_on_screen_30_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen over the last 30 days" + } }, "minutes_on_screen_90_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen over the last 90 days" + } }, "views": { "type": "array", "items": { "properties": { "appId": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "The application being tracked" + } }, "viewId": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "The application view being tracked" + } }, "clicks_total": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the application sub view since we started counting them" + } }, "clicks_7_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the active application sub view over the last 7 days" + } }, "clicks_30_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the active application sub view over the last 30 days" + } }, "clicks_90_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the active application sub view over the last 90 days" + } }, "minutes_on_screen_total": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application sub view is active and on-screen since we started counting them." + } }, "minutes_on_screen_7_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen active application sub view over the last 7 days" + } }, "minutes_on_screen_30_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen active application sub view over the last 30 days" + } }, "minutes_on_screen_90_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen active application sub view over the last 90 days" + } } } } @@ -2923,68 +5323,128 @@ "securitySolution:network": { "properties": { "appId": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "The application being tracked" + } }, "viewId": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "Always `main`" + } }, "clicks_total": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the application since we started counting them" + } }, "clicks_7_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the application over the last 7 days" + } }, "clicks_30_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the application over the last 30 days" + } }, "clicks_90_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the application over the last 90 days" + } }, "minutes_on_screen_total": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen since we started counting them." + } }, "minutes_on_screen_7_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen over the last 7 days" + } }, "minutes_on_screen_30_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen over the last 30 days" + } }, "minutes_on_screen_90_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen over the last 90 days" + } }, "views": { "type": "array", "items": { "properties": { "appId": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "The application being tracked" + } }, "viewId": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "The application view being tracked" + } }, "clicks_total": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the application sub view since we started counting them" + } }, "clicks_7_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the active application sub view over the last 7 days" + } }, "clicks_30_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the active application sub view over the last 30 days" + } }, "clicks_90_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the active application sub view over the last 90 days" + } }, "minutes_on_screen_total": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application sub view is active and on-screen since we started counting them." + } }, "minutes_on_screen_7_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen active application sub view over the last 7 days" + } }, "minutes_on_screen_30_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen active application sub view over the last 30 days" + } }, "minutes_on_screen_90_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen active application sub view over the last 90 days" + } } } } @@ -2994,68 +5454,128 @@ "securitySolution:timelines": { "properties": { "appId": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "The application being tracked" + } }, "viewId": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "Always `main`" + } }, "clicks_total": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the application since we started counting them" + } }, "clicks_7_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the application over the last 7 days" + } }, "clicks_30_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the application over the last 30 days" + } }, "clicks_90_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the application over the last 90 days" + } }, "minutes_on_screen_total": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen since we started counting them." + } }, "minutes_on_screen_7_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen over the last 7 days" + } }, "minutes_on_screen_30_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen over the last 30 days" + } }, "minutes_on_screen_90_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen over the last 90 days" + } }, "views": { "type": "array", "items": { "properties": { "appId": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "The application being tracked" + } }, "viewId": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "The application view being tracked" + } }, "clicks_total": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the application sub view since we started counting them" + } }, "clicks_7_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the active application sub view over the last 7 days" + } }, "clicks_30_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the active application sub view over the last 30 days" + } }, "clicks_90_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the active application sub view over the last 90 days" + } }, "minutes_on_screen_total": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application sub view is active and on-screen since we started counting them." + } }, "minutes_on_screen_7_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen active application sub view over the last 7 days" + } }, "minutes_on_screen_30_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen active application sub view over the last 30 days" + } }, "minutes_on_screen_90_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen active application sub view over the last 90 days" + } } } } @@ -3065,68 +5585,128 @@ "securitySolution:case": { "properties": { "appId": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "The application being tracked" + } }, "viewId": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "Always `main`" + } }, "clicks_total": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the application since we started counting them" + } }, "clicks_7_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the application over the last 7 days" + } }, "clicks_30_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the application over the last 30 days" + } }, "clicks_90_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the application over the last 90 days" + } }, "minutes_on_screen_total": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen since we started counting them." + } }, "minutes_on_screen_7_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen over the last 7 days" + } }, "minutes_on_screen_30_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen over the last 30 days" + } }, "minutes_on_screen_90_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen over the last 90 days" + } }, "views": { "type": "array", "items": { "properties": { "appId": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "The application being tracked" + } }, "viewId": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "The application view being tracked" + } }, "clicks_total": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the application sub view since we started counting them" + } }, "clicks_7_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the active application sub view over the last 7 days" + } }, "clicks_30_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the active application sub view over the last 30 days" + } }, "clicks_90_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the active application sub view over the last 90 days" + } }, "minutes_on_screen_total": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application sub view is active and on-screen since we started counting them." + } }, "minutes_on_screen_7_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen active application sub view over the last 7 days" + } }, "minutes_on_screen_30_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen active application sub view over the last 30 days" + } }, "minutes_on_screen_90_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen active application sub view over the last 90 days" + } } } } @@ -3136,68 +5716,128 @@ "securitySolution:administration": { "properties": { "appId": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "The application being tracked" + } }, "viewId": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "Always `main`" + } }, "clicks_total": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the application since we started counting them" + } }, "clicks_7_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the application over the last 7 days" + } }, "clicks_30_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the application over the last 30 days" + } }, "clicks_90_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the application over the last 90 days" + } }, "minutes_on_screen_total": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen since we started counting them." + } }, "minutes_on_screen_7_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen over the last 7 days" + } }, "minutes_on_screen_30_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen over the last 30 days" + } }, "minutes_on_screen_90_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen over the last 90 days" + } }, "views": { "type": "array", "items": { "properties": { "appId": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "The application being tracked" + } }, "viewId": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "The application view being tracked" + } }, "clicks_total": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the application sub view since we started counting them" + } }, "clicks_7_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the active application sub view over the last 7 days" + } }, "clicks_30_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the active application sub view over the last 30 days" + } }, "clicks_90_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the active application sub view over the last 90 days" + } }, "minutes_on_screen_total": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application sub view is active and on-screen since we started counting them." + } }, "minutes_on_screen_7_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen active application sub view over the last 7 days" + } }, "minutes_on_screen_30_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen active application sub view over the last 30 days" + } }, "minutes_on_screen_90_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen active application sub view over the last 90 days" + } } } } @@ -3207,68 +5847,128 @@ "siem": { "properties": { "appId": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "The application being tracked" + } }, "viewId": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "Always `main`" + } }, "clicks_total": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the application since we started counting them" + } }, "clicks_7_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the application over the last 7 days" + } }, "clicks_30_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the application over the last 30 days" + } }, "clicks_90_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the application over the last 90 days" + } }, "minutes_on_screen_total": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen since we started counting them." + } }, "minutes_on_screen_7_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen over the last 7 days" + } }, "minutes_on_screen_30_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen over the last 30 days" + } }, "minutes_on_screen_90_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen over the last 90 days" + } }, "views": { "type": "array", "items": { "properties": { "appId": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "The application being tracked" + } }, "viewId": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "The application view being tracked" + } }, "clicks_total": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the application sub view since we started counting them" + } }, "clicks_7_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the active application sub view over the last 7 days" + } }, "clicks_30_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the active application sub view over the last 30 days" + } }, "clicks_90_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the active application sub view over the last 90 days" + } }, "minutes_on_screen_total": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application sub view is active and on-screen since we started counting them." + } }, "minutes_on_screen_7_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen active application sub view over the last 7 days" + } }, "minutes_on_screen_30_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen active application sub view over the last 30 days" + } }, "minutes_on_screen_90_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen active application sub view over the last 90 days" + } } } } @@ -3278,68 +5978,128 @@ "space_selector": { "properties": { "appId": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "The application being tracked" + } }, "viewId": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "Always `main`" + } }, "clicks_total": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the application since we started counting them" + } }, "clicks_7_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the application over the last 7 days" + } }, "clicks_30_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the application over the last 30 days" + } }, "clicks_90_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the application over the last 90 days" + } }, "minutes_on_screen_total": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen since we started counting them." + } }, "minutes_on_screen_7_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen over the last 7 days" + } }, "minutes_on_screen_30_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen over the last 30 days" + } }, "minutes_on_screen_90_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen over the last 90 days" + } }, "views": { "type": "array", "items": { "properties": { "appId": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "The application being tracked" + } }, "viewId": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "The application view being tracked" + } }, "clicks_total": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the application sub view since we started counting them" + } }, "clicks_7_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the active application sub view over the last 7 days" + } }, "clicks_30_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the active application sub view over the last 30 days" + } }, "clicks_90_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the active application sub view over the last 90 days" + } }, "minutes_on_screen_total": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application sub view is active and on-screen since we started counting them." + } }, "minutes_on_screen_7_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen active application sub view over the last 7 days" + } }, "minutes_on_screen_30_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen active application sub view over the last 30 days" + } }, "minutes_on_screen_90_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen active application sub view over the last 90 days" + } } } } @@ -3349,68 +6109,128 @@ "uptime": { "properties": { "appId": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "The application being tracked" + } }, "viewId": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "Always `main`" + } }, "clicks_total": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the application since we started counting them" + } }, "clicks_7_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the application over the last 7 days" + } }, "clicks_30_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the application over the last 30 days" + } }, "clicks_90_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the application over the last 90 days" + } }, "minutes_on_screen_total": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen since we started counting them." + } }, "minutes_on_screen_7_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen over the last 7 days" + } }, "minutes_on_screen_30_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen over the last 30 days" + } }, "minutes_on_screen_90_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen over the last 90 days" + } }, "views": { "type": "array", "items": { "properties": { "appId": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "The application being tracked" + } }, "viewId": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "The application view being tracked" + } }, "clicks_total": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the application sub view since we started counting them" + } }, "clicks_7_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the active application sub view over the last 7 days" + } }, "clicks_30_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the active application sub view over the last 30 days" + } }, "clicks_90_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the active application sub view over the last 90 days" + } }, "minutes_on_screen_total": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application sub view is active and on-screen since we started counting them." + } }, "minutes_on_screen_7_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen active application sub view over the last 7 days" + } }, "minutes_on_screen_30_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen active application sub view over the last 30 days" + } }, "minutes_on_screen_90_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen active application sub view over the last 90 days" + } } } } @@ -3420,68 +6240,128 @@ "ux": { "properties": { "appId": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "The application being tracked" + } }, "viewId": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "Always `main`" + } }, "clicks_total": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the application since we started counting them" + } }, "clicks_7_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the application over the last 7 days" + } }, "clicks_30_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the application over the last 30 days" + } }, "clicks_90_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the application over the last 90 days" + } }, "minutes_on_screen_total": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen since we started counting them." + } }, "minutes_on_screen_7_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen over the last 7 days" + } }, "minutes_on_screen_30_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen over the last 30 days" + } }, "minutes_on_screen_90_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen over the last 90 days" + } }, "views": { "type": "array", "items": { "properties": { "appId": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "The application being tracked" + } }, "viewId": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "The application view being tracked" + } }, "clicks_total": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the application sub view since we started counting them" + } }, "clicks_7_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the active application sub view over the last 7 days" + } }, "clicks_30_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the active application sub view over the last 30 days" + } }, "clicks_90_days": { - "type": "long" + "type": "long", + "_meta": { + "description": "General number of clicks in the active application sub view over the last 90 days" + } }, "minutes_on_screen_total": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application sub view is active and on-screen since we started counting them." + } }, "minutes_on_screen_7_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen active application sub view over the last 7 days" + } }, "minutes_on_screen_30_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen active application sub view over the last 30 days" + } }, "minutes_on_screen_90_days": { - "type": "float" + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen active application sub view over the last 90 days" + } } } } @@ -3497,149 +6377,266 @@ "elasticsearch": { "properties": { "sniffOnStart": { - "type": "boolean" + "type": "boolean", + "_meta": { + "description": "Indicates if an attempt should be made to find other Elasticsearch nodes on startup." + } }, "sniffIntervalMs": { - "type": "long" + "type": "long", + "_meta": { + "description": "Time in milliseconds between requests to check Elasticsearch for an updated list of nodes." + } }, "sniffOnConnectionFault": { - "type": "boolean" + "type": "boolean", + "_meta": { + "description": "Indicates if the list of Elasticsearch nodes should be updated immediately following a connection fault." + } }, "numberOfHostsConfigured": { - "type": "long" + "type": "long", + "_meta": { + "description": "Number of Elasticsearch instances configured to use for queries." + } }, "requestHeadersWhitelistConfigured": { - "type": "boolean" + "type": "boolean", + "_meta": { + "description": "Indicates if Kibana client-side headers to send to Elasticsearch is different to the default value." + } }, "customHeadersConfigured": { - "type": "boolean" + "type": "boolean", + "_meta": { + "description": "Indicates if any custom headers have been configured." + } }, "shardTimeoutMs": { - "type": "long" + "type": "long", + "_meta": { + "description": "Time in milliseconds for Elasticsearch to wait for responses from shards." + } }, "requestTimeoutMs": { - "type": "long" + "type": "long", + "_meta": { + "description": "Time in milliseconds to wait for responses from the back end or Elasticsearch." + } }, "pingTimeoutMs": { - "type": "long" + "type": "long", + "_meta": { + "description": "Time in milliseconds to wait for Elasticsearch to respond to pings." + } }, "logQueries": { - "type": "boolean" + "type": "boolean", + "_meta": { + "description": "Indicates if queries sent to Elasticsearch should be logged." + } }, "ssl": { "properties": { "verificationMode": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "The verification of the server certificate that Kibana receives when making an outbound SSL or TLS connection to Elasticsearch" + } }, "certificateAuthoritiesConfigured": { - "type": "boolean" + "type": "boolean", + "_meta": { + "description": "Indicates if any PEM-encoded X.509 certificate authority certificates are configured." + } }, "certificateConfigured": { - "type": "boolean" + "type": "boolean", + "_meta": { + "description": "Indicates if a certificate authority is configured." + } }, "keyConfigured": { - "type": "boolean" + "type": "boolean", + "_meta": { + "description": "Indicates if a certificate key is configured." + } }, "keystoreConfigured": { - "type": "boolean" + "type": "boolean", + "_meta": { + "description": "Indicates if a keystore is configured." + } }, "truststoreConfigured": { - "type": "boolean" + "type": "boolean", + "_meta": { + "description": "Indicates if a path to a PKCS#12 trust store is configured." + } }, "alwaysPresentCertificate": { - "type": "boolean" + "type": "boolean", + "_meta": { + "description": "Indicates if a client certificate is presented when requested by Elasticsearch." + } } } }, "apiVersion": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "Version of the Elasticsearch API used." + } }, "healthCheckDelayMs": { - "type": "long" + "type": "long", + "_meta": { + "description": "The interval in miliseconds between health check requests Kibana sends to the Elasticsearch." + } } } }, "http": { "properties": { "basePathConfigured": { - "type": "boolean" + "type": "boolean", + "_meta": { + "description": "Indicates if a base path has been configured." + } }, "maxPayloadInBytes": { - "type": "long" + "type": "long", + "_meta": { + "description": "Maximum payload size in bytes that is allowed." + } }, "rewriteBasePath": { - "type": "boolean" + "type": "boolean", + "_meta": { + "description": "Indicates if the base path should be rewritten." + } }, "keepaliveTimeout": { - "type": "long" + "type": "long", + "_meta": { + "description": "How long to keep sockets alive globally in milliseconds." + } }, "socketTimeout": { - "type": "long" + "type": "long", + "_meta": { + "description": "How long to wait before closing inactive sockets in milliseconds." + } }, "compression": { "properties": { "enabled": { - "type": "boolean" + "type": "boolean", + "_meta": { + "description": "Indicates if HTTP response compression is enabled." + } }, "referrerWhitelistConfigured": { - "type": "boolean" + "type": "boolean", + "_meta": { + "description": "Indicates if any responses should be compressed." + } } } }, "xsrf": { "properties": { "disableProtection": { - "type": "boolean" + "type": "boolean", + "_meta": { + "description": "Indicates if protection against xsrf should be disabled." + } }, "allowlistConfigured": { - "type": "boolean" + "type": "boolean", + "_meta": { + "description": "Indicates if any http headers have been whitelisted." + } } } }, "requestId": { "properties": { "allowFromAnyIp": { - "type": "boolean" + "type": "boolean", + "_meta": { + "description": "Indicates if any http headers have been whitelisted." + } }, "ipAllowlistConfigured": { - "type": "boolean" + "type": "boolean", + "_meta": { + "description": "Indicates if a list of specific IPs has been configured." + } } } }, "ssl": { "properties": { "certificateAuthoritiesConfigured": { - "type": "boolean" + "type": "boolean", + "_meta": { + "description": "Indicates if ssl certificate authorities have been configured." + } }, "certificateConfigured": { - "type": "boolean" + "type": "boolean", + "_meta": { + "description": "Indicates if an ssl certificate is configured." + } }, "cipherSuites": { "type": "array", "items": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "The keyword of the cipher suite used." + } } }, "keyConfigured": { - "type": "boolean" + "type": "boolean", + "_meta": { + "description": "Indicates if an ssl key has been configured." + } }, "keystoreConfigured": { - "type": "boolean" + "type": "boolean", + "_meta": { + "description": "Indicates if an ssl keystore has been configured." + } }, "truststoreConfigured": { - "type": "boolean" + "type": "boolean", + "_meta": { + "description": "Indicates if a path to a PKCS#12 trust store is configured." + } }, "redirectHttpFromPortConfigured": { - "type": "boolean" + "type": "boolean", + "_meta": { + "description": "Indicates if a port to redirect all http requests has been configured." + } }, "supportedProtocols": { "type": "array", "items": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "The version of a supported protocol used." + } } }, "clientAuthentication": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "The behavior in Kibana for requesting a certificate from client connections." + } } } } @@ -3650,24 +6647,39 @@ "appendersTypesUsed": { "type": "array", "items": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "The type of logging appender confgured." + } } }, "loggersConfiguredCount": { - "type": "long" + "type": "long", + "_meta": { + "description": "The total number of logging appenders configured." + } } } }, "savedObjects": { "properties": { "customIndex": { - "type": "boolean" + "type": "boolean", + "_meta": { + "description": "Indicates if the saved objects index is different to the standard internal .kibana index." + } }, "maxImportPayloadBytes": { - "type": "long" + "type": "long", + "_meta": { + "description": "Maximum size of the payload in bytes of saved objects that can be imported." + } }, "maxImportExportSizeBytes": { - "type": "long" + "type": "long", + "_meta": { + "description": "Maximum size in bytes of saved object that can be imported or exported." + } } } } @@ -3678,13 +6690,22 @@ "memory": { "properties": { "heapSizeLimit": { - "type": "long" + "type": "long", + "_meta": { + "description": "Host memory heap size limit." + } }, "heapTotalBytes": { - "type": "long" + "type": "long", + "_meta": { + "description": "Total memory heap size of host that is available in bytes." + } }, "heapUsedBytes": { - "type": "long" + "type": "long", + "_meta": { + "description": "Total memory heap size of host that is used in bytes." + } } } } @@ -3699,19 +6720,34 @@ "items": { "properties": { "docsCount": { - "type": "long" + "type": "long", + "_meta": { + "description": "The number of documents in the index, including hidden nested documents." + } }, "docsDeleted": { - "type": "long" + "type": "long", + "_meta": { + "description": "The number of deleted documents in the index, including hidden nested documents." + } }, "alias": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "The alias used to map customized saved object index names to standard index names (.kibana or .kibana_task_manager)." + } }, "primaryStoreSizeBytes": { - "type": "long" + "type": "long", + "_meta": { + "description": "The size in bytes of the index, for primaries only." + } }, "storeSizeBytes": { - "type": "long" + "type": "long", + "_meta": { + "description": "The size in bytes of the index, for primaries and replicas." + } } } } @@ -3721,340 +6757,646 @@ } }, "apiCalls.savedObjectsBulkCreate.total": { - "type": "long" + "type": "long", + "_meta": { + "description": "How many times this API has been called." + } }, "apiCalls.savedObjectsBulkCreate.namespace.default.total": { - "type": "long" + "type": "long", + "_meta": { + "description": "How many times this API has been called in the Default space." + } }, "apiCalls.savedObjectsBulkCreate.namespace.default.kibanaRequest.yes": { - "type": "long" + "type": "long", + "_meta": { + "description": "How many times this API has been called by the Kibana client in the Default space." + } }, "apiCalls.savedObjectsBulkCreate.namespace.default.kibanaRequest.no": { - "type": "long" + "type": "long", + "_meta": { + "description": "How many times this API has been called by a non-Kibana client in the Default space." + } }, "apiCalls.savedObjectsBulkCreate.namespace.custom.total": { - "type": "long" + "type": "long", + "_meta": { + "description": "How many times this API has been called in a custom space." + } }, "apiCalls.savedObjectsBulkCreate.namespace.custom.kibanaRequest.yes": { - "type": "long" + "type": "long", + "_meta": { + "description": "How many times this API has been called by the Kibana client in a custom space." + } }, "apiCalls.savedObjectsBulkCreate.namespace.custom.kibanaRequest.no": { - "type": "long" + "type": "long", + "_meta": { + "description": "How many times this API has been called by a non-Kibana client in a custom space." + } }, "apiCalls.savedObjectsBulkGet.total": { - "type": "long" + "type": "long", + "_meta": { + "description": "How many times this API has been called." + } }, "apiCalls.savedObjectsBulkGet.namespace.default.total": { - "type": "long" + "type": "long", + "_meta": { + "description": "How many times this API has been called in the Default space." + } }, "apiCalls.savedObjectsBulkGet.namespace.default.kibanaRequest.yes": { - "type": "long" + "type": "long", + "_meta": { + "description": "How many times this API has been called by the Kibana client in the Default space." + } }, "apiCalls.savedObjectsBulkGet.namespace.default.kibanaRequest.no": { - "type": "long" + "type": "long", + "_meta": { + "description": "How many times this API has been called by a non-Kibana client in the Default space." + } }, "apiCalls.savedObjectsBulkGet.namespace.custom.total": { - "type": "long" + "type": "long", + "_meta": { + "description": "How many times this API has been called in a custom space." + } }, "apiCalls.savedObjectsBulkGet.namespace.custom.kibanaRequest.yes": { - "type": "long" + "type": "long", + "_meta": { + "description": "How many times this API has been called by the Kibana client in a custom space." + } }, "apiCalls.savedObjectsBulkGet.namespace.custom.kibanaRequest.no": { - "type": "long" + "type": "long", + "_meta": { + "description": "How many times this API has been called by a non-Kibana client in a custom space." + } }, "apiCalls.savedObjectsBulkUpdate.total": { - "type": "long" + "type": "long", + "_meta": { + "description": "How many times this API has been called." + } }, "apiCalls.savedObjectsBulkUpdate.namespace.default.total": { - "type": "long" + "type": "long", + "_meta": { + "description": "How many times this API has been called in the Default space." + } }, "apiCalls.savedObjectsBulkUpdate.namespace.default.kibanaRequest.yes": { - "type": "long" + "type": "long", + "_meta": { + "description": "How many times this API has been called by the Kibana client in the Default space." + } }, "apiCalls.savedObjectsBulkUpdate.namespace.default.kibanaRequest.no": { - "type": "long" + "type": "long", + "_meta": { + "description": "How many times this API has been called by a non-Kibana client in the Default space." + } }, "apiCalls.savedObjectsBulkUpdate.namespace.custom.total": { - "type": "long" + "type": "long", + "_meta": { + "description": "How many times this API has been called in a custom space." + } }, "apiCalls.savedObjectsBulkUpdate.namespace.custom.kibanaRequest.yes": { - "type": "long" + "type": "long", + "_meta": { + "description": "How many times this API has been called by the Kibana client in a custom space." + } }, "apiCalls.savedObjectsBulkUpdate.namespace.custom.kibanaRequest.no": { - "type": "long" + "type": "long", + "_meta": { + "description": "How many times this API has been called by a non-Kibana client in a custom space." + } }, "apiCalls.savedObjectsCreate.total": { - "type": "long" + "type": "long", + "_meta": { + "description": "How many times this API has been called." + } }, "apiCalls.savedObjectsCreate.namespace.default.total": { - "type": "long" + "type": "long", + "_meta": { + "description": "How many times this API has been called in the Default space." + } }, "apiCalls.savedObjectsCreate.namespace.default.kibanaRequest.yes": { - "type": "long" + "type": "long", + "_meta": { + "description": "How many times this API has been called by the Kibana client in the Default space." + } }, "apiCalls.savedObjectsCreate.namespace.default.kibanaRequest.no": { - "type": "long" + "type": "long", + "_meta": { + "description": "How many times this API has been called by a non-Kibana client in the Default space." + } }, "apiCalls.savedObjectsCreate.namespace.custom.total": { - "type": "long" + "type": "long", + "_meta": { + "description": "How many times this API has been called in a custom space." + } }, "apiCalls.savedObjectsCreate.namespace.custom.kibanaRequest.yes": { - "type": "long" + "type": "long", + "_meta": { + "description": "How many times this API has been called by the Kibana client in a custom space." + } }, "apiCalls.savedObjectsCreate.namespace.custom.kibanaRequest.no": { - "type": "long" + "type": "long", + "_meta": { + "description": "How many times this API has been called by a non-Kibana client in a custom space." + } }, "apiCalls.savedObjectsDelete.total": { - "type": "long" + "type": "long", + "_meta": { + "description": "How many times this API has been called." + } }, "apiCalls.savedObjectsDelete.namespace.default.total": { - "type": "long" + "type": "long", + "_meta": { + "description": "How many times this API has been called in the Default space." + } }, "apiCalls.savedObjectsDelete.namespace.default.kibanaRequest.yes": { - "type": "long" + "type": "long", + "_meta": { + "description": "How many times this API has been called by the Kibana client in the Default space." + } }, "apiCalls.savedObjectsDelete.namespace.default.kibanaRequest.no": { - "type": "long" + "type": "long", + "_meta": { + "description": "How many times this API has been called by a non-Kibana client in the Default space." + } }, "apiCalls.savedObjectsDelete.namespace.custom.total": { - "type": "long" + "type": "long", + "_meta": { + "description": "How many times this API has been called in a custom space." + } }, "apiCalls.savedObjectsDelete.namespace.custom.kibanaRequest.yes": { - "type": "long" + "type": "long", + "_meta": { + "description": "How many times this API has been called by the Kibana client in a custom space." + } }, "apiCalls.savedObjectsDelete.namespace.custom.kibanaRequest.no": { - "type": "long" + "type": "long", + "_meta": { + "description": "How many times this API has been called by a non-Kibana client in a custom space." + } }, "apiCalls.savedObjectsFind.total": { - "type": "long" + "type": "long", + "_meta": { + "description": "How many times this API has been called." + } }, "apiCalls.savedObjectsFind.namespace.default.total": { - "type": "long" + "type": "long", + "_meta": { + "description": "How many times this API has been called in the Default space." + } }, "apiCalls.savedObjectsFind.namespace.default.kibanaRequest.yes": { - "type": "long" + "type": "long", + "_meta": { + "description": "How many times this API has been called by the Kibana client in the Default space." + } }, "apiCalls.savedObjectsFind.namespace.default.kibanaRequest.no": { - "type": "long" + "type": "long", + "_meta": { + "description": "How many times this API has been called by a non-Kibana client in the Default space." + } }, "apiCalls.savedObjectsFind.namespace.custom.total": { - "type": "long" + "type": "long", + "_meta": { + "description": "How many times this API has been called in a custom space." + } }, "apiCalls.savedObjectsFind.namespace.custom.kibanaRequest.yes": { - "type": "long" + "type": "long", + "_meta": { + "description": "How many times this API has been called by the Kibana client in a custom space." + } }, "apiCalls.savedObjectsFind.namespace.custom.kibanaRequest.no": { - "type": "long" + "type": "long", + "_meta": { + "description": "How many times this API has been called by a non-Kibana client in a custom space." + } }, "apiCalls.savedObjectsGet.total": { - "type": "long" + "type": "long", + "_meta": { + "description": "How many times this API has been called." + } }, "apiCalls.savedObjectsGet.namespace.default.total": { - "type": "long" + "type": "long", + "_meta": { + "description": "How many times this API has been called in the Default space." + } }, "apiCalls.savedObjectsGet.namespace.default.kibanaRequest.yes": { - "type": "long" + "type": "long", + "_meta": { + "description": "How many times this API has been called by the Kibana client in the Default space." + } }, "apiCalls.savedObjectsGet.namespace.default.kibanaRequest.no": { - "type": "long" + "type": "long", + "_meta": { + "description": "How many times this API has been called by a non-Kibana client in the Default space." + } }, "apiCalls.savedObjectsGet.namespace.custom.total": { - "type": "long" + "type": "long", + "_meta": { + "description": "How many times this API has been called in a custom space." + } }, "apiCalls.savedObjectsGet.namespace.custom.kibanaRequest.yes": { - "type": "long" + "type": "long", + "_meta": { + "description": "How many times this API has been called by the Kibana client in a custom space." + } }, "apiCalls.savedObjectsGet.namespace.custom.kibanaRequest.no": { - "type": "long" + "type": "long", + "_meta": { + "description": "How many times this API has been called by a non-Kibana client in a custom space." + } }, "apiCalls.savedObjectsResolve.total": { - "type": "long" + "type": "long", + "_meta": { + "description": "How many times this API has been called." + } }, "apiCalls.savedObjectsResolve.namespace.default.total": { - "type": "long" + "type": "long", + "_meta": { + "description": "How many times this API has been called in the Default space." + } }, "apiCalls.savedObjectsResolve.namespace.default.kibanaRequest.yes": { - "type": "long" + "type": "long", + "_meta": { + "description": "How many times this API has been called by the Kibana client in the Default space." + } }, "apiCalls.savedObjectsResolve.namespace.default.kibanaRequest.no": { - "type": "long" + "type": "long", + "_meta": { + "description": "How many times this API has been called by a non-Kibana client in the Default space." + } }, "apiCalls.savedObjectsResolve.namespace.custom.total": { - "type": "long" + "type": "long", + "_meta": { + "description": "How many times this API has been called in a custom space." + } }, "apiCalls.savedObjectsResolve.namespace.custom.kibanaRequest.yes": { - "type": "long" + "type": "long", + "_meta": { + "description": "How many times this API has been called by the Kibana client in a custom space." + } }, "apiCalls.savedObjectsResolve.namespace.custom.kibanaRequest.no": { - "type": "long" + "type": "long", + "_meta": { + "description": "How many times this API has been called by a non-Kibana client in a custom space." + } }, "apiCalls.savedObjectsUpdate.total": { - "type": "long" + "type": "long", + "_meta": { + "description": "How many times this API has been called." + } }, "apiCalls.savedObjectsUpdate.namespace.default.total": { - "type": "long" + "type": "long", + "_meta": { + "description": "How many times this API has been called in the Default space." + } }, "apiCalls.savedObjectsUpdate.namespace.default.kibanaRequest.yes": { - "type": "long" + "type": "long", + "_meta": { + "description": "How many times this API has been called by the Kibana client in the Default space." + } }, "apiCalls.savedObjectsUpdate.namespace.default.kibanaRequest.no": { - "type": "long" + "type": "long", + "_meta": { + "description": "How many times this API has been called by a non-Kibana client in the Default space." + } }, "apiCalls.savedObjectsUpdate.namespace.custom.total": { - "type": "long" + "type": "long", + "_meta": { + "description": "How many times this API has been called in a custom space." + } }, "apiCalls.savedObjectsUpdate.namespace.custom.kibanaRequest.yes": { - "type": "long" + "type": "long", + "_meta": { + "description": "How many times this API has been called by the Kibana client in a custom space." + } }, "apiCalls.savedObjectsUpdate.namespace.custom.kibanaRequest.no": { - "type": "long" + "type": "long", + "_meta": { + "description": "How many times this API has been called by a non-Kibana client in a custom space." + } }, "apiCalls.savedObjectsImport.total": { - "type": "long" + "type": "long", + "_meta": { + "description": "How many times this API has been called." + } }, "apiCalls.savedObjectsImport.namespace.default.total": { - "type": "long" + "type": "long", + "_meta": { + "description": "How many times this API has been called in the Default space." + } }, "apiCalls.savedObjectsImport.namespace.default.kibanaRequest.yes": { - "type": "long" + "type": "long", + "_meta": { + "description": "How many times this API has been called by the Kibana client in the Default space." + } }, "apiCalls.savedObjectsImport.namespace.default.kibanaRequest.no": { - "type": "long" + "type": "long", + "_meta": { + "description": "How many times this API has been called by a non-Kibana client in the Default space." + } }, "apiCalls.savedObjectsImport.namespace.custom.total": { - "type": "long" + "type": "long", + "_meta": { + "description": "How many times this API has been called in a custom space." + } }, "apiCalls.savedObjectsImport.namespace.custom.kibanaRequest.yes": { - "type": "long" + "type": "long", + "_meta": { + "description": "How many times this API has been called by the Kibana client in a custom space." + } }, "apiCalls.savedObjectsImport.namespace.custom.kibanaRequest.no": { - "type": "long" + "type": "long", + "_meta": { + "description": "How many times this API has been called by a non-Kibana client in a custom space." + } }, "apiCalls.savedObjectsImport.createNewCopiesEnabled.yes": { - "type": "long" + "type": "long", + "_meta": { + "description": "How many times this API has been called with the `createNewCopiesEnabled` option." + } }, "apiCalls.savedObjectsImport.createNewCopiesEnabled.no": { - "type": "long" + "type": "long", + "_meta": { + "description": "How many times this API has been called without the `createNewCopiesEnabled` option." + } }, "apiCalls.savedObjectsImport.overwriteEnabled.yes": { - "type": "long" + "type": "long", + "_meta": { + "description": "How many times this API has been called with the `overwrite` option." + } }, "apiCalls.savedObjectsImport.overwriteEnabled.no": { - "type": "long" + "type": "long", + "_meta": { + "description": "How many times this API has been called without the `overwrite` option." + } }, "apiCalls.savedObjectsResolveImportErrors.total": { - "type": "long" + "type": "long", + "_meta": { + "description": "How many times this API has been called." + } }, "apiCalls.savedObjectsResolveImportErrors.namespace.default.total": { - "type": "long" + "type": "long", + "_meta": { + "description": "How many times this API has been called in the Default space." + } }, "apiCalls.savedObjectsResolveImportErrors.namespace.default.kibanaRequest.yes": { - "type": "long" + "type": "long", + "_meta": { + "description": "How many times this API has been called by the Kibana client in the Default space." + } }, "apiCalls.savedObjectsResolveImportErrors.namespace.default.kibanaRequest.no": { - "type": "long" + "type": "long", + "_meta": { + "description": "How many times this API has been called by a non-Kibana client in the Default space." + } }, "apiCalls.savedObjectsResolveImportErrors.namespace.custom.total": { - "type": "long" + "type": "long", + "_meta": { + "description": "How many times this API has been called in a custom space." + } }, "apiCalls.savedObjectsResolveImportErrors.namespace.custom.kibanaRequest.yes": { - "type": "long" + "type": "long", + "_meta": { + "description": "How many times this API has been called by the Kibana client in a custom space." + } }, "apiCalls.savedObjectsResolveImportErrors.namespace.custom.kibanaRequest.no": { - "type": "long" + "type": "long", + "_meta": { + "description": "How many times this API has been called by a non-Kibana client in a custom space." + } }, "apiCalls.savedObjectsResolveImportErrors.createNewCopiesEnabled.yes": { - "type": "long" + "type": "long", + "_meta": { + "description": "How many times this API has been called with the `createNewCopiesEnabled` option." + } }, "apiCalls.savedObjectsResolveImportErrors.createNewCopiesEnabled.no": { - "type": "long" + "type": "long", + "_meta": { + "description": "How many times this API has been called without the `createNewCopiesEnabled` option." + } }, "apiCalls.savedObjectsExport.total": { - "type": "long" + "type": "long", + "_meta": { + "description": "How many times this API has been called." + } }, "apiCalls.savedObjectsExport.namespace.default.total": { - "type": "long" + "type": "long", + "_meta": { + "description": "How many times this API has been called in the Default space." + } }, "apiCalls.savedObjectsExport.namespace.default.kibanaRequest.yes": { - "type": "long" + "type": "long", + "_meta": { + "description": "How many times this API has been called by the Kibana client in the Default space." + } }, "apiCalls.savedObjectsExport.namespace.default.kibanaRequest.no": { - "type": "long" + "type": "long", + "_meta": { + "description": "How many times this API has been called by a non-Kibana client in the Default space." + } }, "apiCalls.savedObjectsExport.namespace.custom.total": { - "type": "long" + "type": "long", + "_meta": { + "description": "How many times this API has been called in a custom space." + } }, "apiCalls.savedObjectsExport.namespace.custom.kibanaRequest.yes": { - "type": "long" + "type": "long", + "_meta": { + "description": "How many times this API has been called by the Kibana client in a custom space." + } }, "apiCalls.savedObjectsExport.namespace.custom.kibanaRequest.no": { - "type": "long" + "type": "long", + "_meta": { + "description": "How many times this API has been called by a non-Kibana client in a custom space." + } }, "apiCalls.savedObjectsExport.allTypesSelected.yes": { - "type": "long" + "type": "long", + "_meta": { + "description": "How many times this API has been called with the `createNewCopiesEnabled` option." + } }, "apiCalls.savedObjectsExport.allTypesSelected.no": { - "type": "long" + "type": "long", + "_meta": { + "description": "How many times this API has been called without all types selected." + } } } }, "csp": { "properties": { "strict": { - "type": "boolean" + "type": "boolean", + "_meta": { + "description": "Indicates if strict mode should be used." + } }, "warnLegacyBrowsers": { - "type": "boolean" + "type": "boolean", + "_meta": { + "description": "Indicates if legacy browser versions should be warned." + } }, "rulesChangedFromDefault": { - "type": "boolean" + "type": "boolean", + "_meta": { + "description": "Indicates if the rules have been changed from the default." + } } } }, "kibana": { "properties": { "index": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "The index storing the saved objects" + } }, "dashboard": { "properties": { "total": { - "type": "long" + "type": "long", + "_meta": { + "description": "Total number of dashboard saved objects" + } } } }, "visualization": { "properties": { "total": { - "type": "long" + "type": "long", + "_meta": { + "description": "Total number of visualization saved objects" + } } } }, "search": { "properties": { "total": { - "type": "long" + "type": "long", + "_meta": { + "description": "Total number of search saved objects" + } } } }, "index_pattern": { "properties": { "total": { - "type": "long" + "type": "long", + "_meta": { + "description": "Total number of index_pattern saved objects" + } } } }, "graph_workspace": { "properties": { "total": { - "type": "long" + "type": "long", + "_meta": { + "description": "Total number of graph_workspace saved objects" + } } } }, "timelion_sheet": { "properties": { "total": { - "type": "long" + "type": "long", + "_meta": { + "description": "Total number of timelion_sheet saved objects" + } } } } @@ -4063,327 +7405,633 @@ "localization": { "properties": { "locale": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "The default locale set on the Kibana system" + } }, "integrities": { "properties": { "DYNAMIC_KEY": { - "type": "text" + "type": "text", + "_meta": { + "description": "Translation file hash. If the hash is different it indicates that a custom translation file is used" + } } } }, "labelsCount": { - "type": "long" + "type": "long", + "_meta": { + "description": "The number of translated labels" + } } } }, "stack_management": { "properties": { "timelion:quandl.key": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "Default value of the setting was changed." + } }, "securitySolution:defaultIndex": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "Default value of the setting was changed." + } }, "securitySolution:newsFeedUrl": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "Default value of the setting was changed." + } }, "xpackReporting:customPdfLogo": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "Default value of the setting was changed." + } }, "notifications:banner": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "Default value of the setting was changed." + } }, "timelion:graphite.url": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "Default value of the setting changed." + } }, "xpackDashboardMode:roles": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "Default value of the setting was changed." + } }, "securitySolution:ipReputationLinks": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "Default value of the setting was changed." + } }, "visualize:enableLabs": { - "type": "boolean" + "type": "boolean", + "_meta": { + "description": "Non-default value of setting." + } }, "visualization:heatmap:maxBuckets": { - "type": "long" + "type": "long", + "_meta": { + "description": "Non-default value of setting." + } }, "visualization:colorMapping": { - "type": "text" + "type": "text", + "_meta": { + "description": "Non-default value of setting." + } }, "visualization:regionmap:showWarnings": { - "type": "boolean" + "type": "boolean", + "_meta": { + "description": "Non-default value of setting." + } }, "visualization:dimmingOpacity": { - "type": "float" + "type": "float", + "_meta": { + "description": "Non-default value of setting." + } }, "visualization:tileMap:maxPrecision": { - "type": "long" + "type": "long", + "_meta": { + "description": "Non-default value of setting." + } }, "csv:separator": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "Non-default value of setting." + } }, "visualization:tileMap:WMSdefaults": { - "type": "text" + "type": "text", + "_meta": { + "description": "Non-default value of setting." + } }, "timelion:target_buckets": { - "type": "long" + "type": "long", + "_meta": { + "description": "Non-default value of setting." + } }, "timelion:max_buckets": { - "type": "long" + "type": "long", + "_meta": { + "description": "Non-default value of setting." + } }, "timelion:es.timefield": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "Non-default value of setting." + } }, "timelion:min_interval": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "Non-default value of setting." + } }, "timelion:default_rows": { - "type": "long" + "type": "long", + "_meta": { + "description": "Non-default value of setting." + } }, "timelion:default_columns": { - "type": "long" + "type": "long", + "_meta": { + "description": "Non-default value of setting." + } }, "timelion:es.default_index": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "Non-default value of setting." + } }, "timelion:showTutorial": { - "type": "boolean" + "type": "boolean", + "_meta": { + "description": "Non-default value of setting." + } }, "securitySolution:timeDefaults": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "Non-default value of setting." + } }, "securitySolution:defaultAnomalyScore": { - "type": "long" + "type": "long", + "_meta": { + "description": "Non-default value of setting." + } }, "securitySolution:refreshIntervalDefaults": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "Non-default value of setting." + } }, "securitySolution:enableNewsFeed": { - "type": "boolean" + "type": "boolean", + "_meta": { + "description": "Non-default value of setting." + } }, "search:includeFrozen": { - "type": "boolean" + "type": "boolean", + "_meta": { + "description": "Non-default value of setting." + } }, "courier:maxConcurrentShardRequests": { - "type": "long" + "type": "long", + "_meta": { + "description": "Non-default value of setting." + } }, "courier:batchSearches": { - "type": "boolean" + "type": "boolean", + "_meta": { + "description": "Non-default value of setting." + } }, "courier:setRequestPreference": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "Non-default value of setting." + } }, "courier:customRequestPreference": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "Non-default value of setting." + } }, "courier:ignoreFilterIfFieldNotInIndex": { - "type": "boolean" + "type": "boolean", + "_meta": { + "description": "Non-default value of setting." + } }, "rollups:enableIndexPatterns": { - "type": "boolean" + "type": "boolean", + "_meta": { + "description": "Non-default value of setting." + } }, "notifications:lifetime:warning": { - "type": "long" + "type": "long", + "_meta": { + "description": "Non-default value of setting." + } }, "notifications:lifetime:banner": { - "type": "long" + "type": "long", + "_meta": { + "description": "Non-default value of setting." + } }, "notifications:lifetime:info": { - "type": "long" + "type": "long", + "_meta": { + "description": "Non-default value of setting." + } }, "notifications:lifetime:error": { - "type": "long" + "type": "long", + "_meta": { + "description": "Non-default value of setting." + } }, "doc_table:highlight": { - "type": "boolean" + "type": "boolean", + "_meta": { + "description": "Non-default value of setting." + } }, "discover:searchOnPageLoad": { - "type": "boolean" + "type": "boolean", + "_meta": { + "description": "Non-default value of setting." + } }, "doc_table:hideTimeColumn": { - "type": "boolean" + "type": "boolean", + "_meta": { + "description": "Non-default value of setting." + } }, "discover:sampleSize": { - "type": "long" + "type": "long", + "_meta": { + "description": "Non-default value of setting." + } }, "defaultColumns": { "type": "array", "items": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "Non-default value of setting." + } } }, "context:defaultSize": { - "type": "long" + "type": "long", + "_meta": { + "description": "Non-default value of setting." + } }, "discover:aggs:terms:size": { - "type": "long" + "type": "long", + "_meta": { + "description": "Non-default value of setting." + } }, "context:tieBreakerFields": { "type": "array", "items": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "Non-default value of setting." + } } }, "discover:sort:defaultOrder": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "Non-default value of setting." + } }, "context:step": { - "type": "long" + "type": "long", + "_meta": { + "description": "Non-default value of setting." + } }, "accessibility:disableAnimations": { - "type": "boolean" + "type": "boolean", + "_meta": { + "description": "Non-default value of setting." + } }, - "ml:fileDataVisualizerMaxFileSize": { - "type": "keyword" + "fileUpload:maxFileSize": { + "type": "keyword", + "_meta": { + "description": "Non-default value of setting." + } }, "ml:anomalyDetection:results:enableTimeDefaults": { - "type": "boolean" + "type": "boolean", + "_meta": { + "description": "Non-default value of setting." + } }, "ml:anomalyDetection:results:timeDefaults": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "Non-default value of setting." + } }, "truncate:maxHeight": { - "type": "long" + "type": "long", + "_meta": { + "description": "Non-default value of setting." + } }, "timepicker:timeDefaults": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "Non-default value of setting." + } }, "timepicker:refreshIntervalDefaults": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "Non-default value of setting." + } }, "timepicker:quickRanges": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "Non-default value of setting." + } }, "theme:version": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "Non-default value of setting." + } }, "theme:darkMode": { - "type": "boolean" + "type": "boolean", + "_meta": { + "description": "Non-default value of setting." + } }, "state:storeInSessionStorage": { - "type": "boolean" + "type": "boolean", + "_meta": { + "description": "Non-default value of setting." + } }, "savedObjects:perPage": { - "type": "long" + "type": "long", + "_meta": { + "description": "Non-default value of setting." + } }, "search:queryLanguage": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "Non-default value of setting." + } }, "shortDots:enable": { - "type": "boolean" + "type": "boolean", + "_meta": { + "description": "Non-default value of setting." + } }, "sort:options": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "Non-default value of setting." + } }, "savedObjects:listingLimit": { - "type": "long" + "type": "long", + "_meta": { + "description": "Non-default value of setting." + } }, "query:queryString:options": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "Non-default value of setting." + } }, "metrics:max_buckets": { - "type": "long" + "type": "long", + "_meta": { + "description": "Non-default value of setting." + } }, "query:allowLeadingWildcards": { - "type": "boolean" + "type": "boolean", + "_meta": { + "description": "Non-default value of setting." + } }, "metaFields": { "type": "array", "items": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "Non-default value of setting." + } } }, "indexPattern:placeholder": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "Non-default value of setting." + } }, "histogram:barTarget": { - "type": "long" + "type": "long", + "_meta": { + "description": "Non-default value of setting." + } }, "histogram:maxBars": { - "type": "long" + "type": "long", + "_meta": { + "description": "Non-default value of setting." + } }, "format:number:defaultLocale": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "Non-default value of setting." + } }, "format:percent:defaultPattern": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "Non-default value of setting." + } }, "format:number:defaultPattern": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "Non-default value of setting." + } }, "history:limit": { - "type": "long" + "type": "long", + "_meta": { + "description": "Non-default value of setting." + } }, "format:defaultTypeMap": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "Non-default value of setting." + } }, "format:currency:defaultPattern": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "Non-default value of setting." + } }, "defaultIndex": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "Non-default value of setting." + } }, "format:bytes:defaultPattern": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "Non-default value of setting." + } }, "filters:pinnedByDefault": { - "type": "boolean" + "type": "boolean", + "_meta": { + "description": "Non-default value of setting." + } }, "filterEditor:suggestValues": { - "type": "boolean" + "type": "boolean", + "_meta": { + "description": "Non-default value of setting." + } }, "fields:popularLimit": { - "type": "long" + "type": "long", + "_meta": { + "description": "Non-default value of setting." + } }, "dateNanosFormat": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "Non-default value of setting." + } }, "defaultRoute": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "Non-default value of setting." + } }, "dateFormat:tz": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "Non-default value of setting." + } }, "dateFormat:scaled": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "Non-default value of setting." + } }, "csv:quoteValues": { - "type": "boolean" + "type": "boolean", + "_meta": { + "description": "Non-default value of setting." + } }, "dateFormat:dow": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "Non-default value of setting." + } }, "dateFormat": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "Non-default value of setting." + } }, "autocomplete:useTimeRange": { - "type": "boolean" + "type": "boolean", + "_meta": { + "description": "Non-default value of setting." + } }, "search:timeout": { - "type": "long" + "type": "long", + "_meta": { + "description": "Non-default value of setting." + } }, "visualization:visualize:legacyChartsLibrary": { - "type": "boolean" + "type": "boolean", + "_meta": { + "description": "Non-default value of setting." + } }, "doc_table:legacy": { - "type": "boolean" + "type": "boolean", + "_meta": { + "description": "Non-default value of setting." + } }, "discover:modifyColumnsOnSwitch": { - "type": "boolean" + "type": "boolean", + "_meta": { + "description": "Non-default value of setting." + } }, "discover:searchFieldsFromSource": { - "type": "boolean" + "type": "boolean", + "_meta": { + "description": "Non-default value of setting." + } }, "securitySolution:rulesTableRefresh": { - "type": "text" + "type": "text", + "_meta": { + "description": "Non-default value of setting." + } }, "apm:enableSignificantTerms": { - "type": "boolean" + "type": "boolean", + "_meta": { + "description": "Non-default value of setting." + } }, "apm:enableServiceOverview": { - "type": "boolean" + "type": "boolean", + "_meta": { + "description": "Non-default value of setting." + } } } }, @@ -4394,22 +8042,40 @@ "items": { "properties": { "appName": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "Name of the app reporting ui counts." + } }, "eventName": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "Name of the event that happened." + } }, "lastUpdatedAt": { - "type": "date" + "type": "date", + "_meta": { + "description": "Time at which the metric was last updated." + } }, "fromTimestamp": { - "type": "date" + "type": "date", + "_meta": { + "description": "Time at which the metric was captured." + } }, "counterType": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "The type of counter used." + } }, "total": { - "type": "integer" + "type": "integer", + "_meta": { + "description": "The total number of times the event happened." + } } } } @@ -4423,10 +8089,16 @@ "items": { "properties": { "key": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "The event that is tracked" + } }, "value": { - "type": "long" + "type": "long", + "_meta": { + "description": "The value of the event" + } } } } @@ -4436,10 +8108,16 @@ "items": { "properties": { "key": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "The event that is tracked" + } }, "value": { - "type": "long" + "type": "long", + "_meta": { + "description": "The value of the event" + } } } } @@ -4449,10 +8127,16 @@ "items": { "properties": { "key": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "The event that is tracked" + } }, "value": { - "type": "long" + "type": "long", + "_meta": { + "description": "The value of the event" + } } } } @@ -4462,10 +8146,16 @@ "items": { "properties": { "key": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "The event that is tracked" + } }, "value": { - "type": "long" + "type": "long", + "_meta": { + "description": "The value of the event" + } } } } @@ -4475,10 +8165,16 @@ "items": { "properties": { "key": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "The event that is tracked" + } }, "value": { - "type": "long" + "type": "long", + "_meta": { + "description": "The value of the event" + } } } } @@ -4488,10 +8184,16 @@ "items": { "properties": { "key": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "The event that is tracked" + } }, "value": { - "type": "long" + "type": "long", + "_meta": { + "description": "The value of the event" + } } } } @@ -4501,10 +8203,16 @@ "items": { "properties": { "key": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "The event that is tracked" + } }, "value": { - "type": "long" + "type": "long", + "_meta": { + "description": "The value of the event" + } } } } @@ -4514,10 +8222,16 @@ "items": { "properties": { "key": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "The event that is tracked" + } }, "value": { - "type": "long" + "type": "long", + "_meta": { + "description": "The value of the event" + } } } } @@ -4527,10 +8241,16 @@ "items": { "properties": { "key": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "The event that is tracked" + } }, "value": { - "type": "long" + "type": "long", + "_meta": { + "description": "The value of the event" + } } } } @@ -4540,10 +8260,16 @@ "items": { "properties": { "key": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "The event that is tracked" + } }, "value": { - "type": "long" + "type": "long", + "_meta": { + "description": "The value of the event" + } } } } @@ -4553,10 +8279,16 @@ "items": { "properties": { "key": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "The event that is tracked" + } }, "value": { - "type": "long" + "type": "long", + "_meta": { + "description": "The value of the event" + } } } } @@ -4566,10 +8298,16 @@ "items": { "properties": { "key": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "The event that is tracked" + } }, "value": { - "type": "long" + "type": "long", + "_meta": { + "description": "The value of the event" + } } } } @@ -4579,10 +8317,16 @@ "items": { "properties": { "key": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "The event that is tracked" + } }, "value": { - "type": "long" + "type": "long", + "_meta": { + "description": "The value of the event" + } } } } @@ -4592,10 +8336,16 @@ "items": { "properties": { "key": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "The event that is tracked" + } }, "value": { - "type": "long" + "type": "long", + "_meta": { + "description": "The value of the event" + } } } } @@ -4605,10 +8355,16 @@ "items": { "properties": { "key": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "The event that is tracked" + } }, "value": { - "type": "long" + "type": "long", + "_meta": { + "description": "The value of the event" + } } } } @@ -4618,10 +8374,16 @@ "items": { "properties": { "key": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "The event that is tracked" + } }, "value": { - "type": "long" + "type": "long", + "_meta": { + "description": "The value of the event" + } } } } @@ -4631,10 +8393,16 @@ "items": { "properties": { "key": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "The event that is tracked" + } }, "value": { - "type": "long" + "type": "long", + "_meta": { + "description": "The value of the event" + } } } } @@ -4644,10 +8412,16 @@ "items": { "properties": { "key": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "The event that is tracked" + } }, "value": { - "type": "long" + "type": "long", + "_meta": { + "description": "The value of the event" + } } } } @@ -4657,10 +8431,16 @@ "items": { "properties": { "key": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "The event that is tracked" + } }, "value": { - "type": "long" + "type": "long", + "_meta": { + "description": "The value of the event" + } } } } @@ -4670,10 +8450,16 @@ "items": { "properties": { "key": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "The event that is tracked" + } }, "value": { - "type": "long" + "type": "long", + "_meta": { + "description": "The value of the event" + } } } } @@ -4683,10 +8469,16 @@ "items": { "properties": { "key": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "The event that is tracked" + } }, "value": { - "type": "long" + "type": "long", + "_meta": { + "description": "The value of the event" + } } } } @@ -4696,10 +8488,16 @@ "items": { "properties": { "key": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "The event that is tracked" + } }, "value": { - "type": "long" + "type": "long", + "_meta": { + "description": "The value of the event" + } } } } @@ -4709,10 +8507,16 @@ "items": { "properties": { "key": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "The event that is tracked" + } }, "value": { - "type": "long" + "type": "long", + "_meta": { + "description": "The value of the event" + } } } } @@ -4722,10 +8526,16 @@ "items": { "properties": { "key": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "The event that is tracked" + } }, "value": { - "type": "long" + "type": "long", + "_meta": { + "description": "The value of the event" + } } } } @@ -4735,10 +8545,16 @@ "items": { "properties": { "key": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "The event that is tracked" + } }, "value": { - "type": "long" + "type": "long", + "_meta": { + "description": "The value of the event" + } } } } @@ -4748,10 +8564,16 @@ "items": { "properties": { "key": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "The event that is tracked" + } }, "value": { - "type": "long" + "type": "long", + "_meta": { + "description": "The value of the event" + } } } } @@ -4761,10 +8583,16 @@ "items": { "properties": { "key": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "The event that is tracked" + } }, "value": { - "type": "long" + "type": "long", + "_meta": { + "description": "The value of the event" + } } } } @@ -4774,10 +8602,16 @@ "items": { "properties": { "key": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "The event that is tracked" + } }, "value": { - "type": "long" + "type": "long", + "_meta": { + "description": "The value of the event" + } } } } @@ -4787,10 +8621,16 @@ "items": { "properties": { "key": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "The event that is tracked" + } }, "value": { - "type": "long" + "type": "long", + "_meta": { + "description": "The value of the event" + } } } } @@ -4800,10 +8640,16 @@ "items": { "properties": { "key": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "The event that is tracked" + } }, "value": { - "type": "long" + "type": "long", + "_meta": { + "description": "The value of the event" + } } } } @@ -4813,10 +8659,16 @@ "items": { "properties": { "key": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "The event that is tracked" + } }, "value": { - "type": "long" + "type": "long", + "_meta": { + "description": "The value of the event" + } } } } @@ -4826,10 +8678,16 @@ "items": { "properties": { "key": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "The event that is tracked" + } }, "value": { - "type": "long" + "type": "long", + "_meta": { + "description": "The value of the event" + } } } } @@ -4839,10 +8697,16 @@ "items": { "properties": { "key": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "The event that is tracked" + } }, "value": { - "type": "long" + "type": "long", + "_meta": { + "description": "The value of the event" + } } } } @@ -4852,10 +8716,16 @@ "items": { "properties": { "key": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "The event that is tracked" + } }, "value": { - "type": "long" + "type": "long", + "_meta": { + "description": "The value of the event" + } } } } @@ -4865,10 +8735,16 @@ "items": { "properties": { "key": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "The event that is tracked" + } }, "value": { - "type": "long" + "type": "long", + "_meta": { + "description": "The value of the event" + } } } } @@ -4878,10 +8754,16 @@ "items": { "properties": { "key": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "The event that is tracked" + } }, "value": { - "type": "long" + "type": "long", + "_meta": { + "description": "The value of the event" + } } } } @@ -4891,10 +8773,16 @@ "items": { "properties": { "key": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "The event that is tracked" + } }, "value": { - "type": "long" + "type": "long", + "_meta": { + "description": "The value of the event" + } } } } @@ -4904,10 +8792,16 @@ "items": { "properties": { "key": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "The event that is tracked" + } }, "value": { - "type": "long" + "type": "long", + "_meta": { + "description": "The value of the event" + } } } } @@ -4917,10 +8811,16 @@ "items": { "properties": { "key": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "The event that is tracked" + } }, "value": { - "type": "long" + "type": "long", + "_meta": { + "description": "The value of the event" + } } } } @@ -4930,10 +8830,16 @@ "items": { "properties": { "key": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "The event that is tracked" + } }, "value": { - "type": "long" + "type": "long", + "_meta": { + "description": "The value of the event" + } } } } @@ -4943,10 +8849,16 @@ "items": { "properties": { "key": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "The event that is tracked" + } }, "value": { - "type": "long" + "type": "long", + "_meta": { + "description": "The value of the event" + } } } } @@ -4956,10 +8868,16 @@ "items": { "properties": { "key": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "The event that is tracked" + } }, "value": { - "type": "long" + "type": "long", + "_meta": { + "description": "The value of the event" + } } } } @@ -4969,10 +8887,16 @@ "items": { "properties": { "key": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "The event that is tracked" + } }, "value": { - "type": "long" + "type": "long", + "_meta": { + "description": "The value of the event" + } } } } @@ -4982,10 +8906,16 @@ "items": { "properties": { "key": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "The event that is tracked" + } }, "value": { - "type": "long" + "type": "long", + "_meta": { + "description": "The value of the event" + } } } } @@ -4995,10 +8925,16 @@ "items": { "properties": { "key": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "The event that is tracked" + } }, "value": { - "type": "long" + "type": "long", + "_meta": { + "description": "The value of the event" + } } } } @@ -5008,10 +8944,16 @@ "items": { "properties": { "key": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "The event that is tracked" + } }, "value": { - "type": "long" + "type": "long", + "_meta": { + "description": "The value of the event" + } } } } @@ -5021,10 +8963,16 @@ "items": { "properties": { "key": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "The event that is tracked" + } }, "value": { - "type": "long" + "type": "long", + "_meta": { + "description": "The value of the event" + } } } } @@ -5034,10 +8982,16 @@ "items": { "properties": { "key": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "The event that is tracked" + } }, "value": { - "type": "long" + "type": "long", + "_meta": { + "description": "The value of the event" + } } } } @@ -5047,10 +9001,16 @@ "items": { "properties": { "key": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "The event that is tracked" + } }, "value": { - "type": "long" + "type": "long", + "_meta": { + "description": "The value of the event" + } } } } @@ -5060,10 +9020,16 @@ "items": { "properties": { "key": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "The event that is tracked" + } }, "value": { - "type": "long" + "type": "long", + "_meta": { + "description": "The value of the event" + } } } } @@ -5073,10 +9039,16 @@ "items": { "properties": { "key": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "The event that is tracked" + } }, "value": { - "type": "long" + "type": "long", + "_meta": { + "description": "The value of the event" + } } } } @@ -5086,10 +9058,16 @@ "items": { "properties": { "key": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "The event that is tracked" + } }, "value": { - "type": "long" + "type": "long", + "_meta": { + "description": "The value of the event" + } } } } @@ -5099,10 +9077,16 @@ "items": { "properties": { "key": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "The event that is tracked" + } }, "value": { - "type": "long" + "type": "long", + "_meta": { + "description": "The value of the event" + } } } } @@ -5112,10 +9096,16 @@ "items": { "properties": { "key": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "The event that is tracked" + } }, "value": { - "type": "long" + "type": "long", + "_meta": { + "description": "The value of the event" + } } } } @@ -5125,10 +9115,16 @@ "items": { "properties": { "key": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "The event that is tracked" + } }, "value": { - "type": "long" + "type": "long", + "_meta": { + "description": "The value of the event" + } } } } @@ -5138,10 +9134,16 @@ "items": { "properties": { "key": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "The event that is tracked" + } }, "value": { - "type": "long" + "type": "long", + "_meta": { + "description": "The value of the event" + } } } } @@ -5151,10 +9153,16 @@ "items": { "properties": { "key": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "The event that is tracked" + } }, "value": { - "type": "long" + "type": "long", + "_meta": { + "description": "The value of the event" + } } } } diff --git a/src/plugins/usage_collection/README.mdx b/src/plugins/usage_collection/README.mdx index 07ead377bf3963..9516ff656f4605 100644 --- a/src/plugins/usage_collection/README.mdx +++ b/src/plugins/usage_collection/README.mdx @@ -205,11 +205,23 @@ In the case of using a custom ES or SavedObjects client, it is up to the plugin ##### Schema Field -The `schema` field is a proscribed data model assists with detecting changes in usage collector payloads. To define the collector schema add a schema field that specifies every possible field reported (including optional fields) when registering the collector. Whenever the `schema` field is set or changed please run `node scripts/telemetry_check.js --fix` to update the stored schema json files. +The `schema` field is a proscribed data model assists with detecting changes in usage collector payloads. To define the collector schema add a schema field that specifies every possible field reported (including optional fields) when registering the collector. The schema supports descriptions as simple strings that allow developers to document what the data represents. The `_meta` field only supports a description property. +``` +schema: { + my_greeting: { + type: 'keyword', + _meta: { + description: 'The greeting keyword', + } + } +} +``` + +Whenever the `schema` field is set or changed please run `node scripts/telemetry_check.js --fix` to update the stored schema json files. ###### Allowed Schema Types -The `AllowedSchemaTypes` is the list of allowed schema types for the usage fields getting reported: +The `AllowedSchemaTypes` is the list of allowed schema types for the usage fields getting reported by the `fetch` method: ``` 'long', 'integer', 'short', 'byte', 'double', 'float', 'keyword', 'text', 'boolean', 'date' diff --git a/src/plugins/usage_collection/server/collector/collector.test.ts b/src/plugins/usage_collection/server/collector/collector.test.ts index 49c2ac18c7c523..fa3966f4f2d3c6 100644 --- a/src/plugins/usage_collection/server/collector/collector.test.ts +++ b/src/plugins/usage_collection/server/collector/collector.test.ts @@ -167,5 +167,44 @@ describe('collector', () => { }); expect(collector).toBeDefined(); }); + + test('TS allows _meta.descriptions in schema', () => { + const collector = new Collector(logger, { + type: 'my_test_collector_with_description', + isReady: () => false, + fetch: () => ({ testPass: 100 }), + schema: { + testPass: { type: 'long' }, + _meta: { description: 'Count of testPass as number' }, + }, + }); + expect(collector).toBeDefined(); + }); + + test('schema allows _meta as a data field', () => { + const collector = new Collector(logger, { + type: 'my_test_collector_with_meta_field', + isReady: () => false, + fetch: () => ({ testPass: 100, _meta: 'metaData' }), + schema: { + testPass: { type: 'long' }, + _meta: { type: 'keyword' }, + }, + }); + expect(collector).toBeDefined(); + }); + + test('schema allows _meta as a data field that has a description', () => { + const collector = new Collector(logger, { + type: 'my_test_collector_with_meta_field', + isReady: () => false, + fetch: () => ({ testPass: 100, _meta: 'metaData' }), + schema: { + testPass: { type: 'long' }, + _meta: { type: 'keyword', _meta: { description: '_meta data as a keyword' } }, + }, + }); + expect(collector).toBeDefined(); + }); }); }); diff --git a/src/plugins/usage_collection/server/collector/collector.ts b/src/plugins/usage_collection/server/collector/collector.ts index 5f189479decfeb..8e114df440cbec 100644 --- a/src/plugins/usage_collection/server/collector/collector.ts +++ b/src/plugins/usage_collection/server/collector/collector.ts @@ -45,7 +45,7 @@ export type PossibleSchemaTypes = U extends string export type RecursiveMakeSchemaFrom = U extends object ? MakeSchemaFrom - : { type: PossibleSchemaTypes }; + : { type: PossibleSchemaTypes; _meta?: { description: string } }; // Using Required to enforce all optional keys in the object export type MakeSchemaFrom = { diff --git a/test/functional/apps/management/_import_objects.ts b/test/functional/apps/management/_import_objects.ts index ca8d8c392ce49b..a3daaf86294939 100644 --- a/test/functional/apps/management/_import_objects.ts +++ b/test/functional/apps/management/_import_objects.ts @@ -23,7 +23,6 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { const testSubjects = getService('testSubjects'); const log = getService('log'); - // FLAKY: https://github.com/elastic/kibana/issues/89478 describe('import objects', function describeIndexTests() { describe('.ndjson file', () => { beforeEach(async function () { diff --git a/x-pack/plugins/actions/README.md b/x-pack/plugins/actions/README.md index 78094f4c0eb0b1..3ec8545017ca11 100644 --- a/x-pack/plugins/actions/README.md +++ b/x-pack/plugins/actions/README.md @@ -33,42 +33,14 @@ Table of Contents - [actionsClient.execute(options)](#actionsclientexecuteoptions) - [Example](#example-2) - [Built-in Action Types](#built-in-action-types) - - [Server log](#server-log) - - [`config`](#config) - - [`secrets`](#secrets) - - [`params`](#params) - - [Email](#email) - - [`config`](#config-1) - - [`secrets`](#secrets-1) - - [`params`](#params-1) - - [Slack](#slack) - - [`config`](#config-2) - - [`secrets`](#secrets-2) - - [`params`](#params-2) - - [Index](#index) - - [`config`](#config-3) - - [`secrets`](#secrets-3) - - [`params`](#params-3) - - [Webhook](#webhook) - - [`config`](#config-4) - - [`secrets`](#secrets-4) - - [`params`](#params-4) - - [PagerDuty](#pagerduty) - - [`config`](#config-5) - - [`secrets`](#secrets-5) - - [`params`](#params-5) - [ServiceNow](#servicenow) - - [`config`](#config-6) - - [`secrets`](#secrets-6) - - [`params`](#params-6) + - [`params`](#params) - [`subActionParams (pushToService)`](#subactionparams-pushtoservice) - [`subActionParams (getFields)`](#subactionparams-getfields) - [`subActionParams (getIncident)`](#subactionparams-getincident) - [`subActionParams (getChoices)`](#subactionparams-getchoices) - [Jira](#jira) - - [`config`](#config-7) - - [`secrets`](#secrets-7) - - [`params`](#params-7) + - [`params`](#params-1) - [`subActionParams (pushToService)`](#subactionparams-pushtoservice-1) - [`subActionParams (getIncident)`](#subactionparams-getincident-1) - [`subActionParams (issueTypes)`](#subactionparams-issuetypes) @@ -77,9 +49,7 @@ Table of Contents - [`subActionParams (issue)`](#subactionparams-issue) - [`subActionParams (getFields)`](#subactionparams-getfields-1) - [IBM Resilient](#ibm-resilient) - - [`config`](#config-8) - - [`secrets`](#secrets-8) - - [`params`](#params-8) + - [`params`](#params-2) - [`subActionParams (pushToService)`](#subactionparams-pushtoservice-2) - [`subActionParams (getFields)`](#subactionparams-getfields-2) - [`subActionParams (incidentTypes)`](#subactionparams-incidenttypes) @@ -272,6 +242,160 @@ const result = await actionsClient.execute({ Kibana ships with a set of built-in action types. See [Actions and connector types Documentation](https://www.elastic.co/guide/en/kibana/master/action-types.html). +In addition to the documented configurations, several built in action type offer additional `params` configurations. + +## ServiceNow + +The [ServiceNow user documentation `params`](https://www.elastic.co/guide/en/kibana/master/servicenow-action-type.html) lists configuration properties for the `pushToService` subaction. In addition, several other subaction types are available. +### `params` + +| Property | Description | Type | +| --------------- | -------------------------------------------------------------------------------------------------- | ------ | +| subAction | The subaction to perform. It can be `pushToService`, `getFields`, `getIncident`, and `getChoices`. | string | +| subActionParams | The parameters of the subaction. | object | + +#### `subActionParams (pushToService)` + +| Property | Description | Type | +| -------- | ------------------------------------------------------------------------------------------------------------- | --------------------- | +| incident | The ServiceNow incident. | object | +| comments | The comments of the case. A comment is of the form `{ commentId: string, version: string, comment: string }`. | object[] _(optional)_ | + +The following table describes the properties of the `incident` object. + +| Property | Description | Type | +| ----------------- | ------------------------------------------------------------------------------------------------------------------------- | ------------------- | +| short_description | The title of the incident. | string | +| description | The description of the incident. | string _(optional)_ | +| externalId | The ID of the incident in ServiceNow. If present, the incident is updated. Otherwise, a new incident is created. | string _(optional)_ | +| severity | The severity in ServiceNow. | string _(optional)_ | +| urgency | The urgency in ServiceNow. | string _(optional)_ | +| impact | The impact in ServiceNow. | string _(optional)_ | +| category | The category in ServiceNow. | string _(optional)_ | +| subcategory | The subcategory in ServiceNow. | string _(optional)_ | + +#### `subActionParams (getFields)` + +No parameters for the `getFields` subaction. Provide an empty object `{}`. + +#### `subActionParams (getIncident)` + +| Property | Description | Type | +| ---------- | ------------------------------------- | ------ | +| externalId | The ID of the incident in ServiceNow. | string | + + +#### `subActionParams (getChoices)` + +| Property | Description | Type | +| -------- | ------------------------------------------------------------ | -------- | +| fields | An array of fields. Example: `[priority, category, impact]`. | string[] | + +--- + +## Jira + +The [Jira user documentation `params`](https://www.elastic.co/guide/en/kibana/master/jira-action-type.html) lists configuration properties for the `pushToService` subaction. In addition, several other subaction types are available. +### `params` + +| Property | Description | Type | +| --------------- | ------------------------------------------------------------------------------------------------------------------------------------------ | ------ | +| subAction | The subaction to perform. It can be `pushToService`, `getIncident`, `issueTypes`, `fieldsByIssueType`, `issues`, `issue`, and `getFields`. | string | +| subActionParams | The parameters of the subaction. | object | + +#### `subActionParams (pushToService)` + +| Property | Description | Type | +| -------- | ------------------------------------------------------------------------------------------------------------- | --------------------- | +| incident | The Jira incident. | object | +| comments | The comments of the case. A comment is of the form `{ commentId: string, version: string, comment: string }`. | object[] _(optional)_ | + +The following table describes the properties of the `incident` object. + +| Property | Description | Type | +| ----------- | ---------------------------------------------------------------------------------------------------------------- | --------------------- | +| summary | The title of the issue. | string | +| description | The description of the issue. | string _(optional)_ | +| externalId | The ID of the issue in Jira. If present, the incident is updated. Otherwise, a new incident is created. | string _(optional)_ | +| issueType | The ID of the issue type in Jira. | string _(optional)_ | +| priority | The name of the priority in Jira. Example: `Medium`. | string _(optional)_ | +| labels | An array of labels. Labels cannot contain spaces. | string[] _(optional)_ | +| parent | The ID or key of the parent issue. Only for `Sub-task` issue types. | string _(optional)_ | + +#### `subActionParams (getIncident)` + +| Property | Description | Type | +| ---------- | --------------------------- | ------ | +| externalId | The ID of the issue in Jira. | string | + +#### `subActionParams (issueTypes)` + +No parameters for the `issueTypes` subaction. Provide an empty object `{}`. + +#### `subActionParams (fieldsByIssueType)` + +| Property | Description | Type | +| -------- | -------------------------------- | ------ | +| id | The ID of the issue type in Jira. | string | + +#### `subActionParams (issues)` + +| Property | Description | Type | +| -------- | ----------------------- | ------ | +| title | The title to search for. | string | + +#### `subActionParams (issue)` + +| Property | Description | Type | +| -------- | --------------------------- | ------ | +| id | The ID of the issue in Jira. | string | + +#### `subActionParams (getFields)` + +No parameters for the `getFields` subaction. Provide an empty object `{}`. + +--- +## IBM Resilient + +The [IBM Resilient user documentation `params`](https://www.elastic.co/guide/en/kibana/master/resilient-action-type.html) lists configuration properties for the `pushToService` subaction. In addition, several other subaction types are available. + +### `params` + +| Property | Description | Type | +| --------------- | -------------------------------------------------------------------------------------------------- | ------ | +| subAction | The subaction to perform. It can be `pushToService`, `getFields`, `incidentTypes`, and `severity. | string | +| subActionParams | The parameters of the subaction. | object | + +#### `subActionParams (pushToService)` + +| Property | Description | Type | +| -------- | ------------------------------------------------------------------------------------------------------------- | --------------------- | +| incident | The IBM Resilient incident. | object | +| comments | The comments of the case. A comment is of the form `{ commentId: string, version: string, comment: string }`. | object[] _(optional)_ | + +The following table describes the properties of the `incident` object. + +| Property | Description | Type | +| ------------- | ---------------------------------------------------------------------------------------------------------------------------- | --------------------- | +| name | The title of the incident. | string _(optional)_ | +| description | The description of the incident. | string _(optional)_ | +| externalId | The ID of the incident in IBM Resilient. If present, the incident is updated. Otherwise, a new incident is created. | string _(optional)_ | +| incidentTypes | An array with the IDs of IBM Resilient incident types. | number[] _(optional)_ | +| severityCode | IBM Resilient ID of the severity code. | number _(optional)_ | + +#### `subActionParams (getFields)` + +No parameters for the `getFields` subaction. Provide an empty object `{}`. + +#### `subActionParams (incidentTypes)` + +No parameters for the `incidentTypes` subaction. Provide an empty object `{}`. + +#### `subActionParams (severity)` + +No parameters for the `severity` subaction. Provide an empty object `{}`. + +--- # Command Line Utility The [`kbn-action`](https://github.com/pmuellr/kbn-action) tool can be used to send HTTP requests to the Actions plugin. For instance, to create a Slack action from the `.slack` Action Type, use the following command: @@ -310,7 +434,9 @@ Actions that take URLs or hostnames should check that those values are allowed. ## documentation -You should also create some asciidoc for the new action type. An entry should be made in the action type index - [`docs/user/alerting/action-types.asciidoc`](../../../docs/user/alerting/action-types.asciidoc) which points to a new document for the action type that should be in the directory [`docs/user/alerting/action-types`](../../../docs/user/alerting/action-types). +You should create asciidoc for the new action type. Add an entry to the action type index - [`docs/user/alerting/action-types.asciidoc`](../../../docs/user/alerting/action-types.asciidoc), which points to a new document for the action type that should be in the directory [`docs/user/alerting/action-types`](../../../docs/user/alerting/action-types). + +We suggest following the template provided in `docs/action-type-template.asciidoc`. The [Email action type](https://www.elastic.co/guide/en/kibana/master/email-action-type.html) is an example of documentation created following the template. ## tests diff --git a/x-pack/plugins/alerts/README.md b/x-pack/plugins/alerts/README.md index 07bad42a3bfa3d..057d86e4c0f31c 100644 --- a/x-pack/plugins/alerts/README.md +++ b/x-pack/plugins/alerts/README.md @@ -19,9 +19,10 @@ Table of Contents - [Alert types](#alert-types) - [Methods](#methods) - [Executor](#executor) - - [Licensing](#licensing) - - [Documentation](#documentation) - - [Tests](#tests) + - [Action variables](#action-variables) + - [Licensing](#licensing) + - [Documentation](#documentation) + - [Tests](#tests) - [Example](#example) - [Role Based Access-Control](#role-based-access-control) - [Alert Navigation](#alert-navigation) @@ -147,9 +148,9 @@ This is the primary function for an alert type. Whenever the alert needs to exec |createdBy|The userid that created this alert.| |updatedBy|The userid that last updated this alert.| -### The `actionVariables` property +### Action Variables -This property should contain the **flattened** names of the state and context variables available when an executor calls `alertInstance.scheduleActions(actionGroup, context)`. These names are meant to be used in prompters in the alerting user interface, are used as text values for display, and can be inserted into to an action parameter text entry field via UI gesture (eg, clicking a menu item from a menu built with these names). They should be flattened, so if a state or context variable is an object with properties, these should be listed with the "parent" property/properties in the name, separated by a `.` (period). +The `actionVariables` property should contain the **flattened** names of the state and context variables available when an executor calls `alertInstance.scheduleActions(actionGroup, context)`. These names are meant to be used in prompters in the alerting user interface, are used as text values for display, and can be inserted into to an action parameter text entry field via UI gesture (eg, clicking a menu item from a menu built with these names). They should be flattened, so if a state or context variable is an object with properties, these should be listed with the "parent" property/properties in the name, separated by a `.` (period). For example, if the `context` has one variable `foo` which is an object that has one property `bar`, and there are no `state` variables, the `actionVariables` value would be in the following shape: @@ -167,7 +168,12 @@ Currently most of the alerts are free features. But some alert types are subscri ## Documentation -You should create documentation for the new alert type. Make an entry in the alert type index [`docs/user/alerting/alert-types.asciidoc`](../../../docs/user/alerting/alert-types.asciidoc) that points to a new document for the alert type that should be in the proper application directory. +You should create asciidoc for the new alert type. +* For stack alerts, add an entry to the alert type index - [`docs/user/alerting/alert-types.asciidoc`](../../../docs/user/alerting/alert-types.asciidoc) which points to a new document for the alert type that should be in the directory [`docs/user/alerting/stack-alerts`](../../../docs/user/alerting/stack-alerts). + +* Solution specific alert documentation should live within the docs for the solution. + +We suggest following the template provided in `docs/alert-type-template.asciidoc`. The [Index Threshold alert type](https://www.elastic.co/guide/en/kibana/master/alert-type-index-threshold.html) is an example of documentation created following the template. ## Tests diff --git a/x-pack/plugins/apm/public/components/app/service_profiling/service_profiling_flamegraph.tsx b/x-pack/plugins/apm/public/components/app/service_profiling/service_profiling_flamegraph.tsx index fa1da99dbf072d..1adf58d0394c60 100644 --- a/x-pack/plugins/apm/public/components/app/service_profiling/service_profiling_flamegraph.tsx +++ b/x-pack/plugins/apm/public/components/app/service_profiling/service_profiling_flamegraph.tsx @@ -323,7 +323,6 @@ export function ServiceProfilingFlamegraph({ config={{ fillLabel: { fontFamily: theme.eui.euiCodeFontFamily, - // @ts-expect-error (coming soon in Elastic charts) clipText: true, }, drilldown: true, diff --git a/x-pack/plugins/apm/server/lib/anomaly_detection/create_anomaly_detection_jobs.ts b/x-pack/plugins/apm/server/lib/anomaly_detection/create_anomaly_detection_jobs.ts index dd36e7cbeb24eb..d93514c42bbdda 100644 --- a/x-pack/plugins/apm/server/lib/anomaly_detection/create_anomaly_detection_jobs.ts +++ b/x-pack/plugins/apm/server/lib/anomaly_detection/create_anomaly_detection_jobs.ts @@ -19,6 +19,7 @@ import { } from '../../../common/elasticsearch_fieldnames'; import { APM_ML_JOB_GROUP, ML_MODULE_ID_APM_TRANSACTION } from './constants'; import { withApmSpan } from '../../utils/with_apm_span'; +import { getAnomalyDetectionJobs } from './get_anomaly_detection_jobs'; export async function createAnomalyDetectionJobs( setup: Setup, @@ -38,14 +39,19 @@ export async function createAnomalyDetectionJobs( throw Boom.forbidden(ML_ERRORS.ML_NOT_AVAILABLE_IN_SPACE); } + const uniqueMlJobEnvs = await getUniqueMlJobEnvs(setup, environments, logger); + if (uniqueMlJobEnvs.length === 0) { + return []; + } + return withApmSpan('create_anomaly_detection_jobs', async () => { logger.info( - `Creating ML anomaly detection jobs for environments: [${environments}].` + `Creating ML anomaly detection jobs for environments: [${uniqueMlJobEnvs}].` ); const indexPatternName = indices['apm_oss.transactionIndices']; const responses = await Promise.all( - environments.map((environment) => + uniqueMlJobEnvs.map((environment) => createAnomalyDetectionJob({ ml, environment, indexPatternName }) ) ); @@ -105,3 +111,24 @@ async function createAnomalyDetectionJob({ }); }); } + +async function getUniqueMlJobEnvs( + setup: Setup, + environments: string[], + logger: Logger +) { + // skip creation of duplicate ML jobs + const jobs = await getAnomalyDetectionJobs(setup, logger); + const existingMlJobEnvs = jobs.map(({ environment }) => environment); + const requestedExistingMlJobEnvs = environments.filter((env) => + existingMlJobEnvs.includes(env) + ); + + if (requestedExistingMlJobEnvs.length) { + logger.warn( + `Skipping creation of existing ML jobs for environments: [${requestedExistingMlJobEnvs}]}` + ); + } + + return environments.filter((env) => !existingMlJobEnvs.includes(env)); +} diff --git a/x-pack/plugins/apm/server/routes/settings/anomaly_detection.ts b/x-pack/plugins/apm/server/routes/settings/anomaly_detection.ts index 25afb11f264590..e5922d9ed3e941 100644 --- a/x-pack/plugins/apm/server/routes/settings/anomaly_detection.ts +++ b/x-pack/plugins/apm/server/routes/settings/anomaly_detection.ts @@ -66,6 +66,7 @@ export const createAnomalyDetectionJobsRoute = createRoute({ } await createAnomalyDetectionJobs(setup, environments, context.logger); + notifyFeatureUsage({ licensingPlugin: context.licensing, featureName: 'ml', diff --git a/x-pack/plugins/canvas/PLUGINS.mdx b/x-pack/plugins/canvas/PLUGINS.mdx new file mode 100644 index 00000000000000..0f93948d663a07 --- /dev/null +++ b/x-pack/plugins/canvas/PLUGINS.mdx @@ -0,0 +1,239 @@ +--- +id: canvasPlugins +slug: /playground/kibana/canvas-plugins +title: Develop Canvas plugins +summary: Introduction to +date: 2021-02-18 +tags: ['kibana', 'canvas', 'plugins'] +related: [] +--- + +To develop your own Canvas plugins, you simply create a Kibana plugin, and register your customizations with Canvas. + +The following is a step-by-step guide to adding your own custom random number Canvas plugin. + +## Generating a Kibana plugin + +```bash +# in the kibana directory +# Rename canvas_example to whatever you want your plugin to be named +node scripts/generate_plugin.js canvas_example +``` + +This will prompt you for some input. Generally, you can answer as follows: + +``` +❯ node scripts/generate_plugin.js canvas_example +? Would you like to create the plugin in a different folder? No +? Provide a short description An awesome Kibana plugin +? What Kibana version are you targeting? master +? Should an app component be generated? No +? Should a server API be generated? No +? Should translation files be generated? No +? Would you like to use a custom eslint file? No +``` + +Once this has completed, go to your plugin directory: + +```bash +cd plugins/canvas_example +``` + +Open that folder in your code editor of choice: `code .` + +### Creating a Canvas element and function +Open your plugin's `kibana.json` file. Make sure that `ui` has a value of true, and that `'canvas'` is included in `requiredPlugins`. It should look something like this. + +```json +{ + "id": "canvasExample", + "version": "7.8.0", + "server": false, + "ui": true, + "requiredPlugins": ["canvas"], + "optionalPlugins": [] +} +``` + +In your plugin folder, create a new folder `public` and an `index.ts` file within it. + +This `index.ts` will need export a Kibana Plugin. You can use this as a starting point for your plugin. + +```typescript +import { Plugin, CoreSetup, CoreStart } from '../../../src/core/public'; +import { CanvasSetup } from '../../../x-pack/plugins/canvas/public'; + +interface CanvasExampleSetupPlugins { + canvas: CanvasSetup; +} + +interface CanvasExampleStartPlugins {} + +class CanvasExamplePlugin + implements Plugin { + setup(core: CoreSetup, plugins: CanvasExampleSetupPlugins) {} + + start(core: CoreStart) {} +} + +export const plugin = () => new CanvasExamplePlugin(); +``` + + +Now that the Kibana plugin boilerplate is out of the way, you can start adding functionality to Canvas. + +Let's start by adding a new function. + +In your `index.ts` add a new function definition: + +```typescript +const canvasFunctions = [ + () => ({ + name: 'random', + help: 'Make a random number between 1 and 100', + args: {}, + fn() { + return Math.floor(Math.random() * 100) + 1; + } + }), +]; +``` + +Then, in the `setup` method of your plugin, you can add this new function definition to Canvas: + +```typescript +setup(core: CoreSetup, plugins: CanvasExampleSetupPlugins) { + plugins.canvas.addFunctions(canvasFunctions); +} +``` + +Now, let's add a new Element type. In your `index.ts` add a new element definition: + +```typescript +const elements = [ + () => ({ + name: 'randomNumber', + displayName: 'Random Number', + help: 'A random number between 1 and 100', + image: 'https://images.contentstack.io/v3/assets/bltefdd0b53724fa2ce/bltb59c89a07c05b937/5c583a6602ac90e80ba0ab8f/icon-white-circle-elastic-stack.svg', + expression: 'random | metric "Random Number"', + }), +]; +``` + +And then, in the `setup` method of the plugin, add this new element definition to Canvas, just like you did with the function: + +```typescript +setup(core: CoreSetup, plugins: CanvasExampleSetupPlugins) { + plugins.canvas.addFunctions(canvasFunctions); + plugins.canvas.addElements(elements); +} +``` + +Now, your 'Random Number' element will show up in the list of other Canvas elements. + +### Trying out your new plugin + +In the terminal, in your plugin's directory, run: + +```bash +# In plugins/canvas_example +yarn start +``` + +- Pull up Kibana in your browser: `http://localhost:5601` +- Go to canvas, and click: "Create workpad" +- Click: "Add element" +- Click: "Other" +- Click: "Random Number" + +### Adding a server-side function + +> Server side functions may be deprecated in a later version of Kibana + +Now, let's add a function which runs on the server. + +In your plugin's `kibana.json` file, set `server` to true, and add `"expressions"` as a requiredPlugin. + +```typescript +{ + "id": "canvasExample", + "version": "8.0.0", + "server": false, + "ui": true, + "requiredPlugins": ["canvas", "expressions"], + "optionalPlugins": [] +} +``` + +Now, much like we made the client plugin, we'll make a server plugin. + +Start by making the `server` directory and an `index.ts` file with a shell for your server plugin: + +```typescript +import { Plugin, CoreSetup, CoreStart } from '../../../src/core/server'; +import { ExpressionsServerSetup } from '../../../src/plugins/expressions/server'; + +interface CanvasExamplePluginsSetup { + expressions: ExpressionsServerSetup; +} + +class CanvasExamplePlugin implements Plugin { + setup(core: CoreSetup, plugins: CanvasExamplePluginsSetup) {} + + start(core: CoreStart) {} +} + +export const plugin = () => new CanvasExamplePlugin(); +``` + +Now, we'll create a simple function definition that we will register on the server: + +```typescript +const serverFunctions = [ + () => ({ + name: 'serverTime', + help: 'Get the server time in milliseconds', + args: {}, + fn() { + return Date.now(); + }, + }), +]; +``` + +And then in our setup method, register it with the Expressions plugin: + +```typescript +setup(core: CoreSetup, plugins: CanvasExamplePluginsSetup) { + serverFunctions.forEach((f) => plugins.expressions.registerFunction(f)); +} +``` + +Now, let's try out our new server function. + +- Refresh your browser. +- In the same Canvas workpad: + - Add another Random Number element as before + - Click that element to select it + - Click "Expression editor" + - Modify the expression to look like this: `serverTime | metric "Server Time in ms"` + - Click "Run" + +You should now see one random number and one "Server Time in ms" value. + +> More information about building Kibana Plugins can be found in [src/core](https://github.com/elastic/kibana/blob/master/src/core/README.md) + +### My Canvas Plugin stopped working + +If your Kibana Server is crashing on startup with a message like + +> **FATAL** Error: Unmet requirement "canvas" for plugin "your_plugin_name" + +or + +> **FATAL** Error: Unmet requirement "interpreter" for plugin "your_plugin_name" + +then your plugin was likely created to work on a previous version of Kibana. Starting with version 7.8, the plugin system was redesigned and caused breaking changes to these earlier plugins. + +The good news is that all of your existing Canvas extension code can be reused, it just needs to be in an updated Kibana plugin. Follow the [instructions](#generating-a-kibana-plugin) for creating a new Canvas Kibana plugin, and then add in your existing functions and elements. diff --git a/x-pack/plugins/canvas/README.md b/x-pack/plugins/canvas/README.md index f77585b5b062c0..754a4dc29d0073 100644 --- a/x-pack/plugins/canvas/README.md +++ b/x-pack/plugins/canvas/README.md @@ -6,246 +6,6 @@ Canvas is included with X-Pack and requires a Basic license or better to use. -## Developing in Canvas - -To develop your own Canvas plugins, you simply create a Kibana plugin, and register your customizations with Canvas. - -The following is a step-by-step guide to adding your own custom random number Canvas plugin. - -### Generating a Kibana plugin - -```bash -# in the kibana directory -# Rename canvas_example to whatever you want your plugin to be named -node scripts/generate_plugin.js canvas_example -``` - -This will prompt you for some input. Generally, you can answer as follows: - -``` -❯ node scripts/generate_plugin.js canvas_example -? Would you like to create the plugin in a different folder? No -? Provide a short description An awesome Kibana plugin -? What Kibana version are you targeting? master -? Should an app component be generated? No -? Should a server API be generated? No -? Should translation files be generated? No -? Would you like to use a custom eslint file? No -``` - -Once this has completed, go to your plugin directory: - -```bash -cd plugins/canvas_example -``` - -Open that folder in your code editor of choice: `code .` - -#### Creating a Canvas element and function -Open your plugin's `kibana.json` file. Make sure that `ui` has a value of true, and that `'canvas'` is included in `requiredPlugins`. It should look something like this. - -```json -{ - "id": "canvasExample", - "version": "7.8.0", - "server": false, - "ui": true, - "requiredPlugins": ["canvas"], - "optionalPlugins": [] -} -``` - -In your plugin folder, create a new folder `public` and an `index.ts` file within it. - -This `index.ts` will need export a Kibana Plugin. You can use this as a starting point for your plugin. - -```typescript -import { Plugin, CoreSetup, CoreStart } from '../../../src/core/public'; -import { CanvasSetup } from '../../../x-pack/plugins/canvas/public'; - -interface CanvasExampleSetupPlugins { - canvas: CanvasSetup; -} - -interface CanvasExampleStartPlugins {} - -class CanvasExamplePlugin - implements Plugin { - setup(core: CoreSetup, plugins: CanvasExampleSetupPlugins) {} - - start(core: CoreStart) {} -} - -export const plugin = () => new CanvasExamplePlugin(); -``` - - -Now that the Kibana plugin boilerplate is out of the way, you can start adding functionality to Canvas. - -Let's start by adding a new function. - -In your `index.ts` add a new function definition: - -```typescript -const canvasFunctions = [ - () => ({ - name: 'random', - help: 'Make a random number between 1 and 100', - args: {}, - fn() { - return Math.floor(Math.random() * 100) + 1; - } - }), -]; -``` - -Then, in the `setup` method of your plugin, you can add this new function definition to Canvas: - -```typescript -setup(core: CoreSetup, plugins: CanvasExampleSetupPlugins) { - plugins.canvas.addFunctions(canvasFunctions); -} -``` - -Now, let's add a new Element type. In your `index.ts` add a new element definition: - -```typescript -const elements = [ - () => ({ - name: 'randomNumber', - displayName: 'Random Number', - help: 'A random number between 1 and 100', - image: 'https://images.contentstack.io/v3/assets/bltefdd0b53724fa2ce/bltb59c89a07c05b937/5c583a6602ac90e80ba0ab8f/icon-white-circle-elastic-stack.svg', - expression: 'random | metric "Random Number"', - }), -]; -``` - -And then, in the `setup` method of the plugin, add this new element definition to Canvas, just like you did with the function: - -```typescript -setup(core: CoreSetup, plugins: CanvasExampleSetupPlugins) { - plugins.canvas.addFunctions(canvasFunctions); - plugins.canvas.addElements(elements); -} -``` - -Now, your 'Random Number' element will show up in the list of other Canvas elements. - -#### Trying out your new plugin - -In the terminal, in your plugin's directory, run: - -```bash -# In plugins/canvas_example -yarn start -``` - -- Pull up Kibana in your browser: `http://localhost:5601` -- Go to canvas, and click: "Create workpad" -- Click: "Add element" -- Click: "Other" -- Click: "Random Number" - -#### Adding a server-side function - -> Server side functions may be deprecated in a later version of Kibana - -Now, let's add a function which runs on the server. - -In your plugin's `kibana.json` file, set `server` to true, and add `"expressions"` as a requiredPlugin. - -```typescript -{ - "id": "canvasExample", - "version": "8.0.0", - "server": false, - "ui": true, - "requiredPlugins": ["canvas", "expressions"], - "optionalPlugins": [] -} -``` - -Now, much like we made the client plugin, we'll make a server plugin. - -Start by making the `server` directory and an `index.ts` file with a shell for your server plugin: - -```typescript -import { Plugin, CoreSetup, CoreStart } from '../../../src/core/server'; -import { ExpressionsServerSetup } from '../../../src/plugins/expressions/server'; - -interface CanvasExamplePluginsSetup { - expressions: ExpressionsServerSetup; -} - -class CanvasExamplePlugin implements Plugin { - setup(core: CoreSetup, plugins: CanvasExamplePluginsSetup) {} - - start(core: CoreStart) {} -} - -export const plugin = () => new CanvasExamplePlugin(); -``` - -Now, we'll create a simple function definition that we will register on the server: - -```typescript -const serverFunctions = [ - () => ({ - name: 'serverTime', - help: 'Get the server time in milliseconds', - args: {}, - fn() { - return Date.now(); - }, - }), -]; -``` - -And then in our setup method, register it with the Expressions plugin: - -```typescript -setup(core: CoreSetup, plugins: CanvasExamplePluginsSetup) { - serverFunctions.forEach((f) => plugins.expressions.registerFunction(f)); -} -``` - -Now, let's try out our new server function. - -- Refresh your browser. -- In the same Canvas workpad: - - Add another Random Number element as before - - Click that element to select it - - Click "Expression editor" - - Modify the expression to look like this: `serverTime | metric "Server Time in ms"` - - Click "Run" - -You should now see one random number and one "Server Time in ms" value. - -> More information about building Kibana Plugins can be found in [src/core](https://github.com/elastic/kibana/blob/master/src/core/README.md) - -#### My Canvas Plugin stopped working - -If your Kibana Server is crashing on startup with a message like - -> **FATAL** Error: Unmet requirement "canvas" for plugin "your_plugin_name" - -or - -> **FATAL** Error: Unmet requirement "interpreter" for plugin "your_plugin_name" - -then your plugin was likely created to work on a previous version of Kibana. Starting with version 7.8, the plugin system was redesigned and caused breaking changes to these earlier plugins. - -The good news is that all of your existing Canvas extension code can be reused, it just needs to be in an updated Kibana plugin. Follow the [instructions](#generating-a-kibana-plugin) for creating a new Canvas Kibana plugin, and then add in your existing functions and elements. - -## Scripts - -There are several scripts available once you are in that path as well. - -- `node scripts/lint` - local linter setup, can also be used with the `--fix` flag for automatic fixes. -- `node scripts/test` - local test runner, does not require a real Kibana instance. Runs all the same unit tests the normal runner does, just limited to Canvas, and *waaaaaay* faster (currently 12 seconds or less). -- `node scripts/test_dev` - Same as above, but watches for changes and only runs tests for the given scope (browser, server, or common). - ## Feature Questions **Why are there no tooltips** diff --git a/x-pack/plugins/canvas/shareable_runtime/README.md b/x-pack/plugins/canvas/shareable_runtime/README.mdx similarity index 88% rename from x-pack/plugins/canvas/shareable_runtime/README.md rename to x-pack/plugins/canvas/shareable_runtime/README.mdx index 3839e7c4ecb3fd..8f1c9e06ca788a 100644 --- a/x-pack/plugins/canvas/shareable_runtime/README.md +++ b/x-pack/plugins/canvas/shareable_runtime/README.mdx @@ -1,35 +1,12 @@ -# Canvas Shareable Workpads - -- [Introduction](#introduction) -- [Quick Start](#quick-start) -- [Using the Runtime](#using-the-runtime) - - [Assumptions](#assumptions) - - [Restrictions](#restrictions) - - [JS](#js) - - [HTML](#html) - - [Options](#options) -- [Testing](#testing) - - [Download a ZIP from Canvas](#download-a-zip-from-canvas) - - [Test the Runtime Directly from Webpack](#test-the-runtime-directly-from-webpack) - - [Run the Canvas Storybook](#run-the-canvas-storybook) - - [Run the Jest Tests](#run-the-jest-tests) - - [Gathering Test Coverage](#gathering-test-coverage) -- [Building](#building) - - [Build Options](#build-options) -- [Development](#development) - - [Prerequisite](#prerequisite) - - [Webpack Dev Server](#webpack-dev-server) - - [Gathering Statistics](#gathering-statistics) -- [Architecture](#architecture) - - [The Build](#the-build) - - [Supported Expressions](#supported-expressions) - - [Expression Interpreter](#expression-interpreter) - - [Build Size](#build-size) - - [The App](#the-app) - - [App State](#app-state) - - [CSS](#css) - -## Introduction +--- +id: canvasShareableWorkpads +slug: /playground/kibana/canvas-shareable-workpads +title: Share a Canvas Workpad on a Website +summary: How to share a static snapshot of a workpad on an external website. +date: 2021-02-18 +tags: ['kibana', 'canvas', 'share'] +related: [] +--- The Canvas Shareable Runtime is designed to render Shareable Canvas Workpads outside of Kibana in a different website or application. It uses the intermediate, "transient" state of a workpad, which is a JSON-blob state after element expressions are initially evaluated against their data sources, but before the elements are rendered to the screen. This "transient" state, therefore, has no dependency or access to ES/Kibana data, making it lightweight and portable. @@ -228,11 +205,7 @@ The `index.html` file contains a call to the `CanvasShareable` runtime. Currentl ``` -There are three workpads available, in `test/workpads`: - -- `hello.json` - A simple 'Hello, Canvas' workpad. -- `austin.json` - A workpad from an Elastic{ON} talk in Austin, TX. -- `test.json` - A couple of pages with customized CSS animations and charts. +There are three test workpads available, in `test/workpads`. ### Gathering Statistics diff --git a/x-pack/plugins/data_enhanced/public/autocomplete/providers/kql_query_suggestion/field.test.ts b/x-pack/plugins/data_enhanced/public/autocomplete/providers/kql_query_suggestion/field.test.ts index bea695779fda62..afc55d13af9d9a 100644 --- a/x-pack/plugins/data_enhanced/public/autocomplete/providers/kql_query_suggestion/field.test.ts +++ b/x-pack/plugins/data_enhanced/public/autocomplete/providers/kql_query_suggestion/field.test.ts @@ -78,6 +78,17 @@ describe('Kuery field suggestions', () => { expect(suggestions.find(({ text }) => text === 'machine.os ')).toBeDefined(); }); + test('should field names that match the search', async () => { + const prefix = 'machi'; + const suffix = 'ne.os'; + const suggestions = await getSuggestions( + querySuggestionsArgs, + mockKueryNode({ prefix, suffix }) + ); + + expect(suggestions.find(({ text }) => text === 'machine.os ')).toBeDefined(); + }); + test('should return field names that start with the query first', async () => { const prefix = 'e'; const suffix = ''; diff --git a/x-pack/plugins/data_enhanced/public/autocomplete/providers/kql_query_suggestion/field.tsx b/x-pack/plugins/data_enhanced/public/autocomplete/providers/kql_query_suggestion/field.tsx index ef0f27ee93bb7a..ac6f7de888320e 100644 --- a/x-pack/plugins/data_enhanced/public/autocomplete/providers/kql_query_suggestion/field.tsx +++ b/x-pack/plugins/data_enhanced/public/autocomplete/providers/kql_query_suggestion/field.tsx @@ -58,8 +58,7 @@ export const setupGetFieldSuggestions: KqlQuerySuggestionProvider { - const { mount } = new LogicMounter(AppLogic); - - beforeEach(() => { - mount(); - }); - - const DEFAULT_VALUES = { - hasInitialized: false, - account: {}, - configuredLimits: {}, - ilmEnabled: false, - myRole: {}, + const mount = (props = {}) => { + AppLogic({ ...DEFAULT_INITIAL_APP_DATA, ...props }); + AppLogic.mount(); }; - it('has expected default values', () => { - expect(AppLogic.values).toEqual(DEFAULT_VALUES); + beforeEach(() => { + jest.clearAllMocks(); + resetContext({}); }); - describe('initializeAppData()', () => { - it('sets values based on passed props', () => { - AppLogic.actions.initializeAppData(DEFAULT_INITIAL_APP_DATA); + it('sets values from props', () => { + mount(); - expect(AppLogic.values).toEqual({ - hasInitialized: true, - ilmEnabled: true, - configuredLimits: { - engine: { - maxDocumentByteSize: 102400, - maxEnginesPerMetaEngine: 15, - }, - }, - account: { - accountId: 'some-id-string', - onboardingComplete: true, - role: DEFAULT_INITIAL_APP_DATA.appSearch.role, + expect(AppLogic.values).toEqual({ + ilmEnabled: true, + configuredLimits: { + engine: { + maxDocumentByteSize: 102400, + maxEnginesPerMetaEngine: 15, }, - myRole: expect.objectContaining({ - id: 'account_id:somestring|user_oid:somestring', - roleType: 'owner', - availableRoleTypes: ['owner', 'admin'], - credentialTypes: ['admin', 'private', 'search'], - canAccessAllEngines: true, - canViewAccountCredentials: true, - // Truncated for brevity - see utils/role/index.test.ts for full output - }), - }); + }, + account: { + accountId: 'some-id-string', + onboardingComplete: true, + role: DEFAULT_INITIAL_APP_DATA.appSearch.role, + }, + myRole: expect.objectContaining({ + id: 'account_id:somestring|user_oid:somestring', + roleType: 'owner', + availableRoleTypes: ['owner', 'admin'], + credentialTypes: ['admin', 'private', 'search'], + canAccessAllEngines: true, + canViewAccountCredentials: true, + // Truncated for brevity - see utils/role/index.test.ts for full output + }), }); + }); - it('gracefully handles missing initial data', () => { - AppLogic.actions.initializeAppData({}); + describe('actions', () => { + describe('setOnboardingComplete()', () => { + it('sets true', () => { + mount({ appSearch: { onboardingComplete: false } }); - expect(AppLogic.values).toEqual({ - ...DEFAULT_VALUES, - hasInitialized: true, + AppLogic.actions.setOnboardingComplete(); + expect(AppLogic.values.account.onboardingComplete).toEqual(true); }); }); }); - describe('setOnboardingComplete()', () => { - it('sets true', () => { - expect(AppLogic.values.account.onboardingComplete).toBeFalsy(); - AppLogic.actions.setOnboardingComplete(); - expect(AppLogic.values.account.onboardingComplete).toEqual(true); + describe('selectors', () => { + describe('myRole', () => { + it('falls back to an empty object if role is missing', () => { + mount({ appSearch: {} }); + + expect(AppLogic.values.myRole).toEqual({}); + }); }); }); }); diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/app_logic.ts b/x-pack/plugins/enterprise_search/public/applications/app_search/app_logic.ts index c33a0e89d2aeea..44416b596e6ef9 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/app_logic.ts +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/app_logic.ts @@ -14,53 +14,33 @@ import { ConfiguredLimits, Account, Role } from './types'; import { getRoleAbilities } from './utils/role'; interface AppValues { - hasInitialized: boolean; ilmEnabled: boolean; - configuredLimits: Partial; - account: Partial; - myRole: Partial; + configuredLimits: ConfiguredLimits; + account: Account; + myRole: Role; } interface AppActions { - initializeAppData(props: InitialAppData): Required; setOnboardingComplete(): boolean; } -export const AppLogic = kea>({ +export const AppLogic = kea>>({ path: ['enterprise_search', 'app_search', 'app_logic'], actions: { - initializeAppData: (props) => props, setOnboardingComplete: () => true, }, - reducers: { - hasInitialized: [ - false, - { - initializeAppData: () => true, - }, - ], + reducers: ({ props }) => ({ account: [ - {}, + props.appSearch, { - initializeAppData: (_, { appSearch: account }) => account || {}, setOnboardingComplete: (account) => ({ ...account, onboardingComplete: true, }), }, ], - configuredLimits: [ - {}, - { - initializeAppData: (_, { configuredLimits }) => configuredLimits?.appSearch || {}, - }, - ], - ilmEnabled: [ - false, - { - initializeAppData: (_, { ilmEnabled }) => !!ilmEnabled, - }, - ], - }, + configuredLimits: [props.configuredLimits.appSearch, {}], + ilmEnabled: [props.ilmEnabled, {}], + }), selectors: { myRole: [ (selectors) => [selectors.account], diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/document_creation/creation_mode_components/paste_json_text.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/document_creation/creation_mode_components/paste_json_text.tsx index 2d4a6de26333f1..a52a55569e4a20 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/document_creation/creation_mode_components/paste_json_text.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/document_creation/creation_mode_components/paste_json_text.tsx @@ -55,8 +55,11 @@ export const FlyoutHeader: React.FC = () => { }; export const FlyoutBody: React.FC = () => { - const { configuredLimits } = useValues(AppLogic); - const maxDocumentByteSize = configuredLimits?.engine?.maxDocumentByteSize; + const { + configuredLimits: { + engine: { maxDocumentByteSize }, + }, + } = useValues(AppLogic); const { textInput, errors } = useValues(DocumentCreationLogic); const { setTextInput } = useActions(DocumentCreationLogic); diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/document_creation/creation_mode_components/upload_json_file.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/document_creation/creation_mode_components/upload_json_file.tsx index 5d50ae55fcd109..5fb439715a60c1 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/document_creation/creation_mode_components/upload_json_file.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/document_creation/creation_mode_components/upload_json_file.tsx @@ -54,8 +54,11 @@ export const FlyoutHeader: React.FC = () => { }; export const FlyoutBody: React.FC = () => { - const { configuredLimits } = useValues(AppLogic); - const maxDocumentByteSize = configuredLimits?.engine?.maxDocumentByteSize; + const { + configuredLimits: { + engine: { maxDocumentByteSize }, + }, + } = useValues(AppLogic); const { isUploading, errors } = useValues(DocumentCreationLogic); const { setFileInput } = useActions(DocumentCreationLogic); diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/engines/constants.ts b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engines/constants.ts index 401d4ccd6d117b..e0e36afa8e0c4b 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/engines/constants.ts +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engines/constants.ts @@ -22,3 +22,25 @@ export const CREATE_AN_ENGINE_BUTTON_LABEL = i18n.translate( defaultMessage: 'Create an engine', } ); + +export const CREATE_A_META_ENGINE_BUTTON_LABEL = i18n.translate( + 'xpack.enterpriseSearch.appSearch.engines.createAMetaEngineButton.ButtonLabel', + { + defaultMessage: 'Create a meta engine', + } +); + +export const META_ENGINE_EMPTY_PROMPT_TITLE = i18n.translate( + 'xpack.enterpriseSearch.appSearch.engines.metaEngines.emptyPrompTitle', + { + defaultMessage: 'No meta engines yet', + } +); + +export const META_ENGINE_EMPTY_PROMPT_DESCRIPTION = i18n.translate( + 'xpack.enterpriseSearch.appSearch.engines.metaEngines.emptyPromptDescription', + { + defaultMessage: + 'Meta engines allow you to combine multiple engines into one searchable engine.', + } +); diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/engines/engines_overview.test.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engines/engines_overview.test.tsx index c25f27c81ff48b..5a3f7309407600 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/engines/engines_overview.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engines/engines_overview.test.tsx @@ -12,6 +12,8 @@ import React from 'react'; import { shallow, ShallowWrapper } from 'enzyme'; +import { EuiEmptyPrompt } from '@elastic/eui'; + import { LoadingState, EmptyState } from './components'; import { EnginesTable } from './engines_table'; @@ -19,7 +21,6 @@ import { EnginesOverview } from './'; describe('EnginesOverview', () => { const values = { - hasPlatinumLicense: false, dataLoading: false, engines: [], enginesMeta: { @@ -39,6 +40,7 @@ describe('EnginesOverview', () => { }, }, metaEnginesLoading: false, + hasPlatinumLicense: false, }; const actions = { loadEngines: jest.fn(), @@ -73,7 +75,7 @@ describe('EnginesOverview', () => { const valuesWithEngines = { ...values, dataLoading: false, - engines: ['dummy-engine'], + engines: ['test-engine'], enginesMeta: { page: { current: 1, @@ -84,6 +86,7 @@ describe('EnginesOverview', () => { }; beforeEach(() => { + jest.clearAllMocks(); setMockValues(valuesWithEngines); }); @@ -102,18 +105,47 @@ describe('EnginesOverview', () => { ).toEqual('/engine_creation'); }); - describe('when on a platinum license', () => { - it('renders a 2nd meta engines table & makes a 2nd meta engines API call', async () => { + describe('when user has a platinum license', () => { + let wrapper: ShallowWrapper; + + beforeEach(() => { setMockValues({ ...valuesWithEngines, hasPlatinumLicense: true, - metaEngines: ['dummy-meta-engine'], }); - const wrapper = shallow(); + wrapper = shallow(); + }); + it('renders a 2nd meta engines table ', async () => { expect(wrapper.find(EnginesTable)).toHaveLength(2); + }); + + it('makes a 2nd meta engines call', () => { expect(actions.loadMetaEngines).toHaveBeenCalled(); }); + + it('renders a create engine button which takes users to the create meta engine page', () => { + expect( + wrapper.find('[data-test-subj="appSearchEnginesMetaEngineCreationButton"]').prop('to') + ).toEqual('/meta_engine_creation'); + }); + + it('contains an EuiEmptyPrompt that takes users to the create meta when metaEngines is empty', () => { + setMockValues({ + ...valuesWithEngines, + hasPlatinumLicense: true, + metaEngines: [], + }); + wrapper = shallow(); + const metaEnginesTable = wrapper.find(EnginesTable).last().dive(); + const emptyPrompt = metaEnginesTable.dive().find(EuiEmptyPrompt).dive(); + + expect( + emptyPrompt + .find('[data-test-subj="appSearchMetaEnginesEmptyStateCreationButton"]') + .prop('to') + ).toEqual('/meta_engine_creation'); + }); }); describe('pagination', () => { @@ -150,7 +182,7 @@ describe('EnginesOverview', () => { setMockValues({ ...valuesWithEngines, hasPlatinumLicense: true, - metaEngines: ['dummy-meta-engine'], + metaEngines: ['test-meta-engine'], }); const wrapper = shallow(); const pageEvent = { page: { index: 0 } }; diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/engines/engines_overview.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engines/engines_overview.tsx index a26fe87365536c..4cfa5d90781620 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/engines/engines_overview.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engines/engines_overview.tsx @@ -16,6 +16,7 @@ import { EuiPageContentBody, EuiTitle, EuiSpacer, + EuiEmptyPrompt, } from '@elastic/eui'; import { FlashMessages } from '../../../shared/flash_messages'; @@ -24,12 +25,19 @@ import { LicensingLogic } from '../../../shared/licensing'; import { EuiButtonTo } from '../../../shared/react_router_helpers'; import { convertMetaToPagination, handlePageChange } from '../../../shared/table_pagination'; import { SendAppSearchTelemetry as SendTelemetry } from '../../../shared/telemetry'; -import { ENGINE_CREATION_PATH } from '../../routes'; +import { ENGINE_CREATION_PATH, META_ENGINE_CREATION_PATH } from '../../routes'; import { EngineIcon } from './assets/engine_icon'; import { MetaEngineIcon } from './assets/meta_engine_icon'; import { EnginesOverviewHeader, LoadingState, EmptyState } from './components'; -import { CREATE_AN_ENGINE_BUTTON_LABEL, ENGINES_TITLE, META_ENGINES_TITLE } from './constants'; +import { + CREATE_AN_ENGINE_BUTTON_LABEL, + CREATE_A_META_ENGINE_BUTTON_LABEL, + ENGINES_TITLE, + META_ENGINE_EMPTY_PROMPT_DESCRIPTION, + META_ENGINE_EMPTY_PROMPT_TITLE, + META_ENGINES_TITLE, +} from './constants'; import { EnginesLogic } from './engines_logic'; import { EnginesTable } from './engines_table'; @@ -37,6 +45,7 @@ import './engines_overview.scss'; export const EnginesOverview: React.FC = () => { const { hasPlatinumLicense } = useValues(LicensingLogic); + const { dataLoading, engines, @@ -46,6 +55,7 @@ export const EnginesOverview: React.FC = () => { metaEnginesMeta, metaEnginesLoading, } = useValues(EnginesLogic); + const { loadEngines, loadMetaEngines, onEnginesPagination, onMetaEnginesPagination } = useActions( EnginesLogic ); @@ -100,15 +110,27 @@ export const EnginesOverview: React.FC = () => { /> - {metaEngines.length > 0 && ( + {hasPlatinumLicense && ( <> - -

- {META_ENGINES_TITLE} -

-
+ + +

+ {META_ENGINES_TITLE} +

+
+
+ + + {CREATE_A_META_ENGINE_BUTTON_LABEL} + +
{ ...convertMetaToPagination(metaEnginesMeta), hidePerPageOptions: true, }} + noItemsMessage={ + {META_ENGINE_EMPTY_PROMPT_TITLE}} + body={

{META_ENGINE_EMPTY_PROMPT_DESCRIPTION}

} + actions={ + + {CREATE_A_META_ENGINE_BUTTON_LABEL} + + } + /> + } onChange={handlePageChange(onMetaEnginesPagination)} />
diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/engines/engines_table.test.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engines/engines_table.test.tsx index f8ad9bc6b2bc3b..51c65e1478d13e 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/engines/engines_table.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engines/engines_table.test.tsx @@ -88,6 +88,13 @@ describe('EnginesTable', () => { }); }); + describe('noItemsMessage', () => { + it('passes the noItemsMessage prop', () => { + const wrapper = mountWithIntl(); + expect(wrapper.find(EuiBasicTable).prop('noItemsMessage')).toEqual('No items.'); + }); + }); + describe('language field', () => { it('renders language when available', () => { const wrapper = mountWithIntl( diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/engines/engines_table.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engines/engines_table.tsx index fe61ba8cbcc43d..f542d123182443 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/engines/engines_table.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engines/engines_table.tsx @@ -5,7 +5,7 @@ * 2.0. */ -import React from 'react'; +import React, { ReactNode } from 'react'; import { useActions } from 'kea'; @@ -24,6 +24,7 @@ import { EngineDetails } from '../engine/types'; interface EnginesTableProps { items: EngineDetails[]; loading: boolean; + noItemsMessage?: ReactNode; pagination: { pageIndex: number; pageSize: number; @@ -36,6 +37,7 @@ interface EnginesTableProps { export const EnginesTable: React.FC = ({ items, loading, + noItemsMessage, pagination, onChange, }) => { @@ -148,6 +150,7 @@ export const EnginesTable: React.FC = ({ loading={loading} pagination={pagination} onChange={onChange} + noItemsMessage={noItemsMessage} /> ); }; diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/meta_engine_creation/constants.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/meta_engine_creation/constants.tsx new file mode 100644 index 00000000000000..aff5942d497a86 --- /dev/null +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/meta_engine_creation/constants.tsx @@ -0,0 +1,119 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React from 'react'; + +import { EuiLink } from '@elastic/eui'; +import { i18n } from '@kbn/i18n'; +import { FormattedMessage } from '@kbn/i18n/react'; + +import { DOCS_PREFIX } from '../../routes'; + +export const DEFAULT_LANGUAGE = 'Universal'; + +export const META_ENGINE_CREATION_TITLE = i18n.translate( + 'xpack.enterpriseSearch.appSearch.metaEngineCreation.title', + { + defaultMessage: 'Create a meta engine', + } +); + +export const META_ENGINE_CREATION_FORM_TITLE = i18n.translate( + 'xpack.enterpriseSearch.appSearch.metaEngineCreation.form.title', + { + defaultMessage: 'Name your meta engine', + } +); + +export const META_ENGINE_CREATION_FORM_SUBMIT_BUTTON_LABEL = i18n.translate( + 'xpack.enterpriseSearch.appSearch.metaEngineCreation.form.submitButton.buttonLabel', + { + defaultMessage: 'Create meta engine', + } +); + +export const META_ENGINE_CREATION_FORM_META_ENGINE_DESCRIPTION = i18n.translate( + 'xpack.enterpriseSearch.appSearch.metaEngineCreation.form.metaEngineDescription', + { + defaultMessage: + 'Meta engines allow you to combine multiple engines into one searchable engine.', + } +); + +export const META_ENGINE_CREATION_FORM_DOCUMENTATION_LINK = i18n.translate( + 'xpack.enterpriseSearch.appSearch.metaEngineCreation.form.documentationLink', + { + defaultMessage: 'Read the documentation', + } +); + +export const META_ENGINE_CREATION_FORM_DOCUMENTATION_DESCRIPTION = ( + + {META_ENGINE_CREATION_FORM_DOCUMENTATION_LINK} + + ), + }} + /> +); + +export const META_ENGINE_CREATION_FORM_ENGINE_NAME_LABEL = i18n.translate( + 'xpack.enterpriseSearch.appSearch.metaEngineCreation.form.engineName.label', + { + defaultMessage: 'Meta engine name', + } +); + +export const ALLOWED_CHARS_NOTE = i18n.translate( + 'xpack.enterpriseSearch.appSearch.metaEngineCreation.form.engineName.allowedCharactersHelpText', + { + defaultMessage: 'Meta engine names can only contain lowercase letters, numbers, and hyphens', + } +); + +export const SANITIZED_NAME_NOTE = i18n.translate( + 'xpack.enterpriseSearch.appSearch.metaEngineCreation.form.engineName.sanitizedNameHelpText', + { + defaultMessage: 'Your meta engine will be named', + } +); + +export const META_ENGINE_CREATION_FORM_ENGINE_NAME_PLACEHOLDER = i18n.translate( + 'xpack.enterpriseSearch.appSearch.metaEngineCreation.form.engineName.placeholder', + { + defaultMessage: 'i.e., my-meta-engine', + } +); + +export const META_ENGINE_CREATION_FORM_ENGINE_SOURCE_ENGINES_LABEL = i18n.translate( + 'xpack.enterpriseSearch.appSearch.metaEngineCreation.form.sourceEngines.label', + { + defaultMessage: 'Add source engines to this meta engine', + } +); + +export const META_ENGINE_CREATION_FORM_MAX_SOURCE_ENGINES_WARNING_TITLE = ( + maxEnginesPerMetaEngine: number +) => + i18n.translate( + 'xpack.enterpriseSearch.appSearch.metaEngineCreation.form.sourceEngines.maxSourceEnginesWarningTitle', + { + defaultMessage: 'Meta engines have a limit of {maxEnginesPerMetaEngine} source engines', + values: { maxEnginesPerMetaEngine }, + } + ); + +export const META_ENGINE_CREATION_SUCCESS_MESSAGE = i18n.translate( + 'xpack.enterpriseSearch.appSearch.metaEngineCreation.successMessage', + { + defaultMessage: 'Successfully created meta engine.', + } +); diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/meta_engine_creation/index.ts b/x-pack/plugins/enterprise_search/public/applications/app_search/components/meta_engine_creation/index.ts new file mode 100644 index 00000000000000..2d33322a84fc6d --- /dev/null +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/meta_engine_creation/index.ts @@ -0,0 +1,8 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +export { MetaEngineCreation } from './meta_engine_creation'; diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/meta_engine_creation/meta_engine_creation.test.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/meta_engine_creation/meta_engine_creation.test.tsx new file mode 100644 index 00000000000000..51ccc7b83b1fc1 --- /dev/null +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/meta_engine_creation/meta_engine_creation.test.tsx @@ -0,0 +1,187 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import '../../../__mocks__/shallow_useeffect.mock'; +import { setMockActions, setMockValues } from '../../../__mocks__'; + +import React from 'react'; + +import { shallow } from 'enzyme'; + +import { EuiCallOut } from '@elastic/eui'; + +import { MetaEngineCreation } from './'; + +const DEFAULT_VALUES = { + // MetaEngineLogic + name: 'test-meta-engine', + rawName: 'test-meta-engine', + indexedEngineNames: [], + selectedIndexedEngineNames: ['one'], + // AppLogic + configuredLimits: { engine: { maxEnginesPerMetaEngine: 10 } }, +}; + +const MOCK_ACTIONS = { + setRawName: jest.fn(), + setSelectedIndexedEngineNames: jest.fn(), + fetchIndexedEngineNames: jest.fn(), + submitEngine: jest.fn(), +}; + +describe('MetaEngineCreation', () => { + beforeEach(() => { + jest.clearAllMocks(); + setMockValues(DEFAULT_VALUES); + setMockActions(MOCK_ACTIONS); + }); + + it('renders and calls fetchIndexedEngineNames', () => { + const wrapper = shallow(); + expect(wrapper.find('[data-test-subj="MetaEngineCreation"]')).toHaveLength(1); + expect(MOCK_ACTIONS.fetchIndexedEngineNames).toHaveBeenCalledTimes(1); + }); + + describe('MetaEngineCreationNameInput', () => { + it('uses rawName as its value', () => { + const wrapper = shallow(); + expect( + wrapper + .find('[data-test-subj="MetaEngineCreationNameInput"]') + .render() + .find('input') // as far as I can tell I can't include this input in the .find() two lines above + .attr('value') + ).toEqual('test-meta-engine'); + }); + + it('EngineCreationForm calls submitEngine on form submit', () => { + const wrapper = shallow(); + const simulatedEvent = { + preventDefault: jest.fn(), + }; + wrapper.find('[data-test-subj="MetaEngineCreationForm"]').simulate('submit', simulatedEvent); + + expect(MOCK_ACTIONS.submitEngine).toHaveBeenCalledTimes(1); + }); + + it('MetaEngineCreationNameInput calls setRawName on change', () => { + const wrapper = shallow(); + const simulatedEvent = { + currentTarget: { value: 'new-raw-name' }, + }; + wrapper + .find('[data-test-subj="MetaEngineCreationNameInput"]') + .simulate('change', simulatedEvent); + expect(MOCK_ACTIONS.setRawName).toHaveBeenCalledWith('new-raw-name'); + }); + }); + + describe('EngineCreationNameFormRow', () => { + it('renders sanitized name helptext when the raw name is being sanitized', () => { + setMockValues({ + ...DEFAULT_VALUES, + name: 'name-with-special-characters', + rawName: 'Name__With#$&*%Special--Characters', + }); + + const wrapper = shallow(); + const formRow = wrapper.find('[data-test-subj="MetaEngineCreationNameFormRow"]').dive(); + + expect(formRow.contains('Your meta engine will be named')).toBeTruthy(); + }); + + it('renders allowed character helptext when rawName and sanitizedName match', () => { + setMockValues({ + ...DEFAULT_VALUES, + name: 'name-without-special-characters', + rawName: 'name-without-special-characters', + }); + + const wrapper = shallow(); + const formRow = wrapper.find('[data-test-subj="MetaEngineCreationNameFormRow"]').dive(); + + expect( + formRow.contains( + 'Meta engine names can only contain lowercase letters, numbers, and hyphens' + ) + ).toBeTruthy(); + }); + }); + + it('MetaEngineCreationSourceEnginesInput calls calls setSelectedIndexedEngines on change', () => { + const wrapper = shallow(); + + wrapper + .find('[data-test-subj="MetaEngineCreationSourceEnginesInput"]') + .simulate('change', [{ label: 'foo', value: 'foo' }]); + + expect(MOCK_ACTIONS.setSelectedIndexedEngineNames).toHaveBeenCalledWith(['foo']); + }); + + it('renders a warning callout when user has selected too many engines', () => { + setMockValues({ + ...DEFAULT_VALUES, + ...{ + selectedIndexedEngineNames: ['one', 'two', 'three'], + configuredLimits: { engine: { maxEnginesPerMetaEngine: 2 } }, + }, + }); + const wrapper = shallow(); + + expect(wrapper.find(EuiCallOut).prop('title')).toContain('Meta engines have a limit of'); + }); + + describe('NewMetaEngineSubmitButton', () => { + it('is enabled for a valid submission', () => { + const wrapper = shallow(); + const submitButton = wrapper.find('[data-test-subj="NewMetaEngineSubmitButton"]'); + + expect(submitButton.prop('disabled')).toEqual(false); + }); + + it('is disabled when name is empty', () => { + setMockValues({ + ...DEFAULT_VALUES, + ...{ + name: '', + rawName: '', + }, + }); + const wrapper = shallow(); + const submitButton = wrapper.find('[data-test-subj="NewMetaEngineSubmitButton"]'); + + expect(submitButton.prop('disabled')).toEqual(true); + }); + + it('is disabled when user has selected no engines', () => { + setMockValues({ + ...DEFAULT_VALUES, + ...{ + selectedIndexedEngineNames: [], + }, + }); + const wrapper = shallow(); + const submitButton = wrapper.find('[data-test-subj="NewMetaEngineSubmitButton"]'); + + expect(submitButton.prop('disabled')).toEqual(true); + }); + + it('is disabled when user has selected too many engines', () => { + setMockValues({ + ...DEFAULT_VALUES, + ...{ + selectedIndexedEngineNames: ['one', 'two', 'three'], + configuredLimits: { engine: { maxEnginesPerMetaEngine: 2 } }, + }, + }); + const wrapper = shallow(); + const submitButton = wrapper.find('[data-test-subj="NewMetaEngineSubmitButton"]'); + + expect(submitButton.prop('disabled')).toEqual(true); + }); + }); +}); diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/meta_engine_creation/meta_engine_creation.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/meta_engine_creation/meta_engine_creation.tsx new file mode 100644 index 00000000000000..d701ee37a16581 --- /dev/null +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/meta_engine_creation/meta_engine_creation.tsx @@ -0,0 +1,170 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React, { useEffect } from 'react'; + +import { useActions, useValues } from 'kea'; + +import { + EuiCallOut, + EuiComboBox, + EuiComboBoxOptionOption, + EuiForm, + EuiFlexGroup, + EuiFormRow, + EuiFlexItem, + EuiFieldText, + EuiPageContent, + EuiPageHeader, + EuiPageHeaderSection, + EuiSpacer, + EuiText, + EuiTitle, + EuiButton, +} from '@elastic/eui'; + +import { FlashMessages } from '../../../shared/flash_messages'; +import { SetAppSearchChrome as SetPageChrome } from '../../../shared/kibana_chrome'; +import { AppLogic } from '../../app_logic'; + +import { + ALLOWED_CHARS_NOTE, + META_ENGINE_CREATION_FORM_DOCUMENTATION_DESCRIPTION, + META_ENGINE_CREATION_FORM_ENGINE_NAME_LABEL, + META_ENGINE_CREATION_FORM_ENGINE_NAME_PLACEHOLDER, + META_ENGINE_CREATION_FORM_ENGINE_SOURCE_ENGINES_LABEL, + META_ENGINE_CREATION_FORM_MAX_SOURCE_ENGINES_WARNING_TITLE, + META_ENGINE_CREATION_FORM_META_ENGINE_DESCRIPTION, + META_ENGINE_CREATION_FORM_SUBMIT_BUTTON_LABEL, + META_ENGINE_CREATION_FORM_TITLE, + META_ENGINE_CREATION_TITLE, + SANITIZED_NAME_NOTE, +} from './constants'; +import { MetaEngineCreationLogic } from './meta_engine_creation_logic'; + +const engineNameToComboBoxOption = (engineName: string): EuiComboBoxOptionOption => ({ + label: engineName, +}); + +const comboBoxOptionToEngineName = (option: EuiComboBoxOptionOption): string => + option.label; + +export const MetaEngineCreation: React.FC = () => { + const { + configuredLimits: { + engine: { maxEnginesPerMetaEngine }, + }, + } = useValues(AppLogic); + + const { + fetchIndexedEngineNames, + setRawName, + setSelectedIndexedEngineNames, + submitEngine, + } = useActions(MetaEngineCreationLogic); + + const { rawName, name, indexedEngineNames, selectedIndexedEngineNames } = useValues( + MetaEngineCreationLogic + ); + + useEffect(() => { + fetchIndexedEngineNames(); + }, []); + + return ( +
+ + + + +

{META_ENGINE_CREATION_TITLE}

+
+ {META_ENGINE_CREATION_FORM_META_ENGINE_DESCRIPTION} + {META_ENGINE_CREATION_FORM_DOCUMENTATION_DESCRIPTION} +
+
+ + + { + e.preventDefault(); + submitEngine(); + }} + > + + {META_ENGINE_CREATION_FORM_TITLE} + + + + + 0 && rawName !== name ? ( + <> + {SANITIZED_NAME_NOTE} {name} + + ) : ( + ALLOWED_CHARS_NOTE + ) + } + fullWidth + > + setRawName(event.currentTarget.value)} + fullWidth + data-test-subj="MetaEngineCreationNameInput" + placeholder={META_ENGINE_CREATION_FORM_ENGINE_NAME_PLACEHOLDER} + autoFocus + /> + + + + + + { + setSelectedIndexedEngineNames(options.map(comboBoxOptionToEngineName)); + }} + /> + + + {selectedIndexedEngineNames.length > maxEnginesPerMetaEngine && ( + + )} + + maxEnginesPerMetaEngine + } + type="submit" + data-test-subj="NewMetaEngineSubmitButton" + fill + color="secondary" + > + {META_ENGINE_CREATION_FORM_SUBMIT_BUTTON_LABEL} + + + +
+ ); +}; diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/meta_engine_creation/meta_engine_creation_logic.test.ts b/x-pack/plugins/enterprise_search/public/applications/app_search/components/meta_engine_creation/meta_engine_creation_logic.test.ts new file mode 100644 index 00000000000000..6ffe7034584a16 --- /dev/null +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/meta_engine_creation/meta_engine_creation_logic.test.ts @@ -0,0 +1,175 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { + LogicMounter, + mockHttpValues, + mockFlashMessageHelpers, + mockKibanaValues, +} from '../../../__mocks__'; + +import { nextTick } from '@kbn/test/jest'; + +import { MetaEngineCreationLogic } from './meta_engine_creation_logic'; + +describe('MetaEngineCreationLogic', () => { + const { mount } = new LogicMounter(MetaEngineCreationLogic); + const { http } = mockHttpValues; + const { navigateToUrl } = mockKibanaValues; + const { setQueuedSuccessMessage, flashAPIErrors } = mockFlashMessageHelpers; + + const DEFAULT_VALUES = { + indexedEngineNames: [], + name: '', + rawName: '', + selectedIndexedEngineNames: [], + }; + + it('has expected default values', () => { + mount(); + expect(MetaEngineCreationLogic.values).toEqual(DEFAULT_VALUES); + }); + + describe('actions', () => { + describe('setRawName', () => { + beforeAll(() => { + jest.clearAllMocks(); + mount(); + MetaEngineCreationLogic.actions.setRawName('Name__With#$&*%Special--Characters'); + }); + + it('should set rawName to provided value', () => { + expect(MetaEngineCreationLogic.values.rawName).toEqual( + 'Name__With#$&*%Special--Characters' + ); + }); + + it('should set name to a sanitized value', () => { + expect(MetaEngineCreationLogic.values.name).toEqual('name-with-special-characters'); + }); + }); + + describe('setIndexedEngineNames', () => { + it('should set indexedEngineNames to provided value', () => { + mount(); + MetaEngineCreationLogic.actions.setIndexedEngineNames(['first', 'middle', 'last']); + expect(MetaEngineCreationLogic.values.indexedEngineNames).toEqual([ + 'first', + 'middle', + 'last', + ]); + }); + }); + + describe('setSelectedIndexedEngineNames', () => { + it('should set selectedIndexedEngineNames to provided value', () => { + mount(); + MetaEngineCreationLogic.actions.setSelectedIndexedEngineNames(['one', 'two', 'three']); + expect(MetaEngineCreationLogic.values.selectedIndexedEngineNames).toEqual([ + 'one', + 'two', + 'three', + ]); + }); + }); + }); + + describe('listeners', () => { + describe('fetchIndexedEngineNames', () => { + beforeEach(() => { + jest.clearAllMocks(); + }); + + it('calls flashAPIErrors on API Error', async () => { + http.get.mockReturnValueOnce(Promise.reject()); + MetaEngineCreationLogic.actions.fetchIndexedEngineNames(); + await nextTick(); + expect(flashAPIErrors).toHaveBeenCalledTimes(1); + }); + + it('calls onEngineCreationSuccess on valid submission', async () => { + jest.spyOn(MetaEngineCreationLogic.actions, 'setIndexedEngineNames'); + http.get.mockReturnValueOnce( + Promise.resolve({ results: [{ name: 'foo' }], meta: { page: { total_pages: 1 } } }) + ); + MetaEngineCreationLogic.actions.fetchIndexedEngineNames(); + await nextTick(); + expect(MetaEngineCreationLogic.actions.setIndexedEngineNames).toHaveBeenCalledWith(['foo']); + }); + + it('if there are remaining pages it should call fetchIndexedEngineNames recursively with an incremented page', async () => { + jest.spyOn(MetaEngineCreationLogic.actions, 'fetchIndexedEngineNames'); + http.get.mockReturnValueOnce( + Promise.resolve({ results: [{ name: 'foo' }], meta: { page: { total_pages: 2 } } }) + ); + MetaEngineCreationLogic.actions.fetchIndexedEngineNames(); + await nextTick(); + expect(MetaEngineCreationLogic.actions.fetchIndexedEngineNames).toHaveBeenCalledWith(2); + }); + + it('if there are no remaining pages it should end without calling recursively', async () => { + jest.spyOn(MetaEngineCreationLogic.actions, 'fetchIndexedEngineNames'); + http.get.mockReturnValueOnce( + Promise.resolve({ results: [{ name: 'foo' }], meta: { page: { total_pages: 1 } } }) + ); + MetaEngineCreationLogic.actions.fetchIndexedEngineNames(); + await nextTick(); + expect(MetaEngineCreationLogic.actions.fetchIndexedEngineNames).toHaveBeenCalledTimes(1); // it's one time cause we called it two lines above + }); + }); + + describe('onEngineCreationSuccess', () => { + beforeAll(() => { + jest.clearAllMocks(); + mount({ language: 'English', rawName: 'test' }); + MetaEngineCreationLogic.actions.onEngineCreationSuccess(); + }); + + it('should set a success message', () => { + expect(setQueuedSuccessMessage).toHaveBeenCalledWith('Successfully created meta engine.'); + }); + + it('should navigate the user to the engine page', () => { + expect(navigateToUrl).toHaveBeenCalledWith('/engines/test'); + }); + }); + + describe('submitEngine', () => { + beforeAll(() => { + jest.clearAllMocks(); + mount({ rawName: 'test', selectedIndexedEngineNames: ['foo'] }); + }); + + it('POSTS to /api/app_search/engines', () => { + const body = JSON.stringify({ + name: 'test', + type: 'meta', + source_engines: ['foo'], + }); + MetaEngineCreationLogic.actions.submitEngine(); + expect(http.post).toHaveBeenCalledWith('/api/app_search/engines', { body }); + }); + + it('calls onEngineCreationSuccess on valid submission', async () => { + jest.spyOn(MetaEngineCreationLogic.actions, 'onEngineCreationSuccess'); + http.post.mockReturnValueOnce(Promise.resolve({})); + MetaEngineCreationLogic.actions.submitEngine(); + await nextTick(); + expect(MetaEngineCreationLogic.actions.onEngineCreationSuccess).toHaveBeenCalledTimes(1); + }); + + it('calls flashAPIErrors on API Error', async () => { + jest.spyOn(MetaEngineCreationLogic.actions, 'setIndexedEngineNames'); + http.post.mockReturnValueOnce(Promise.reject()); + MetaEngineCreationLogic.actions.submitEngine(); + await nextTick(); + expect(flashAPIErrors).toHaveBeenCalledTimes(1); + expect(MetaEngineCreationLogic.actions.setIndexedEngineNames).not.toHaveBeenCalled(); + }); + }); + }); +}); diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/meta_engine_creation/meta_engine_creation_logic.ts b/x-pack/plugins/enterprise_search/public/applications/app_search/components/meta_engine_creation/meta_engine_creation_logic.ts new file mode 100644 index 00000000000000..d94eb82a49c0eb --- /dev/null +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/meta_engine_creation/meta_engine_creation_logic.ts @@ -0,0 +1,127 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { generatePath } from 'react-router-dom'; + +import { kea, MakeLogicType } from 'kea'; + +import { Meta } from '../../../../../common/types'; +import { DEFAULT_META } from '../../../shared/constants'; +import { flashAPIErrors, setQueuedSuccessMessage } from '../../../shared/flash_messages'; +import { HttpLogic } from '../../../shared/http'; +import { KibanaLogic } from '../../../shared/kibana'; +import { ENGINE_PATH } from '../../routes'; +import { formatApiName } from '../../utils/format_api_name'; +import { EngineDetails } from '../engine/types'; + +import { META_ENGINE_CREATION_SUCCESS_MESSAGE } from './constants'; + +interface MetaEngineCreationValues { + indexedEngineNames: string[]; + name: string; + rawName: string; + selectedIndexedEngineNames: string[]; +} + +interface MetaEngineCreationActions { + fetchIndexedEngineNames(page?: number): { page: number }; + onEngineCreationSuccess(): void; + setIndexedEngineNames( + indexedEngineNames: MetaEngineCreationValues['indexedEngineNames'] + ): { indexedEngineNames: MetaEngineCreationValues['indexedEngineNames'] }; + setRawName(rawName: string): { rawName: string }; + setSelectedIndexedEngineNames( + selectedIndexedEngineNames: MetaEngineCreationValues['selectedIndexedEngineNames'] + ): { selectedIndexedEngineNames: MetaEngineCreationValues['selectedIndexedEngineNames'] }; + submitEngine(): void; +} + +export const MetaEngineCreationLogic = kea< + MakeLogicType +>({ + path: ['enterprise_search', 'app_search', 'meta_engine_creation_logic'], + actions: { + fetchIndexedEngineNames: (page = DEFAULT_META.page.current) => ({ page }), + onEngineCreationSuccess: true, + setIndexedEngineNames: (indexedEngineNames) => ({ indexedEngineNames }), + setRawName: (rawName) => ({ rawName }), + setSelectedIndexedEngineNames: (selectedIndexedEngineNames) => ({ selectedIndexedEngineNames }), + submitEngine: () => null, + }, + reducers: { + indexedEngineNames: [ + [], + { + setIndexedEngineNames: (_, { indexedEngineNames }) => indexedEngineNames, + }, + ], + rawName: [ + '', + { + setRawName: (_, { rawName }) => rawName, + }, + ], + selectedIndexedEngineNames: [ + [], + { + setSelectedIndexedEngineNames: (_, { selectedIndexedEngineNames }) => + selectedIndexedEngineNames, + }, + ], + }, + selectors: ({ selectors }) => ({ + name: [() => [selectors.rawName], (rawName: string) => formatApiName(rawName)], + }), + listeners: ({ values, actions }) => ({ + fetchIndexedEngineNames: async ({ page }) => { + const { http } = HttpLogic.values; + let response: { results: EngineDetails[]; meta: Meta } | undefined; + + try { + response = await http.get('/api/app_search/engines', { + query: { type: 'indexed', 'page[current]': page, 'page[size]': DEFAULT_META.page.size }, + }); + } catch (e) { + flashAPIErrors(e); + } + + if (response) { + const engineNames = response.results.map((result) => result.name); + actions.setIndexedEngineNames([...values.indexedEngineNames, ...engineNames]); + + if (page < response.meta.page.total_pages) { + actions.fetchIndexedEngineNames(page + 1); + } + } + }, + onEngineCreationSuccess: () => { + const { name } = values; + const { navigateToUrl } = KibanaLogic.values; + const enginePath = generatePath(ENGINE_PATH, { engineName: name }); + + setQueuedSuccessMessage(META_ENGINE_CREATION_SUCCESS_MESSAGE); + navigateToUrl(enginePath); + }, + submitEngine: async () => { + const { http } = HttpLogic.values; + const { name, selectedIndexedEngineNames } = values; + + const body = JSON.stringify({ + name, + type: 'meta', + source_engines: selectedIndexedEngineNames, + }); + + try { + await http.post('/api/app_search/engines', { body }); + actions.onEngineCreationSuccess(); + } catch (e) { + flashAPIErrors(e); + } + }, + }), +}); diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/index.test.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/index.test.tsx index 5150a4996eb84d..6827f4f5e827d8 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/index.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/index.test.tsx @@ -5,22 +5,26 @@ * 2.0. */ -import '../__mocks__/shallow_useeffect.mock'; +import { DEFAULT_INITIAL_APP_DATA } from '../../../common/__mocks__'; import '../__mocks__/enterprise_search_url.mock'; -import { setMockValues, setMockActions } from '../__mocks__'; +import { setMockValues, rerender } from '../__mocks__'; import React from 'react'; import { Redirect } from 'react-router-dom'; -import { shallow } from 'enzyme'; +import { shallow, ShallowWrapper } from 'enzyme'; import { Layout, SideNav, SideNavLink } from '../shared/layout'; +jest.mock('./app_logic', () => ({ AppLogic: jest.fn() })); +import { AppLogic } from './app_logic'; + import { EngineRouter } from './components/engine'; import { EngineCreation } from './components/engine_creation'; import { EnginesOverview } from './components/engines'; import { ErrorConnecting } from './components/error_connecting'; +import { MetaEngineCreation } from './components/meta_engine_creation'; import { SetupGuide } from './components/setup_guide'; import { AppSearch, AppSearchUnconfigured, AppSearchConfigured, AppSearchNav } from './'; @@ -51,52 +55,34 @@ describe('AppSearchUnconfigured', () => { }); describe('AppSearchConfigured', () => { - beforeEach(() => { - // Mock resets + let wrapper: ShallowWrapper; + + beforeAll(() => { setMockValues({ myRole: {} }); - setMockActions({ initializeAppData: () => {} }); + wrapper = shallow(); }); it('renders with layout', () => { - const wrapper = shallow(); - expect(wrapper.find(Layout)).toHaveLength(2); expect(wrapper.find(Layout).last().prop('readOnlyMode')).toBeFalsy(); expect(wrapper.find(EnginesOverview)).toHaveLength(1); expect(wrapper.find(EngineRouter)).toHaveLength(1); }); - it('initializes app data with passed props', () => { - const initializeAppData = jest.fn(); - setMockActions({ initializeAppData }); - - shallow(); - - expect(initializeAppData).toHaveBeenCalledWith({ ilmEnabled: true }); - }); - - it('does not re-initialize app data', () => { - const initializeAppData = jest.fn(); - setMockActions({ initializeAppData }); - setMockValues({ myRole: {}, hasInitialized: true }); - - shallow(); - - expect(initializeAppData).not.toHaveBeenCalled(); + it('mounts AppLogic with passed initial data props', () => { + expect(AppLogic).toHaveBeenCalledWith(DEFAULT_INITIAL_APP_DATA); }); it('renders ErrorConnecting', () => { setMockValues({ myRole: {}, errorConnecting: true }); - - const wrapper = shallow(); + rerender(wrapper); expect(wrapper.find(ErrorConnecting)).toHaveLength(1); }); it('passes readOnlyMode state', () => { setMockValues({ myRole: {}, readOnlyMode: true }); - - const wrapper = shallow(); + rerender(wrapper); expect(wrapper.find(Layout).first().prop('readOnlyMode')).toEqual(true); }); @@ -105,18 +91,34 @@ describe('AppSearchConfigured', () => { describe('canManageEngines', () => { it('renders EngineCreation when user canManageEngines is true', () => { setMockValues({ myRole: { canManageEngines: true } }); - const wrapper = shallow(); + rerender(wrapper); expect(wrapper.find(EngineCreation)).toHaveLength(1); }); it('does not render EngineCreation when user canManageEngines is false', () => { setMockValues({ myRole: { canManageEngines: false } }); - const wrapper = shallow(); + rerender(wrapper); expect(wrapper.find(EngineCreation)).toHaveLength(0); }); }); + + describe('canManageMetaEngines', () => { + it('renders MetaEngineCreation when user canManageMetaEngines is true', () => { + setMockValues({ myRole: { canManageMetaEngines: true } }); + rerender(wrapper); + + expect(wrapper.find(MetaEngineCreation)).toHaveLength(1); + }); + + it('does not render MetaEngineCreation when user canManageMetaEngines is false', () => { + setMockValues({ myRole: { canManageMetaEngines: false } }); + rerender(wrapper); + + expect(wrapper.find(MetaEngineCreation)).toHaveLength(0); + }); + }); }); }); diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/index.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/index.tsx index 40dfc1426e4029..88db4004ea9e2a 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/index.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/index.tsx @@ -5,10 +5,10 @@ * 2.0. */ -import React, { useEffect } from 'react'; +import React from 'react'; import { Route, Redirect, Switch } from 'react-router-dom'; -import { useActions, useValues } from 'kea'; +import { useValues } from 'kea'; import { APP_SEARCH_PLUGIN } from '../../../common/constants'; import { InitialAppData } from '../../../common/types'; @@ -25,6 +25,7 @@ import { EngineCreation } from './components/engine_creation'; import { EnginesOverview, ENGINES_TITLE } from './components/engines'; import { ErrorConnecting } from './components/error_connecting'; import { Library } from './components/library'; +import { MetaEngineCreation } from './components/meta_engine_creation'; import { ROLE_MAPPINGS_TITLE } from './components/role_mappings'; import { Settings, SETTINGS_TITLE } from './components/settings'; import { SetupGuide } from './components/setup_guide'; @@ -38,11 +39,16 @@ import { ENGINES_PATH, ENGINE_PATH, LIBRARY_PATH, + META_ENGINE_CREATION_PATH, } from './routes'; export const AppSearch: React.FC = (props) => { const { config } = useValues(KibanaLogic); - return !config.host ? : ; + return !config.host ? ( + + ) : ( + )} /> + ); }; export const AppSearchUnconfigured: React.FC = () => ( @@ -56,18 +62,12 @@ export const AppSearchUnconfigured: React.FC = () => ( ); -export const AppSearchConfigured: React.FC = (props) => { - const { initializeAppData } = useActions(AppLogic); +export const AppSearchConfigured: React.FC> = (props) => { const { - hasInitialized, - myRole: { canManageEngines }, - } = useValues(AppLogic); + myRole: { canManageEngines, canManageMetaEngines }, + } = useValues(AppLogic(props)); const { errorConnecting, readOnlyMode } = useValues(HttpLogic); - useEffect(() => { - if (!hasInitialized) initializeAppData(props); - }, [hasInitialized]); - return ( @@ -106,6 +106,11 @@ export const AppSearchConfigured: React.FC = (props) => { )} + {canManageMetaEngines && ( + + + + )} diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/routes.ts b/x-pack/plugins/enterprise_search/public/applications/app_search/routes.ts index 6fe9be083405e0..907a27c8660d21 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/routes.ts +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/routes.ts @@ -40,6 +40,7 @@ export const ENGINE_REINDEX_JOB_PATH = `${ENGINE_PATH}/reindex-job/:activeReinde export const ENGINE_CRAWLER_PATH = `${ENGINE_PATH}/crawler`; // TODO: Crawler sub-pages +export const META_ENGINE_CREATION_PATH = '/meta_engine_creation'; export const META_ENGINE_SOURCE_ENGINES_PATH = `${ENGINE_PATH}/engines`; export const ENGINE_RELEVANCE_TUNING_PATH = `${ENGINE_PATH}/relevance_tuning`; diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/components/layout/nav.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/components/layout/nav.tsx index 16722c1554ddf0..f2edc04a5661c4 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/components/layout/nav.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/components/layout/nav.tsx @@ -10,7 +10,6 @@ import React from 'react'; import { EuiSpacer } from '@elastic/eui'; import { WORKPLACE_SEARCH_PLUGIN } from '../../../../../common/constants'; -import { getWorkplaceSearchUrl } from '../../../shared/enterprise_search_url'; import { SideNav, SideNavLink } from '../../../shared/layout'; import { NAV } from '../../constants'; import { @@ -43,9 +42,7 @@ export const WorkplaceSearchNav: React.FC = ({ {NAV.GROUPS} - - {NAV.ROLE_MAPPINGS} - + {NAV.ROLE_MAPPINGS} {NAV.SECURITY} {NAV.SETTINGS} diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/index.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/index.tsx index 3cd1a3bd136b89..656c93053e22bb 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/index.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/index.tsx @@ -26,6 +26,7 @@ import { SOURCES_PATH, PERSONAL_SOURCES_PATH, ORG_SETTINGS_PATH, + ROLE_MAPPINGS_PATH, SECURITY_PATH, } from './routes'; import { SourcesRouter } from './views/content_sources'; @@ -36,6 +37,7 @@ import { GroupsRouter } from './views/groups'; import { GroupSubNav } from './views/groups/components/group_sub_nav'; import { Overview } from './views/overview'; import { Overview as OverviewMVP } from './views/overview_mvp'; +import { RoleMappingsRouter } from './views/role_mappings'; import { Security } from './views/security'; import { SettingsRouter } from './views/settings'; import { SettingsSubNav } from './views/settings/components/settings_sub_nav'; @@ -111,6 +113,11 @@ export const WorkplaceSearchConfigured: React.FC = (props) => { + + } restrictWidth readOnlyMode={readOnlyMode}> + + + } restrictWidth readOnlyMode={readOnlyMode}> diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/routes.ts b/x-pack/plugins/enterprise_search/public/applications/workplace_search/routes.ts index 462f89abd6143c..50f6596a860c5f 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/routes.ts +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/routes.ts @@ -133,3 +133,4 @@ export const getReindexJobRoute = ( isOrganization: boolean ) => getSourcesPath(generatePath(REINDEX_JOB_PATH, { sourceId, activeReindexJobId }), isOrganization); +export const getRoleMappingPath = (roleId: string) => generatePath(ROLE_MAPPING_PATH, { roleId }); diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/types.ts b/x-pack/plugins/enterprise_search/public/applications/workplace_search/types.ts index 44e0fd5b6f2872..79fe6dc8c92cbd 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/types.ts +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/types.ts @@ -22,6 +22,8 @@ export interface Meta { page: MetaPage; } +export type Role = 'admin' | 'user'; + export interface Group { id: string; name: string; diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/role_mappings/constants.ts b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/role_mappings/constants.ts new file mode 100644 index 00000000000000..5930f7862cd83f --- /dev/null +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/role_mappings/constants.ts @@ -0,0 +1,105 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { i18n } from '@kbn/i18n'; + +export const DELETE_ROLE_MAPPING_MESSAGE = i18n.translate( + 'xpack.enterpriseSearch.workplaceSearch.roleMapping.deleteRoleMappingButtonMessage', + { + defaultMessage: + 'Are you sure you want to permanently delete this mapping? This action is not reversible and some users might lose access.', + } +); + +export const DEFAULT_GROUP_NAME = i18n.translate( + 'xpack.enterpriseSearch.workplaceSearch.roleMapping.defaultGroupName', + { + defaultMessage: 'Default', + } +); + +export const ADMIN_ROLE_TYPE_DESCRIPTION = i18n.translate( + 'xpack.enterpriseSearch.workplaceSearch.roleMapping.adminRoleTypeDescription', + { + defaultMessage: + 'Admins have complete access to all organization-wide settings, including content source, group and user management functionality.', + } +); + +export const USER_ROLE_TYPE_DESCRIPTION = i18n.translate( + 'xpack.enterpriseSearch.workplaceSearch.roleMapping.userRoleTypeDescription', + { + defaultMessage: + "Users' feature access is limited to search interfaces and personal settings management.", + } +); + +export const ROLE_SELECTOR_DISABLED_TEXT = i18n.translate( + 'xpack.enterpriseSearch.workplaceSearch.roleMapping.roleSelectorDisabledText', + { + defaultMessage: + 'You need at least one admin role mapping before you can create a user role mapping.', + } +); + +export const GROUP_ASSIGNMENT_TITLE = i18n.translate( + 'xpack.enterpriseSearch.workplaceSearch.roleMapping.groupAssignmentTitle', + { + defaultMessage: 'Group assignment', + } +); + +export const GROUP_ASSIGNMENT_INVALID_ERROR = i18n.translate( + 'xpack.enterpriseSearch.workplaceSearch.roleMapping.groupAssignmentInvalidError', + { + defaultMessage: 'At least one assigned group is required.', + } +); + +export const GROUP_ASSIGNMENT_ALL_GROUPS_LABEL = i18n.translate( + 'xpack.enterpriseSearch.workplaceSearch.roleMapping.groupAssignmentAllGroupsLabel', + { + defaultMessage: 'Include in all groups, including future groups', + } +); + +export const EMPTY_ROLE_MAPPINGS_TITLE = i18n.translate( + 'xpack.enterpriseSearch.workplaceSearch.roleMapping.emptyRoleMappingsTitle', + { + defaultMessage: 'No role mappings yet', + } +); + +export const EMPTY_ROLE_MAPPINGS_BODY = i18n.translate( + 'xpack.enterpriseSearch.workplaceSearch.roleMapping.emptyRoleMappingsBody', + { + defaultMessage: + 'New team members are assigned the admin role by default. An admin can access everything. Create a new role to override the default.', + } +); + +export const ROLE_MAPPINGS_TABLE_HEADER = i18n.translate( + 'xpack.enterpriseSearch.workplaceSearch.roleMapping.roleMappingsTableHeader', + { + defaultMessage: 'Group Access', + } +); + +export const ROLE_MAPPINGS_TITLE = i18n.translate( + 'xpack.enterpriseSearch.workplaceSearch.roleMapping.roleMappingsTitle', + { + defaultMessage: 'Users & roles', + } +); + +export const ROLE_MAPPINGS_DESCRIPTION = i18n.translate( + 'xpack.enterpriseSearch.workplaceSearch.roleMapping.roleMappingsDescription', + { + defaultMessage: + 'Define role mappings for elasticsearch-native and elasticsearch-saml authentication.', + } +); diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/role_mappings/index.ts b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/role_mappings/index.ts new file mode 100644 index 00000000000000..ce4b1de6e399d8 --- /dev/null +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/role_mappings/index.ts @@ -0,0 +1,8 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +export { RoleMappingsRouter } from './role_mappings_router'; diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/role_mappings/role_mapping.test.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/role_mappings/role_mapping.test.tsx new file mode 100644 index 00000000000000..4742b741c96401 --- /dev/null +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/role_mappings/role_mapping.test.tsx @@ -0,0 +1,121 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import '../../../__mocks__/shallow_useeffect.mock'; +import { setMockActions, setMockValues } from '../../../__mocks__'; + +import React from 'react'; + +import { shallow } from 'enzyme'; + +import { EuiCheckbox } from '@elastic/eui'; + +import { Loading } from '../../../shared/loading'; +import { + AttributeSelector, + DeleteMappingCallout, + RoleSelector, +} from '../../../shared/role_mapping'; +import { wsRoleMapping } from '../../../shared/role_mapping/__mocks__/roles'; + +import { RoleMapping } from './role_mapping'; + +describe('RoleMapping', () => { + const initializeRoleMappings = jest.fn(); + const initializeRoleMapping = jest.fn(); + const handleSaveMapping = jest.fn(); + const handleGroupSelectionChange = jest.fn(); + const handleAllGroupsSelectionChange = jest.fn(); + const handleAttributeValueChange = jest.fn(); + const handleAttributeSelectorChange = jest.fn(); + const handleDeleteMapping = jest.fn(); + const handleRoleChange = jest.fn(); + const handleAuthProviderChange = jest.fn(); + const resetState = jest.fn(); + const groups = [ + { + name: 'Group 1', + id: 'g1', + }, + { + name: 'Group 2', + id: 'g2', + }, + ]; + const mockValues = { + attributes: [], + elasticsearchRoles: [], + dataLoading: false, + roleType: 'admin', + roleMappings: [wsRoleMapping], + attributeValue: '', + attributeName: 'username', + availableGroups: groups, + selectedGroups: new Set(), + includeInAllGroups: false, + availableAuthProviders: [], + multipleAuthProvidersConfig: true, + selectedAuthProviders: [], + }; + + beforeEach(() => { + setMockActions({ + initializeRoleMappings, + initializeRoleMapping, + handleSaveMapping, + handleGroupSelectionChange, + handleAllGroupsSelectionChange, + handleAttributeValueChange, + handleAttributeSelectorChange, + handleDeleteMapping, + handleRoleChange, + handleAuthProviderChange, + resetState, + }); + setMockValues(mockValues); + }); + + it('renders', () => { + const wrapper = shallow(); + + expect(wrapper.find(AttributeSelector)).toHaveLength(1); + expect(wrapper.find(RoleSelector)).toHaveLength(2); + }); + + it('returns Loading when loading', () => { + setMockValues({ ...mockValues, dataLoading: true }); + const wrapper = shallow(); + + expect(wrapper.find(Loading)).toHaveLength(1); + }); + + it('hides DeleteMappingCallout for new mapping', () => { + const wrapper = shallow(); + + expect(wrapper.find(DeleteMappingCallout)).toHaveLength(0); + }); + + it('handles group checkbox click', () => { + const wrapper = shallow(); + wrapper + .find(EuiCheckbox) + .first() + .simulate('change', { target: { checked: true } }); + + expect(handleGroupSelectionChange).toHaveBeenCalledWith(groups[0].id, true); + }); + + it('handles all groups checkbox click', () => { + const wrapper = shallow(); + wrapper + .find(EuiCheckbox) + .last() + .simulate('change', { target: { checked: true } }); + + expect(handleAllGroupsSelectionChange).toHaveBeenCalledWith(true); + }); +}); diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/role_mappings/role_mapping.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/role_mappings/role_mapping.tsx new file mode 100644 index 00000000000000..b2911bbcc64c26 --- /dev/null +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/role_mappings/role_mapping.tsx @@ -0,0 +1,216 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React, { useEffect } from 'react'; + +import { useParams } from 'react-router-dom'; + +import { useActions, useValues } from 'kea'; + +import { + EuiButton, + EuiCheckbox, + EuiFlexGroup, + EuiFlexItem, + EuiFormRow, + EuiPanel, + EuiSpacer, + EuiTitle, +} from '@elastic/eui'; +import { i18n } from '@kbn/i18n'; + +import { FlashMessages } from '../../../shared/flash_messages'; +import { Loading } from '../../../shared/loading'; +import { + AttributeSelector, + DeleteMappingCallout, + RoleSelector, +} from '../../../shared/role_mapping'; +import { ROLE_LABEL } from '../../../shared/role_mapping/constants'; +import { ViewContentHeader } from '../../components/shared/view_content_header'; +import { Role } from '../../types'; + +import { + ADMIN_ROLE_TYPE_DESCRIPTION, + USER_ROLE_TYPE_DESCRIPTION, + ROLE_SELECTOR_DISABLED_TEXT, + GROUP_ASSIGNMENT_TITLE, + GROUP_ASSIGNMENT_INVALID_ERROR, + GROUP_ASSIGNMENT_ALL_GROUPS_LABEL, +} from './constants'; + +import { RoleMappingsLogic } from './role_mappings_logic'; + +interface RoleType { + type: Role; + description: string; +} + +const roleTypes = [ + { + type: 'admin', + description: ADMIN_ROLE_TYPE_DESCRIPTION, + }, + { + type: 'user', + description: USER_ROLE_TYPE_DESCRIPTION, + }, +] as RoleType[]; + +interface RoleMappingProps { + isNew?: boolean; +} + +export const RoleMapping: React.FC = ({ isNew }) => { + const { roleId } = useParams() as { roleId: string }; + const { + initializeRoleMappings, + initializeRoleMapping, + handleSaveMapping, + handleGroupSelectionChange, + handleAllGroupsSelectionChange, + handleAttributeValueChange, + handleAttributeSelectorChange, + handleDeleteMapping, + handleRoleChange, + handleAuthProviderChange, + resetState, + } = useActions(RoleMappingsLogic); + + const { + attributes, + elasticsearchRoles, + dataLoading, + roleType, + roleMappings, + attributeValue, + attributeName, + availableGroups, + selectedGroups, + includeInAllGroups, + availableAuthProviders, + multipleAuthProvidersConfig, + selectedAuthProviders, + } = useValues(RoleMappingsLogic); + + useEffect(() => { + initializeRoleMappings(); + initializeRoleMapping(roleId); + return resetState; + }, [roleId]); + + if (dataLoading) return ; + + const hasGroupAssignment = selectedGroups.size > 0 || includeInAllGroups; + + const SAVE_ROLE_MAPPING_LABEL = i18n.translate( + 'xpack.enterpriseSearch.workplaceSearch.roleMapping.saveRoleMappingButtonMessage', + { + defaultMessage: '{operation} role mapping', + values: { operation: isNew ? 'Save' : 'Update' }, + } + ); + + const saveRoleMappingButton = ( + + {SAVE_ROLE_MAPPING_LABEL} + + ); + + const hasAdminRoleMapping = roleMappings.some( + ({ roleType: roleMappingRoleType }: { roleType: string }) => + roleMappingRoleType === ('admin' as string) + ); + + return ( + <> + + +
+ + + + + + + +

{ROLE_LABEL}

+
+ + {roleTypes.map(({ type, description }) => ( + + ))} +
+
+ + + +

{GROUP_ASSIGNMENT_TITLE}

+
+ +
+ + <> + {availableGroups.map(({ id, name }) => ( + { + handleGroupSelectionChange(id, e.target.checked); + }} + label={name} + disabled={includeInAllGroups} + /> + ))} + + { + handleAllGroupsSelectionChange(e.target.checked); + }} + label={GROUP_ASSIGNMENT_ALL_GROUPS_LABEL} + /> + + +
+
+
+
+ + {!isNew && } +
+ + ); +}; diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/role_mappings/role_mappings.test.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/role_mappings/role_mappings.test.tsx new file mode 100644 index 00000000000000..c6da903e209128 --- /dev/null +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/role_mappings/role_mappings.test.tsx @@ -0,0 +1,57 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import '../../../__mocks__/shallow_useeffect.mock'; +import { setMockActions, setMockValues } from '../../../__mocks__'; + +import React from 'react'; + +import { shallow } from 'enzyme'; + +import { EuiEmptyPrompt } from '@elastic/eui'; + +import { Loading } from '../../../shared/loading'; +import { RoleMappingsTable } from '../../../shared/role_mapping'; +import { wsRoleMapping } from '../../../shared/role_mapping/__mocks__/roles'; + +import { RoleMappings } from './role_mappings'; + +describe('RoleMappings', () => { + const initializeRoleMappings = jest.fn(); + const mockValues = { + roleMappings: [wsRoleMapping], + dataLoading: false, + multipleAuthProvidersConfig: false, + }; + + beforeEach(() => { + setMockActions({ + initializeRoleMappings, + }); + setMockValues(mockValues); + }); + + it('renders', () => { + const wrapper = shallow(); + + expect(wrapper.find(RoleMappingsTable)).toHaveLength(1); + }); + + it('returns Loading when loading', () => { + setMockValues({ ...mockValues, dataLoading: true }); + const wrapper = shallow(); + + expect(wrapper.find(Loading)).toHaveLength(1); + }); + + it('renders empty state', () => { + setMockValues({ ...mockValues, roleMappings: [] }); + const wrapper = shallow(); + + expect(wrapper.find(EuiEmptyPrompt)).toHaveLength(1); + }); +}); diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/role_mappings/role_mappings.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/role_mappings/role_mappings.tsx new file mode 100644 index 00000000000000..e47b2646459df2 --- /dev/null +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/role_mappings/role_mappings.tsx @@ -0,0 +1,70 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React, { useEffect } from 'react'; + +import { useActions, useValues } from 'kea'; + +import { EuiEmptyPrompt } from '@elastic/eui'; + +import { FlashMessages } from '../../../shared/flash_messages'; +import { Loading } from '../../../shared/loading'; +import { AddRoleMappingButton, RoleMappingsTable } from '../../../shared/role_mapping'; +import { ViewContentHeader } from '../../components/shared/view_content_header'; +import { getRoleMappingPath, ROLE_MAPPING_NEW_PATH } from '../../routes'; + +import { + EMPTY_ROLE_MAPPINGS_TITLE, + EMPTY_ROLE_MAPPINGS_BODY, + ROLE_MAPPINGS_TABLE_HEADER, + ROLE_MAPPINGS_TITLE, + ROLE_MAPPINGS_DESCRIPTION, +} from './constants'; + +import { RoleMappingsLogic } from './role_mappings_logic'; + +export const RoleMappings: React.FC = () => { + const { initializeRoleMappings } = useActions(RoleMappingsLogic); + + const { roleMappings, dataLoading, multipleAuthProvidersConfig } = useValues(RoleMappingsLogic); + + useEffect(() => { + initializeRoleMappings(); + }, []); + + if (dataLoading) return ; + + const addMappingButton = ; + const emptyPrompt = ( + {EMPTY_ROLE_MAPPINGS_TITLE}} + body={

{EMPTY_ROLE_MAPPINGS_BODY}

} + actions={addMappingButton} + /> + ); + const roleMappingsTable = ( + + ); + + return ( + <> + +
+ + {roleMappings.length === 0 ? emptyPrompt : roleMappingsTable} +
+ + ); +}; diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/role_mappings/role_mappings_logic.test.ts b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/role_mappings/role_mappings_logic.test.ts new file mode 100644 index 00000000000000..a9526d9450993d --- /dev/null +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/role_mappings/role_mappings_logic.test.ts @@ -0,0 +1,394 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { mockFlashMessageHelpers, mockHttpValues, mockKibanaValues } from '../../../__mocks__'; +import { LogicMounter } from '../../../__mocks__/kea.mock'; + +import { groups } from '../../__mocks__/groups.mock'; + +import { nextTick } from '@kbn/test/jest'; + +import { wsRoleMapping } from '../../../shared/role_mapping/__mocks__/roles'; +import { ANY_AUTH_PROVIDER } from '../../../shared/role_mapping/constants'; + +import { RoleMappingsLogic } from './role_mappings_logic'; + +describe('RoleMappingsLogic', () => { + const { http } = mockHttpValues; + const { navigateToUrl } = mockKibanaValues; + const { clearFlashMessages, flashAPIErrors } = mockFlashMessageHelpers; + const { mount } = new LogicMounter(RoleMappingsLogic); + const defaultValues = { + attributes: [], + availableAuthProviders: [], + elasticsearchRoles: [], + roleMapping: null, + roleMappings: [], + roleType: 'admin', + attributeValue: '', + attributeName: 'username', + dataLoading: true, + multipleAuthProvidersConfig: false, + availableGroups: [], + selectedGroups: new Set(), + includeInAllGroups: false, + selectedAuthProviders: [ANY_AUTH_PROVIDER], + }; + const roleGroup = { + id: '123', + name: 'Role Group', + }; + const defaultGroup = { + id: '124', + name: 'Default', + }; + + const mappingsServerProps = { multipleAuthProvidersConfig: true, roleMappings: [wsRoleMapping] }; + const mappingServerProps = { + attributes: [], + authProviders: [], + availableGroups: [roleGroup, defaultGroup], + elasticsearchRoles: [], + multipleAuthProvidersConfig: false, + roleMapping: wsRoleMapping, + }; + + beforeEach(() => { + jest.clearAllMocks(); + mount(); + }); + + it('has expected default values', () => { + expect(RoleMappingsLogic.values).toEqual(defaultValues); + }); + + describe('actions', () => { + it('setRoleMappingsData', () => { + RoleMappingsLogic.actions.setRoleMappingsData(mappingsServerProps); + + expect(RoleMappingsLogic.values.roleMappings).toEqual([wsRoleMapping]); + expect(RoleMappingsLogic.values.dataLoading).toEqual(false); + expect(RoleMappingsLogic.values.multipleAuthProvidersConfig).toEqual(true); + }); + + describe('setRoleMappingData', () => { + it('sets data correctly', () => { + RoleMappingsLogic.actions.setRoleMappingData(mappingServerProps); + + expect(RoleMappingsLogic.values.roleMapping).toEqual(wsRoleMapping); + expect(RoleMappingsLogic.values.dataLoading).toEqual(false); + expect(RoleMappingsLogic.values.attributes).toEqual(mappingServerProps.attributes); + expect(RoleMappingsLogic.values.availableGroups).toEqual( + mappingServerProps.availableGroups + ); + expect(RoleMappingsLogic.values.includeInAllGroups).toEqual(true); + expect(RoleMappingsLogic.values.elasticsearchRoles).toEqual( + mappingServerProps.elasticsearchRoles + ); + expect(RoleMappingsLogic.values.selectedGroups).toEqual( + new Set([wsRoleMapping.groups[0].id]) + ); + }); + + it('sets default group with new role mapping', () => { + RoleMappingsLogic.actions.setRoleMappingData({ + ...mappingServerProps, + roleMapping: undefined, + }); + + expect(RoleMappingsLogic.values.selectedGroups).toEqual(new Set([defaultGroup.id])); + }); + }); + + it('handleRoleChange', () => { + RoleMappingsLogic.actions.handleRoleChange('user'); + + expect(RoleMappingsLogic.values.roleType).toEqual('user'); + }); + + it('handleGroupSelectionChange', () => { + const group = wsRoleMapping.groups[0]; + const otherGroup = groups[0]; + RoleMappingsLogic.actions.setRoleMappingData({ + ...mappingServerProps, + roleMapping: { + ...wsRoleMapping, + groups: [group, otherGroup], + }, + }); + + RoleMappingsLogic.actions.handleGroupSelectionChange(otherGroup.id, true); + expect(RoleMappingsLogic.values.selectedGroups).toEqual(new Set([group.id, otherGroup.id])); + + RoleMappingsLogic.actions.handleGroupSelectionChange(otherGroup.id, false); + expect(RoleMappingsLogic.values.selectedGroups).toEqual(new Set([group.id])); + }); + + it('handleAllGroupsSelectionChange', () => { + RoleMappingsLogic.actions.handleAllGroupsSelectionChange(true); + + expect(RoleMappingsLogic.values.includeInAllGroups).toEqual(true); + }); + + describe('handleAttributeSelectorChange', () => { + const elasticsearchRoles = ['foo', 'bar']; + + it('sets values correctly', () => { + RoleMappingsLogic.actions.setRoleMappingData({ + ...mappingServerProps, + elasticsearchRoles, + }); + RoleMappingsLogic.actions.handleAttributeSelectorChange('role', elasticsearchRoles[0]); + + expect(RoleMappingsLogic.values.attributeValue).toEqual(elasticsearchRoles[0]); + expect(RoleMappingsLogic.values.attributeName).toEqual('role'); + }); + + it('correctly handles "role" fallback', () => { + RoleMappingsLogic.actions.handleAttributeSelectorChange('username', elasticsearchRoles[0]); + + expect(RoleMappingsLogic.values.attributeValue).toEqual(''); + }); + }); + + it('handleAttributeValueChange', () => { + RoleMappingsLogic.actions.handleAttributeValueChange('changed_value'); + + expect(RoleMappingsLogic.values.attributeValue).toEqual('changed_value'); + }); + + describe('handleAuthProviderChange', () => { + beforeEach(() => { + RoleMappingsLogic.actions.setRoleMappingData({ + ...mappingServerProps, + roleMapping: { + ...wsRoleMapping, + authProvider: ['foo'], + }, + }); + }); + const providers = ['bar', 'baz']; + const providerWithAny = [ANY_AUTH_PROVIDER, providers[1]]; + it('handles empty state', () => { + RoleMappingsLogic.actions.handleAuthProviderChange([]); + + expect(RoleMappingsLogic.values.selectedAuthProviders).toEqual([ANY_AUTH_PROVIDER]); + }); + + it('handles single value', () => { + RoleMappingsLogic.actions.handleAuthProviderChange([providers[0]]); + + expect(RoleMappingsLogic.values.selectedAuthProviders).toEqual([providers[0]]); + }); + + it('handles multiple values', () => { + RoleMappingsLogic.actions.handleAuthProviderChange(providers); + + expect(RoleMappingsLogic.values.selectedAuthProviders).toEqual(providers); + }); + + it('handles "any" auth in previous state', () => { + RoleMappingsLogic.actions.setRoleMappingData({ + ...mappingServerProps, + roleMapping: { + ...wsRoleMapping, + authProvider: [ANY_AUTH_PROVIDER], + }, + }); + RoleMappingsLogic.actions.handleAuthProviderChange(providerWithAny); + + expect(RoleMappingsLogic.values.selectedAuthProviders).toEqual([providers[1]]); + }); + + it('handles catch-all state', () => { + RoleMappingsLogic.actions.handleAuthProviderChange(providerWithAny); + + expect(RoleMappingsLogic.values.selectedAuthProviders).toEqual([ANY_AUTH_PROVIDER]); + }); + }); + + it('resetState', () => { + RoleMappingsLogic.actions.setRoleMappingsData(mappingsServerProps); + RoleMappingsLogic.actions.setRoleMappingData(mappingServerProps); + RoleMappingsLogic.actions.resetState(); + + expect(RoleMappingsLogic.values.dataLoading).toEqual(true); + expect(RoleMappingsLogic.values.roleMappings).toEqual([]); + expect(RoleMappingsLogic.values.roleMapping).toEqual(null); + expect(RoleMappingsLogic.values.attributeValue).toEqual(''); + expect(RoleMappingsLogic.values.attributeName).toEqual('username'); + expect(clearFlashMessages).toHaveBeenCalled(); + }); + }); + + describe('listeners', () => { + describe('initializeRoleMappings', () => { + it('calls API and sets values', async () => { + const setRoleMappingsDataSpy = jest.spyOn(RoleMappingsLogic.actions, 'setRoleMappingsData'); + http.get.mockReturnValue(Promise.resolve(mappingsServerProps)); + RoleMappingsLogic.actions.initializeRoleMappings(); + + expect(http.get).toHaveBeenCalledWith('/api/workplace_search/org/role_mappings'); + await nextTick(); + expect(setRoleMappingsDataSpy).toHaveBeenCalledWith(mappingsServerProps); + }); + + it('handles error', async () => { + http.get.mockReturnValue(Promise.reject('this is an error')); + RoleMappingsLogic.actions.initializeRoleMappings(); + await nextTick(); + + expect(flashAPIErrors).toHaveBeenCalledWith('this is an error'); + }); + }); + + describe('initializeRoleMapping', () => { + it('calls API and sets values for new mapping', async () => { + const setRoleMappingDataSpy = jest.spyOn(RoleMappingsLogic.actions, 'setRoleMappingData'); + http.get.mockReturnValue(Promise.resolve(mappingServerProps)); + RoleMappingsLogic.actions.initializeRoleMapping(); + + expect(http.get).toHaveBeenCalledWith('/api/workplace_search/org/role_mappings/new'); + await nextTick(); + expect(setRoleMappingDataSpy).toHaveBeenCalledWith(mappingServerProps); + }); + + it('calls API and sets values for existing mapping', async () => { + const setRoleMappingDataSpy = jest.spyOn(RoleMappingsLogic.actions, 'setRoleMappingData'); + http.get.mockReturnValue(Promise.resolve(mappingServerProps)); + RoleMappingsLogic.actions.initializeRoleMapping('123'); + + expect(http.get).toHaveBeenCalledWith('/api/workplace_search/org/role_mappings/123'); + await nextTick(); + expect(setRoleMappingDataSpy).toHaveBeenCalledWith(mappingServerProps); + }); + + it('handles error', async () => { + http.get.mockReturnValue(Promise.reject('this is an error')); + RoleMappingsLogic.actions.initializeRoleMapping(); + await nextTick(); + + expect(flashAPIErrors).toHaveBeenCalledWith('this is an error'); + }); + + it('redirects when there is a 404 status', async () => { + http.get.mockReturnValue(Promise.reject({ status: 404 })); + RoleMappingsLogic.actions.initializeRoleMapping(); + await nextTick(); + + expect(navigateToUrl).toHaveBeenCalled(); + }); + }); + + describe('handleSaveMapping', () => { + it('calls API and navigates when new mapping', async () => { + RoleMappingsLogic.actions.setRoleMappingsData(mappingsServerProps); + + http.post.mockReturnValue(Promise.resolve(mappingServerProps)); + RoleMappingsLogic.actions.handleSaveMapping(); + + expect(http.post).toHaveBeenCalledWith('/api/workplace_search/org/role_mappings', { + body: JSON.stringify({ + rules: { + username: '', + }, + roleType: 'admin', + groups: [], + allGroups: false, + authProvider: [ANY_AUTH_PROVIDER], + }), + }); + await nextTick(); + + expect(navigateToUrl).toHaveBeenCalled(); + }); + + it('calls API and navigates when existing mapping', async () => { + RoleMappingsLogic.actions.setRoleMappingData(mappingServerProps); + + http.put.mockReturnValue(Promise.resolve(mappingServerProps)); + RoleMappingsLogic.actions.handleSaveMapping(); + + expect(http.put).toHaveBeenCalledWith( + `/api/workplace_search/org/role_mappings/${wsRoleMapping.id}`, + { + body: JSON.stringify({ + rules: { + username: 'user', + }, + roleType: 'admin', + groups: [], + allGroups: true, + authProvider: [ANY_AUTH_PROVIDER, 'other_auth'], + }), + } + ); + await nextTick(); + + expect(navigateToUrl).toHaveBeenCalled(); + }); + + it('handles error', async () => { + http.post.mockReturnValue(Promise.reject('this is an error')); + RoleMappingsLogic.actions.handleSaveMapping(); + await nextTick(); + + expect(flashAPIErrors).toHaveBeenCalledWith('this is an error'); + }); + }); + + describe('handleDeleteMapping', () => { + let confirmSpy: any; + + beforeEach(() => { + confirmSpy = jest.spyOn(window, 'confirm'); + confirmSpy.mockImplementation(jest.fn(() => true)); + }); + + afterEach(() => { + confirmSpy.mockRestore(); + }); + + it('returns when no mapping', () => { + RoleMappingsLogic.actions.handleDeleteMapping(); + + expect(http.delete).not.toHaveBeenCalled(); + }); + + it('calls API and navigates', async () => { + RoleMappingsLogic.actions.setRoleMappingData(mappingServerProps); + http.delete.mockReturnValue(Promise.resolve({})); + RoleMappingsLogic.actions.handleDeleteMapping(); + + expect(http.delete).toHaveBeenCalledWith( + `/api/workplace_search/org/role_mappings/${wsRoleMapping.id}` + ); + await nextTick(); + + expect(navigateToUrl).toHaveBeenCalled(); + }); + + it('handles error', async () => { + RoleMappingsLogic.actions.setRoleMappingData(mappingServerProps); + http.delete.mockReturnValue(Promise.reject('this is an error')); + RoleMappingsLogic.actions.handleDeleteMapping(); + await nextTick(); + + expect(flashAPIErrors).toHaveBeenCalledWith('this is an error'); + }); + + it('will do nothing if not confirmed', async () => { + RoleMappingsLogic.actions.setRoleMappingData(mappingServerProps); + window.confirm = () => false; + RoleMappingsLogic.actions.handleDeleteMapping(); + + expect(http.delete).not.toHaveBeenCalled(); + await nextTick(); + }); + }); + }); +}); diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/role_mappings/role_mappings_logic.ts b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/role_mappings/role_mappings_logic.ts new file mode 100644 index 00000000000000..6fc3867d7ab1ef --- /dev/null +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/role_mappings/role_mappings_logic.ts @@ -0,0 +1,311 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { kea, MakeLogicType } from 'kea'; + +import { clearFlashMessages, flashAPIErrors } from '../../../shared/flash_messages'; +import { HttpLogic } from '../../../shared/http'; +import { KibanaLogic } from '../../../shared/kibana'; +import { AttributeName } from '../../../shared/role_mapping/attribute_selector'; +import { ANY_AUTH_PROVIDER } from '../../../shared/role_mapping/constants'; +import { ROLE_MAPPINGS_PATH } from '../../routes'; +import { RoleGroup, WSRoleMapping, Role } from '../../types'; + +import { DELETE_ROLE_MAPPING_MESSAGE, DEFAULT_GROUP_NAME } from './constants'; + +interface RoleMappingsServerDetails { + multipleAuthProvidersConfig: boolean; + roleMappings: WSRoleMapping[]; +} + +interface RoleMappingServerDetails { + attributes: string[]; + authProviders: string[]; + availableGroups: RoleGroup[]; + elasticsearchRoles: string[]; + multipleAuthProvidersConfig: boolean; + roleMapping?: WSRoleMapping; +} + +interface RoleMappingsActions { + setRoleMappingsData(data: RoleMappingsServerDetails): RoleMappingsServerDetails; + setRoleMappingData(data: RoleMappingServerDetails): RoleMappingServerDetails; + handleRoleChange(roleType: Role): { roleType: Role }; + handleAllGroupsSelectionChange(selected: boolean): { selected: boolean }; + handleAttributeSelectorChange( + value: AttributeName, + firstElasticsearchRole: string + ): { value: AttributeName; firstElasticsearchRole: string }; + handleAttributeValueChange(value: string): { value: string }; + handleGroupSelectionChange( + groupId: string, + selected: boolean + ): { groupId: string; selected: boolean }; + handleAuthProviderChange(value: string[]): { value: string[] }; + resetState(): void; + initializeRoleMapping(roleId?: string): { roleId?: string }; + handleSaveMapping(): void; + handleDeleteMapping(): void; + initializeRoleMappings(): void; +} + +interface RoleMappingsValues { + attributes: string[]; + availableAuthProviders: string[]; + elasticsearchRoles: string[]; + roleMapping: WSRoleMapping | null; + roleMappings: WSRoleMapping[]; + roleType: Role; + attributeValue: string; + attributeName: AttributeName; + dataLoading: boolean; + multipleAuthProvidersConfig: boolean; + availableGroups: RoleGroup[]; + selectedGroups: Set; + includeInAllGroups: boolean; + selectedAuthProviders: string[]; +} + +const getFirstAttributeName = (roleMapping: WSRoleMapping): AttributeName => + Object.entries(roleMapping.rules)[0][0] as AttributeName; +const getFirstAttributeValue = (roleMapping: WSRoleMapping): string => + Object.entries(roleMapping.rules)[0][1] as string; + +export const RoleMappingsLogic = kea>({ + actions: { + setRoleMappingsData: (data: RoleMappingsServerDetails) => data, + setRoleMappingData: (data: RoleMappingServerDetails) => data, + handleRoleChange: (roleType: Role) => ({ roleType }), + handleGroupSelectionChange: (groupId: string, selected: boolean) => ({ groupId, selected }), + handleAllGroupsSelectionChange: (selected: boolean) => ({ selected }), + handleAttributeSelectorChange: (value: string, firstElasticsearchRole: string) => ({ + value, + firstElasticsearchRole, + }), + handleAttributeValueChange: (value: string) => ({ value }), + handleAuthProviderChange: (value: string[]) => ({ value }), + resetState: () => true, + initializeRoleMapping: (roleId?: string) => ({ roleId }), + handleSaveMapping: () => true, + handleDeleteMapping: () => true, + initializeRoleMappings: () => true, + }, + reducers: { + dataLoading: [ + true, + { + setRoleMappingsData: () => false, + setRoleMappingData: () => false, + resetState: () => true, + }, + ], + roleMappings: [ + [], + { + setRoleMappingsData: (_, { roleMappings }) => roleMappings, + resetState: () => [], + }, + ], + attributes: [ + [], + { + setRoleMappingData: (_, { attributes }) => attributes, + }, + ], + availableGroups: [ + [], + { + setRoleMappingData: (_, { availableGroups }) => availableGroups, + }, + ], + selectedGroups: [ + new Set(), + { + setRoleMappingData: (_, { roleMapping, availableGroups }) => + roleMapping + ? new Set(roleMapping.groups.map((group) => group.id)) + : new Set( + availableGroups + .filter((group) => group.name === DEFAULT_GROUP_NAME) + .map((group) => group.id) + ), + handleGroupSelectionChange: (groups, { groupId, selected }) => { + const newSelectedGroupNames = new Set(groups as Set); + if (selected) { + newSelectedGroupNames.add(groupId); + } else { + newSelectedGroupNames.delete(groupId); + } + return newSelectedGroupNames; + }, + }, + ], + includeInAllGroups: [ + false, + { + setRoleMappingData: (_, { roleMapping }) => (roleMapping ? roleMapping.allGroups : false), + handleAllGroupsSelectionChange: (_, { selected }) => selected, + }, + ], + elasticsearchRoles: [ + [], + { + setRoleMappingData: (_, { elasticsearchRoles }) => elasticsearchRoles, + }, + ], + roleMapping: [ + null, + { + setRoleMappingData: (_, { roleMapping }) => roleMapping || null, + resetState: () => null, + }, + ], + roleType: [ + 'admin', + { + setRoleMappingData: (_, { roleMapping }) => + roleMapping ? (roleMapping.roleType as Role) : 'admin', + handleRoleChange: (_, { roleType }) => roleType, + }, + ], + attributeValue: [ + '', + { + setRoleMappingData: (_, { roleMapping }) => + roleMapping ? getFirstAttributeValue(roleMapping) : '', + handleAttributeSelectorChange: (_, { value, firstElasticsearchRole }) => + value === 'role' ? firstElasticsearchRole : '', + handleAttributeValueChange: (_, { value }) => value, + resetState: () => '', + }, + ], + attributeName: [ + 'username', + { + setRoleMappingData: (_, { roleMapping }) => + roleMapping ? getFirstAttributeName(roleMapping) : 'username', + handleAttributeSelectorChange: (_, { value }) => value, + resetState: () => 'username', + }, + ], + availableAuthProviders: [ + [], + { + setRoleMappingData: (_, { authProviders }) => authProviders, + }, + ], + multipleAuthProvidersConfig: [ + false, + { + setRoleMappingsData: (_, { multipleAuthProvidersConfig }) => multipleAuthProvidersConfig, + setRoleMappingData: (_, { multipleAuthProvidersConfig }) => multipleAuthProvidersConfig, + resetState: () => false, + }, + ], + selectedAuthProviders: [ + [ANY_AUTH_PROVIDER], + { + handleAuthProviderChange: (previous, { value }) => { + const previouslyContainedAny = previous.includes(ANY_AUTH_PROVIDER); + const newSelectionsContainAny = value.includes(ANY_AUTH_PROVIDER); + + if (value.length < 1) return [ANY_AUTH_PROVIDER]; + if (value.length === 1) return value; + if (!newSelectionsContainAny) return value; + if (previouslyContainedAny) return value.filter((v) => v !== ANY_AUTH_PROVIDER); + return [ANY_AUTH_PROVIDER]; + }, + setRoleMappingData: (_, { roleMapping }) => + roleMapping ? roleMapping.authProvider : [ANY_AUTH_PROVIDER], + }, + ], + }, + listeners: ({ actions, values }) => ({ + initializeRoleMappings: async () => { + const { http } = HttpLogic.values; + const route = '/api/workplace_search/org/role_mappings'; + + try { + const response = await http.get(route); + actions.setRoleMappingsData(response); + } catch (e) { + flashAPIErrors(e); + } + }, + initializeRoleMapping: async ({ roleId }) => { + const { http } = HttpLogic.values; + const { navigateToUrl } = KibanaLogic.values; + const route = roleId + ? `/api/workplace_search/org/role_mappings/${roleId}` + : '/api/workplace_search/org/role_mappings/new'; + + try { + const response = await http.get(route); + actions.setRoleMappingData(response); + } catch (e) { + if (e.status === 404) { + navigateToUrl(ROLE_MAPPINGS_PATH); + } + flashAPIErrors(e); + } + }, + handleDeleteMapping: async () => { + const { http } = HttpLogic.values; + const { navigateToUrl } = KibanaLogic.values; + const { roleMapping } = values; + if (!roleMapping) { + return; + } + const route = `/api/workplace_search/org/role_mappings/${roleMapping.id}`; + if (window.confirm(DELETE_ROLE_MAPPING_MESSAGE)) { + try { + await http.delete(route); + navigateToUrl(ROLE_MAPPINGS_PATH); + } catch (e) { + flashAPIErrors(e); + } + } + }, + handleSaveMapping: async () => { + const { http } = HttpLogic.values; + const { navigateToUrl } = KibanaLogic.values; + const { + attributeName, + attributeValue, + roleType, + roleMapping, + selectedGroups, + includeInAllGroups, + selectedAuthProviders, + } = values; + + const body = JSON.stringify({ + rules: { + [attributeName]: attributeValue, + }, + roleType, + groups: includeInAllGroups ? [] : Array.from(selectedGroups), + allGroups: includeInAllGroups, + authProvider: selectedAuthProviders, + }); + + const request = !roleMapping + ? http.post('/api/workplace_search/org/role_mappings', { body }) + : http.put(`/api/workplace_search/org/role_mappings/${roleMapping.id}`, { body }); + + try { + await request; + navigateToUrl(ROLE_MAPPINGS_PATH); + } catch (e) { + flashAPIErrors(e); + } + }, + resetState: () => { + clearFlashMessages(); + }, + }), +}); diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/role_mappings/role_mappings_router.test.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/role_mappings/role_mappings_router.test.tsx new file mode 100644 index 00000000000000..e9fc40ba1dbb43 --- /dev/null +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/role_mappings/role_mappings_router.test.tsx @@ -0,0 +1,26 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React from 'react'; +import { Route, Switch } from 'react-router-dom'; + +import { shallow } from 'enzyme'; + +import { RoleMapping } from './role_mapping'; +import { RoleMappings } from './role_mappings'; +import { RoleMappingsRouter } from './role_mappings_router'; + +describe('RoleMappingsRouter', () => { + it('renders', () => { + const wrapper = shallow(); + + expect(wrapper.find(Switch)).toHaveLength(1); + expect(wrapper.find(Route)).toHaveLength(3); + expect(wrapper.find(RoleMapping)).toHaveLength(2); + expect(wrapper.find(RoleMappings)).toHaveLength(1); + }); +}); diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/role_mappings/role_mappings_router.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/role_mappings/role_mappings_router.tsx new file mode 100644 index 00000000000000..fa5ab12c8afc0e --- /dev/null +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/role_mappings/role_mappings_router.tsx @@ -0,0 +1,34 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React from 'react'; + +import { Route, Switch } from 'react-router-dom'; + +import { SetWorkplaceSearchChrome as SetPageChrome } from '../../../shared/kibana_chrome'; +import { NAV } from '../../constants'; +import { ROLE_MAPPING_NEW_PATH, ROLE_MAPPING_PATH, ROLE_MAPPINGS_PATH } from '../../routes'; + +import { RoleMapping } from './role_mapping'; +import { RoleMappings } from './role_mappings'; + +export const RoleMappingsRouter: React.FC = () => ( + <> + + + + + + + + + + + + + +); diff --git a/x-pack/plugins/enterprise_search/server/lib/check_access.ts b/x-pack/plugins/enterprise_search/server/lib/check_access.ts index 0a5e0c9e2b8323..a88eb49d7b02ab 100644 --- a/x-pack/plugins/enterprise_search/server/lib/check_access.ts +++ b/x-pack/plugins/enterprise_search/server/lib/check_access.ts @@ -9,6 +9,7 @@ import { KibanaRequest, Logger } from 'src/core/server'; import { SecurityPluginSetup } from '../../../security/server'; import { SpacesPluginStart } from '../../../spaces/server'; +import { ProductAccess } from '../../common/types'; import { ConfigType } from '../index'; import { callEnterpriseSearchConfigAPI } from './enterprise_search_config_api'; @@ -20,10 +21,6 @@ interface CheckAccess { config: ConfigType; log: Logger; } -export interface Access { - hasAppSearchAccess: boolean; - hasWorkplaceSearchAccess: boolean; -} const ALLOW_ALL_PLUGINS = { hasAppSearchAccess: true, @@ -45,7 +42,7 @@ export const checkAccess = async ({ spaces, request, log, -}: CheckAccess): Promise => { +}: CheckAccess): Promise => { const isRbacEnabled = security?.authz.mode.useRbacForRequest(request) ?? false; // We can only retrieve the active space when either: diff --git a/x-pack/plugins/enterprise_search/server/lib/enterprise_search_config_api.test.ts b/x-pack/plugins/enterprise_search/server/lib/enterprise_search_config_api.test.ts index 6c6744ef3e32bf..de13077cd1b099 100644 --- a/x-pack/plugins/enterprise_search/server/lib/enterprise_search_config_api.test.ts +++ b/x-pack/plugins/enterprise_search/server/lib/enterprise_search_config_api.test.ts @@ -108,12 +108,12 @@ describe('callEnterpriseSearchConfigAPI', () => { }); expect(await callEnterpriseSearchConfigAPI(mockDependencies)).toEqual({ + ...DEFAULT_INITIAL_APP_DATA, access: { hasAppSearchAccess: true, hasWorkplaceSearchAccess: false, }, publicUrl: 'http://some.vanity.url', - ...DEFAULT_INITIAL_APP_DATA, }); }); diff --git a/x-pack/plugins/enterprise_search/server/lib/enterprise_search_config_api.ts b/x-pack/plugins/enterprise_search/server/lib/enterprise_search_config_api.ts index 0ed4ad257f30b4..ebe718dfebd309 100644 --- a/x-pack/plugins/enterprise_search/server/lib/enterprise_search_config_api.ts +++ b/x-pack/plugins/enterprise_search/server/lib/enterprise_search_config_api.ts @@ -14,15 +14,12 @@ import { stripTrailingSlash } from '../../common/strip_slashes'; import { InitialAppData } from '../../common/types'; import { ConfigType } from '../index'; -import { Access } from './check_access'; - interface Params { request: KibanaRequest; config: ConfigType; log: Logger; } interface Return extends InitialAppData { - access?: Access; publicUrl?: string; } diff --git a/x-pack/plugins/enterprise_search/server/routes/app_search/engines.test.ts b/x-pack/plugins/enterprise_search/server/routes/app_search/engines.test.ts index 779c51131b4721..6b78f29a6b7316 100644 --- a/x-pack/plugins/enterprise_search/server/routes/app_search/engines.test.ts +++ b/x-pack/plugins/enterprise_search/server/routes/app_search/engines.test.ts @@ -122,19 +122,56 @@ describe('engine routes', () => { }); describe('validates', () => { - it('correctly', () => { - const request = { body: { name: 'some-engine', language: 'en' } }; - mockRouter.shouldValidate(request); - }); - - it('missing name', () => { - const request = { body: { language: 'en' } }; - mockRouter.shouldThrow(request); - }); - - it('optional language', () => { - const request = { body: { name: 'some-engine' } }; - mockRouter.shouldValidate(request); + describe('indexed engines', () => { + it('correctly', () => { + const request = { body: { name: 'some-engine', language: 'en' } }; + mockRouter.shouldValidate(request); + }); + + it('missing name', () => { + const request = { body: { language: 'en' } }; + mockRouter.shouldThrow(request); + }); + + it('optional language', () => { + const request = { body: { name: 'some-engine' } }; + mockRouter.shouldValidate(request); + }); + }); + + describe('meta engines', () => { + it('all properties', () => { + const request = { + body: { name: 'some-meta-engine', type: 'any', language: 'en', source_engines: [] }, + }; + mockRouter.shouldValidate(request); + }); + + it('missing name', () => { + const request = { + body: { type: 'any', language: 'en', source_engines: [] }, + }; + mockRouter.shouldThrow(request); + }); + + it('optional language', () => { + const request = { + body: { name: 'some-meta-engine', type: 'any', source_engines: [] }, + }; + mockRouter.shouldValidate(request); + }); + + it('optional source_engines', () => { + const request = { + body: { name: 'some-meta-engine', type: 'any', language: 'en' }, + }; + mockRouter.shouldValidate(request); + }); + + it('optional type', () => { + const request = { body: { name: 'some-engine' } }; + mockRouter.shouldValidate(request); + }); }); }); }); diff --git a/x-pack/plugins/enterprise_search/server/routes/app_search/engines.ts b/x-pack/plugins/enterprise_search/server/routes/app_search/engines.ts index 9bff6cf127dd3f..766be196e70e78 100644 --- a/x-pack/plugins/enterprise_search/server/routes/app_search/engines.ts +++ b/x-pack/plugins/enterprise_search/server/routes/app_search/engines.ts @@ -45,6 +45,8 @@ export function registerEnginesRoutes({ body: schema.object({ name: schema.string(), language: schema.maybe(schema.string()), + source_engines: schema.maybe(schema.arrayOf(schema.string())), + type: schema.maybe(schema.string()), }), }, }, diff --git a/x-pack/plugins/enterprise_search/server/routes/enterprise_search/config_data.test.ts b/x-pack/plugins/enterprise_search/server/routes/enterprise_search/config_data.test.ts index 1545547c1dd4ef..b3d2733e233b32 100644 --- a/x-pack/plugins/enterprise_search/server/routes/enterprise_search/config_data.test.ts +++ b/x-pack/plugins/enterprise_search/server/routes/enterprise_search/config_data.test.ts @@ -33,12 +33,8 @@ describe('Enterprise Search Config Data API', () => { describe('GET /api/enterprise_search/config_data', () => { it('returns an initial set of config data from Enterprise Search', async () => { const mockData = { - access: { - hasAppSearchAccess: true, - hasWorkplaceSearchAccess: true, - }, - publicUrl: 'http://localhost:3002', ...DEFAULT_INITIAL_APP_DATA, + publicUrl: 'http://localhost:3002', }; (callEnterpriseSearchConfigAPI as jest.Mock).mockImplementationOnce(() => { diff --git a/x-pack/plugins/enterprise_search/server/routes/workplace_search/index.ts b/x-pack/plugins/enterprise_search/server/routes/workplace_search/index.ts index cc6226e3406533..a21ffac02a48cd 100644 --- a/x-pack/plugins/enterprise_search/server/routes/workplace_search/index.ts +++ b/x-pack/plugins/enterprise_search/server/routes/workplace_search/index.ts @@ -9,6 +9,7 @@ import { RouteDependencies } from '../../plugin'; import { registerGroupsRoutes } from './groups'; import { registerOverviewRoute } from './overview'; +import { registerRoleMappingsRoutes } from './role_mappings'; import { registerSecurityRoutes } from './security'; import { registerSettingsRoutes } from './settings'; import { registerSourcesRoutes } from './sources'; @@ -16,6 +17,7 @@ import { registerSourcesRoutes } from './sources'; export const registerWorkplaceSearchRoutes = (dependencies: RouteDependencies) => { registerOverviewRoute(dependencies); registerGroupsRoutes(dependencies); + registerRoleMappingsRoutes(dependencies); registerSourcesRoutes(dependencies); registerSettingsRoutes(dependencies); registerSecurityRoutes(dependencies); diff --git a/x-pack/plugins/enterprise_search/server/routes/workplace_search/role_mappings.test.ts b/x-pack/plugins/enterprise_search/server/routes/workplace_search/role_mappings.test.ts new file mode 100644 index 00000000000000..0dade134767e44 --- /dev/null +++ b/x-pack/plugins/enterprise_search/server/routes/workplace_search/role_mappings.test.ts @@ -0,0 +1,154 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { MockRouter, mockRequestHandler, mockDependencies } from '../../__mocks__'; + +import { + registerOrgRoleMappingsRoute, + registerOrgRoleMappingRoute, + registerOrgNewRoleMappingRoute, +} from './role_mappings'; + +describe('role mappings routes', () => { + describe('GET /api/workplace_search/org/role_mappings', () => { + let mockRouter: MockRouter; + + beforeEach(() => { + jest.clearAllMocks(); + mockRouter = new MockRouter({ + method: 'get', + path: '/api/workplace_search/org/role_mappings', + }); + + registerOrgRoleMappingsRoute({ + ...mockDependencies, + router: mockRouter.router, + }); + }); + + it('creates a request handler', () => { + expect(mockRequestHandler.createRequest).toHaveBeenCalledWith({ + path: '/ws/org/role_mappings/collection', + }); + }); + }); + + describe('POST /api/workplace_search/org/role_mappings', () => { + let mockRouter: MockRouter; + + beforeEach(() => { + jest.clearAllMocks(); + mockRouter = new MockRouter({ + method: 'post', + path: '/api/workplace_search/org/role_mappings', + }); + + registerOrgRoleMappingsRoute({ + ...mockDependencies, + router: mockRouter.router, + }); + }); + + it('creates a request handler', () => { + expect(mockRequestHandler.createRequest).toHaveBeenCalledWith({ + path: '/ws/org/role_mappings/collection', + }); + }); + }); + + describe('GET /api/workplace_search/org/role_mappings/{id}', () => { + let mockRouter: MockRouter; + + beforeEach(() => { + jest.clearAllMocks(); + mockRouter = new MockRouter({ + method: 'get', + path: '/api/workplace_search/org/role_mappings/{id}', + }); + + registerOrgRoleMappingRoute({ + ...mockDependencies, + router: mockRouter.router, + }); + }); + + it('creates a request handler', () => { + expect(mockRequestHandler.createRequest).toHaveBeenCalledWith({ + path: '/ws/org/role_mappings/:id', + }); + }); + }); + + describe('PUT /api/workplace_search/org/role_mappings/{id}', () => { + let mockRouter: MockRouter; + + beforeEach(() => { + jest.clearAllMocks(); + mockRouter = new MockRouter({ + method: 'put', + path: '/api/workplace_search/org/role_mappings/{id}', + }); + + registerOrgRoleMappingRoute({ + ...mockDependencies, + router: mockRouter.router, + }); + }); + + it('creates a request handler', () => { + expect(mockRequestHandler.createRequest).toHaveBeenCalledWith({ + path: '/ws/org/role_mappings/:id', + }); + }); + }); + + describe('DELETE /api/workplace_search/org/role_mappings/{id}', () => { + let mockRouter: MockRouter; + + beforeEach(() => { + jest.clearAllMocks(); + mockRouter = new MockRouter({ + method: 'delete', + path: '/api/workplace_search/org/role_mappings/{id}', + }); + + registerOrgRoleMappingRoute({ + ...mockDependencies, + router: mockRouter.router, + }); + }); + + it('creates a request handler', () => { + expect(mockRequestHandler.createRequest).toHaveBeenCalledWith({ + path: '/ws/org/role_mappings/:id', + }); + }); + }); + + describe('GET /api/workplace_search/org/role_mappings/new', () => { + let mockRouter: MockRouter; + + beforeEach(() => { + jest.clearAllMocks(); + mockRouter = new MockRouter({ + method: 'get', + path: '/api/workplace_search/org/role_mappings/new', + }); + + registerOrgNewRoleMappingRoute({ + ...mockDependencies, + router: mockRouter.router, + }); + }); + + it('creates a request handler', () => { + expect(mockRequestHandler.createRequest).toHaveBeenCalledWith({ + path: '/ws/org/role_mappings/new', + }); + }); + }); +}); diff --git a/x-pack/plugins/enterprise_search/server/routes/workplace_search/role_mappings.ts b/x-pack/plugins/enterprise_search/server/routes/workplace_search/role_mappings.ts new file mode 100644 index 00000000000000..8c7792f56fd6cd --- /dev/null +++ b/x-pack/plugins/enterprise_search/server/routes/workplace_search/role_mappings.ts @@ -0,0 +1,117 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { schema } from '@kbn/config-schema'; + +import { RouteDependencies } from '../../plugin'; + +const roleMappingBaseSchema = { + rules: schema.recordOf(schema.string(), schema.string()), + roleType: schema.string(), + groups: schema.arrayOf(schema.string()), + allGroups: schema.boolean(), + authProvider: schema.arrayOf(schema.string()), +}; + +export function registerOrgRoleMappingsRoute({ + router, + enterpriseSearchRequestHandler, +}: RouteDependencies) { + router.get( + { + path: '/api/workplace_search/org/role_mappings', + validate: false, + }, + enterpriseSearchRequestHandler.createRequest({ + path: '/ws/org/role_mappings/collection', + }) + ); + + router.post( + { + path: '/api/workplace_search/org/role_mappings', + validate: { + body: schema.object(roleMappingBaseSchema), + }, + }, + enterpriseSearchRequestHandler.createRequest({ + path: '/ws/org/role_mappings/collection', + }) + ); +} + +export function registerOrgRoleMappingRoute({ + router, + enterpriseSearchRequestHandler, +}: RouteDependencies) { + router.get( + { + path: '/api/workplace_search/org/role_mappings/{id}', + validate: { + params: schema.object({ + id: schema.string(), + }), + }, + }, + enterpriseSearchRequestHandler.createRequest({ + path: '/ws/org/role_mappings/:id', + }) + ); + + router.put( + { + path: '/api/workplace_search/org/role_mappings/{id}', + validate: { + body: schema.object({ + ...roleMappingBaseSchema, + id: schema.string(), + }), + params: schema.object({ + id: schema.string(), + }), + }, + }, + enterpriseSearchRequestHandler.createRequest({ + path: '/ws/org/role_mappings/:id', + }) + ); + + router.delete( + { + path: '/api/workplace_search/org/role_mappings/{id}', + validate: { + params: schema.object({ + id: schema.string(), + }), + }, + }, + enterpriseSearchRequestHandler.createRequest({ + path: '/ws/org/role_mappings/:id', + }) + ); +} + +export function registerOrgNewRoleMappingRoute({ + router, + enterpriseSearchRequestHandler, +}: RouteDependencies) { + router.get( + { + path: '/api/workplace_search/org/role_mappings/new', + validate: false, + }, + enterpriseSearchRequestHandler.createRequest({ + path: '/ws/org/role_mappings/new', + }) + ); +} + +export const registerRoleMappingsRoutes = (dependencies: RouteDependencies) => { + registerOrgRoleMappingsRoute(dependencies); + registerOrgRoleMappingRoute(dependencies); + registerOrgNewRoleMappingRoute(dependencies); +}; diff --git a/x-pack/plugins/file_upload/common/constants.ts b/x-pack/plugins/file_upload/common/constants.ts index 11ad80f5c955ee..ea36e51466703f 100644 --- a/x-pack/plugins/file_upload/common/constants.ts +++ b/x-pack/plugins/file_upload/common/constants.ts @@ -5,6 +5,8 @@ * 2.0. */ +export const UI_SETTING_MAX_FILE_SIZE = 'fileUpload:maxFileSize'; + export const MB = Math.pow(2, 20); export const MAX_FILE_SIZE = '100MB'; export const MAX_FILE_SIZE_BYTES = 104857600; // 100MB diff --git a/x-pack/plugins/file_upload/kibana.json b/x-pack/plugins/file_upload/kibana.json index 7676a01d0b0f96..6d55e4f46d7e87 100644 --- a/x-pack/plugins/file_upload/kibana.json +++ b/x-pack/plugins/file_upload/kibana.json @@ -4,5 +4,6 @@ "kibanaVersion": "kibana", "server": true, "ui": true, - "requiredPlugins": ["data", "usageCollection"] + "requiredPlugins": ["data", "usageCollection"], + "requiredBundles": ["kibanaReact"] } diff --git a/x-pack/plugins/file_upload/public/api/index.ts b/x-pack/plugins/file_upload/public/api/index.ts index 359bc4a1687b53..8884c398fa2e61 100644 --- a/x-pack/plugins/file_upload/public/api/index.ts +++ b/x-pack/plugins/file_upload/public/api/index.ts @@ -12,6 +12,8 @@ import type { IImporter, ImportFactoryOptions } from '../importer'; export interface FileUploadStartApi { getFileUploadComponent(): Promise>; importerFactory(format: string, options: ImportFactoryOptions): Promise; + getMaxBytes(): number; + getMaxBytesFormatted(): string; } export async function getFileUploadComponent(): Promise< diff --git a/x-pack/plugins/file_upload/public/components/geojson_file_picker.tsx b/x-pack/plugins/file_upload/public/components/geojson_file_picker.tsx new file mode 100644 index 00000000000000..724a23a43202fb --- /dev/null +++ b/x-pack/plugins/file_upload/public/components/geojson_file_picker.tsx @@ -0,0 +1,155 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React, { Component } from 'react'; +import { EuiFilePicker, EuiFormRow } from '@elastic/eui'; +import { i18n } from '@kbn/i18n'; +import { MB } from '../../common'; +import { getMaxBytesFormatted } from '../get_max_bytes'; +import { validateFile } from '../importer'; +import { GeoJsonImporter, GeoJsonPreview, GEOJSON_FILE_TYPES } from '../importer/geojson_importer'; + +interface Props { + onSelect: ({ + features, + hasPoints, + hasShapes, + importer, + indexName, + previewCoverage, + }: GeoJsonPreview & { + indexName: string; + importer: GeoJsonImporter; + }) => void; + onClear: () => void; +} + +interface State { + error: string | null; + isLoadingPreview: boolean; + previewSummary: string | null; +} + +export class GeoJsonFilePicker extends Component { + private _isMounted = false; + + state: State = { + error: null, + isLoadingPreview: false, + previewSummary: null, + }; + + async componentDidMount() { + this._isMounted = true; + } + + componentWillUnmount() { + this._isMounted = false; + } + + _onFileSelect = (files: FileList | null) => { + this.props.onClear(); + + this.setState({ + error: null, + isLoadingPreview: false, + previewSummary: null, + }); + + if (files && files.length) { + this._loadFilePreview(files[0]); + } + }; + + async _loadFilePreview(file: File) { + this.setState({ isLoadingPreview: true }); + + let importer: GeoJsonImporter | null = null; + let previewError: string | null = null; + let preview: GeoJsonPreview | null = null; + try { + validateFile(file, GEOJSON_FILE_TYPES); + importer = new GeoJsonImporter(file); + preview = await importer.previewFile(10000, MB * 3); + if (preview.features.length === 0) { + previewError = i18n.translate('xpack.fileUpload.geojsonFilePicker.noFeaturesDetected', { + defaultMessage: 'No GeoJson features found in selected file.', + }); + } + } catch (error) { + previewError = error.message; + } + + if (!this._isMounted) { + return; + } + + this.setState({ + error: previewError, + isLoadingPreview: false, + previewSummary: + !previewError && preview + ? i18n.translate('xpack.fileUpload.geojsonFilePicker.previewSummary', { + defaultMessage: 'Previewing {numFeatures} features, {previewCoverage}% of file.', + values: { + numFeatures: preview.features.length, + previewCoverage: preview.previewCoverage, + }, + }) + : null, + }); + + if (importer && preview) { + this.props.onSelect({ + ...preview, + importer, + indexName: file.name.split('.')[0].toLowerCase(), + }); + } + } + + _renderHelpText() { + return this.state.previewSummary !== null ? ( + this.state.previewSummary + ) : ( + + {i18n.translate('xpack.fileUpload.geojsonFilePicker.acceptedFormats', { + defaultMessage: 'Formats accepted: {fileTypes}', + values: { fileTypes: GEOJSON_FILE_TYPES.join(', ') }, + })} +
+ {i18n.translate('xpack.fileUpload.geojsonFilePicker.maxSize', { + defaultMessage: 'Max size: {maxFileSize}', + values: { maxFileSize: getMaxBytesFormatted() }, + })} +
+ {i18n.translate('xpack.fileUpload.geojsonFilePicker.acceptedCoordinateSystem', { + defaultMessage: 'Coordinates must be in EPSG:4326 coordinate reference system.', + })} +
+ ); + } + + render() { + return ( + + + + ); + } +} diff --git a/x-pack/plugins/file_upload/public/components/import_complete_view.tsx b/x-pack/plugins/file_upload/public/components/import_complete_view.tsx new file mode 100644 index 00000000000000..c6209ae765c72c --- /dev/null +++ b/x-pack/plugins/file_upload/public/components/import_complete_view.tsx @@ -0,0 +1,159 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React, { Component, Fragment } from 'react'; +import { i18n } from '@kbn/i18n'; +import { + EuiButtonIcon, + EuiCallOut, + EuiCopy, + EuiFlexGroup, + EuiFlexItem, + EuiSpacer, + EuiText, + EuiTitle, +} from '@elastic/eui'; +import { FormattedMessage } from '@kbn/i18n/react'; +import { CodeEditor, KibanaContextProvider } from '../../../../../src/plugins/kibana_react/public'; +import { getHttp, getUiSettings } from '../kibana_services'; +import { ImportResponse } from '../../common'; + +const services = { + uiSettings: getUiSettings(), +}; + +interface Props { + importResp?: ImportResponse; + indexPatternResp?: object; +} + +export class ImportCompleteView extends Component { + _renderCodeEditor(json: object | undefined, title: string, copyButtonDataTestSubj: string) { + if (!json) { + return null; + } + + const jsonAsString = JSON.stringify(json, null, 2); + + return ( + + + + +

{title}

+
+
+ + + + {(copy) => ( + + )} + + +
+
+ {}} + options={{ + readOnly: true, + lineNumbers: 'off', + fontSize: 12, + minimap: { + enabled: false, + }, + scrollBeyondLastLine: false, + wordWrap: 'on', + wrappingIndent: 'indent', + automaticLayout: true, + }} + /> +
+ +
+ ); + } + + _getStatusMsg() { + if (!this.props.importResp || !this.props.importResp.success) { + return i18n.translate('xpack.fileUpload.uploadFailureMsg', { + defaultMessage: 'File upload failed.', + }); + } + + const successMsg = i18n.translate('xpack.fileUpload.uploadSuccessMsg', { + defaultMessage: 'File upload complete: indexed {numFeatures} features.', + values: { + numFeatures: this.props.importResp.docCount, + }, + }); + + const failedFeaturesMsg = this.props.importResp.failures.length + ? i18n.translate('xpack.fileUpload.failedFeaturesMsg', { + defaultMessage: 'Unable to index {numFailures} features.', + values: { + numFailures: this.props.importResp.failures.length, + }, + }) + : ''; + + return `${successMsg} ${failedFeaturesMsg}`; + } + + render() { + return ( + + +

{this._getStatusMsg()}

+
+ {this._renderCodeEditor( + this.props.importResp, + i18n.translate('xpack.fileUpload.jsonImport.indexingResponse', { + defaultMessage: 'Import response', + }), + 'indexRespCopyButton' + )} + {this._renderCodeEditor( + this.props.indexPatternResp, + i18n.translate('xpack.fileUpload.jsonImport.indexPatternResponse', { + defaultMessage: 'Index pattern response', + }), + 'indexPatternRespCopyButton' + )} + +
+ + + + +
+
+
+ ); + } +} diff --git a/x-pack/plugins/file_upload/public/components/index_settings.js b/x-pack/plugins/file_upload/public/components/index_settings.js index 3cad31cdbe3dfc..7d7ab3516e6519 100644 --- a/x-pack/plugins/file_upload/public/components/index_settings.js +++ b/x-pack/plugins/file_upload/public/components/index_settings.js @@ -118,6 +118,7 @@ export class IndexSettings extends Component { text: indexType, value: indexType, }))} + value={this.props.selectedIndexType} onChange={({ target }) => setSelectedIndexType(target.value)} /> diff --git a/x-pack/plugins/file_upload/public/components/json_import_progress.js b/x-pack/plugins/file_upload/public/components/json_import_progress.js deleted file mode 100644 index 1adf7d9039e56b..00000000000000 --- a/x-pack/plugins/file_upload/public/components/json_import_progress.js +++ /dev/null @@ -1,135 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import React, { Fragment, Component } from 'react'; -import { i18n } from '@kbn/i18n'; -import { EuiCodeBlock, EuiSpacer, EuiText, EuiTitle, EuiProgress, EuiCallOut } from '@elastic/eui'; -import { FormattedMessage } from '@kbn/i18n/react'; -import { getHttp } from '../kibana_services'; - -export class JsonImportProgress extends Component { - state = { - indexDataJson: null, - indexPatternJson: null, - indexName: '', - importStage: '', - }; - - componentDidUpdate(prevProps, prevState) { - this._setIndex(this.props); - this._formatIndexDataResponse({ ...this.state, ...this.props }); - this._formatIndexPatternResponse({ ...this.state, ...this.props }); - if (prevState.importStage !== this.props.importStage) { - this.setState({ - importStage: this.props.importStage, - }); - } - } - - // Retain last index for UI purposes - _setIndex = ({ indexName }) => { - if (indexName && !this.state.indexName) { - this.setState({ indexName }); - } - }; - - // Format json responses - _formatIndexDataResponse = ({ indexDataResp, indexDataJson }) => { - if (indexDataResp && !indexDataJson) { - this.setState({ indexDataJson: JSON.stringify(indexDataResp, null, 2) }); - } - }; - - _formatIndexPatternResponse = ({ indexPatternResp, indexPatternJson }) => { - if (indexPatternResp && !indexPatternJson) { - this.setState({ indexPatternJson: JSON.stringify(indexPatternResp, null, 2) }); - } - }; - - render() { - const { complete } = this.props; - const { indexPatternJson, indexDataJson, indexName, importStage } = this.state; - const importMessage = complete ? importStage : `${importStage}: ${indexName}`; - - return ( - - {!complete ? : null} - -

- -

-
- {importMessage &&

{importMessage}

}
- - {complete ? ( - - {indexDataJson ? ( - - -

- -

-
- - {indexDataJson} - - -
- ) : null} - {indexPatternJson ? ( - - -

- -

-
- - {indexPatternJson} - - -
- ) : null} - -
- {i18n.translate('xpack.fileUpload.jsonImport.indexModsMsg', { - defaultMessage: 'Further index modifications can be made using\n', - })} - - {i18n.translate('xpack.fileUpload.jsonImport.indexMgmtLink', { - defaultMessage: 'Index Management', - })} - - . -
-
-
- ) : null} -
- ); - } -} diff --git a/x-pack/plugins/file_upload/public/components/json_index_file_picker.js b/x-pack/plugins/file_upload/public/components/json_index_file_picker.js deleted file mode 100644 index 78bf7378578de8..00000000000000 --- a/x-pack/plugins/file_upload/public/components/json_index_file_picker.js +++ /dev/null @@ -1,267 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import React, { Fragment, Component } from 'react'; -import { EuiFilePicker, EuiFormRow, EuiProgress } from '@elastic/eui'; -import { FormattedMessage } from '@kbn/i18n/react'; -import { i18n } from '@kbn/i18n'; - -const MAX_FILE_SIZE = 52428800; -const ACCEPTABLE_FILETYPES = ['json', 'geojson']; -const acceptedFileTypeString = ACCEPTABLE_FILETYPES.map((type) => `.${type}`).join(','); -const acceptedFileTypeStringMessage = ACCEPTABLE_FILETYPES.map((type) => `.${type}`).join(', '); - -export class JsonIndexFilePicker extends Component { - state = { - fileUploadError: '', - percentageProcessed: 0, - featuresProcessed: 0, - fileParseActive: false, - currentFileTracker: null, - }; - - async componentDidMount() { - this._isMounted = true; - } - - componentWillUnmount() { - this._isMounted = false; - } - - isFileParseActive = () => this._isMounted && this.state.fileParseActive; - - _fileHandler = (fileList) => { - const fileArr = Array.from(fileList); - this.props.resetFileAndIndexSettings(); - this.setState({ - fileUploadError: '', - percentageProcessed: 0, - featuresProcessed: 0, - }); - if (fileArr.length === 0) { - // Remove - this.setState({ - fileParseActive: false, - }); - return; - } - const file = fileArr[0]; - - this.setState( - { - fileParseActive: true, - currentFileTracker: Symbol(), - }, - () => this._parseFile(file) - ); - }; - - _getFileNameAndCheckType({ name }) { - let fileNameOnly; - try { - if (!name) { - throw new Error( - i18n.translate('xpack.fileUpload.jsonIndexFilePicker.noFileNameError', { - defaultMessage: 'No file name provided', - }) - ); - } - - const splitNameArr = name.split('.'); - const fileType = splitNameArr.pop(); - if (!ACCEPTABLE_FILETYPES.includes(fileType)) { - //should only occur if browser does not accept the accept parameter - throw new Error( - i18n.translate('xpack.fileUpload.jsonIndexFilePicker.acceptableTypesError', { - defaultMessage: 'File is not one of acceptable types: {types}', - values: { - types: ACCEPTABLE_FILETYPES.join(', '), - }, - }) - ); - } - - fileNameOnly = splitNameArr[0]; - } catch (error) { - this.setState({ - fileUploadError: i18n.translate( - 'xpack.fileUpload.jsonIndexFilePicker.fileProcessingError', - { - defaultMessage: 'File processing error: {errorMessage}', - values: { - errorMessage: error.message, - }, - } - ), - }); - return; - } - return fileNameOnly.toLowerCase(); - } - - setFileProgress = ({ featuresProcessed, bytesProcessed, totalBytes }) => { - const percentageProcessed = parseInt((100 * bytesProcessed) / totalBytes); - if (this.isFileParseActive()) { - this.setState({ featuresProcessed, percentageProcessed }); - } - }; - - async _parseFile(file) { - const { currentFileTracker } = this.state; - const { setFileRef, setParsedFile, resetFileAndIndexSettings } = this.props; - - if (file.size > MAX_FILE_SIZE) { - this.setState({ - fileUploadError: i18n.translate('xpack.fileUpload.jsonIndexFilePicker.acceptableFileSize', { - defaultMessage: 'File size {fileSize} exceeds maximum file size of {maxFileSize}', - values: { - fileSize: bytesToSize(file.size), - maxFileSize: bytesToSize(MAX_FILE_SIZE), - }, - }), - }); - resetFileAndIndexSettings(); - return; - } - - const defaultIndexName = this._getFileNameAndCheckType(file); - if (!defaultIndexName) { - resetFileAndIndexSettings(); - return; - } - - const fileResult = await this.props.geojsonImporter - .readFile(file, this.setFileProgress, this.isFileParseActive) - .catch((err) => { - if (this._isMounted) { - this.setState({ - fileParseActive: false, - percentageProcessed: 0, - featuresProcessed: 0, - fileUploadError: ( - - ), - }); - resetFileAndIndexSettings(); - return; - } - }); - - if (!this._isMounted) { - return; - } - - // If another file is replacing this one, leave file parse active - this.setState({ - percentageProcessed: 0, - featuresProcessed: 0, - fileParseActive: currentFileTracker !== this.state.currentFileTracker, - }); - if (!fileResult) { - resetFileAndIndexSettings(); - return; - } - - if (fileResult.errors.length) { - this.setState({ - fileUploadError: ( - - ), - }); - } - setFileRef(file); - setParsedFile(fileResult, defaultIndexName); - } - - render() { - const { fileUploadError, percentageProcessed, featuresProcessed } = this.state; - - return ( - - {percentageProcessed ? ( - - ) : null} - - } - isInvalid={fileUploadError !== ''} - error={[fileUploadError]} - helpText={ - percentageProcessed ? ( - i18n.translate('xpack.fileUpload.jsonIndexFilePicker.parsingFile', { - defaultMessage: '{featuresProcessed} features parsed...', - values: { - featuresProcessed, - }, - }) - ) : ( - - {i18n.translate('xpack.fileUpload.jsonIndexFilePicker.formatsAccepted', { - defaultMessage: 'Formats accepted: {acceptedFileTypeStringMessage}', - values: { - acceptedFileTypeStringMessage, - }, - })}{' '} -
- -
- {i18n.translate('xpack.fileUpload.jsonIndexFilePicker.coordinateSystemAccepted', { - defaultMessage: 'Coordinates must be in EPSG:4326 coordinate reference system.', - })}{' '} -
- ) - } - > - - } - onChange={this._fileHandler} - accept={acceptedFileTypeString} - /> -
-
- ); - } -} - -function bytesToSize(bytes) { - const sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB']; - if (bytes === 0) return 'n/a'; - const i = parseInt(Math.floor(Math.log(bytes) / Math.log(1024)), 10); - if (i === 0) return `${bytes} ${sizes[i]})`; - return `${(bytes / 1024 ** i).toFixed(1)} ${sizes[i]}`; -} diff --git a/x-pack/plugins/file_upload/public/components/json_upload_and_parse.js b/x-pack/plugins/file_upload/public/components/json_upload_and_parse.js index d4f6858eb59950..ae9f5e9ac81547 100644 --- a/x-pack/plugins/file_upload/public/components/json_upload_and_parse.js +++ b/x-pack/plugins/file_upload/public/components/json_upload_and_parse.js @@ -7,65 +7,41 @@ import React, { Component, Fragment } from 'react'; import { i18n } from '@kbn/i18n'; -import { EuiForm } from '@elastic/eui'; +import { EuiForm, EuiProgress, EuiText } from '@elastic/eui'; import PropTypes from 'prop-types'; import { IndexSettings } from './index_settings'; -import { JsonIndexFilePicker } from './json_index_file_picker'; -import { JsonImportProgress } from './json_import_progress'; -import _ from 'lodash'; -import { GeoJsonImporter } from '../importer/geojson_importer'; -import { ES_FIELD_TYPES } from '../../../../../src/plugins/data/public'; import { getIndexPatternService } from '../kibana_services'; +import { GeoJsonFilePicker } from './geojson_file_picker'; +import { ImportCompleteView } from './import_complete_view'; +import { ES_FIELD_TYPES } from '../../../../../src/plugins/data/public'; -const INDEXING_STAGE = { - INDEXING_STARTED: i18n.translate('xpack.fileUpload.jsonUploadAndParse.dataIndexingStarted', { - defaultMessage: 'Data indexing started', - }), - WRITING_TO_INDEX: i18n.translate('xpack.fileUpload.jsonUploadAndParse.writingToIndex', { - defaultMessage: 'Writing to index', - }), - INDEXING_COMPLETE: i18n.translate('xpack.fileUpload.jsonUploadAndParse.indexingComplete', { - defaultMessage: 'Indexing complete', - }), - CREATING_INDEX_PATTERN: i18n.translate( - 'xpack.fileUpload.jsonUploadAndParse.creatingIndexPattern', - { defaultMessage: 'Creating index pattern' } - ), - INDEX_PATTERN_COMPLETE: i18n.translate( - 'xpack.fileUpload.jsonUploadAndParse.indexPatternComplete', - { defaultMessage: 'Index pattern complete' } - ), - INDEXING_ERROR: i18n.translate('xpack.fileUpload.jsonUploadAndParse.dataIndexingError', { - defaultMessage: 'Data indexing error', - }), - INDEX_PATTERN_ERROR: i18n.translate('xpack.fileUpload.jsonUploadAndParse.indexPatternError', { - defaultMessage: 'Index pattern error', - }), +const PHASE = { + CONFIGURE: 'CONFIGURE', + IMPORT: 'IMPORT', + COMPLETE: 'COMPLETE', }; -export class JsonUploadAndParse extends Component { - geojsonImporter = new GeoJsonImporter(); +function getWritingToIndexMsg(progress) { + return i18n.translate('xpack.fileUpload.jsonUploadAndParse.writingToIndex', { + defaultMessage: 'Writing to index: {progress}% complete', + values: { progress }, + }); +} +export class JsonUploadAndParse extends Component { state = { - // File state - fileRef: null, - parsedFile: null, - indexedFile: null, - // Index state indexTypes: [], selectedIndexType: '', indexName: '', - indexRequestInFlight: false, - indexPatternRequestInFlight: false, hasIndexErrors: false, isIndexReady: false, // Progress-tracking state - showImportProgress: false, - currentIndexingStage: INDEXING_STAGE.INDEXING_STARTED, - indexDataResp: '', - indexPatternResp: '', + importStatus: '', + phase: PHASE.CONFIGURE, + importResp: undefined, + indexPatternResp: undefined, }; componentDidMount() { @@ -74,102 +50,36 @@ export class JsonUploadAndParse extends Component { componentWillUnmount() { this._isMounted = false; - } - - _resetFileAndIndexSettings = () => { - if (this.props.onFileRemove && this.state.fileRef) { - this.props.onFileRemove(this.state.fileRef); - } - this.setState({ - indexTypes: [], - selectedIndexType: '', - indexName: '', - indexedFile: null, - parsedFile: null, - fileRef: null, - }); - }; - - componentDidUpdate() { - this._updateIndexType(); - this._setIndexReady({ ...this.state, ...this.props }); - this._indexData({ ...this.state, ...this.props }); - if (this.props.isIndexingTriggered && !this.state.showImportProgress && this._isMounted) { - this.setState({ showImportProgress: true }); + if (this._geojsonImporter) { + this._geojsonImporter.destroy(); + this._geojsonImporter = null; } } - _updateIndexType() { - let nextIndexTypes = []; - if (this.state.parsedFile) { - nextIndexTypes = - this.state.parsedFile.geometryTypes.includes('Point') || - this.state.parsedFile.geometryTypes.includes('MultiPoint') - ? [ES_FIELD_TYPES.GEO_POINT, ES_FIELD_TYPES.GEO_SHAPE] - : [ES_FIELD_TYPES.GEO_SHAPE]; - } - if (!_.isEqual(nextIndexTypes, this.state.indexTypes)) { - this.setState({ indexTypes: nextIndexTypes }); - } - - if (!this.state.selectedIndexType && nextIndexTypes.length) { - // auto select index type - this.setState({ selectedIndexType: nextIndexTypes[0] }); - } else if ( - this.state.selectedIndexType && - !nextIndexTypes.includes(this.state.selectedIndexType) - ) { - // unselected indexType if selected type is not longer an option - this.setState({ selectedIndexType: null }); + componentDidUpdate() { + this._setIndexReady(); + if (this.props.isIndexingTriggered && this.state.phase === PHASE.CONFIGURE) { + this._import(); } } - _setIndexReady = ({ - parsedFile, - selectedIndexType, - indexName, - hasIndexErrors, - indexRequestInFlight, - onIndexReady, - }) => { + _setIndexReady = () => { const isIndexReady = - !!parsedFile && - !!selectedIndexType && - !!indexName && - !hasIndexErrors && - !indexRequestInFlight; + this._geojsonImporter !== undefined && + !!this.state.selectedIndexType && + !!this.state.indexName && + !this.state.hasIndexErrors && + this.state.phase === PHASE.CONFIGURE; if (isIndexReady !== this.state.isIndexReady) { this.setState({ isIndexReady }); - if (onIndexReady) { - onIndexReady(isIndexReady); - } + this.props.onIndexReady(isIndexReady); } }; - _indexData = async ({ - indexedFile, - parsedFile, - indexRequestInFlight, - indexName, - selectedIndexType, - isIndexingTriggered, - isIndexReady, - onIndexingComplete, - onIndexingError, - }) => { - // Check index ready - const filesAreEqual = _.isEqual(indexedFile, parsedFile); - if (!isIndexingTriggered || filesAreEqual || !isIndexReady || indexRequestInFlight) { - return; - } - this.setState({ - indexRequestInFlight: true, - currentIndexingStage: INDEXING_STAGE.WRITING_TO_INDEX, - }); - - this.geojsonImporter.setDocs(parsedFile.parsedGeojson, selectedIndexType); - - // initialize import + _import = async () => { + // + // create index + // const settings = { number_of_shards: 1, }; @@ -181,8 +91,16 @@ export class JsonUploadAndParse extends Component { }, }; const ingestPipeline = {}; - const initializeImportResp = await this.geojsonImporter.initializeImport( - indexName, + this.setState({ + importStatus: i18n.translate('xpack.fileUpload.jsonUploadAndParse.dataIndexingStarted', { + defaultMessage: 'Creating index: {indexName}', + values: { indexName: this.state.indexName }, + }), + phase: PHASE.IMPORT, + }); + this._geojsonImporter.setGeoFieldType(this.state.selectedIndexType); + const initializeImportResp = await this._geojsonImporter.initializeImport( + this.state.indexName, settings, mappings, ingestPipeline @@ -192,131 +110,180 @@ export class JsonUploadAndParse extends Component { } if (initializeImportResp.index === undefined || initializeImportResp.id === undefined) { this.setState({ - indexRequestInFlight: false, - currentIndexingStage: INDEXING_STAGE.INDEXING_ERROR, + phase: PHASE.COMPLETE, }); - this._resetFileAndIndexSettings(); - onIndexingError(); + this.props.onIndexingError(); return; } + // // import file - const importResp = await this.geojsonImporter.import( + // + this.setState({ + importStatus: getWritingToIndexMsg(0), + }); + const importResp = await this._geojsonImporter.import( initializeImportResp.id, - indexName, + this.state.indexName, initializeImportResp.pipelineId, - () => {} + (progress) => { + if (this._isMounted) { + this.setState({ + importStatus: getWritingToIndexMsg(progress), + }); + } + } ); if (!this._isMounted) { return; } + if (!importResp.success) { this.setState({ - indexDataResp: importResp, - indexRequestInFlight: false, - currentIndexingStage: INDEXING_STAGE.INDEXING_ERROR, + importResp, + importStatus: i18n.translate('xpack.fileUpload.jsonUploadAndParse.dataIndexingError', { + defaultMessage: 'Data indexing error', + }), + phase: PHASE.COMPLETE, }); - this._resetFileAndIndexSettings(); - onIndexingError(); + this.props.onIndexingError(); return; } - this.setState({ - indexDataResp: importResp, - indexedFile: parsedFile, - currentIndexingStage: INDEXING_STAGE.INDEXING_COMPLETE, - }); + // // create index pattern + // this.setState({ - indexPatternRequestInFlight: true, - currentIndexingStage: INDEXING_STAGE.CREATING_INDEX_PATTERN, + importResp, + importStatus: i18n.translate('xpack.fileUpload.jsonUploadAndParse.creatingIndexPattern', { + defaultMessage: 'Creating index pattern: {indexName}', + values: { indexName: this.state.indexName }, + }), }); let indexPattern; try { indexPattern = await getIndexPatternService().createAndSave( { - title: indexName, + title: this.state.indexName, }, true ); } catch (error) { if (this._isMounted) { this.setState({ - indexPatternRequestInFlight: false, - currentIndexingStage: INDEXING_STAGE.INDEX_PATTERN_ERROR, + importStatus: i18n.translate('xpack.fileUpload.jsonUploadAndParse.indexPatternError', { + defaultMessage: 'Index pattern error', + }), + phase: PHASE.COMPLETE, }); - this._resetFileAndIndexSettings(); - onIndexingError(); + this.props.onIndexingError(); } return; } if (!this._isMounted) { return; } + + // + // Successful import + // this.setState({ indexPatternResp: { success: true, id: indexPattern.id, fields: indexPattern.fields, }, - indexPatternRequestInFlight: false, + phase: PHASE.COMPLETE, + importStatus: '', }); - this.setState({ - currentIndexingStage: INDEXING_STAGE.INDEX_PATTERN_COMPLETE, - }); - this._resetFileAndIndexSettings(); - onIndexingComplete({ + this.props.onIndexingComplete({ indexDataResp: importResp, indexPattern, }); }; - render() { - const { - currentIndexingStage, - indexDataResp, - indexPatternResp, - fileRef, + _onFileSelect = ({ features, hasPoints, hasShapes, importer, indexName, previewCoverage }) => { + this._geojsonImporter = importer; + + const geoFieldTypes = hasPoints + ? [ES_FIELD_TYPES.GEO_POINT, ES_FIELD_TYPES.GEO_SHAPE] + : [ES_FIELD_TYPES.GEO_SHAPE]; + + const newState = { + indexTypes: geoFieldTypes, + indexName, + }; + if (!this.state.selectedIndexType) { + // auto select index type + newState.selectedIndexType = + hasPoints && !hasShapes ? ES_FIELD_TYPES.GEO_POINT : ES_FIELD_TYPES.GEO_SHAPE; + } else if ( + this.state.selectedIndexType && + !geoFieldTypes.includes(this.state.selectedIndexType) + ) { + // unselected indexType if selected type is not longer an option + newState.selectedIndexType = ''; + } + this.setState(newState); + + this.props.onFileUpload( + { + type: 'FeatureCollection', + features, + }, indexName, - indexTypes, - showImportProgress, - } = this.state; + previewCoverage + ); + }; + + _onFileClear = () => { + if (this._geojsonImporter) { + this._geojsonImporter.destroy(); + this._geojsonImporter = undefined; + } + + this.props.onFileRemove(); + + this.setState({ + indexTypes: [], + selectedIndexType: '', + indexName: '', + }); + }; + + render() { + if (this.state.phase === PHASE.IMPORT) { + return ( + + + +

{this.state.importStatus}

+
+
+ ); + } + + if (this.state.phase === PHASE.COMPLETE) { + return ( + + ); + } return ( - {showImportProgress ? ( - - ) : ( - - this.setState({ fileRef })} - setParsedFile={(parsedFile, indexName) => { - this.setState({ parsedFile, indexName }); - this.props.onFileUpload(parsedFile.parsedGeojson, indexName); - }} - resetFileAndIndexSettings={this._resetFileAndIndexSettings} - geojsonImporter={this.geojsonImporter} - /> - this.setState({ indexName })} - indexTypes={indexTypes} - setSelectedIndexType={(selectedIndexType) => this.setState({ selectedIndexType })} - setHasIndexErrors={(hasIndexErrors) => this.setState({ hasIndexErrors })} - /> - - )} + + this.setState({ indexName })} + indexTypes={this.state.indexTypes} + selectedIndexType={this.state.selectedIndexType} + setSelectedIndexType={(selectedIndexType) => this.setState({ selectedIndexType })} + setHasIndexErrors={(hasIndexErrors) => this.setState({ hasIndexErrors })} + /> ); } diff --git a/x-pack/plugins/file_upload/public/get_max_bytes.ts b/x-pack/plugins/file_upload/public/get_max_bytes.ts new file mode 100644 index 00000000000000..2e002e65248c90 --- /dev/null +++ b/x-pack/plugins/file_upload/public/get_max_bytes.ts @@ -0,0 +1,31 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +// @ts-ignore +import numeral from '@elastic/numeral'; +import { + MAX_FILE_SIZE, + MAX_FILE_SIZE_BYTES, + ABSOLUTE_MAX_FILE_SIZE_BYTES, + FILE_SIZE_DISPLAY_FORMAT, + UI_SETTING_MAX_FILE_SIZE, +} from '../common'; +import { getUiSettings } from './kibana_services'; + +export function getMaxBytes() { + const maxFileSize = getUiSettings().get(UI_SETTING_MAX_FILE_SIZE, MAX_FILE_SIZE); + // @ts-ignore + const maxBytes = numeral(maxFileSize.toUpperCase()).value(); + if (maxBytes < MAX_FILE_SIZE_BYTES) { + return MAX_FILE_SIZE_BYTES; + } + return maxBytes <= ABSOLUTE_MAX_FILE_SIZE_BYTES ? maxBytes : ABSOLUTE_MAX_FILE_SIZE_BYTES; +} + +export function getMaxBytesFormatted() { + return numeral(getMaxBytes()).format(FILE_SIZE_DISPLAY_FORMAT); +} diff --git a/x-pack/plugins/file_upload/public/importer/geojson_importer/geojson_importer.test.js b/x-pack/plugins/file_upload/public/importer/geojson_importer/geojson_importer.test.js index e348686dc060ae..98f14f3e58166e 100644 --- a/x-pack/plugins/file_upload/public/importer/geojson_importer/geojson_importer.test.js +++ b/x-pack/plugins/file_upload/public/importer/geojson_importer/geojson_importer.test.js @@ -5,7 +5,7 @@ * 2.0. */ -import { GeoJsonImporter } from './geojson_importer'; +import { GeoJsonImporter, toEsDocs } from './geojson_importer'; import { ES_FIELD_TYPES } from '../../../../../../src/plugins/data/public'; import '@loaders.gl/polyfills'; @@ -25,9 +25,7 @@ const FEATURE_COLLECTION = { ], }; -describe('readFile', () => { - const setFileProgress = jest.fn((a) => a); - +describe('previewFile', () => { const FILE_WITH_FEATURE_COLLECTION = new File( [JSON.stringify(FEATURE_COLLECTION)], 'testfile.json', @@ -39,38 +37,26 @@ describe('readFile', () => { jest.restoreAllMocks(); }); - test('should throw error if no file provided', async () => { - const importer = new GeoJsonImporter(); - await importer - .readFile(null, setFileProgress, () => { - return true; - }) - .catch((e) => { - expect(e.message).toMatch('Error, no file provided'); - }); - }); - - test('should abort if file parse is cancelled', async () => { - const importer = new GeoJsonImporter(); - - const results = await importer.readFile(FILE_WITH_FEATURE_COLLECTION, setFileProgress, () => { - return false; + test('should stop reading when importer is destroyed', async () => { + const importer = new GeoJsonImporter(FILE_WITH_FEATURE_COLLECTION); + importer.destroy(); + const results = await importer.previewFile(); + expect(results).toEqual({ + features: [], + previewCoverage: 0, + hasPoints: false, + hasShapes: false, }); - - expect(results).toBeNull(); }); test('should read features from feature collection', async () => { - const importer = new GeoJsonImporter(); - const results = await importer.readFile(FILE_WITH_FEATURE_COLLECTION, setFileProgress, () => { - return true; - }); - - expect(setFileProgress).toHaveBeenCalled(); + const importer = new GeoJsonImporter(FILE_WITH_FEATURE_COLLECTION); + const results = await importer.previewFile(); expect(results).toEqual({ - errors: [], - geometryTypes: ['Point'], - parsedGeojson: FEATURE_COLLECTION, + previewCoverage: 100, + hasPoints: true, + hasShapes: false, + features: FEATURE_COLLECTION.features, }); }); @@ -99,20 +85,14 @@ describe('readFile', () => { { type: 'text/json' } ); - const importer = new GeoJsonImporter(); - const results = await importer.readFile( - fileWithFeaturesWithoutGeometry, - setFileProgress, - () => { - return true; - } - ); + const importer = new GeoJsonImporter(fileWithFeaturesWithoutGeometry); + const results = await importer.previewFile(); - expect(setFileProgress).toHaveBeenCalled(); expect(results).toEqual({ - errors: ['2 features without geometry omitted'], - geometryTypes: ['Point'], - parsedGeojson: FEATURE_COLLECTION, + previewCoverage: 100, + hasPoints: true, + hasShapes: false, + features: FEATURE_COLLECTION.features, }); }); @@ -134,20 +114,18 @@ describe('readFile', () => { { type: 'text/json' } ); - const importer = new GeoJsonImporter(); - const results = await importer.readFile(fileWithUnwrapedFeature, setFileProgress, () => { - return true; - }); + const importer = new GeoJsonImporter(fileWithUnwrapedFeature); + const results = await importer.previewFile(); - expect(setFileProgress).toHaveBeenCalled(); expect(results).toEqual({ - errors: [], - geometryTypes: ['Point'], - parsedGeojson: FEATURE_COLLECTION, + previewCoverage: 100, + hasPoints: true, + hasShapes: false, + features: FEATURE_COLLECTION.features, }); }); - test('should throw if no features', async () => { + test('should return empty feature collection if no features', async () => { const fileWithNoFeatures = new File( [ JSON.stringify({ @@ -159,17 +137,18 @@ describe('readFile', () => { { type: 'text/json' } ); - const importer = new GeoJsonImporter(); - await importer - .readFile(fileWithNoFeatures, setFileProgress, () => { - return true; - }) - .catch((e) => { - expect(e.message).toMatch('Error, no features detected'); - }); + const importer = new GeoJsonImporter(fileWithNoFeatures); + const results = await importer.previewFile(); + + expect(results).toEqual({ + previewCoverage: 100, + hasPoints: false, + hasShapes: false, + features: [], + }); }); - test('should throw if no features with geometry', async () => { + test('should return empty feature collection if no features with geometry', async () => { const fileWithFeaturesWithNoGeometry = new File( [ JSON.stringify({ @@ -186,22 +165,22 @@ describe('readFile', () => { { type: 'text/json' } ); - const importer = new GeoJsonImporter(); - await importer - .readFile(fileWithFeaturesWithNoGeometry, setFileProgress, () => { - return true; - }) - .catch((e) => { - expect(e.message).toMatch('Error, no features detected'); - }); + const importer = new GeoJsonImporter(fileWithFeaturesWithNoGeometry); + const results = await importer.previewFile(); + + expect(results).toEqual({ + previewCoverage: 100, + hasPoints: false, + hasShapes: false, + features: [], + }); }); }); -describe('setDocs', () => { +describe('toEsDocs', () => { test('should convert features to geo_point ES documents', () => { - const importer = new GeoJsonImporter(); - importer.setDocs(FEATURE_COLLECTION, ES_FIELD_TYPES.GEO_POINT); - expect(importer.getDocs()).toEqual([ + const esDocs = toEsDocs(FEATURE_COLLECTION.features, ES_FIELD_TYPES.GEO_POINT); + expect(esDocs).toEqual([ { coordinates: [-112.0372, 46.608058], population: 200, @@ -210,9 +189,8 @@ describe('setDocs', () => { }); test('should convert features to geo_shape ES documents', () => { - const importer = new GeoJsonImporter(); - importer.setDocs(FEATURE_COLLECTION, ES_FIELD_TYPES.GEO_SHAPE); - expect(importer.getDocs()).toEqual([ + const esDocs = toEsDocs(FEATURE_COLLECTION.features, ES_FIELD_TYPES.GEO_SHAPE); + expect(esDocs).toEqual([ { coordinates: { type: 'point', diff --git a/x-pack/plugins/file_upload/public/importer/geojson_importer/geojson_importer.ts b/x-pack/plugins/file_upload/public/importer/geojson_importer/geojson_importer.ts index 189084e9180daa..3294655916b5b5 100644 --- a/x-pack/plugins/file_upload/public/importer/geojson_importer/geojson_importer.ts +++ b/x-pack/plugins/file_upload/public/importer/geojson_importer/geojson_importer.ts @@ -7,7 +7,6 @@ import { Feature, - FeatureCollection, Point, MultiPoint, LineString, @@ -18,161 +17,274 @@ import { import { i18n } from '@kbn/i18n'; // @ts-expect-error import { JSONLoader, loadInBatches } from './loaders'; -import { CreateDocsResponse } from '../types'; -import { Importer } from '../importer'; +import { CreateDocsResponse, ImportResults } from '../types'; +import { callImportRoute, Importer, IMPORT_RETRIES } from '../importer'; import { ES_FIELD_TYPES } from '../../../../../../src/plugins/data/public'; // @ts-expect-error import { geoJsonCleanAndValidate } from './geojson_clean_and_validate'; +import { ImportFailure, ImportResponse, MB } from '../../../common'; + +const IMPORT_CHUNK_SIZE_MB = 10 * MB; +export const GEOJSON_FILE_TYPES = ['.json', '.geojson']; + +export interface GeoJsonPreview { + features: Feature[]; + hasPoints: boolean; + hasShapes: boolean; + previewCoverage: number; +} export class GeoJsonImporter extends Importer { - constructor() { + private _file: File; + private _isActive = true; + private _iterator?: Iterator; + private _hasNext = true; + private _features: Feature[] = []; + private _totalBytesProcessed = 0; + private _unimportedBytesProcessed = 0; + private _totalFeatures = 0; + private _geometryTypesMap = new Map(); + private _invalidFeatures: ImportFailure[] = []; + private _prevBatchLastFeature?: Feature; + private _geoFieldType: ES_FIELD_TYPES.GEO_POINT | ES_FIELD_TYPES.GEO_SHAPE = + ES_FIELD_TYPES.GEO_SHAPE; + + constructor(file: File) { super(); + + this._file = file; } - public read(data: ArrayBuffer): { success: boolean } { - throw new Error('read(data: ArrayBuffer) not supported, use readFile instead.'); + public destroy() { + this._isActive = false; } - protected _createDocs(text: string): CreateDocsResponse { - throw new Error('_createDocs not implemented.'); + public async previewFile(rowLimit?: number, sizeLimit?: number): Promise { + await this._readUntil(rowLimit, sizeLimit); + return { + features: [...this._features], + previewCoverage: this._hasNext + ? Math.round((this._unimportedBytesProcessed / this._file.size) * 100) + : 100, + hasPoints: this._geometryTypesMap.has('Point') || this._geometryTypesMap.has('MultiPoint'), + hasShapes: + this._geometryTypesMap.has('LineString') || + this._geometryTypesMap.has('MultiLineString') || + this._geometryTypesMap.has('Polygon') || + this._geometryTypesMap.has('MultiPolygon'), + }; } - public getDocs() { - return this._docArray; + public setGeoFieldType(geoFieldType: ES_FIELD_TYPES.GEO_POINT | ES_FIELD_TYPES.GEO_SHAPE) { + this._geoFieldType = geoFieldType; } - public setDocs( - featureCollection: FeatureCollection, - geoFieldType: ES_FIELD_TYPES.GEO_POINT | ES_FIELD_TYPES.GEO_SHAPE - ) { - this._docArray = []; - for (let i = 0; i < featureCollection.features.length; i++) { - const feature = featureCollection.features[i]; - const geometry = feature.geometry as - | Point - | MultiPoint - | LineString - | MultiLineString - | Polygon - | MultiPolygon; - const coordinates = - geoFieldType === ES_FIELD_TYPES.GEO_SHAPE - ? { - type: geometry.type.toLowerCase(), - coordinates: geometry.coordinates, - } - : geometry.coordinates; - const properties = feature.properties ? feature.properties : {}; - this._docArray.push({ - coordinates, - ...properties, - }); + public async import( + id: string, + index: string, + pipelineId: string, + setImportProgress: (progress: number) => void + ): Promise { + if (!id || !index) { + return { + success: false, + error: i18n.translate('xpack.fileUpload.import.noIdOrIndexSuppliedErrorMessage', { + defaultMessage: 'no ID or index supplied', + }), + }; } + + let success = true; + const failures: ImportFailure[] = [...this._invalidFeatures]; + let error; + + while ((this._features.length > 0 || this._hasNext) && this._isActive) { + await this._readUntil(undefined, IMPORT_CHUNK_SIZE_MB); + if (!this._isActive) { + return { + success: false, + failures, + docCount: this._totalFeatures, + }; + } + + let retries = IMPORT_RETRIES; + let resp: ImportResponse = { + success: false, + failures: [], + docCount: 0, + id: '', + index: '', + pipelineId: '', + }; + const data = toEsDocs(this._features, this._geoFieldType); + const progress = Math.round((this._totalBytesProcessed / this._file.size) * 100); + this._features = []; + this._unimportedBytesProcessed = 0; + + while (resp.success === false && retries > 0) { + try { + resp = await callImportRoute({ + id, + index, + data, + settings: {}, + mappings: {}, + ingestPipeline: { + id: pipelineId, + }, + }); + + if (retries < IMPORT_RETRIES) { + // eslint-disable-next-line no-console + console.log(`Retrying import ${IMPORT_RETRIES - retries}`); + } + + retries--; + } catch (err) { + resp.success = false; + resp.error = err; + retries = 0; + } + } + + failures.push(...resp.failures); + + if (!resp.success) { + success = false; + error = resp.error; + break; + } + + setImportProgress(progress); + } + + const result: ImportResults = { + success, + failures, + docCount: this._totalFeatures, + }; + + if (success) { + setImportProgress(100); + } else { + result.error = error; + } + + return result; } - public async readFile( - file: File, - setFileProgress: ({ - featuresProcessed, - bytesProcessed, - totalBytes, - }: { - featuresProcessed: number; - bytesProcessed: number; - totalBytes: number; - }) => void, - isFileParseActive: () => boolean - ): Promise<{ - errors: string[]; - geometryTypes: string[]; - parsedGeojson: FeatureCollection; - } | null> { - if (!file) { - throw new Error( - i18n.translate('xpack.fileUpload.fileParser.noFileProvided', { - defaultMessage: 'Error, no file provided', - }) - ); + private async _readUntil(rowLimit?: number, sizeLimit?: number) { + while ( + this._isActive && + this._hasNext && + (rowLimit === undefined || this._features.length < rowLimit) && + (sizeLimit === undefined || this._unimportedBytesProcessed < sizeLimit) + ) { + await this._next(); } + } - return new Promise(async (resolve, reject) => { - const batches = await loadInBatches(file, JSONLoader, { + private async _next() { + if (this._iterator === undefined) { + this._iterator = await loadInBatches(this._file, JSONLoader, { json: { jsonpaths: ['$.features'], _rootObjectBatches: true, }, }); + } - const rawFeatures: unknown[] = []; - for await (const batch of batches) { - if (!isFileParseActive()) { - break; - } + if (!this._isActive || !this._iterator) { + return; + } - if (batch.batchType === 'root-object-batch-complete') { - // Handle single feature geoJson - if (rawFeatures.length === 0) { - rawFeatures.push(batch.container); - } - } else { - rawFeatures.push(...batch.data); - } + const { value: batch, done } = await this._iterator.next(); - setFileProgress({ - featuresProcessed: rawFeatures.length, - bytesProcessed: batch.bytesUsed, - totalBytes: file.size, - }); - } + if (!this._isActive || done) { + this._hasNext = false; + return; + } + + if ('bytesUsed' in batch) { + const bytesRead = batch.bytesUsed - this._totalBytesProcessed; + this._unimportedBytesProcessed += bytesRead; + this._totalBytesProcessed = batch.bytesUsed; + } - if (!isFileParseActive()) { - resolve(null); - return; + const rawFeatures: unknown[] = this._prevBatchLastFeature ? [this._prevBatchLastFeature] : []; + this._prevBatchLastFeature = undefined; + const isLastBatch = batch.batchType === 'root-object-batch-complete'; + if (isLastBatch) { + // Handle single feature geoJson + if (this._totalFeatures === 0) { + rawFeatures.push(batch.container); } + } else { + rawFeatures.push(...batch.data); + } - if (rawFeatures.length === 0) { - reject( - new Error( - i18n.translate('xpack.fileUpload.fileParser.noFeaturesDetected', { - defaultMessage: 'Error, no features detected', - }) - ) - ); - return; + for (let i = 0; i < rawFeatures.length; i++) { + const rawFeature = rawFeatures[i] as Feature; + if (!isLastBatch && i === rawFeatures.length - 1) { + // Do not process last feature until next batch is read, features on batch boundary may be incomplete. + this._prevBatchLastFeature = rawFeature; + continue; } - const features: Feature[] = []; - const geometryTypesMap = new Map(); - let invalidCount = 0; - for (let i = 0; i < rawFeatures.length; i++) { - const rawFeature = rawFeatures[i] as Feature; - if (!rawFeature.geometry || !rawFeature.geometry.type) { - invalidCount++; - } else { - if (!geometryTypesMap.has(rawFeature.geometry.type)) { - geometryTypesMap.set(rawFeature.geometry.type, true); - } - features.push(geoJsonCleanAndValidate(rawFeature)); + this._totalFeatures++; + if (!rawFeature.geometry || !rawFeature.geometry.type) { + this._invalidFeatures.push({ + item: this._totalFeatures, + reason: i18n.translate('xpack.fileUpload.geojsonImporter.noGeometry', { + defaultMessage: 'Feature does not contain required field "geometry"', + }), + doc: rawFeature, + }); + } else { + if (!this._geometryTypesMap.has(rawFeature.geometry.type)) { + this._geometryTypesMap.set(rawFeature.geometry.type, true); } + this._features.push(geoJsonCleanAndValidate(rawFeature)); } + } + } - const errors: string[] = []; - if (invalidCount > 0) { - errors.push( - i18n.translate('xpack.fileUpload.fileParser.featuresOmitted', { - defaultMessage: '{invalidCount} features without geometry omitted', - values: { invalidCount }, - }) - ); - } - resolve({ - errors, - geometryTypes: Array.from(geometryTypesMap.keys()), - parsedGeojson: { - type: 'FeatureCollection', - features, - }, - }); + public read(data: ArrayBuffer): { success: boolean } { + throw new Error('read(data: ArrayBuffer) not supported, use readFile instead.'); + } + + protected _createDocs(text: string): CreateDocsResponse { + throw new Error('_createDocs not implemented.'); + } +} + +export function toEsDocs( + features: Feature[], + geoFieldType: ES_FIELD_TYPES.GEO_POINT | ES_FIELD_TYPES.GEO_SHAPE +) { + const esDocs = []; + for (let i = 0; i < features.length; i++) { + const feature = features[i]; + const geometry = feature.geometry as + | Point + | MultiPoint + | LineString + | MultiLineString + | Polygon + | MultiPolygon; + const coordinates = + geoFieldType === ES_FIELD_TYPES.GEO_SHAPE + ? { + type: geometry.type.toLowerCase(), + coordinates: geometry.coordinates, + } + : geometry.coordinates; + const properties = feature.properties ? feature.properties : {}; + esDocs.push({ + coordinates, + ...properties, }); } + return esDocs; } diff --git a/x-pack/plugins/file_upload/public/importer/geojson_importer/index.ts b/x-pack/plugins/file_upload/public/importer/geojson_importer/index.ts index 9ffb84e603161b..b5f6845e283247 100644 --- a/x-pack/plugins/file_upload/public/importer/geojson_importer/index.ts +++ b/x-pack/plugins/file_upload/public/importer/geojson_importer/index.ts @@ -5,4 +5,4 @@ * 2.0. */ -export { GeoJsonImporter } from './geojson_importer'; +export { GeoJsonImporter, GeoJsonPreview, GEOJSON_FILE_TYPES } from './geojson_importer'; diff --git a/x-pack/plugins/file_upload/public/importer/importer.ts b/x-pack/plugins/file_upload/public/importer/importer.ts index 8bdb465bd69cf4..2689f3badc3975 100644 --- a/x-pack/plugins/file_upload/public/importer/importer.ts +++ b/x-pack/plugins/file_upload/public/importer/importer.ts @@ -22,7 +22,7 @@ import { CreateDocsResponse, IImporter, ImportResults } from './types'; const CHUNK_SIZE = 5000; const MAX_CHUNK_CHAR_COUNT = 1000000; -const IMPORT_RETRIES = 5; +export const IMPORT_RETRIES = 5; const STRING_CHUNKS_MB = 100; export abstract class Importer implements IImporter { @@ -232,7 +232,7 @@ function createDocumentChunks(docArray: ImportDoc[]) { return chunks; } -function callImportRoute({ +export function callImportRoute({ id, index, data, diff --git a/x-pack/plugins/file_upload/public/importer/index.ts b/x-pack/plugins/file_upload/public/importer/index.ts index face822f91efba..22465ae2df8a77 100644 --- a/x-pack/plugins/file_upload/public/importer/index.ts +++ b/x-pack/plugins/file_upload/public/importer/index.ts @@ -6,4 +6,5 @@ */ export { importerFactory } from './importer_factory'; +export { validateFile } from './validate_file'; export * from './types'; diff --git a/x-pack/plugins/file_upload/public/importer/validate_file.ts b/x-pack/plugins/file_upload/public/importer/validate_file.ts new file mode 100644 index 00000000000000..4c7fe704d8afad --- /dev/null +++ b/x-pack/plugins/file_upload/public/importer/validate_file.ts @@ -0,0 +1,52 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { i18n } from '@kbn/i18n'; +import { getMaxBytes, getMaxBytesFormatted } from '../get_max_bytes'; + +export function validateFile(file: File, types: string[]) { + if (file.size > getMaxBytes()) { + throw new Error( + i18n.translate('xpack.fileUpload.fileSizeError', { + defaultMessage: 'File size {fileSize} exceeds maximum file size of {maxFileSize}', + values: { + fileSize: bytesToSize(file.size), + maxFileSize: getMaxBytesFormatted(), + }, + }) + ); + } + + if (!file.name) { + throw new Error( + i18n.translate('xpack.fileUpload.noFileNameError', { + defaultMessage: 'File name not provided', + }) + ); + } + + const nameSplit = file.name.split('.'); + const fileType = nameSplit.pop(); + if (!types.includes(`.${fileType}`)) { + throw new Error( + i18n.translate('xpack.fileUpload.fileTypeError', { + defaultMessage: 'File is not one of acceptable types: {types}', + values: { + types: types.join(', '), + }, + }) + ); + } +} + +function bytesToSize(bytes: number) { + if (bytes === 0) return 'n/a'; + const sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB']; + const i = Math.round(Math.floor(Math.log(bytes) / Math.log(1024))); + if (i === 0) return `${bytes} ${sizes[i]})`; + return `${(bytes / 1024 ** i).toFixed(1)} ${sizes[i]}`; +} diff --git a/x-pack/plugins/file_upload/public/kibana_services.ts b/x-pack/plugins/file_upload/public/kibana_services.ts index c007c5c2273a8a..a604136ca34e49 100644 --- a/x-pack/plugins/file_upload/public/kibana_services.ts +++ b/x-pack/plugins/file_upload/public/kibana_services.ts @@ -18,3 +18,4 @@ export function setStartServices(core: CoreStart, plugins: FileUploadStartDepend export const getIndexPatternService = () => pluginsStart.data.indexPatterns; export const getHttp = () => coreStart.http; export const getSavedObjectsClient = () => coreStart.savedObjects.client; +export const getUiSettings = () => coreStart.uiSettings; diff --git a/x-pack/plugins/file_upload/public/lazy_load_bundle/index.ts b/x-pack/plugins/file_upload/public/lazy_load_bundle/index.ts index 9cfc0896f5c2de..a61faa5bef0c4f 100644 --- a/x-pack/plugins/file_upload/public/lazy_load_bundle/index.ts +++ b/x-pack/plugins/file_upload/public/lazy_load_bundle/index.ts @@ -12,7 +12,7 @@ import { IImporter, ImportFactoryOptions, ImportResults } from '../importer'; export interface FileUploadComponentProps { isIndexingTriggered: boolean; - onFileUpload: (geojsonFile: FeatureCollection, name: string) => void; + onFileUpload: (geojsonFile: FeatureCollection, name: string, previewCoverage: number) => void; onFileRemove: () => void; onIndexReady: (indexReady: boolean) => void; onIndexingComplete: (results: { diff --git a/x-pack/plugins/file_upload/public/plugin.ts b/x-pack/plugins/file_upload/public/plugin.ts index 5d3918193d48a1..af3dd65b788a78 100644 --- a/x-pack/plugins/file_upload/public/plugin.ts +++ b/x-pack/plugins/file_upload/public/plugin.ts @@ -9,6 +9,7 @@ import { CoreStart, Plugin } from '../../../../src/core/public'; import { FileUploadStartApi, getFileUploadComponent, importerFactory } from './api'; import { setStartServices } from './kibana_services'; import { DataPublicPluginStart } from '../../../../src/plugins/data/public'; +import { getMaxBytes, getMaxBytesFormatted } from './get_max_bytes'; // eslint-disable-next-line @typescript-eslint/no-empty-interface export interface FileUploadSetupDependencies {} @@ -34,6 +35,8 @@ export class FileUploadPlugin return { getFileUploadComponent, importerFactory, + getMaxBytes, + getMaxBytesFormatted, }; } } diff --git a/x-pack/plugins/file_upload/server/plugin.ts b/x-pack/plugins/file_upload/server/plugin.ts index 74a18633d8a264..94b4f0368d562c 100644 --- a/x-pack/plugins/file_upload/server/plugin.ts +++ b/x-pack/plugins/file_upload/server/plugin.ts @@ -5,10 +5,13 @@ * 2.0. */ +import { i18n } from '@kbn/i18n'; import { CoreSetup, CoreStart, Plugin } from 'src/core/server'; +import { schema } from '@kbn/config-schema'; import { fileUploadRoutes } from './routes'; import { initFileUploadTelemetry } from './telemetry'; import { UsageCollectionSetup } from '../../../../src/plugins/usage_collection/server'; +import { UI_SETTING_MAX_FILE_SIZE, MAX_FILE_SIZE } from '../common'; interface SetupDeps { usageCollection: UsageCollectionSetup; @@ -18,6 +21,26 @@ export class FileUploadPlugin implements Plugin { async setup(coreSetup: CoreSetup, plugins: SetupDeps) { fileUploadRoutes(coreSetup.http.createRouter()); + coreSetup.uiSettings.register({ + [UI_SETTING_MAX_FILE_SIZE]: { + name: i18n.translate('xpack.fileUpload.maxFileSizeUiSetting.name', { + defaultMessage: 'Maximum file upload size', + }), + value: MAX_FILE_SIZE, + description: i18n.translate('xpack.fileUpload.maxFileSizeUiSetting.description', { + defaultMessage: + 'Sets the file size limit when importing files. The highest supported value for this setting is 1GB.', + }), + schema: schema.string(), + validation: { + regexString: '\\d+[mMgG][bB]', + message: i18n.translate('xpack.fileUpload.maxFileSizeUiSetting.error', { + defaultMessage: 'Should be a valid data size. e.g. 200MB, 1GB', + }), + }, + }, + }); + initFileUploadTelemetry(coreSetup, plugins.usageCollection); } diff --git a/x-pack/plugins/fleet/common/constants/agent_policy.ts b/x-pack/plugins/fleet/common/constants/agent_policy.ts index bed9b6e8390b87..51cf0382e2dbce 100644 --- a/x-pack/plugins/fleet/common/constants/agent_policy.ts +++ b/x-pack/plugins/fleet/common/constants/agent_policy.ts @@ -6,7 +6,8 @@ */ import { defaultPackages } from './epm'; -import { AgentPolicy } from '../types'; +import type { AgentPolicy } from '../types'; + export const AGENT_POLICY_SAVED_OBJECT_TYPE = 'ingest-agent-policies'; export const AGENT_POLICY_INDEX = '.fleet-policies'; export const agentPolicyStatuses = { diff --git a/x-pack/plugins/fleet/common/constants/output.ts b/x-pack/plugins/fleet/common/constants/output.ts index 9022be10867443..80c7e56dbb52ff 100644 --- a/x-pack/plugins/fleet/common/constants/output.ts +++ b/x-pack/plugins/fleet/common/constants/output.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { NewOutput } from '../types'; +import type { NewOutput } from '../types'; export const OUTPUT_SAVED_OBJECT_TYPE = 'ingest-outputs'; diff --git a/x-pack/plugins/fleet/common/mocks.ts b/x-pack/plugins/fleet/common/mocks.ts index 4edc0fa6f81e9c..7ea4be0ee35c64 100644 --- a/x-pack/plugins/fleet/common/mocks.ts +++ b/x-pack/plugins/fleet/common/mocks.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { NewPackagePolicy, PackagePolicy } from './types'; +import type { NewPackagePolicy, PackagePolicy } from './types'; export const createNewPackagePolicyMock = (): NewPackagePolicy => { return { diff --git a/x-pack/plugins/fleet/common/services/agent_status.ts b/x-pack/plugins/fleet/common/services/agent_status.ts index 1b49ba0c015e9c..6d1d1c6a309d80 100644 --- a/x-pack/plugins/fleet/common/services/agent_status.ts +++ b/x-pack/plugins/fleet/common/services/agent_status.ts @@ -6,7 +6,7 @@ */ import { AGENT_POLLING_THRESHOLD_MS, AGENT_SAVED_OBJECT_TYPE } from '../constants'; -import { Agent, AgentStatus } from '../types'; +import type { Agent, AgentStatus } from '../types'; export function getAgentStatus(agent: Agent, now: number = Date.now()): AgentStatus { const { last_checkin: lastCheckIn } = agent; diff --git a/x-pack/plugins/fleet/common/services/full_agent_policy_kibana_config.ts b/x-pack/plugins/fleet/common/services/full_agent_policy_kibana_config.ts index 46fddd8bf040b5..6b2709cc1961dc 100644 --- a/x-pack/plugins/fleet/common/services/full_agent_policy_kibana_config.ts +++ b/x-pack/plugins/fleet/common/services/full_agent_policy_kibana_config.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { FullAgentPolicyKibanaConfig } from '../types'; +import type { FullAgentPolicyKibanaConfig } from '../types'; export function getFullAgentPolicyKibanaConfig(kibanaUrls: string[]): FullAgentPolicyKibanaConfig { // paths and protocol are validated to be the same for all urls, so use the first to get them diff --git a/x-pack/plugins/fleet/common/services/full_agent_policy_to_yaml.ts b/x-pack/plugins/fleet/common/services/full_agent_policy_to_yaml.ts index 3dafc65a652353..64d297922f5703 100644 --- a/x-pack/plugins/fleet/common/services/full_agent_policy_to_yaml.ts +++ b/x-pack/plugins/fleet/common/services/full_agent_policy_to_yaml.ts @@ -6,7 +6,7 @@ */ import { safeDump } from 'js-yaml'; -import { FullAgentPolicy } from '../types'; +import type { FullAgentPolicy } from '../types'; const POLICY_KEYS_ORDER = [ 'id', diff --git a/x-pack/plugins/fleet/common/services/is_agent_upgradeable.test.ts b/x-pack/plugins/fleet/common/services/is_agent_upgradeable.test.ts index ed5e2a22709c4a..38ae63933a0760 100644 --- a/x-pack/plugins/fleet/common/services/is_agent_upgradeable.test.ts +++ b/x-pack/plugins/fleet/common/services/is_agent_upgradeable.test.ts @@ -6,7 +6,7 @@ */ import { isAgentUpgradeable } from './is_agent_upgradeable'; -import { Agent } from '../types/models/agent'; +import type { Agent } from '../types/models/agent'; const getAgent = ({ version, diff --git a/x-pack/plugins/fleet/common/services/is_agent_upgradeable.ts b/x-pack/plugins/fleet/common/services/is_agent_upgradeable.ts index 12129816581f1e..7de4e7c11d09e7 100644 --- a/x-pack/plugins/fleet/common/services/is_agent_upgradeable.ts +++ b/x-pack/plugins/fleet/common/services/is_agent_upgradeable.ts @@ -7,7 +7,7 @@ import semverCoerce from 'semver/functions/coerce'; import semverLt from 'semver/functions/lt'; -import { Agent } from '../types'; +import type { Agent } from '../types'; export function isAgentUpgradeable(agent: Agent, kibanaVersion: string) { let agentVersion: string; diff --git a/x-pack/plugins/fleet/common/services/license.ts b/x-pack/plugins/fleet/common/services/license.ts index a480dd56d8b0cb..68cbee5786d3ba 100644 --- a/x-pack/plugins/fleet/common/services/license.ts +++ b/x-pack/plugins/fleet/common/services/license.ts @@ -6,7 +6,7 @@ */ import { Observable, Subscription } from 'rxjs'; -import { ILicense } from '../../../licensing/common/types'; +import type { ILicense } from '../../../licensing/common/types'; // Generic license service class that works with the license observable // Both server and client plugins instancates a singleton version of this class diff --git a/x-pack/plugins/fleet/common/services/limited_package.ts b/x-pack/plugins/fleet/common/services/limited_package.ts index da4ee176ee443b..e247b61869de12 100644 --- a/x-pack/plugins/fleet/common/services/limited_package.ts +++ b/x-pack/plugins/fleet/common/services/limited_package.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { PackageInfo, AgentPolicy, PackagePolicy } from '../types'; +import type { PackageInfo, AgentPolicy, PackagePolicy } from '../types'; // Assume packages only ever include 1 config template for now export const isPackageLimited = (packageInfo: PackageInfo): boolean => { diff --git a/x-pack/plugins/fleet/common/services/package_policies_to_agent_inputs.test.ts b/x-pack/plugins/fleet/common/services/package_policies_to_agent_inputs.test.ts index ee67263f159beb..930a111f66d6b0 100644 --- a/x-pack/plugins/fleet/common/services/package_policies_to_agent_inputs.test.ts +++ b/x-pack/plugins/fleet/common/services/package_policies_to_agent_inputs.test.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { PackagePolicy, PackagePolicyInput } from '../types'; +import type { PackagePolicy, PackagePolicyInput } from '../types'; import { storedPackagePoliciesToAgentInputs } from './package_policies_to_agent_inputs'; describe('Fleet - storedPackagePoliciesToAgentInputs', () => { diff --git a/x-pack/plugins/fleet/common/services/package_policies_to_agent_inputs.ts b/x-pack/plugins/fleet/common/services/package_policies_to_agent_inputs.ts index f1cd2f60896e77..61d7764a832b16 100644 --- a/x-pack/plugins/fleet/common/services/package_policies_to_agent_inputs.ts +++ b/x-pack/plugins/fleet/common/services/package_policies_to_agent_inputs.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { PackagePolicy, FullAgentPolicyInput, FullAgentPolicyInputStream } from '../types'; +import type { PackagePolicy, FullAgentPolicyInput, FullAgentPolicyInputStream } from '../types'; import { DEFAULT_OUTPUT } from '../constants'; export const storedPackagePoliciesToAgentInputs = ( diff --git a/x-pack/plugins/fleet/common/services/package_to_package_policy.test.ts b/x-pack/plugins/fleet/common/services/package_to_package_policy.test.ts index bb07ff152c0852..e8ede61098dc2a 100644 --- a/x-pack/plugins/fleet/common/services/package_to_package_policy.test.ts +++ b/x-pack/plugins/fleet/common/services/package_to_package_policy.test.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { PackageInfo } from '../types'; +import type { PackageInfo } from '../types'; import { packageToPackagePolicy, packageToPackagePolicyInputs } from './package_to_package_policy'; describe('Fleet - packageToPackagePolicy', () => { diff --git a/x-pack/plugins/fleet/common/services/package_to_package_policy.ts b/x-pack/plugins/fleet/common/services/package_to_package_policy.ts index 36f5dc6ec41672..1fa4d39666cee9 100644 --- a/x-pack/plugins/fleet/common/services/package_to_package_policy.ts +++ b/x-pack/plugins/fleet/common/services/package_to_package_policy.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { +import type { PackageInfo, RegistryPolicyTemplate, RegistryVarsEntry, diff --git a/x-pack/plugins/fleet/common/types/models/agent.ts b/x-pack/plugins/fleet/common/types/models/agent.ts index 2e18d427272ce5..60eb47a6ecc434 100644 --- a/x-pack/plugins/fleet/common/types/models/agent.ts +++ b/x-pack/plugins/fleet/common/types/models/agent.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { FullAgentPolicy } from './agent_policy'; +import type { FullAgentPolicy } from './agent_policy'; import { AGENT_TYPE_EPHEMERAL, AGENT_TYPE_PERMANENT, AGENT_TYPE_TEMPORARY } from '../../constants'; export type AgentType = diff --git a/x-pack/plugins/fleet/common/types/models/agent_policy.ts b/x-pack/plugins/fleet/common/types/models/agent_policy.ts index bc139537400cc4..1aaca4fc5d932f 100644 --- a/x-pack/plugins/fleet/common/types/models/agent_policy.ts +++ b/x-pack/plugins/fleet/common/types/models/agent_policy.ts @@ -6,9 +6,9 @@ */ import { agentPolicyStatuses } from '../../constants'; -import { DataType, ValueOf } from '../../types'; -import { PackagePolicy, PackagePolicyPackage } from './package_policy'; -import { Output } from './output'; +import type { DataType, ValueOf } from '../../types'; +import type { PackagePolicy, PackagePolicyPackage } from './package_policy'; +import type { Output } from './output'; export type AgentPolicyStatus = typeof agentPolicyStatuses; diff --git a/x-pack/plugins/fleet/common/types/models/epm.ts b/x-pack/plugins/fleet/common/types/models/epm.ts index 5c99831eaac34a..e42ef7515b4c1f 100644 --- a/x-pack/plugins/fleet/common/types/models/epm.ts +++ b/x-pack/plugins/fleet/common/types/models/epm.ts @@ -7,7 +7,7 @@ // Follow pattern from https://github.com/elastic/kibana/pull/52447 // TODO: Update when https://github.com/elastic/kibana/issues/53021 is closed -import { SavedObject, SavedObjectAttributes, SavedObjectReference } from 'src/core/public'; +import type { SavedObject, SavedObjectAttributes, SavedObjectReference } from 'src/core/public'; import { ASSETS_SAVED_OBJECT_TYPE, agentAssetTypes, @@ -16,8 +16,8 @@ import { installationStatuses, requiredPackages, } from '../../constants'; -import { ValueOf } from '../../types'; -import { PackageSpecManifest, PackageSpecScreenshot } from './package_spec'; +import type { ValueOf } from '../../types'; +import type { PackageSpecManifest, PackageSpecScreenshot } from './package_spec'; export type InstallationStatus = typeof installationStatuses; diff --git a/x-pack/plugins/fleet/common/types/models/package_spec.ts b/x-pack/plugins/fleet/common/types/models/package_spec.ts index f9de06704a697d..65be72cbb7b6b3 100644 --- a/x-pack/plugins/fleet/common/types/models/package_spec.ts +++ b/x-pack/plugins/fleet/common/types/models/package_spec.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { RegistryPolicyTemplate } from './epm'; +import type { RegistryPolicyTemplate } from './epm'; // Based on https://github.com/elastic/package-spec/blob/master/versions/1/manifest.spec.yml#L8 export interface PackageSpecManifest { diff --git a/x-pack/plugins/fleet/common/types/models/settings.ts b/x-pack/plugins/fleet/common/types/models/settings.ts index 04adfb6a3089cb..56557fb6703b46 100644 --- a/x-pack/plugins/fleet/common/types/models/settings.ts +++ b/x-pack/plugins/fleet/common/types/models/settings.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { SavedObjectAttributes } from 'src/core/public'; +import type { SavedObjectAttributes } from 'src/core/public'; export interface BaseSettings { agent_auto_upgrade: boolean; diff --git a/x-pack/plugins/fleet/common/types/rest_spec/agent.ts b/x-pack/plugins/fleet/common/types/rest_spec/agent.ts index 4c4c77c784d84e..93cbb8369a3b13 100644 --- a/x-pack/plugins/fleet/common/types/rest_spec/agent.ts +++ b/x-pack/plugins/fleet/common/types/rest_spec/agent.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { +import type { Agent, AgentAction, NewAgentAction, diff --git a/x-pack/plugins/fleet/common/types/rest_spec/agent_policy.ts b/x-pack/plugins/fleet/common/types/rest_spec/agent_policy.ts index 5f8461019ab49f..4b64044e1f2deb 100644 --- a/x-pack/plugins/fleet/common/types/rest_spec/agent_policy.ts +++ b/x-pack/plugins/fleet/common/types/rest_spec/agent_policy.ts @@ -5,8 +5,8 @@ * 2.0. */ -import { AgentPolicy, NewAgentPolicy, FullAgentPolicy } from '../models'; -import { ListWithKuery } from './common'; +import type { AgentPolicy, NewAgentPolicy, FullAgentPolicy } from '../models'; +import type { ListWithKuery } from './common'; export interface GetAgentPoliciesRequest { query: ListWithKuery & { diff --git a/x-pack/plugins/fleet/common/types/rest_spec/common.ts b/x-pack/plugins/fleet/common/types/rest_spec/common.ts index de5e87d2e59a5d..15a280a62450a2 100644 --- a/x-pack/plugins/fleet/common/types/rest_spec/common.ts +++ b/x-pack/plugins/fleet/common/types/rest_spec/common.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { HttpFetchQuery } from 'src/core/public'; +import type { HttpFetchQuery } from 'src/core/public'; export interface ListWithKuery extends HttpFetchQuery { page?: number; diff --git a/x-pack/plugins/fleet/common/types/rest_spec/data_stream.ts b/x-pack/plugins/fleet/common/types/rest_spec/data_stream.ts index dc46e0514abd07..bc2eef71721ff6 100644 --- a/x-pack/plugins/fleet/common/types/rest_spec/data_stream.ts +++ b/x-pack/plugins/fleet/common/types/rest_spec/data_stream.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { DataStream } from '../models'; +import type { DataStream } from '../models'; export interface GetDataStreamsResponse { data_streams: DataStream[]; diff --git a/x-pack/plugins/fleet/common/types/rest_spec/enrollment_api_key.ts b/x-pack/plugins/fleet/common/types/rest_spec/enrollment_api_key.ts index b0373e58b045ce..da870deb31d9c4 100644 --- a/x-pack/plugins/fleet/common/types/rest_spec/enrollment_api_key.ts +++ b/x-pack/plugins/fleet/common/types/rest_spec/enrollment_api_key.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { EnrollmentAPIKey } from '../models'; +import type { EnrollmentAPIKey } from '../models'; export interface GetEnrollmentAPIKeysRequest { query: { diff --git a/x-pack/plugins/fleet/common/types/rest_spec/epm.ts b/x-pack/plugins/fleet/common/types/rest_spec/epm.ts index af622a51c719b3..3a9c9a0cfae9f8 100644 --- a/x-pack/plugins/fleet/common/types/rest_spec/epm.ts +++ b/x-pack/plugins/fleet/common/types/rest_spec/epm.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { +import type { AssetReference, CategorySummaryList, Installable, diff --git a/x-pack/plugins/fleet/common/types/rest_spec/output.ts b/x-pack/plugins/fleet/common/types/rest_spec/output.ts index 43a7e2cfd2e00e..ef3c2f9f998ca5 100644 --- a/x-pack/plugins/fleet/common/types/rest_spec/output.ts +++ b/x-pack/plugins/fleet/common/types/rest_spec/output.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { Output } from '../models'; +import type { Output } from '../models'; export interface GetOneOutputResponse { item: Output; diff --git a/x-pack/plugins/fleet/common/types/rest_spec/package_policy.ts b/x-pack/plugins/fleet/common/types/rest_spec/package_policy.ts index eeadf6a2f9b6dd..e6d893b9376a78 100644 --- a/x-pack/plugins/fleet/common/types/rest_spec/package_policy.ts +++ b/x-pack/plugins/fleet/common/types/rest_spec/package_policy.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { PackagePolicy, NewPackagePolicy, UpdatePackagePolicy } from '../models'; +import type { PackagePolicy, NewPackagePolicy, UpdatePackagePolicy } from '../models'; export interface GetPackagePoliciesRequest { query: { diff --git a/x-pack/plugins/fleet/common/types/rest_spec/settings.ts b/x-pack/plugins/fleet/common/types/rest_spec/settings.ts index caff6573ddd0a9..0b01815b2ef445 100644 --- a/x-pack/plugins/fleet/common/types/rest_spec/settings.ts +++ b/x-pack/plugins/fleet/common/types/rest_spec/settings.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { Settings } from '../models'; +import type { Settings } from '../models'; export interface GetSettingsResponse { item: Settings; diff --git a/x-pack/plugins/fleet/public/applications/fleet/hooks/use_config.ts b/x-pack/plugins/fleet/public/applications/fleet/hooks/use_config.ts index f32975d1180cd6..cee563280e7bf6 100644 --- a/x-pack/plugins/fleet/public/applications/fleet/hooks/use_config.ts +++ b/x-pack/plugins/fleet/public/applications/fleet/hooks/use_config.ts @@ -6,7 +6,7 @@ */ import React, { useContext } from 'react'; -import { FleetConfigType } from '../../../plugin'; +import type { FleetConfigType } from '../../../plugin'; export const ConfigContext = React.createContext(null); diff --git a/x-pack/plugins/fleet/public/applications/fleet/hooks/use_core.ts b/x-pack/plugins/fleet/public/applications/fleet/hooks/use_core.ts index 21dfdbfc321396..30b3a5da94e1c4 100644 --- a/x-pack/plugins/fleet/public/applications/fleet/hooks/use_core.ts +++ b/x-pack/plugins/fleet/public/applications/fleet/hooks/use_core.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { FleetStartServices } from '../../../plugin'; +import type { FleetStartServices } from '../../../plugin'; import { useKibana } from '../../../../../../../src/plugins/kibana_react/public'; export function useStartServices(): FleetStartServices { diff --git a/x-pack/plugins/fleet/public/applications/fleet/hooks/use_link.ts b/x-pack/plugins/fleet/public/applications/fleet/hooks/use_link.ts index 0463e512bff3ee..bcb8c4c749211c 100644 --- a/x-pack/plugins/fleet/public/applications/fleet/hooks/use_link.ts +++ b/x-pack/plugins/fleet/public/applications/fleet/hooks/use_link.ts @@ -5,13 +5,8 @@ * 2.0. */ -import { - BASE_PATH, - StaticPage, - DynamicPage, - DynamicPagePathValues, - pagePathGetters, -} from '../constants'; +import { BASE_PATH, pagePathGetters } from '../constants'; +import type { StaticPage, DynamicPage, DynamicPagePathValues } from '../constants'; import { useStartServices } from './'; const getPath = (page: StaticPage | DynamicPage, values: DynamicPagePathValues = {}): string => { diff --git a/x-pack/plugins/fleet/public/applications/fleet/hooks/use_package_icon_type.ts b/x-pack/plugins/fleet/public/applications/fleet/hooks/use_package_icon_type.ts index 0d0b455999a8b5..679c44f2c0ea91 100644 --- a/x-pack/plugins/fleet/public/applications/fleet/hooks/use_package_icon_type.ts +++ b/x-pack/plugins/fleet/public/applications/fleet/hooks/use_package_icon_type.ts @@ -7,7 +7,7 @@ import { useEffect, useState } from 'react'; import { ICON_TYPES } from '@elastic/eui'; -import { PackageInfo, PackageListItem } from '../types'; +import type { PackageInfo, PackageListItem } from '../types'; import { useLinks } from '../sections/epm/hooks'; import { sendGetPackageInfoByKey } from './index'; diff --git a/x-pack/plugins/fleet/public/applications/fleet/hooks/use_request/agent_policy.ts b/x-pack/plugins/fleet/public/applications/fleet/hooks/use_request/agent_policy.ts index 2cba3b48a95646..d60383c15d2f4d 100644 --- a/x-pack/plugins/fleet/public/applications/fleet/hooks/use_request/agent_policy.ts +++ b/x-pack/plugins/fleet/public/applications/fleet/hooks/use_request/agent_policy.ts @@ -5,14 +5,10 @@ * 2.0. */ -import { - useRequest, - sendRequest, - useConditionalRequest, - SendConditionalRequestConfig, -} from './use_request'; +import { useRequest, sendRequest, useConditionalRequest } from './use_request'; +import type { SendConditionalRequestConfig } from './use_request'; import { agentPolicyRouteService } from '../../services'; -import { +import type { GetAgentPoliciesRequest, GetAgentPoliciesResponse, GetOneAgentPolicyResponse, diff --git a/x-pack/plugins/fleet/public/applications/fleet/hooks/use_request/agents.ts b/x-pack/plugins/fleet/public/applications/fleet/hooks/use_request/agents.ts index 7f774a85ff9d63..a40ebbf78e0f2d 100644 --- a/x-pack/plugins/fleet/public/applications/fleet/hooks/use_request/agents.ts +++ b/x-pack/plugins/fleet/public/applications/fleet/hooks/use_request/agents.ts @@ -5,9 +5,10 @@ * 2.0. */ -import { useRequest, UseRequestConfig, sendRequest } from './use_request'; +import { useRequest, sendRequest } from './use_request'; +import type { UseRequestConfig } from './use_request'; import { agentRouteService } from '../../services'; -import { +import type { GetOneAgentResponse, GetOneAgentEventsResponse, GetOneAgentEventsRequest, diff --git a/x-pack/plugins/fleet/public/applications/fleet/hooks/use_request/app.ts b/x-pack/plugins/fleet/public/applications/fleet/hooks/use_request/app.ts index 00f093474695f0..2e93a1700d08c5 100644 --- a/x-pack/plugins/fleet/public/applications/fleet/hooks/use_request/app.ts +++ b/x-pack/plugins/fleet/public/applications/fleet/hooks/use_request/app.ts @@ -7,7 +7,7 @@ import { sendRequest } from './use_request'; import { appRoutesService } from '../../services'; -import { CheckPermissionsResponse } from '../../types'; +import type { CheckPermissionsResponse } from '../../types'; export const sendGetPermissionsCheck = () => { return sendRequest({ diff --git a/x-pack/plugins/fleet/public/applications/fleet/hooks/use_request/data_stream.ts b/x-pack/plugins/fleet/public/applications/fleet/hooks/use_request/data_stream.ts index 9e275e606f6675..16e27596e70909 100644 --- a/x-pack/plugins/fleet/public/applications/fleet/hooks/use_request/data_stream.ts +++ b/x-pack/plugins/fleet/public/applications/fleet/hooks/use_request/data_stream.ts @@ -7,7 +7,7 @@ import { useRequest } from './use_request'; import { dataStreamRouteService } from '../../services'; -import { GetDataStreamsResponse } from '../../types'; +import type { GetDataStreamsResponse } from '../../types'; export const useGetDataStreams = () => { return useRequest({ diff --git a/x-pack/plugins/fleet/public/applications/fleet/hooks/use_request/enrollment_api_keys.ts b/x-pack/plugins/fleet/public/applications/fleet/hooks/use_request/enrollment_api_keys.ts index cd0397d611df1b..4aad8b73144828 100644 --- a/x-pack/plugins/fleet/public/applications/fleet/hooks/use_request/enrollment_api_keys.ts +++ b/x-pack/plugins/fleet/public/applications/fleet/hooks/use_request/enrollment_api_keys.ts @@ -5,15 +5,10 @@ * 2.0. */ -import { - useRequest, - UseRequestConfig, - sendRequest, - useConditionalRequest, - SendConditionalRequestConfig, -} from './use_request'; +import { useRequest, sendRequest, useConditionalRequest } from './use_request'; +import type { UseRequestConfig, SendConditionalRequestConfig } from './use_request'; import { enrollmentAPIKeyRouteService } from '../../services'; -import { +import type { GetOneEnrollmentAPIKeyResponse, GetEnrollmentAPIKeysResponse, GetEnrollmentAPIKeysRequest, diff --git a/x-pack/plugins/fleet/public/applications/fleet/hooks/use_request/epm.ts b/x-pack/plugins/fleet/public/applications/fleet/hooks/use_request/epm.ts index f518ee2ea44ff6..45e754849b5bc9 100644 --- a/x-pack/plugins/fleet/public/applications/fleet/hooks/use_request/epm.ts +++ b/x-pack/plugins/fleet/public/applications/fleet/hooks/use_request/epm.ts @@ -7,7 +7,7 @@ import { useRequest, sendRequest } from './use_request'; import { epmRouteService } from '../../services'; -import { +import type { GetCategoriesRequest, GetCategoriesResponse, GetPackagesRequest, @@ -17,7 +17,7 @@ import { InstallPackageResponse, DeletePackageResponse, } from '../../types'; -import { GetStatsResponse } from '../../../../../common'; +import type { GetStatsResponse } from '../../../../../common'; export const useGetCategories = (query: GetCategoriesRequest['query'] = {}) => { return useRequest({ diff --git a/x-pack/plugins/fleet/public/applications/fleet/hooks/use_request/outputs.ts b/x-pack/plugins/fleet/public/applications/fleet/hooks/use_request/outputs.ts index 1c43b84b2bc02d..64c82d2a04790b 100644 --- a/x-pack/plugins/fleet/public/applications/fleet/hooks/use_request/outputs.ts +++ b/x-pack/plugins/fleet/public/applications/fleet/hooks/use_request/outputs.ts @@ -7,7 +7,7 @@ import { sendRequest, useRequest } from './use_request'; import { outputRoutesService } from '../../services'; -import { PutOutputRequest, GetOutputsResponse } from '../../types'; +import type { PutOutputRequest, GetOutputsResponse } from '../../types'; export function useGetOutputs() { return useRequest({ diff --git a/x-pack/plugins/fleet/public/applications/fleet/hooks/use_request/package_policy.ts b/x-pack/plugins/fleet/public/applications/fleet/hooks/use_request/package_policy.ts index ee4a4e4c24e280..1266f47a80e21b 100644 --- a/x-pack/plugins/fleet/public/applications/fleet/hooks/use_request/package_policy.ts +++ b/x-pack/plugins/fleet/public/applications/fleet/hooks/use_request/package_policy.ts @@ -7,13 +7,13 @@ import { sendRequest, useRequest } from './use_request'; import { packagePolicyRouteService } from '../../services'; -import { +import type { CreatePackagePolicyRequest, CreatePackagePolicyResponse, UpdatePackagePolicyRequest, UpdatePackagePolicyResponse, } from '../../types'; -import { +import type { DeletePackagePoliciesRequest, DeletePackagePoliciesResponse, GetPackagePoliciesRequest, diff --git a/x-pack/plugins/fleet/public/applications/fleet/hooks/use_request/settings.ts b/x-pack/plugins/fleet/public/applications/fleet/hooks/use_request/settings.ts index 9cc54a5c4223bd..bf4ea6eacb3c15 100644 --- a/x-pack/plugins/fleet/public/applications/fleet/hooks/use_request/settings.ts +++ b/x-pack/plugins/fleet/public/applications/fleet/hooks/use_request/settings.ts @@ -7,7 +7,7 @@ import { sendRequest, useRequest } from './use_request'; import { settingsRoutesService } from '../../services'; -import { PutSettingsResponse, PutSettingsRequest, GetSettingsResponse } from '../../types'; +import type { PutSettingsResponse, PutSettingsRequest, GetSettingsResponse } from '../../types'; export function useGetSettings() { return useRequest({ diff --git a/x-pack/plugins/fleet/public/applications/fleet/hooks/use_request/setup.ts b/x-pack/plugins/fleet/public/applications/fleet/hooks/use_request/setup.ts index 0f52712e8ded96..001b8af99aec5e 100644 --- a/x-pack/plugins/fleet/public/applications/fleet/hooks/use_request/setup.ts +++ b/x-pack/plugins/fleet/public/applications/fleet/hooks/use_request/setup.ts @@ -7,7 +7,7 @@ import { sendRequest } from './use_request'; import { setupRouteService, fleetSetupRouteService } from '../../services'; -import { GetFleetStatusResponse } from '../../types'; +import type { GetFleetStatusResponse } from '../../types'; export const sendSetup = () => { return sendRequest({ diff --git a/x-pack/plugins/fleet/public/applications/fleet/hooks/use_request/use_request.ts b/x-pack/plugins/fleet/public/applications/fleet/hooks/use_request/use_request.ts index 4c4433c2b4f89e..985f4d71d6a754 100644 --- a/x-pack/plugins/fleet/public/applications/fleet/hooks/use_request/use_request.ts +++ b/x-pack/plugins/fleet/public/applications/fleet/hooks/use_request/use_request.ts @@ -6,14 +6,16 @@ */ import { useState, useEffect } from 'react'; -import { HttpSetup } from 'src/core/public'; +import type { HttpSetup } from 'src/core/public'; import { - SendRequestConfig, - SendRequestResponse, UseRequestConfig as _UseRequestConfig, sendRequest as _sendRequest, useRequest as _useRequest, } from '../../../../../../../../src/plugins/es_ui_shared/public'; +import type { + SendRequestConfig, + SendRequestResponse, +} from '../../../../../../../../src/plugins/es_ui_shared/public'; let httpClient: HttpSetup; diff --git a/x-pack/plugins/fleet/public/applications/fleet/hooks/use_ui_extension.ts b/x-pack/plugins/fleet/public/applications/fleet/hooks/use_ui_extension.ts index 00eff8f91490b2..f6b3cfd2b36424 100644 --- a/x-pack/plugins/fleet/public/applications/fleet/hooks/use_ui_extension.ts +++ b/x-pack/plugins/fleet/public/applications/fleet/hooks/use_ui_extension.ts @@ -6,7 +6,7 @@ */ import React, { useContext } from 'react'; -import { UIExtensionPoint, UIExtensionsStorage } from '../types'; +import type { UIExtensionPoint, UIExtensionsStorage } from '../types'; export const UIExtensionsContext = React.createContext({}); diff --git a/x-pack/plugins/fleet/public/applications/fleet/hooks/use_url_pagination.ts b/x-pack/plugins/fleet/public/applications/fleet/hooks/use_url_pagination.ts index 7224a460bf4144..090ce34ae244a6 100644 --- a/x-pack/plugins/fleet/public/applications/fleet/hooks/use_url_pagination.ts +++ b/x-pack/plugins/fleet/public/applications/fleet/hooks/use_url_pagination.ts @@ -8,7 +8,8 @@ import { useCallback, useEffect, useMemo } from 'react'; import { useHistory, useLocation } from 'react-router-dom'; import { useUrlParams } from './use_url_params'; -import { PAGE_SIZE_OPTIONS, Pagination, usePagination } from './use_pagination'; +import { PAGE_SIZE_OPTIONS, usePagination } from './use_pagination'; +import type { Pagination } from './use_pagination'; type SetUrlPagination = (pagination: Pagination) => void; interface UrlPagination { diff --git a/x-pack/plugins/fleet/public/applications/fleet/mock/plugin_configuration.ts b/x-pack/plugins/fleet/public/applications/fleet/mock/plugin_configuration.ts index c5ae6d7fd4089f..81ef6a6703c343 100644 --- a/x-pack/plugins/fleet/public/applications/fleet/mock/plugin_configuration.ts +++ b/x-pack/plugins/fleet/public/applications/fleet/mock/plugin_configuration.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { FleetConfigType } from '../../../plugin'; +import type { FleetConfigType } from '../../../plugin'; export const createConfigurationMock = (): FleetConfigType => { return { diff --git a/x-pack/plugins/fleet/public/applications/fleet/mock/plugin_dependencies.ts b/x-pack/plugins/fleet/public/applications/fleet/mock/plugin_dependencies.ts index f8b05e13e29560..8207e3d89fc561 100644 --- a/x-pack/plugins/fleet/public/applications/fleet/mock/plugin_dependencies.ts +++ b/x-pack/plugins/fleet/public/applications/fleet/mock/plugin_dependencies.ts @@ -8,7 +8,7 @@ import { dataPluginMock } from '../../../../../../../src/plugins/data/public/mocks'; import { licensingMock } from '../../../../../licensing/public/mocks'; import { homePluginMock } from '../../../../../../../src/plugins/home/public/mocks'; -import { MockedFleetSetupDeps, MockedFleetStartDeps } from './types'; +import type { MockedFleetSetupDeps, MockedFleetStartDeps } from './types'; export const createSetupDepsMock = (): MockedFleetSetupDeps => { return { diff --git a/x-pack/plugins/fleet/public/applications/fleet/mock/plugin_interfaces.ts b/x-pack/plugins/fleet/public/applications/fleet/mock/plugin_interfaces.ts index d11ca5b041be1b..3c76452f17ce72 100644 --- a/x-pack/plugins/fleet/public/applications/fleet/mock/plugin_interfaces.ts +++ b/x-pack/plugins/fleet/public/applications/fleet/mock/plugin_interfaces.ts @@ -5,9 +5,9 @@ * 2.0. */ -import { UIExtensionsStorage } from '../types'; +import type { UIExtensionsStorage } from '../types'; import { createExtensionRegistrationCallback } from '../services/ui_extensions'; -import { MockedFleetStart } from './types'; +import type { MockedFleetStart } from './types'; export const createStartMock = (extensionsStorage: UIExtensionsStorage = {}): MockedFleetStart => { return { diff --git a/x-pack/plugins/fleet/public/applications/fleet/mock/types.ts b/x-pack/plugins/fleet/public/applications/fleet/mock/types.ts index 0a55fa43bf18da..660fe6af29fb1f 100644 --- a/x-pack/plugins/fleet/public/applications/fleet/mock/types.ts +++ b/x-pack/plugins/fleet/public/applications/fleet/mock/types.ts @@ -5,8 +5,13 @@ * 2.0. */ -import { MockedKeys } from '@kbn/utility-types/jest'; -import { FleetSetupDeps, FleetStart, FleetStartDeps, FleetStartServices } from '../../../plugin'; +import type { MockedKeys } from '@kbn/utility-types/jest'; +import type { + FleetSetupDeps, + FleetStart, + FleetStartDeps, + FleetStartServices, +} from '../../../plugin'; export type MockedFleetStartServices = MockedKeys; diff --git a/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/services/has_invalid_but_required_var.ts b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/services/has_invalid_but_required_var.ts index 84bdb3798f73f2..a9a0480098323d 100644 --- a/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/services/has_invalid_but_required_var.ts +++ b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/services/has_invalid_but_required_var.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { PackagePolicyConfigRecord, RegistryVarsEntry } from '../../../../types'; +import type { PackagePolicyConfigRecord, RegistryVarsEntry } from '../../../../types'; import { validatePackagePolicyConfig } from './'; export const hasInvalidButRequiredVar = ( diff --git a/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/services/is_advanced_var.ts b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/services/is_advanced_var.ts index 1e60b5e6e0bbb2..1f72073573d7b8 100644 --- a/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/services/is_advanced_var.ts +++ b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/services/is_advanced_var.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { RegistryVarsEntry } from '../../../../types'; +import type { RegistryVarsEntry } from '../../../../types'; export const isAdvancedVar = (varDef: RegistryVarsEntry): boolean => { if (varDef.show_user || (varDef.required && varDef.default === undefined)) { diff --git a/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/services/validate_package_policy.test.ts b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/services/validate_package_policy.test.ts index 5e05f10cd74be7..e1e0d026966c3c 100644 --- a/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/services/validate_package_policy.test.ts +++ b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/services/validate_package_policy.test.ts @@ -6,7 +6,7 @@ */ import { installationStatuses } from '../../../../../../../common/constants'; -import { PackageInfo, NewPackagePolicy, RegistryPolicyTemplate } from '../../../../types'; +import type { PackageInfo, NewPackagePolicy, RegistryPolicyTemplate } from '../../../../types'; import { validatePackagePolicy, validationHasErrors } from './validate_package_policy'; describe('Fleet - validatePackagePolicy()', () => { diff --git a/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/services/validate_package_policy.ts b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/services/validate_package_policy.ts index c39dfb4a99c12c..c727be683c130f 100644 --- a/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/services/validate_package_policy.ts +++ b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/services/validate_package_policy.ts @@ -8,7 +8,7 @@ import { i18n } from '@kbn/i18n'; import { safeLoad } from 'js-yaml'; import { getFlattenedObject, isValidNamespace } from '../../../../services'; -import { +import type { NewPackagePolicy, PackagePolicyInput, PackagePolicyInputStream, diff --git a/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/step_define_package_policy.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/step_define_package_policy.tsx index c66a28944ea710..64837b208ae457 100644 --- a/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/step_define_package_policy.tsx +++ b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/step_define_package_policy.tsx @@ -47,7 +47,7 @@ export const StepDefinePackagePolicy: React.FunctionComponent<{ const pkgPoliciesWithMatchingNames = (agentPolicy.package_policies as PackagePolicy[]) .filter((ds) => Boolean(ds.name.match(pkgPoliciesNamePattern))) .map((ds) => parseInt(ds.name.match(pkgPoliciesNamePattern)![1], 10)) - .sort(); + .sort((a, b) => a - b); updatePackagePolicy({ // FIXME: Improve package policies name uniqueness - https://github.com/elastic/kibana/issues/72948 diff --git a/x-pack/plugins/fleet/public/applications/fleet/sections/epm/components/release_badge.ts b/x-pack/plugins/fleet/public/applications/fleet/sections/epm/components/release_badge.ts index 21d205f4ac56d0..9e4e51e410e7e4 100644 --- a/x-pack/plugins/fleet/public/applications/fleet/sections/epm/components/release_badge.ts +++ b/x-pack/plugins/fleet/public/applications/fleet/sections/epm/components/release_badge.ts @@ -6,7 +6,7 @@ */ import { i18n } from '@kbn/i18n'; -import { RegistryRelease } from '../../../types'; +import type { RegistryRelease } from '../../../types'; export const RELEASE_BADGE_LABEL: { [key in Exclude]: string } = { beta: i18n.translate('xpack.fleet.epm.releaseBadge.betaLabel', { diff --git a/x-pack/plugins/fleet/public/applications/fleet/sections/epm/screens/detail/policies/use_package_policies_with_agent_policy.ts b/x-pack/plugins/fleet/public/applications/fleet/sections/epm/screens/detail/policies/use_package_policies_with_agent_policy.ts index ff8343314b4acb..77811a92093eee 100644 --- a/x-pack/plugins/fleet/public/applications/fleet/sections/epm/screens/detail/policies/use_package_policies_with_agent_policy.ts +++ b/x-pack/plugins/fleet/public/applications/fleet/sections/epm/screens/detail/policies/use_package_policies_with_agent_policy.ts @@ -6,7 +6,7 @@ */ import { useEffect, useMemo, useState } from 'react'; -import { +import type { PackagePolicy, GetAgentPoliciesResponse, GetAgentPoliciesResponseItem, @@ -15,10 +15,8 @@ import { import { agentPolicyRouteService } from '../../../../../services'; import { AGENT_POLICY_SAVED_OBJECT_TYPE } from '../../../../../constants'; import { useGetPackagePolicies } from '../../../../../hooks'; -import { - SendConditionalRequestConfig, - useConditionalRequest, -} from '../../../../../hooks/use_request/use_request'; +import { useConditionalRequest } from '../../../../../hooks/use_request/use_request'; +import type { SendConditionalRequestConfig } from '../../../../../hooks/use_request/use_request'; export interface PackagePolicyEnriched extends PackagePolicy { _agentPolicy: GetAgentPoliciesResponseItem | undefined; diff --git a/x-pack/plugins/fleet/public/applications/fleet/services/ui_extensions.test.ts b/x-pack/plugins/fleet/public/applications/fleet/services/ui_extensions.test.ts index d0e22f90e26405..bcddcb4afdbb34 100644 --- a/x-pack/plugins/fleet/public/applications/fleet/services/ui_extensions.test.ts +++ b/x-pack/plugins/fleet/public/applications/fleet/services/ui_extensions.test.ts @@ -6,8 +6,7 @@ */ import { lazy } from 'react'; - -import { +import type { PackagePolicyEditExtensionComponent, UIExtensionRegistrationCallback, UIExtensionsStorage, diff --git a/x-pack/plugins/fleet/public/applications/fleet/services/ui_extensions.ts b/x-pack/plugins/fleet/public/applications/fleet/services/ui_extensions.ts index 3583c9be93b991..d8b3e6212dbc19 100644 --- a/x-pack/plugins/fleet/public/applications/fleet/services/ui_extensions.ts +++ b/x-pack/plugins/fleet/public/applications/fleet/services/ui_extensions.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { UIExtensionRegistrationCallback, UIExtensionsStorage } from '../types'; +import type { UIExtensionRegistrationCallback, UIExtensionsStorage } from '../types'; /** Factory that returns a callback that can be used to register UI extensions */ export const createExtensionRegistrationCallback = ( diff --git a/x-pack/plugins/fleet/public/applications/fleet/types/intra_app_route_state.ts b/x-pack/plugins/fleet/public/applications/fleet/types/intra_app_route_state.ts index 52d93924a63125..b118797d7d38e1 100644 --- a/x-pack/plugins/fleet/public/applications/fleet/types/intra_app_route_state.ts +++ b/x-pack/plugins/fleet/public/applications/fleet/types/intra_app_route_state.ts @@ -5,8 +5,8 @@ * 2.0. */ -import { ApplicationStart } from 'kibana/public'; -import { PackagePolicy } from './'; +import type { ApplicationStart } from 'kibana/public'; +import type { PackagePolicy } from './'; /** * Supported routing state for the create package policy page routes diff --git a/x-pack/plugins/fleet/public/applications/fleet/types/ui_extensions.ts b/x-pack/plugins/fleet/public/applications/fleet/types/ui_extensions.ts index 2765c7e4b8b843..a9cea79ee7d8b7 100644 --- a/x-pack/plugins/fleet/public/applications/fleet/types/ui_extensions.ts +++ b/x-pack/plugins/fleet/public/applications/fleet/types/ui_extensions.ts @@ -5,8 +5,8 @@ * 2.0. */ -import { ComponentType, LazyExoticComponent } from 'react'; -import { NewPackagePolicy, PackageInfo, PackagePolicy } from './index'; +import type { ComponentType, LazyExoticComponent } from 'react'; +import type { NewPackagePolicy, PackageInfo, PackagePolicy } from './index'; /** Register a Fleet UI extension */ export type UIExtensionRegistrationCallback = (extensionPoint: UIExtensionPoint) => void; diff --git a/x-pack/plugins/fleet/public/index.ts b/x-pack/plugins/fleet/public/index.ts index 34bdc99abdf771..3b1136747f3433 100644 --- a/x-pack/plugins/fleet/public/index.ts +++ b/x-pack/plugins/fleet/public/index.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { PluginInitializerContext } from 'src/core/public'; +import type { PluginInitializerContext } from 'src/core/public'; import { FleetPlugin } from './plugin'; export { FleetSetup, FleetStart } from './plugin'; diff --git a/x-pack/plugins/fleet/public/plugin.ts b/x-pack/plugins/fleet/public/plugin.ts index 50e647e271ecc7..7f2fd4ee24d4f1 100644 --- a/x-pack/plugins/fleet/public/plugin.ts +++ b/x-pack/plugins/fleet/public/plugin.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { +import type { AppMountParameters, CoreSetup, Plugin, @@ -14,18 +14,18 @@ import { } from 'src/core/public'; import { i18n } from '@kbn/i18n'; import { DEFAULT_APP_CATEGORIES, AppNavLinkStatus } from '../../../../src/core/public'; -import { DataPublicPluginSetup, DataPublicPluginStart } from '../../../../src/plugins/data/public'; -import { - HomePublicPluginSetup, - FeatureCatalogueCategory, -} from '../../../../src/plugins/home/public'; +import type { + DataPublicPluginSetup, + DataPublicPluginStart, +} from '../../../../src/plugins/data/public'; +import { FeatureCatalogueCategory } from '../../../../src/plugins/home/public'; +import type { HomePublicPluginSetup } from '../../../../src/plugins/home/public'; import { Storage } from '../../../../src/plugins/kibana_utils/public'; -import { LicensingPluginSetup } from '../../licensing/public'; -import { PLUGIN_ID, CheckPermissionsResponse, PostIngestSetupResponse } from '../common'; +import type { LicensingPluginSetup } from '../../licensing/public'; +import { PLUGIN_ID, setupRouteService, appRoutesService } from '../common'; +import type { CheckPermissionsResponse, PostIngestSetupResponse } from '../common'; import { BASE_PATH } from './applications/fleet/constants'; - -import { FleetConfigType } from '../common/types'; -import { setupRouteService, appRoutesService } from '../common'; +import type { FleetConfigType } from '../common/types'; import { licenseService } from './applications/fleet/hooks/use_license'; import { setHttpClient } from './applications/fleet/hooks/use_request/use_request'; import { @@ -34,7 +34,10 @@ import { TutorialModuleNotice, } from './applications/fleet/components/home_integration'; import { createExtensionRegistrationCallback } from './applications/fleet/services/ui_extensions'; -import { UIExtensionRegistrationCallback, UIExtensionsStorage } from './applications/fleet/types'; +import type { + UIExtensionRegistrationCallback, + UIExtensionsStorage, +} from './applications/fleet/types'; export { FleetConfigType } from '../common/types'; diff --git a/x-pack/plugins/fleet/scripts/dev_agent/script.ts b/x-pack/plugins/fleet/scripts/dev_agent/script.ts index fc4a10f4f655fc..87727ef657e5f2 100644 --- a/x-pack/plugins/fleet/scripts/dev_agent/script.ts +++ b/x-pack/plugins/fleet/scripts/dev_agent/script.ts @@ -8,7 +8,7 @@ import { createFlagError, run, ToolingLog } from '@kbn/dev-utils'; import fetch from 'node-fetch'; import os from 'os'; -import { +import type { Agent as _Agent, PostAgentCheckinRequest, PostAgentCheckinResponse, diff --git a/x-pack/plugins/fleet/server/collectors/agent_collectors.ts b/x-pack/plugins/fleet/server/collectors/agent_collectors.ts index ce4fb3e3df7d4c..9aeae1dba0ea5e 100644 --- a/x-pack/plugins/fleet/server/collectors/agent_collectors.ts +++ b/x-pack/plugins/fleet/server/collectors/agent_collectors.ts @@ -5,7 +5,8 @@ * 2.0. */ -import { ElasticsearchClient, SavedObjectsClient } from 'kibana/server'; +import { SavedObjectsClient } from 'kibana/server'; +import type { ElasticsearchClient } from 'kibana/server'; import { FleetConfigType } from '../../common/types'; import * as AgentService from '../services/agents'; import { isFleetServerSetup } from '../services/fleet_server'; diff --git a/x-pack/plugins/fleet/server/collectors/config_collectors.ts b/x-pack/plugins/fleet/server/collectors/config_collectors.ts index d6a9e4868c9ab1..d651ad4b5d3bea 100644 --- a/x-pack/plugins/fleet/server/collectors/config_collectors.ts +++ b/x-pack/plugins/fleet/server/collectors/config_collectors.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { FleetConfigType } from '..'; +import type { FleetConfigType } from '..'; export const getIsAgentsEnabled = (config: FleetConfigType) => { return config.agents.enabled; diff --git a/x-pack/plugins/fleet/server/collectors/helpers.ts b/x-pack/plugins/fleet/server/collectors/helpers.ts index 6104b8a8adee95..4de2330e70a2cf 100644 --- a/x-pack/plugins/fleet/server/collectors/helpers.ts +++ b/x-pack/plugins/fleet/server/collectors/helpers.ts @@ -5,8 +5,9 @@ * 2.0. */ -import { CoreSetup } from 'kibana/server'; -import { ElasticsearchClient, SavedObjectsClient } from '../../../../../src/core/server'; +import type { CoreSetup } from 'kibana/server'; +import { SavedObjectsClient } from '../../../../../src/core/server'; +import type { ElasticsearchClient } from '../../../../../src/core/server'; export async function getInternalClients( core: CoreSetup diff --git a/x-pack/plugins/fleet/server/collectors/package_collectors.ts b/x-pack/plugins/fleet/server/collectors/package_collectors.ts index 542208a5571824..e0f5667fbe458f 100644 --- a/x-pack/plugins/fleet/server/collectors/package_collectors.ts +++ b/x-pack/plugins/fleet/server/collectors/package_collectors.ts @@ -9,7 +9,7 @@ import { SavedObjectsClient } from 'kibana/server'; import _ from 'lodash'; import { getPackageSavedObjects } from '../services/epm/packages/get'; import { agentPolicyService } from '../services'; -import { NewPackagePolicy } from '../types'; +import type { NewPackagePolicy } from '../types'; export interface PackageUsage { name: string; diff --git a/x-pack/plugins/fleet/server/collectors/register.ts b/x-pack/plugins/fleet/server/collectors/register.ts index c2e043145cd972..30b3ced2601720 100644 --- a/x-pack/plugins/fleet/server/collectors/register.ts +++ b/x-pack/plugins/fleet/server/collectors/register.ts @@ -5,13 +5,15 @@ * 2.0. */ -import { UsageCollectionSetup } from 'src/plugins/usage_collection/server'; -import { CoreSetup } from 'kibana/server'; +import type { UsageCollectionSetup } from 'src/plugins/usage_collection/server'; +import type { CoreSetup } from 'kibana/server'; import { getIsAgentsEnabled } from './config_collectors'; -import { AgentUsage, getAgentUsage } from './agent_collectors'; +import { getAgentUsage } from './agent_collectors'; +import type { AgentUsage } from './agent_collectors'; import { getInternalClients } from './helpers'; -import { PackageUsage, getPackageUsage } from './package_collectors'; -import { FleetConfigType } from '..'; +import { getPackageUsage } from './package_collectors'; +import type { PackageUsage } from './package_collectors'; +import type { FleetConfigType } from '..'; interface Usage { agents_enabled: boolean; diff --git a/x-pack/plugins/fleet/server/errors/handlers.ts b/x-pack/plugins/fleet/server/errors/handlers.ts index 77db050309a60c..2d5339b158d9bf 100644 --- a/x-pack/plugins/fleet/server/errors/handlers.ts +++ b/x-pack/plugins/fleet/server/errors/handlers.ts @@ -6,9 +6,9 @@ */ import Boom, { isBoom } from '@hapi/boom'; -import { +import { KibanaRequest } from 'src/core/server'; +import type { RequestHandlerContext, - KibanaRequest, IKibanaResponse, KibanaResponseFactory, } from 'src/core/server'; diff --git a/x-pack/plugins/fleet/server/index.ts b/x-pack/plugins/fleet/server/index.ts index 2d189d5f940ae9..cb5eb6413fdf85 100644 --- a/x-pack/plugins/fleet/server/index.ts +++ b/x-pack/plugins/fleet/server/index.ts @@ -5,8 +5,9 @@ * 2.0. */ -import { schema, TypeOf } from '@kbn/config-schema'; -import { PluginConfigDescriptor, PluginInitializerContext } from 'src/core/server'; +import { schema } from '@kbn/config-schema'; +import type { TypeOf } from '@kbn/config-schema'; +import type { PluginConfigDescriptor, PluginInitializerContext } from 'src/core/server'; import { FleetPlugin } from './plugin'; import { AGENT_POLICY_ROLLOUT_RATE_LIMIT_INTERVAL_MS, diff --git a/x-pack/plugins/fleet/server/mocks.ts b/x-pack/plugins/fleet/server/mocks.ts index 430e38bd1bc3ef..3a7f9ebcc9e539 100644 --- a/x-pack/plugins/fleet/server/mocks.ts +++ b/x-pack/plugins/fleet/server/mocks.ts @@ -12,12 +12,11 @@ import { } from 'src/core/server/mocks'; import { coreMock } from '../../../../src/core/server/mocks'; import { licensingMock } from '../../../plugins/licensing/server/mocks'; - -import { FleetAppContext } from './plugin'; +import type { FleetAppContext } from './plugin'; import { encryptedSavedObjectsMock } from '../../encrypted_saved_objects/server/mocks'; import { securityMock } from '../../security/server/mocks'; -import { PackagePolicyServiceInterface } from './services/package_policy'; -import { AgentPolicyServiceInterface, AgentService } from './services'; +import type { PackagePolicyServiceInterface } from './services/package_policy'; +import type { AgentPolicyServiceInterface, AgentService } from './services'; export const createAppContextStartContractMock = (): FleetAppContext => { return { diff --git a/x-pack/plugins/fleet/server/routes/agent/acks_handlers.test.ts b/x-pack/plugins/fleet/server/routes/agent/acks_handlers.test.ts index e1ed453a572f61..b1bd10e8a4a774 100644 --- a/x-pack/plugins/fleet/server/routes/agent/acks_handlers.test.ts +++ b/x-pack/plugins/fleet/server/routes/agent/acks_handlers.test.ts @@ -6,7 +6,7 @@ */ import { postAgentAcksHandlerBuilder } from './acks_handlers'; -import { +import type { ElasticsearchClient, KibanaResponseFactory, RequestHandlerContext, @@ -17,9 +17,9 @@ import { httpServerMock, savedObjectsClientMock, } from '../../../../../../src/core/server/mocks'; -import { PostAgentAcksResponse } from '../../../common/types/rest_spec'; +import type { PostAgentAcksResponse } from '../../../common/types/rest_spec'; import { AckEventSchema } from '../../types/models'; -import { AcksService } from '../../services/agents'; +import type { AcksService } from '../../services/agents'; describe('test acks schema', () => { it('validate that ack event schema expect action id', async () => { diff --git a/x-pack/plugins/fleet/server/routes/agent/acks_handlers.ts b/x-pack/plugins/fleet/server/routes/agent/acks_handlers.ts index 22b5035378a20d..e05638b9e6d8e2 100644 --- a/x-pack/plugins/fleet/server/routes/agent/acks_handlers.ts +++ b/x-pack/plugins/fleet/server/routes/agent/acks_handlers.ts @@ -7,10 +7,10 @@ // handlers that handle events from agents in response to actions received -import { RequestHandler } from 'kibana/server'; -import { AcksService } from '../../services/agents'; -import { AgentEvent } from '../../../common/types/models'; -import { PostAgentAcksRequest, PostAgentAcksResponse } from '../../../common/types/rest_spec'; +import type { RequestHandler } from 'kibana/server'; +import type { AcksService } from '../../services/agents'; +import type { AgentEvent } from '../../../common/types/models'; +import type { PostAgentAcksRequest, PostAgentAcksResponse } from '../../../common/types/rest_spec'; import { defaultIngestErrorHandler } from '../../errors'; export const postAgentAcksHandlerBuilder = function ( diff --git a/x-pack/plugins/fleet/server/routes/agent/actions_handlers.test.ts b/x-pack/plugins/fleet/server/routes/agent/actions_handlers.test.ts index 6affe332b8f877..6c12a826a11df6 100644 --- a/x-pack/plugins/fleet/server/routes/agent/actions_handlers.test.ts +++ b/x-pack/plugins/fleet/server/routes/agent/actions_handlers.test.ts @@ -6,7 +6,7 @@ */ import { NewAgentActionSchema } from '../../types/models'; -import { +import type { ElasticsearchClient, KibanaResponseFactory, RequestHandlerContext, @@ -17,10 +17,10 @@ import { savedObjectsClientMock, httpServerMock, } from 'src/core/server/mocks'; -import { ActionsService } from '../../services/agents'; -import { AgentAction } from '../../../common/types/models'; +import type { ActionsService } from '../../services/agents'; +import type { AgentAction } from '../../../common/types/models'; import { postNewAgentActionHandlerBuilder } from './actions_handlers'; -import { +import type { PostNewAgentActionRequest, PostNewAgentActionResponse, } from '../../../common/types/rest_spec'; diff --git a/x-pack/plugins/fleet/server/routes/agent/actions_handlers.ts b/x-pack/plugins/fleet/server/routes/agent/actions_handlers.ts index d032945245faf0..2d5cfa4fd5b4f8 100644 --- a/x-pack/plugins/fleet/server/routes/agent/actions_handlers.ts +++ b/x-pack/plugins/fleet/server/routes/agent/actions_handlers.ts @@ -7,11 +7,11 @@ // handlers that handle agent actions request -import { RequestHandler } from 'kibana/server'; -import { TypeOf } from '@kbn/config-schema'; +import type { RequestHandler } from 'kibana/server'; +import type { TypeOf } from '@kbn/config-schema'; import { PostNewAgentActionRequestSchema } from '../../types/rest_spec'; -import { ActionsService } from '../../services/agents'; -import { PostNewAgentActionResponse } from '../../../common/types/rest_spec'; +import type { ActionsService } from '../../services/agents'; +import type { PostNewAgentActionResponse } from '../../../common/types/rest_spec'; import { defaultIngestErrorHandler } from '../../errors'; export const postNewAgentActionHandlerBuilder = function ( diff --git a/x-pack/plugins/fleet/server/routes/agent/handlers.ts b/x-pack/plugins/fleet/server/routes/agent/handlers.ts index cd91e8c325c066..d5e2df56da6018 100644 --- a/x-pack/plugins/fleet/server/routes/agent/handlers.ts +++ b/x-pack/plugins/fleet/server/routes/agent/handlers.ts @@ -5,10 +5,10 @@ * 2.0. */ -import { RequestHandler } from 'src/core/server'; -import { TypeOf } from '@kbn/config-schema'; +import type { RequestHandler } from 'src/core/server'; +import type { TypeOf } from '@kbn/config-schema'; import { AbortController } from 'abort-controller'; -import { +import type { GetAgentsResponse, GetOneAgentResponse, GetOneAgentEventsResponse, @@ -25,11 +25,11 @@ import { UpdateAgentRequestSchema, DeleteAgentRequestSchema, GetOneAgentEventsRequestSchema, - PostAgentCheckinRequest, GetAgentStatusRequestSchema, PutAgentReassignRequestSchema, PostBulkAgentReassignRequestSchema, } from '../../types'; +import type { PostAgentCheckinRequest } from '../../types'; import { defaultIngestErrorHandler } from '../../errors'; import { licenseService } from '../../services'; import * as AgentService from '../../services/agents'; diff --git a/x-pack/plugins/fleet/server/routes/agent/index.ts b/x-pack/plugins/fleet/server/routes/agent/index.ts index 86c88aeaf46ac1..0b9e180a1cfd89 100644 --- a/x-pack/plugins/fleet/server/routes/agent/index.ts +++ b/x-pack/plugins/fleet/server/routes/agent/index.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { IRouter, RouteValidationResultFactory } from 'src/core/server'; +import type { IRouter, RouteValidationResultFactory } from 'src/core/server'; import Ajv from 'ajv'; import { PLUGIN_ID, @@ -51,7 +51,7 @@ import * as AgentService from '../../services/agents'; import { postNewAgentActionHandlerBuilder } from './actions_handlers'; import { appContextService } from '../../services'; import { postAgentUnenrollHandler, postBulkAgentsUnenrollHandler } from './unenroll_handler'; -import { FleetConfigType } from '../..'; +import type { FleetConfigType } from '../..'; import { postAgentUpgradeHandler, postBulkAgentsUpgradeHandler } from './upgrade_handler'; const ajv = new Ajv({ diff --git a/x-pack/plugins/fleet/server/routes/agent/unenroll_handler.ts b/x-pack/plugins/fleet/server/routes/agent/unenroll_handler.ts index 614ccd8a266245..07ca776ef104bd 100644 --- a/x-pack/plugins/fleet/server/routes/agent/unenroll_handler.ts +++ b/x-pack/plugins/fleet/server/routes/agent/unenroll_handler.ts @@ -5,9 +5,12 @@ * 2.0. */ -import { RequestHandler } from 'src/core/server'; -import { TypeOf } from '@kbn/config-schema'; -import { PostAgentUnenrollResponse, PostBulkAgentUnenrollResponse } from '../../../common/types'; +import type { RequestHandler } from 'src/core/server'; +import type { TypeOf } from '@kbn/config-schema'; +import type { + PostAgentUnenrollResponse, + PostBulkAgentUnenrollResponse, +} from '../../../common/types'; import { PostAgentUnenrollRequestSchema, PostBulkAgentUnenrollRequestSchema } from '../../types'; import { licenseService } from '../../services'; import * as AgentService from '../../services/agents'; diff --git a/x-pack/plugins/fleet/server/routes/agent/upgrade_handler.ts b/x-pack/plugins/fleet/server/routes/agent/upgrade_handler.ts index 086a9411f20b8d..4999801c4122a7 100644 --- a/x-pack/plugins/fleet/server/routes/agent/upgrade_handler.ts +++ b/x-pack/plugins/fleet/server/routes/agent/upgrade_handler.ts @@ -5,10 +5,10 @@ * 2.0. */ -import { RequestHandler } from 'src/core/server'; -import { TypeOf } from '@kbn/config-schema'; +import type { RequestHandler } from 'src/core/server'; +import type { TypeOf } from '@kbn/config-schema'; import semverCoerce from 'semver/functions/coerce'; -import { PostAgentUpgradeResponse, PostBulkAgentUpgradeResponse } from '../../../common/types'; +import type { PostAgentUpgradeResponse, PostBulkAgentUpgradeResponse } from '../../../common/types'; import { PostAgentUpgradeRequestSchema, PostBulkAgentUpgradeRequestSchema } from '../../types'; import * as AgentService from '../../services/agents'; import { appContextService } from '../../services'; diff --git a/x-pack/plugins/fleet/server/routes/agent_policy/handlers.ts b/x-pack/plugins/fleet/server/routes/agent_policy/handlers.ts index 411f7a74a6ab27..a0a30b1c1190b2 100644 --- a/x-pack/plugins/fleet/server/routes/agent_policy/handlers.ts +++ b/x-pack/plugins/fleet/server/routes/agent_policy/handlers.ts @@ -5,8 +5,8 @@ * 2.0. */ -import { TypeOf } from '@kbn/config-schema'; -import { RequestHandler, ResponseHeaders } from 'src/core/server'; +import type { TypeOf } from '@kbn/config-schema'; +import type { RequestHandler, ResponseHeaders } from 'src/core/server'; import bluebird from 'bluebird'; import { fullAgentPolicyToYaml } from '../../../common/services'; import { appContextService, agentPolicyService, packagePolicyService } from '../../services'; @@ -20,10 +20,10 @@ import { CopyAgentPolicyRequestSchema, DeleteAgentPolicyRequestSchema, GetFullAgentPolicyRequestSchema, - AgentPolicy, - NewPackagePolicy, } from '../../types'; -import { +import type { AgentPolicy, NewPackagePolicy } from '../../types'; +import { defaultPackages } from '../../../common'; +import type { GetAgentPoliciesResponse, GetAgentPoliciesResponseItem, GetOneAgentPolicyResponse, @@ -32,7 +32,6 @@ import { CopyAgentPolicyResponse, DeleteAgentPolicyResponse, GetFullAgentPolicyResponse, - defaultPackages, } from '../../../common'; import { defaultIngestErrorHandler } from '../../errors'; diff --git a/x-pack/plugins/fleet/server/routes/agent_policy/index.ts b/x-pack/plugins/fleet/server/routes/agent_policy/index.ts index 256e24217558ed..5cf58414f79927 100644 --- a/x-pack/plugins/fleet/server/routes/agent_policy/index.ts +++ b/x-pack/plugins/fleet/server/routes/agent_policy/index.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { IRouter } from 'src/core/server'; +import type { IRouter } from 'src/core/server'; import { PLUGIN_ID, AGENT_POLICY_API_ROUTES } from '../../constants'; import { GetAgentPoliciesRequestSchema, diff --git a/x-pack/plugins/fleet/server/routes/app/index.ts b/x-pack/plugins/fleet/server/routes/app/index.ts index 64c1bdf1d02f9e..04c5bf2df47be7 100644 --- a/x-pack/plugins/fleet/server/routes/app/index.ts +++ b/x-pack/plugins/fleet/server/routes/app/index.ts @@ -5,10 +5,10 @@ * 2.0. */ -import { IRouter, RequestHandler } from 'src/core/server'; +import type { IRouter, RequestHandler } from 'src/core/server'; import { APP_API_ROUTES } from '../../constants'; import { appContextService } from '../../services'; -import { CheckPermissionsResponse } from '../../../common'; +import type { CheckPermissionsResponse } from '../../../common'; export const getCheckPermissionsHandler: RequestHandler = async (context, request, response) => { const body: CheckPermissionsResponse = { success: true }; diff --git a/x-pack/plugins/fleet/server/routes/data_streams/handlers.ts b/x-pack/plugins/fleet/server/routes/data_streams/handlers.ts index 4424fc478c682f..2826840d773e0f 100644 --- a/x-pack/plugins/fleet/server/routes/data_streams/handlers.ts +++ b/x-pack/plugins/fleet/server/routes/data_streams/handlers.ts @@ -5,10 +5,11 @@ * 2.0. */ -import { RequestHandler, SavedObjectsClientContract } from 'src/core/server'; import { keyBy, keys, merge } from 'lodash'; -import { DataStream } from '../../types'; -import { GetDataStreamsResponse, KibanaAssetType, KibanaSavedObjectType } from '../../../common'; +import type { RequestHandler, SavedObjectsClientContract } from 'src/core/server'; +import type { DataStream } from '../../types'; +import { KibanaAssetType, KibanaSavedObjectType } from '../../../common'; +import type { GetDataStreamsResponse } from '../../../common'; import { getPackageSavedObjects, getKibanaSavedObject } from '../../services/epm/packages/get'; import { defaultIngestErrorHandler } from '../../errors'; diff --git a/x-pack/plugins/fleet/server/routes/data_streams/index.ts b/x-pack/plugins/fleet/server/routes/data_streams/index.ts index 7373b684002f24..05efff12d01da7 100644 --- a/x-pack/plugins/fleet/server/routes/data_streams/index.ts +++ b/x-pack/plugins/fleet/server/routes/data_streams/index.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { IRouter } from 'src/core/server'; +import type { IRouter } from 'src/core/server'; import { PLUGIN_ID, DATA_STREAM_API_ROUTES } from '../../constants'; import { getListHandler } from './handlers'; diff --git a/x-pack/plugins/fleet/server/routes/enrollment_api_key/handler.ts b/x-pack/plugins/fleet/server/routes/enrollment_api_key/handler.ts index a46675c5be3ff0..b41af3b0c770c4 100644 --- a/x-pack/plugins/fleet/server/routes/enrollment_api_key/handler.ts +++ b/x-pack/plugins/fleet/server/routes/enrollment_api_key/handler.ts @@ -5,15 +5,15 @@ * 2.0. */ -import { RequestHandler } from 'src/core/server'; -import { TypeOf } from '@kbn/config-schema'; +import type { RequestHandler } from 'src/core/server'; +import type { TypeOf } from '@kbn/config-schema'; import { GetEnrollmentAPIKeysRequestSchema, PostEnrollmentAPIKeyRequestSchema, DeleteEnrollmentAPIKeyRequestSchema, GetOneEnrollmentAPIKeyRequestSchema, } from '../../types'; -import { +import type { GetEnrollmentAPIKeysResponse, GetOneEnrollmentAPIKeyResponse, DeleteEnrollmentAPIKeyResponse, diff --git a/x-pack/plugins/fleet/server/routes/enrollment_api_key/index.ts b/x-pack/plugins/fleet/server/routes/enrollment_api_key/index.ts index ee319987d1e912..cf736edd4633e5 100644 --- a/x-pack/plugins/fleet/server/routes/enrollment_api_key/index.ts +++ b/x-pack/plugins/fleet/server/routes/enrollment_api_key/index.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { IRouter } from 'src/core/server'; +import type { IRouter } from 'src/core/server'; import { PLUGIN_ID, ENROLLMENT_API_KEY_ROUTES } from '../../constants'; import { GetEnrollmentAPIKeysRequestSchema, diff --git a/x-pack/plugins/fleet/server/routes/epm/handlers.ts b/x-pack/plugins/fleet/server/routes/epm/handlers.ts index 47e53b27a600f8..09a53f2c0d8ff7 100644 --- a/x-pack/plugins/fleet/server/routes/epm/handlers.ts +++ b/x-pack/plugins/fleet/server/routes/epm/handlers.ts @@ -5,11 +5,11 @@ * 2.0. */ -import { TypeOf } from '@kbn/config-schema'; +import type { TypeOf } from '@kbn/config-schema'; import mime from 'mime-types'; import path from 'path'; -import { RequestHandler, ResponseHeaders, KnownHeaders } from 'src/core/server'; -import { +import type { RequestHandler, ResponseHeaders, KnownHeaders } from 'src/core/server'; +import type { GetInfoResponse, InstallPackageResponse, DeletePackageResponse, @@ -33,7 +33,6 @@ import { GetStatsRequestSchema, } from '../../types'; import { - BulkInstallResponse, bulkInstallPackages, getCategories, getPackages, @@ -47,6 +46,7 @@ import { getInstallationObject, getInstallation, } from '../../services/epm/packages'; +import type { BulkInstallResponse } from '../../services/epm/packages'; import { defaultIngestErrorHandler, ingestErrorToResponseOptions } from '../../errors'; import { splitPkgKey } from '../../services/epm/registry'; import { licenseService } from '../../services'; diff --git a/x-pack/plugins/fleet/server/routes/epm/index.ts b/x-pack/plugins/fleet/server/routes/epm/index.ts index f5788fe252bebd..9ed4d7e11ad29d 100644 --- a/x-pack/plugins/fleet/server/routes/epm/index.ts +++ b/x-pack/plugins/fleet/server/routes/epm/index.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { IRouter } from 'src/core/server'; +import type { IRouter } from 'src/core/server'; import { PLUGIN_ID, EPM_API_ROUTES } from '../../constants'; import { getCategoriesHandler, diff --git a/x-pack/plugins/fleet/server/routes/install_script/index.ts b/x-pack/plugins/fleet/server/routes/install_script/index.ts index c7cc0da1ce48c7..5fb2ea726c62b8 100644 --- a/x-pack/plugins/fleet/server/routes/install_script/index.ts +++ b/x-pack/plugins/fleet/server/routes/install_script/index.ts @@ -6,7 +6,8 @@ */ import url from 'url'; -import { IRouter, BasePath, KibanaRequest } from 'src/core/server'; +import { BasePath, KibanaRequest } from 'src/core/server'; +import type { IRouter } from 'src/core/server'; import { INSTALL_SCRIPT_API_ROUTES } from '../../constants'; import { getScript } from '../../services/install_script'; import { InstallScriptRequestSchema } from '../../types'; diff --git a/x-pack/plugins/fleet/server/routes/limited_concurrency.test.ts b/x-pack/plugins/fleet/server/routes/limited_concurrency.test.ts index f71aeb80a6d3e7..626df529c12361 100644 --- a/x-pack/plugins/fleet/server/routes/limited_concurrency.test.ts +++ b/x-pack/plugins/fleet/server/routes/limited_concurrency.test.ts @@ -11,7 +11,7 @@ import { isLimitedRoute, registerLimitedConcurrencyRoutes, } from './limited_concurrency'; -import { FleetConfigType } from '../index'; +import type { FleetConfigType } from '../index'; describe('registerLimitedConcurrencyRoutes', () => { test(`doesn't call registerOnPreAuth if maxConcurrentConnections is 0`, async () => { diff --git a/x-pack/plugins/fleet/server/routes/limited_concurrency.ts b/x-pack/plugins/fleet/server/routes/limited_concurrency.ts index 92195ae08681ad..ae4cab2839c79c 100644 --- a/x-pack/plugins/fleet/server/routes/limited_concurrency.ts +++ b/x-pack/plugins/fleet/server/routes/limited_concurrency.ts @@ -5,15 +5,15 @@ * 2.0. */ +import { KibanaRequest } from 'kibana/server'; import type { CoreSetup, - KibanaRequest, LifecycleResponseFactory, OnPreAuthToolkit, OnPreAuthHandler, } from 'kibana/server'; import { LIMITED_CONCURRENCY_ROUTE_TAG } from '../../common'; -import { FleetConfigType } from '../index'; +import type { FleetConfigType } from '../index'; export class MaxCounter { constructor(private readonly max: number = 1) {} diff --git a/x-pack/plugins/fleet/server/routes/output/handler.ts b/x-pack/plugins/fleet/server/routes/output/handler.ts index e9f4b8c797689e..a1bbe1112d04b6 100644 --- a/x-pack/plugins/fleet/server/routes/output/handler.ts +++ b/x-pack/plugins/fleet/server/routes/output/handler.ts @@ -5,10 +5,10 @@ * 2.0. */ -import { RequestHandler } from 'src/core/server'; -import { TypeOf } from '@kbn/config-schema'; +import type { RequestHandler } from 'src/core/server'; +import type { TypeOf } from '@kbn/config-schema'; import { GetOneOutputRequestSchema, PutOutputRequestSchema } from '../../types'; -import { GetOneOutputResponse, GetOutputsResponse } from '../../../common'; +import type { GetOneOutputResponse, GetOutputsResponse } from '../../../common'; import { outputService } from '../../services/output'; import { defaultIngestErrorHandler } from '../../errors'; diff --git a/x-pack/plugins/fleet/server/routes/output/index.ts b/x-pack/plugins/fleet/server/routes/output/index.ts index 7114a7c673d6b4..ce4610cf7f85b0 100644 --- a/x-pack/plugins/fleet/server/routes/output/index.ts +++ b/x-pack/plugins/fleet/server/routes/output/index.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { IRouter } from 'src/core/server'; +import type { IRouter } from 'src/core/server'; import { PLUGIN_ID, OUTPUT_API_ROUTES } from '../../constants'; import { getOneOuputHandler, getOutputsHandler, putOuputHandler } from './handler'; import { diff --git a/x-pack/plugins/fleet/server/routes/package_policy/handlers.test.ts b/x-pack/plugins/fleet/server/routes/package_policy/handlers.test.ts index 813279f2a800fc..a94313282a3607 100644 --- a/x-pack/plugins/fleet/server/routes/package_policy/handlers.test.ts +++ b/x-pack/plugins/fleet/server/routes/package_policy/handlers.test.ts @@ -6,14 +6,14 @@ */ import { httpServerMock, httpServiceMock } from 'src/core/server/mocks'; -import { IRouter, KibanaRequest, RequestHandler, RouteConfig } from 'kibana/server'; +import { KibanaRequest } from 'kibana/server'; +import type { IRouter, RequestHandler, RouteConfig } from 'kibana/server'; import { registerRoutes } from './index'; import { PACKAGE_POLICY_API_ROUTES } from '../../../common/constants'; -import { appContextService } from '../../services'; +import { appContextService, packagePolicyService } from '../../services'; import { createAppContextStartContractMock, xpackMocks } from '../../mocks'; -import { PackagePolicyServiceInterface, ExternalCallback } from '../..'; +import type { PackagePolicyServiceInterface, ExternalCallback } from '../..'; import { CreatePackagePolicyRequestSchema } from '../../types/rest_spec'; -import { packagePolicyService } from '../../services'; const packagePolicyServiceMock = packagePolicyService as jest.Mocked; diff --git a/x-pack/plugins/fleet/server/routes/package_policy/handlers.ts b/x-pack/plugins/fleet/server/routes/package_policy/handlers.ts index 6b35f74b3febc2..fb2c853f506c91 100644 --- a/x-pack/plugins/fleet/server/routes/package_policy/handlers.ts +++ b/x-pack/plugins/fleet/server/routes/package_policy/handlers.ts @@ -5,9 +5,10 @@ * 2.0. */ -import { TypeOf } from '@kbn/config-schema'; +import type { TypeOf } from '@kbn/config-schema'; import Boom from '@hapi/boom'; -import { RequestHandler, SavedObjectsErrorHelpers } from '../../../../../../src/core/server'; +import { SavedObjectsErrorHelpers } from '../../../../../../src/core/server'; +import type { RequestHandler } from '../../../../../../src/core/server'; import { appContextService, packagePolicyService } from '../../services'; import { GetPackagePoliciesRequestSchema, @@ -16,7 +17,7 @@ import { UpdatePackagePolicyRequestSchema, DeletePackagePoliciesRequestSchema, } from '../../types'; -import { CreatePackagePolicyResponse, DeletePackagePoliciesResponse } from '../../../common'; +import type { CreatePackagePolicyResponse, DeletePackagePoliciesResponse } from '../../../common'; import { defaultIngestErrorHandler } from '../../errors'; export const getPackagePoliciesHandler: RequestHandler< diff --git a/x-pack/plugins/fleet/server/routes/package_policy/index.ts b/x-pack/plugins/fleet/server/routes/package_policy/index.ts index 2df70e1a51b34f..19fc261685ff7e 100644 --- a/x-pack/plugins/fleet/server/routes/package_policy/index.ts +++ b/x-pack/plugins/fleet/server/routes/package_policy/index.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { IRouter } from 'src/core/server'; +import type { IRouter } from 'src/core/server'; import { PLUGIN_ID, PACKAGE_POLICY_API_ROUTES } from '../../constants'; import { GetPackagePoliciesRequestSchema, diff --git a/x-pack/plugins/fleet/server/routes/security.ts b/x-pack/plugins/fleet/server/routes/security.ts index 995dad545ed944..001dbf4b9b2f4f 100644 --- a/x-pack/plugins/fleet/server/routes/security.ts +++ b/x-pack/plugins/fleet/server/routes/security.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { IRouter, RequestHandler } from 'src/core/server'; +import type { IRouter, RequestHandler } from 'src/core/server'; import { appContextService } from '../services'; export function enforceSuperUser( diff --git a/x-pack/plugins/fleet/server/routes/settings/index.ts b/x-pack/plugins/fleet/server/routes/settings/index.ts index 63b5b9c881e13c..2f71e3967c38c6 100644 --- a/x-pack/plugins/fleet/server/routes/settings/index.ts +++ b/x-pack/plugins/fleet/server/routes/settings/index.ts @@ -5,8 +5,8 @@ * 2.0. */ -import { IRouter, RequestHandler } from 'src/core/server'; -import { TypeOf } from '@kbn/config-schema'; +import type { IRouter, RequestHandler } from 'src/core/server'; +import type { TypeOf } from '@kbn/config-schema'; import { PLUGIN_ID, SETTINGS_API_ROUTES } from '../../constants'; import { PutSettingsRequestSchema, GetSettingsRequestSchema } from '../../types'; import { defaultIngestErrorHandler } from '../../errors'; diff --git a/x-pack/plugins/fleet/server/routes/setup/handlers.test.ts b/x-pack/plugins/fleet/server/routes/setup/handlers.test.ts index 946f17ad8129d5..4016e90ea19b3d 100644 --- a/x-pack/plugins/fleet/server/routes/setup/handlers.test.ts +++ b/x-pack/plugins/fleet/server/routes/setup/handlers.test.ts @@ -6,7 +6,7 @@ */ import { httpServerMock } from 'src/core/server/mocks'; -import { PostIngestSetupResponse } from '../../../common'; +import type { PostIngestSetupResponse } from '../../../common'; import { RegistryError } from '../../errors'; import { createAppContextStartContractMock, xpackMocks } from '../../mocks'; import { FleetSetupHandler } from './handlers'; diff --git a/x-pack/plugins/fleet/server/routes/setup/handlers.ts b/x-pack/plugins/fleet/server/routes/setup/handlers.ts index 0c6ba6d14b1be3..8d4d44276dfc17 100644 --- a/x-pack/plugins/fleet/server/routes/setup/handlers.ts +++ b/x-pack/plugins/fleet/server/routes/setup/handlers.ts @@ -5,10 +5,10 @@ * 2.0. */ -import { RequestHandler } from 'src/core/server'; -import { TypeOf } from '@kbn/config-schema'; +import type { RequestHandler } from 'src/core/server'; +import type { TypeOf } from '@kbn/config-schema'; import { outputService, appContextService } from '../../services'; -import { GetFleetStatusResponse, PostIngestSetupResponse } from '../../../common'; +import type { GetFleetStatusResponse, PostIngestSetupResponse } from '../../../common'; import { setupIngestManager, setupFleet } from '../../services/setup'; import { PostFleetSetupRequestSchema } from '../../types'; import { defaultIngestErrorHandler } from '../../errors'; diff --git a/x-pack/plugins/fleet/server/routes/setup/index.ts b/x-pack/plugins/fleet/server/routes/setup/index.ts index 3698b74c8c02bc..7e07723b4acd8f 100644 --- a/x-pack/plugins/fleet/server/routes/setup/index.ts +++ b/x-pack/plugins/fleet/server/routes/setup/index.ts @@ -5,10 +5,9 @@ * 2.0. */ -import { IRouter } from 'src/core/server'; - +import type { IRouter } from 'src/core/server'; import { PLUGIN_ID, AGENTS_SETUP_API_ROUTES, SETUP_API_ROUTE } from '../../constants'; -import { FleetConfigType } from '../../../common'; +import type { FleetConfigType } from '../../../common'; import { getFleetStatusHandler, createFleetSetupHandler, FleetSetupHandler } from './handlers'; import { PostFleetSetupRequestSchema } from '../../types'; diff --git a/x-pack/plugins/fleet/server/saved_objects/index.ts b/x-pack/plugins/fleet/server/saved_objects/index.ts index d6e3cba9989077..e41881c6f8b09b 100644 --- a/x-pack/plugins/fleet/server/saved_objects/index.ts +++ b/x-pack/plugins/fleet/server/saved_objects/index.ts @@ -5,8 +5,8 @@ * 2.0. */ -import { SavedObjectsServiceSetup, SavedObjectsType } from 'kibana/server'; -import { EncryptedSavedObjectsPluginSetup } from '../../../encrypted_saved_objects/server'; +import type { SavedObjectsServiceSetup, SavedObjectsType } from 'kibana/server'; +import type { EncryptedSavedObjectsPluginSetup } from '../../../encrypted_saved_objects/server'; import { migratePackagePolicyToV7110, migratePackagePolicyToV7120, diff --git a/x-pack/plugins/fleet/server/saved_objects/migrations/to_v7_10_0.ts b/x-pack/plugins/fleet/server/saved_objects/migrations/to_v7_10_0.ts index aa980e4b9428a2..976f02e1f242cf 100644 --- a/x-pack/plugins/fleet/server/saved_objects/migrations/to_v7_10_0.ts +++ b/x-pack/plugins/fleet/server/saved_objects/migrations/to_v7_10_0.ts @@ -5,9 +5,9 @@ * 2.0. */ -import { SavedObjectMigrationFn, SavedObjectUnsanitizedDoc } from 'kibana/server'; -import { EncryptedSavedObjectsPluginSetup } from '../../../../encrypted_saved_objects/server'; -import { +import type { SavedObjectMigrationFn, SavedObjectUnsanitizedDoc } from 'kibana/server'; +import type { EncryptedSavedObjectsPluginSetup } from '../../../../encrypted_saved_objects/server'; +import type { Agent, AgentEvent, AgentPolicy, diff --git a/x-pack/plugins/fleet/server/services/agent_policy.ts b/x-pack/plugins/fleet/server/services/agent_policy.ts index 44962ea31c56c5..bda754a1800b85 100644 --- a/x-pack/plugins/fleet/server/services/agent_policy.ts +++ b/x-pack/plugins/fleet/server/services/agent_policy.ts @@ -8,18 +8,18 @@ import { uniq } from 'lodash'; import { safeLoad } from 'js-yaml'; import uuid from 'uuid/v4'; -import { +import type { ElasticsearchClient, SavedObjectsClientContract, SavedObjectsBulkUpdateResponse, } from 'src/core/server'; -import { AuthenticatedUser } from '../../../security/server'; +import type { AuthenticatedUser } from '../../../security/server'; import { DEFAULT_AGENT_POLICY, AGENT_POLICY_SAVED_OBJECT_TYPE, AGENT_SAVED_OBJECT_TYPE, } from '../constants'; -import { +import type { PackagePolicy, NewAgentPolicy, AgentPolicy, @@ -28,15 +28,13 @@ import { ListWithKuery, } from '../types'; import { - DeleteAgentPolicyResponse, - Settings, agentPolicyStatuses, storedPackagePoliciesToAgentInputs, dataTypes, - FleetServerPolicy, AGENT_POLICY_INDEX, DEFAULT_FLEET_SERVER_AGENT_POLICY, } from '../../common'; +import type { DeleteAgentPolicyResponse, Settings, FleetServerPolicy } from '../../common'; import { AgentPolicyNameExistsError, AgentPolicyDeletionError, diff --git a/x-pack/plugins/fleet/server/services/agent_policy_update.ts b/x-pack/plugins/fleet/server/services/agent_policy_update.ts index 561c8043978ae8..b6acafc667c9bf 100644 --- a/x-pack/plugins/fleet/server/services/agent_policy_update.ts +++ b/x-pack/plugins/fleet/server/services/agent_policy_update.ts @@ -5,7 +5,8 @@ * 2.0. */ -import { ElasticsearchClient, KibanaRequest, SavedObjectsClientContract } from 'src/core/server'; +import { KibanaRequest } from 'src/core/server'; +import type { ElasticsearchClient, SavedObjectsClientContract } from 'src/core/server'; import { generateEnrollmentAPIKey, deleteEnrollmentApiKeyForAgentPolicyId } from './api_keys'; import { isAgentsSetup, unenrollForAgentPolicyId } from './agents'; import { agentPolicyService } from './agent_policy'; diff --git a/x-pack/plugins/fleet/server/services/agents/acks.test.ts b/x-pack/plugins/fleet/server/services/agents/acks.test.ts index 5aec696f5e1440..1a4b89a9b2a945 100644 --- a/x-pack/plugins/fleet/server/services/agents/acks.test.ts +++ b/x-pack/plugins/fleet/server/services/agents/acks.test.ts @@ -6,10 +6,9 @@ */ import Boom from '@hapi/boom'; -import { SavedObjectsBulkResponse } from 'kibana/server'; +import type { SavedObjectsBulkResponse } from 'kibana/server'; import { elasticsearchServiceMock, savedObjectsClientMock } from 'src/core/server/mocks'; - -import { +import type { Agent, AgentActionSOAttributes, BaseAgentActionSOAttributes, diff --git a/x-pack/plugins/fleet/server/services/agents/acks.ts b/x-pack/plugins/fleet/server/services/agents/acks.ts index c639a9b0332ac6..0fecc18f7a6223 100644 --- a/x-pack/plugins/fleet/server/services/agents/acks.ts +++ b/x-pack/plugins/fleet/server/services/agents/acks.ts @@ -5,16 +5,16 @@ * 2.0. */ -import { +import { KibanaRequest } from 'src/core/server'; +import type { ElasticsearchClient, - KibanaRequest, SavedObjectsBulkCreateObject, SavedObjectsBulkResponse, SavedObjectsClientContract, } from 'src/core/server'; import Boom from '@hapi/boom'; import LRU from 'lru-cache'; -import { +import type { Agent, AgentAction, AgentPolicyAction, diff --git a/x-pack/plugins/fleet/server/services/agents/actions.test.ts b/x-pack/plugins/fleet/server/services/agents/actions.test.ts index 3d391cc89a7e31..18e954d4aa9bd5 100644 --- a/x-pack/plugins/fleet/server/services/agents/actions.test.ts +++ b/x-pack/plugins/fleet/server/services/agents/actions.test.ts @@ -6,8 +6,8 @@ */ import { createAgentAction } from './actions'; -import { SavedObject } from 'kibana/server'; -import { AgentAction } from '../../../common/types/models'; +import type { SavedObject } from 'kibana/server'; +import type { AgentAction } from '../../../common/types/models'; import { savedObjectsClientMock, elasticsearchServiceMock } from 'src/core/server/mocks'; describe('test agent actions services', () => { diff --git a/x-pack/plugins/fleet/server/services/agents/actions.ts b/x-pack/plugins/fleet/server/services/agents/actions.ts index 8dfeac11dacf3b..58d52f408f1fbc 100644 --- a/x-pack/plugins/fleet/server/services/agents/actions.ts +++ b/x-pack/plugins/fleet/server/services/agents/actions.ts @@ -5,8 +5,8 @@ * 2.0. */ -import { ElasticsearchClient, SavedObjectsClientContract } from 'kibana/server'; -import { +import type { ElasticsearchClient, SavedObjectsClientContract } from 'kibana/server'; +import type { Agent, AgentAction, AgentPolicyAction, diff --git a/x-pack/plugins/fleet/server/services/agents/authenticate.ts b/x-pack/plugins/fleet/server/services/agents/authenticate.ts index a03c35bdc6e737..10469fcb3a0138 100644 --- a/x-pack/plugins/fleet/server/services/agents/authenticate.ts +++ b/x-pack/plugins/fleet/server/services/agents/authenticate.ts @@ -6,8 +6,9 @@ */ import Boom from '@hapi/boom'; -import { KibanaRequest, SavedObjectsClientContract, ElasticsearchClient } from 'src/core/server'; -import { Agent } from '../../types'; +import { KibanaRequest } from 'src/core/server'; +import type { SavedObjectsClientContract, ElasticsearchClient } from 'src/core/server'; +import type { Agent } from '../../types'; import * as APIKeyService from '../api_keys'; import { getAgentByAccessAPIKeyId } from './crud'; diff --git a/x-pack/plugins/fleet/server/services/agents/checkin/index.ts b/x-pack/plugins/fleet/server/services/agents/checkin/index.ts index bcebedae2e07a1..925006f9e67b36 100644 --- a/x-pack/plugins/fleet/server/services/agents/checkin/index.ts +++ b/x-pack/plugins/fleet/server/services/agents/checkin/index.ts @@ -6,19 +6,18 @@ */ import deepEqual from 'fast-deep-equal'; -import { +import type { ElasticsearchClient, SavedObjectsClientContract, SavedObjectsBulkCreateObject, } from 'src/core/server'; -import { +import type { Agent, NewAgentEvent, AgentEvent, AgentSOAttributes, AgentEventSOAttributes, } from '../../../types'; - import { AGENT_EVENT_SAVED_OBJECT_TYPE } from '../../../constants'; import { agentCheckinState } from './state'; import { getAgentActionsForCheckin } from '../actions'; diff --git a/x-pack/plugins/fleet/server/services/agents/checkin/state.ts b/x-pack/plugins/fleet/server/services/agents/checkin/state.ts index e1cec6292a3553..de965646a59c3b 100644 --- a/x-pack/plugins/fleet/server/services/agents/checkin/state.ts +++ b/x-pack/plugins/fleet/server/services/agents/checkin/state.ts @@ -5,8 +5,8 @@ * 2.0. */ -import { ElasticsearchClient, SavedObjectsClientContract } from 'src/core/server'; -import { Agent } from '../../../types'; +import type { ElasticsearchClient, SavedObjectsClientContract } from 'src/core/server'; +import type { Agent } from '../../../types'; import { appContextService } from '../../app_context'; import { agentCheckinStateConnectedAgentsFactory } from './state_connected_agents'; import { agentCheckinStateNewActionsFactory } from './state_new_actions'; diff --git a/x-pack/plugins/fleet/server/services/agents/checkin/state_new_actions.test.ts b/x-pack/plugins/fleet/server/services/agents/checkin/state_new_actions.test.ts index cd6e0ef61e3f08..1433eccab038b4 100644 --- a/x-pack/plugins/fleet/server/services/agents/checkin/state_new_actions.test.ts +++ b/x-pack/plugins/fleet/server/services/agents/checkin/state_new_actions.test.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { ElasticsearchClient } from 'kibana/server'; +import type { ElasticsearchClient } from 'kibana/server'; import { savedObjectsClientMock } from 'src/core/server/mocks'; import { take } from 'rxjs/operators'; import { @@ -13,7 +13,7 @@ import { createNewActionsSharedObservable, } from './state_new_actions'; import { getNewActionsSince } from '../actions'; -import { Agent, AgentAction, AgentPolicyAction } from '../../../types'; +import type { Agent, AgentAction, AgentPolicyAction } from '../../../types'; import { outputType } from '../../../../common/constants'; jest.mock('../../app_context', () => ({ diff --git a/x-pack/plugins/fleet/server/services/agents/checkin/state_new_actions.ts b/x-pack/plugins/fleet/server/services/agents/checkin/state_new_actions.ts index 01759c2015cdf6..c66bff30a2e57d 100644 --- a/x-pack/plugins/fleet/server/services/agents/checkin/state_new_actions.ts +++ b/x-pack/plugins/fleet/server/services/agents/checkin/state_new_actions.ts @@ -22,8 +22,9 @@ import { timeout, take, } from 'rxjs/operators'; -import { ElasticsearchClient, SavedObjectsClientContract, KibanaRequest } from 'src/core/server'; -import { +import { KibanaRequest } from 'src/core/server'; +import type { ElasticsearchClient, SavedObjectsClientContract } from 'src/core/server'; +import type { Agent, AgentAction, AgentPolicyAction, diff --git a/x-pack/plugins/fleet/server/services/agents/crud.ts b/x-pack/plugins/fleet/server/services/agents/crud.ts index c80fd77fc11ecc..60a2ed8f67ceef 100644 --- a/x-pack/plugins/fleet/server/services/agents/crud.ts +++ b/x-pack/plugins/fleet/server/services/agents/crud.ts @@ -5,8 +5,8 @@ * 2.0. */ -import { SavedObjectsClientContract, ElasticsearchClient } from 'src/core/server'; -import { AgentSOAttributes, Agent, ListWithKuery } from '../../types'; +import type { SavedObjectsClientContract, ElasticsearchClient } from 'src/core/server'; +import type { AgentSOAttributes, Agent, ListWithKuery } from '../../types'; import { appContextService, agentPolicyService } from '../../services'; import * as crudServiceSO from './crud_so'; import * as crudServiceFleetServer from './crud_fleet_server'; diff --git a/x-pack/plugins/fleet/server/services/agents/crud_fleet_server.ts b/x-pack/plugins/fleet/server/services/agents/crud_fleet_server.ts index caff15efff68c2..53a22e842a5446 100644 --- a/x-pack/plugins/fleet/server/services/agents/crud_fleet_server.ts +++ b/x-pack/plugins/fleet/server/services/agents/crud_fleet_server.ts @@ -6,17 +6,18 @@ */ import Boom from '@hapi/boom'; -import { SearchResponse } from 'elasticsearch'; -import { ElasticsearchClient } from 'src/core/server'; - -import { FleetServerAgent, isAgentUpgradeable, SO_SEARCH_LIMIT } from '../../../common'; +import type { SearchResponse } from 'elasticsearch'; +import type { ElasticsearchClient } from 'src/core/server'; +import { isAgentUpgradeable, SO_SEARCH_LIMIT } from '../../../common'; +import type { FleetServerAgent } from '../../../common'; import { AGENT_SAVED_OBJECT_TYPE, AGENTS_INDEX } from '../../constants'; -import { ESSearchHit } from '../../../../../typings/elasticsearch'; -import { AgentSOAttributes, Agent, ListWithKuery } from '../../types'; +import type { ESSearchHit } from '../../../../../typings/elasticsearch'; +import type { AgentSOAttributes, Agent, ListWithKuery } from '../../types'; import { escapeSearchQueryPhrase, normalizeKuery } from '../saved_object'; import { searchHitToAgent, agentSOAttributesToFleetServerAgentDoc } from './helpers'; import { appContextService } from '../../services'; -import { esKuery, KueryNode } from '../../../../../../src/plugins/data/server'; +import { esKuery } from '../../../../../../src/plugins/data/server'; +import type { KueryNode } from '../../../../../../src/plugins/data/server'; const ACTIVE_AGENT_CONDITION = 'active:true'; const INACTIVE_AGENT_CONDITION = `NOT (${ACTIVE_AGENT_CONDITION})`; diff --git a/x-pack/plugins/fleet/server/services/agents/crud_so.ts b/x-pack/plugins/fleet/server/services/agents/crud_so.ts index c3ceb4b7502e26..2daeff9b7344d0 100644 --- a/x-pack/plugins/fleet/server/services/agents/crud_so.ts +++ b/x-pack/plugins/fleet/server/services/agents/crud_so.ts @@ -6,15 +6,15 @@ */ import Boom from '@hapi/boom'; -import { SavedObjectsBulkUpdateObject, SavedObjectsClientContract } from 'src/core/server'; - +import type { SavedObjectsBulkUpdateObject, SavedObjectsClientContract } from 'src/core/server'; import { isAgentUpgradeable } from '../../../common'; import { AGENT_SAVED_OBJECT_TYPE } from '../../constants'; -import { AgentSOAttributes, Agent, ListWithKuery } from '../../types'; +import type { AgentSOAttributes, Agent, ListWithKuery } from '../../types'; import { escapeSearchQueryPhrase, normalizeKuery, findAllSOs } from '../saved_object'; import { savedObjectToAgent } from './saved_objects'; import { appContextService } from '../../services'; -import { esKuery, KueryNode } from '../../../../../../src/plugins/data/server'; +import { esKuery } from '../../../../../../src/plugins/data/server'; +import type { KueryNode } from '../../../../../../src/plugins/data/server'; const ACTIVE_AGENT_CONDITION = `${AGENT_SAVED_OBJECT_TYPE}.attributes.active:true`; const INACTIVE_AGENT_CONDITION = `NOT (${ACTIVE_AGENT_CONDITION})`; diff --git a/x-pack/plugins/fleet/server/services/agents/events.ts b/x-pack/plugins/fleet/server/services/agents/events.ts index 71df5ebad49479..29b42a5de82824 100644 --- a/x-pack/plugins/fleet/server/services/agents/events.ts +++ b/x-pack/plugins/fleet/server/services/agents/events.ts @@ -5,9 +5,9 @@ * 2.0. */ -import { SavedObjectsClientContract } from 'src/core/server'; +import type { SavedObjectsClientContract } from 'src/core/server'; import { AGENT_EVENT_SAVED_OBJECT_TYPE } from '../../constants'; -import { AgentEventSOAttributes, AgentEvent } from '../../types'; +import type { AgentEventSOAttributes, AgentEvent } from '../../types'; import { normalizeKuery } from '../saved_object'; export async function getAgentEvents( diff --git a/x-pack/plugins/fleet/server/services/agents/helpers.ts b/x-pack/plugins/fleet/server/services/agents/helpers.ts index 90d85e98ecd679..1dab3b64755fd0 100644 --- a/x-pack/plugins/fleet/server/services/agents/helpers.ts +++ b/x-pack/plugins/fleet/server/services/agents/helpers.ts @@ -5,8 +5,8 @@ * 2.0. */ -import { ESSearchHit } from '../../../../../typings/elasticsearch'; -import { Agent, AgentSOAttributes, FleetServerAgent } from '../../types'; +import type { ESSearchHit } from '../../../../../typings/elasticsearch'; +import type { Agent, AgentSOAttributes, FleetServerAgent } from '../../types'; export function searchHitToAgent(hit: ESSearchHit): Agent { return { diff --git a/x-pack/plugins/fleet/server/services/agents/saved_objects.ts b/x-pack/plugins/fleet/server/services/agents/saved_objects.ts index 7b439c27299877..45d5a0de040eae 100644 --- a/x-pack/plugins/fleet/server/services/agents/saved_objects.ts +++ b/x-pack/plugins/fleet/server/services/agents/saved_objects.ts @@ -6,8 +6,8 @@ */ import Boom from '@hapi/boom'; -import { SavedObject } from 'src/core/server'; -import { +import type { SavedObject } from 'src/core/server'; +import type { Agent, AgentSOAttributes, AgentAction, diff --git a/x-pack/plugins/fleet/server/services/agents/setup.ts b/x-pack/plugins/fleet/server/services/agents/setup.ts index bbd14209b5b379..b55eb8efb13703 100644 --- a/x-pack/plugins/fleet/server/services/agents/setup.ts +++ b/x-pack/plugins/fleet/server/services/agents/setup.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { SavedObjectsClientContract } from 'src/core/server'; +import type { SavedObjectsClientContract } from 'src/core/server'; import { SO_SEARCH_LIMIT } from '../../constants'; import { agentPolicyService } from '../agent_policy'; import { outputService } from '../output'; diff --git a/x-pack/plugins/fleet/server/services/agents/status.test.ts b/x-pack/plugins/fleet/server/services/agents/status.test.ts index a6b8bf41b6cb45..c6a021195f8f8f 100644 --- a/x-pack/plugins/fleet/server/services/agents/status.test.ts +++ b/x-pack/plugins/fleet/server/services/agents/status.test.ts @@ -8,8 +8,8 @@ import { elasticsearchServiceMock, savedObjectsClientMock } from 'src/core/server/mocks'; import { getAgentStatusById } from './status'; import { AGENT_TYPE_PERMANENT } from '../../../common/constants'; -import { AgentSOAttributes } from '../../../common/types/models'; -import { SavedObject } from 'kibana/server'; +import type { AgentSOAttributes } from '../../../common/types/models'; +import type { SavedObject } from 'kibana/server'; describe('Agent status service', () => { it('should return inactive when agent is not active', async () => { diff --git a/x-pack/plugins/fleet/server/services/agents/status.ts b/x-pack/plugins/fleet/server/services/agents/status.ts index 42d3aff2b0d702..29171adf92bb9b 100644 --- a/x-pack/plugins/fleet/server/services/agents/status.ts +++ b/x-pack/plugins/fleet/server/services/agents/status.ts @@ -5,14 +5,14 @@ * 2.0. */ -import { ElasticsearchClient, SavedObjectsClientContract } from 'src/core/server'; +import type { ElasticsearchClient, SavedObjectsClientContract } from 'src/core/server'; import pMap from 'p-map'; import { getAgent, listAgents } from './crud'; import { AGENT_EVENT_SAVED_OBJECT_TYPE, AGENT_SAVED_OBJECT_TYPE } from '../../constants'; -import { AgentStatus } from '../../types'; - +import type { AgentStatus } from '../../types'; import { AgentStatusKueryHelper } from '../../../common/services'; -import { esKuery, KueryNode } from '../../../../../../src/plugins/data/server'; +import { esKuery } from '../../../../../../src/plugins/data/server'; +import type { KueryNode } from '../../../../../../src/plugins/data/server'; import { normalizeKuery } from '../saved_object'; import { appContextService } from '../app_context'; import { removeSOAttributes } from './crud_fleet_server'; diff --git a/x-pack/plugins/fleet/server/services/agents/unenroll.ts b/x-pack/plugins/fleet/server/services/agents/unenroll.ts index 72d551a1229801..97dc7ea87706ec 100644 --- a/x-pack/plugins/fleet/server/services/agents/unenroll.ts +++ b/x-pack/plugins/fleet/server/services/agents/unenroll.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { ElasticsearchClient, SavedObjectsClientContract } from 'src/core/server'; +import type { ElasticsearchClient, SavedObjectsClientContract } from 'src/core/server'; import * as APIKeyService from '../api_keys'; import { createAgentAction, bulkCreateAgentActions } from './actions'; import { diff --git a/x-pack/plugins/fleet/server/services/agents/update.ts b/x-pack/plugins/fleet/server/services/agents/update.ts index 21087be392bcd0..81214b6fd0eb5e 100644 --- a/x-pack/plugins/fleet/server/services/agents/update.ts +++ b/x-pack/plugins/fleet/server/services/agents/update.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { ElasticsearchClient, SavedObjectsClientContract } from 'src/core/server'; +import type { ElasticsearchClient, SavedObjectsClientContract } from 'src/core/server'; import { listAgents } from './crud'; import { AGENT_SAVED_OBJECT_TYPE } from '../../constants'; import { unenrollAgent } from './unenroll'; diff --git a/x-pack/plugins/fleet/server/services/agents/upgrade.ts b/x-pack/plugins/fleet/server/services/agents/upgrade.ts index d73cc38e32c39d..9986edd3d805f1 100644 --- a/x-pack/plugins/fleet/server/services/agents/upgrade.ts +++ b/x-pack/plugins/fleet/server/services/agents/upgrade.ts @@ -5,8 +5,8 @@ * 2.0. */ -import { ElasticsearchClient, SavedObjectsClientContract } from 'src/core/server'; -import { AgentAction, AgentActionSOAttributes } from '../../types'; +import type { ElasticsearchClient, SavedObjectsClientContract } from 'src/core/server'; +import type { AgentAction, AgentActionSOAttributes } from '../../types'; import { AGENT_ACTION_SAVED_OBJECT_TYPE } from '../../constants'; import { agentPolicyService } from '../../services'; import { IngestManagerError } from '../../errors'; diff --git a/x-pack/plugins/fleet/server/services/api_keys/enrollment_api_key.ts b/x-pack/plugins/fleet/server/services/api_keys/enrollment_api_key.ts index 85812fee3885c8..5d86393f0905e2 100644 --- a/x-pack/plugins/fleet/server/services/api_keys/enrollment_api_key.ts +++ b/x-pack/plugins/fleet/server/services/api_keys/enrollment_api_key.ts @@ -5,8 +5,8 @@ * 2.0. */ -import { SavedObjectsClientContract, ElasticsearchClient } from 'src/core/server'; -import { EnrollmentAPIKey } from '../../types'; +import type { SavedObjectsClientContract, ElasticsearchClient } from 'src/core/server'; +import type { EnrollmentAPIKey } from '../../types'; import { appContextService } from '../app_context'; import * as enrollmentApiKeyServiceSO from './enrollment_api_key_so'; import * as enrollmentApiKeyServiceFleetServer from './enrollment_api_key_fleet_server'; diff --git a/x-pack/plugins/fleet/server/services/api_keys/enrollment_api_key_fleet_server.ts b/x-pack/plugins/fleet/server/services/api_keys/enrollment_api_key_fleet_server.ts index f5d0015297daa0..5cde87da95cdfe 100644 --- a/x-pack/plugins/fleet/server/services/api_keys/enrollment_api_key_fleet_server.ts +++ b/x-pack/plugins/fleet/server/services/api_keys/enrollment_api_key_fleet_server.ts @@ -7,11 +7,11 @@ import uuid from 'uuid'; import Boom from '@hapi/boom'; -import { GetResponse } from 'elasticsearch'; +import type { GetResponse } from 'elasticsearch'; import { ResponseError } from '@elastic/elasticsearch/lib/errors'; -import { SavedObjectsClientContract, ElasticsearchClient } from 'src/core/server'; -import { ESSearchResponse as SearchResponse } from '../../../../../typings/elasticsearch'; -import { EnrollmentAPIKey, FleetServerEnrollmentAPIKey } from '../../types'; +import type { SavedObjectsClientContract, ElasticsearchClient } from 'src/core/server'; +import type { ESSearchResponse as SearchResponse } from '../../../../../typings/elasticsearch'; +import type { EnrollmentAPIKey, FleetServerEnrollmentAPIKey } from '../../types'; import { ENROLLMENT_API_KEYS_INDEX } from '../../constants'; import { createAPIKey, invalidateAPIKeys } from './security'; import { agentPolicyService } from '../agent_policy'; diff --git a/x-pack/plugins/fleet/server/services/api_keys/enrollment_api_key_so.ts b/x-pack/plugins/fleet/server/services/api_keys/enrollment_api_key_so.ts index 014bc58e747ea4..4001cabe76aa34 100644 --- a/x-pack/plugins/fleet/server/services/api_keys/enrollment_api_key_so.ts +++ b/x-pack/plugins/fleet/server/services/api_keys/enrollment_api_key_so.ts @@ -7,8 +7,8 @@ import uuid from 'uuid'; import Boom from '@hapi/boom'; -import { SavedObjectsClientContract, SavedObject } from 'src/core/server'; -import { EnrollmentAPIKey, EnrollmentAPIKeySOAttributes } from '../../types'; +import type { SavedObjectsClientContract, SavedObject } from 'src/core/server'; +import type { EnrollmentAPIKey, EnrollmentAPIKeySOAttributes } from '../../types'; import { ENROLLMENT_API_KEYS_SAVED_OBJECT_TYPE } from '../../constants'; import { createAPIKey, invalidateAPIKeys } from './security'; import { agentPolicyService } from '../agent_policy'; diff --git a/x-pack/plugins/fleet/server/services/api_keys/index.ts b/x-pack/plugins/fleet/server/services/api_keys/index.ts index 911cb700dd56b5..724583e42efe0b 100644 --- a/x-pack/plugins/fleet/server/services/api_keys/index.ts +++ b/x-pack/plugins/fleet/server/services/api_keys/index.ts @@ -5,7 +5,8 @@ * 2.0. */ -import { SavedObjectsClientContract, KibanaRequest } from 'src/core/server'; +import { KibanaRequest } from 'src/core/server'; +import type { SavedObjectsClientContract } from 'src/core/server'; import { createAPIKey } from './security'; export { invalidateAPIKeys } from './security'; diff --git a/x-pack/plugins/fleet/server/services/api_keys/security.ts b/x-pack/plugins/fleet/server/services/api_keys/security.ts index efd46c1a547ddc..356f9012791eb6 100644 --- a/x-pack/plugins/fleet/server/services/api_keys/security.ts +++ b/x-pack/plugins/fleet/server/services/api_keys/security.ts @@ -6,9 +6,10 @@ */ import type { Request } from '@hapi/hapi'; -import { KibanaRequest, SavedObjectsClientContract } from '../../../../../../src/core/server'; +import { KibanaRequest } from '../../../../../../src/core/server'; +import type { SavedObjectsClientContract } from '../../../../../../src/core/server'; import { FleetAdminUserInvalidError, isESClientError } from '../../errors'; -import { CallESAsCurrentUser } from '../../types'; +import type { CallESAsCurrentUser } from '../../types'; import { appContextService } from '../app_context'; import { outputService } from '../output'; diff --git a/x-pack/plugins/fleet/server/services/app_context.ts b/x-pack/plugins/fleet/server/services/app_context.ts index 1ada940dd793c9..f63d3b2d7ccabd 100644 --- a/x-pack/plugins/fleet/server/services/app_context.ts +++ b/x-pack/plugins/fleet/server/services/app_context.ts @@ -8,22 +8,21 @@ import { BehaviorSubject, Observable } from 'rxjs'; import { first } from 'rxjs/operators'; import { kibanaPackageJson } from '@kbn/utils'; - -import { +import { KibanaRequest } from 'src/core/server'; +import type { ElasticsearchClient, SavedObjectsServiceStart, HttpServiceSetup, Logger, - KibanaRequest, } from 'src/core/server'; -import { +import type { EncryptedSavedObjectsClient, EncryptedSavedObjectsPluginSetup, } from '../../../encrypted_saved_objects/server'; -import { SecurityPluginStart } from '../../../security/server'; -import { FleetConfigType } from '../../common'; -import { ExternalCallback, ExternalCallbacksStorage, FleetAppContext } from '../plugin'; -import { CloudSetup } from '../../../cloud/server'; +import type { SecurityPluginStart } from '../../../security/server'; +import type { FleetConfigType } from '../../common'; +import type { ExternalCallback, ExternalCallbacksStorage, FleetAppContext } from '../plugin'; +import type { CloudSetup } from '../../../cloud/server'; class AppContextService { private encryptedSavedObjects: EncryptedSavedObjectsClient | undefined; diff --git a/x-pack/plugins/fleet/server/services/config.ts b/x-pack/plugins/fleet/server/services/config.ts index 3e2c7be1e3fdeb..d14e31e5b510f0 100644 --- a/x-pack/plugins/fleet/server/services/config.ts +++ b/x-pack/plugins/fleet/server/services/config.ts @@ -6,7 +6,7 @@ */ import { Observable, Subscription } from 'rxjs'; -import { FleetConfigType } from '../'; +import type { FleetConfigType } from '../'; /** * Kibana config observable service, *NOT* agent policy diff --git a/x-pack/plugins/fleet/server/services/epm/agent/agent.ts b/x-pack/plugins/fleet/server/services/epm/agent/agent.ts index a71776af245f77..38631ad784ea99 100644 --- a/x-pack/plugins/fleet/server/services/epm/agent/agent.ts +++ b/x-pack/plugins/fleet/server/services/epm/agent/agent.ts @@ -7,7 +7,7 @@ import Handlebars from 'handlebars'; import { safeLoad, safeDump } from 'js-yaml'; -import { PackagePolicyConfigRecord } from '../../../../common'; +import type { PackagePolicyConfigRecord } from '../../../../common'; const handlebars = Handlebars.create(); diff --git a/x-pack/plugins/fleet/server/services/epm/archive/cache.ts b/x-pack/plugins/fleet/server/services/epm/archive/cache.ts index 97e0303e9f50f1..8d4234e3cf538f 100644 --- a/x-pack/plugins/fleet/server/services/epm/archive/cache.ts +++ b/x-pack/plugins/fleet/server/services/epm/archive/cache.ts @@ -5,8 +5,8 @@ * 2.0. */ -import { ArchiveEntry } from './index'; -import { ArchivePackage, RegistryPackage } from '../../../../common'; +import type { ArchiveEntry } from './index'; +import type { ArchivePackage, RegistryPackage } from '../../../../common'; const archiveEntryCache: Map = new Map(); export const getArchiveEntry = (key: string) => archiveEntryCache.get(key); diff --git a/x-pack/plugins/fleet/server/services/epm/archive/extract.ts b/x-pack/plugins/fleet/server/services/epm/archive/extract.ts index 817eff7d427884..8d576310813c0d 100644 --- a/x-pack/plugins/fleet/server/services/epm/archive/extract.ts +++ b/x-pack/plugins/fleet/server/services/epm/archive/extract.ts @@ -8,7 +8,7 @@ import tar from 'tar'; import yauzl from 'yauzl'; import { bufferToStream, streamToBuffer } from '../streams'; -import { ArchiveEntry } from './index'; +import type { ArchiveEntry } from './index'; export async function untarBuffer( buffer: Buffer, diff --git a/x-pack/plugins/fleet/server/services/epm/archive/index.ts b/x-pack/plugins/fleet/server/services/epm/archive/index.ts index 7ee217979cdae3..44046ac749f6c6 100644 --- a/x-pack/plugins/fleet/server/services/epm/archive/index.ts +++ b/x-pack/plugins/fleet/server/services/epm/archive/index.ts @@ -5,10 +5,9 @@ * 2.0. */ -import { AssetParts, InstallSource } from '../../../../common/types'; +import type { AssetParts, InstallSource } from '../../../../common/types'; import { PackageInvalidArchiveError, PackageUnsupportedMediaTypeError } from '../../../errors'; import { - SharedKey, getArchiveEntry, setArchiveEntry, deleteArchiveEntry, @@ -17,6 +16,7 @@ import { deleteArchiveFilelist, deletePackageInfo, } from './cache'; +import type { SharedKey } from './cache'; import { getBufferExtractor } from './extract'; export * from './cache'; diff --git a/x-pack/plugins/fleet/server/services/epm/archive/storage.ts b/x-pack/plugins/fleet/server/services/epm/archive/storage.ts index 20e1e8825fbd8f..671d428918caf1 100644 --- a/x-pack/plugins/fleet/server/services/epm/archive/storage.ts +++ b/x-pack/plugins/fleet/server/services/epm/archive/storage.ts @@ -11,15 +11,16 @@ import { safeLoad } from 'js-yaml'; import { isBinaryFile } from 'isbinaryfile'; import mime from 'mime-types'; import uuidv5 from 'uuid/v5'; -import { SavedObjectsClientContract, SavedObjectsBulkCreateObject } from 'src/core/server'; -import { - ASSETS_SAVED_OBJECT_TYPE, +import type { SavedObjectsClientContract, SavedObjectsBulkCreateObject } from 'src/core/server'; +import { ASSETS_SAVED_OBJECT_TYPE } from '../../../../common'; +import type { InstallablePackage, InstallSource, PackageAssetReference, RegistryDataStream, } from '../../../../common'; -import { ArchiveEntry, getArchiveEntry, setArchiveEntry, setArchiveFilelist } from './index'; +import { getArchiveEntry, setArchiveEntry, setArchiveFilelist } from './index'; +import type { ArchiveEntry } from './index'; import { parseAndVerifyPolicyTemplates, parseAndVerifyStreams } from './validation'; import { pkgToPkgKey } from '../registry'; diff --git a/x-pack/plugins/fleet/server/services/epm/archive/validation.ts b/x-pack/plugins/fleet/server/services/epm/archive/validation.ts index 05daa985790793..03f30cab457343 100644 --- a/x-pack/plugins/fleet/server/services/epm/archive/validation.ts +++ b/x-pack/plugins/fleet/server/services/epm/archive/validation.ts @@ -7,7 +7,7 @@ import yaml from 'js-yaml'; import { pick, uniq } from 'lodash'; -import { +import type { ArchivePackage, RegistryPolicyTemplate, RegistryDataStream, diff --git a/x-pack/plugins/fleet/server/services/epm/elasticsearch/datastream_ilm/install.ts b/x-pack/plugins/fleet/server/services/epm/elasticsearch/datastream_ilm/install.ts index a18c2710ce776d..e18cf2eb52bcd5 100644 --- a/x-pack/plugins/fleet/server/services/epm/elasticsearch/datastream_ilm/install.ts +++ b/x-pack/plugins/fleet/server/services/epm/elasticsearch/datastream_ilm/install.ts @@ -5,14 +5,14 @@ * 2.0. */ -import { SavedObjectsClientContract } from 'kibana/server'; -import { - ElasticsearchAssetType, +import type { SavedObjectsClientContract } from 'kibana/server'; +import { ElasticsearchAssetType } from '../../../../../common/types/models'; +import type { EsAssetReference, InstallablePackage, RegistryDataStream, } from '../../../../../common/types/models'; -import { CallESAsCurrentUser } from '../../../../types'; +import type { CallESAsCurrentUser } from '../../../../types'; import { getInstallation } from '../../packages'; import { deleteIlmRefs, deleteIlms } from './remove'; import { saveInstalledEsRefs } from '../../packages/install'; diff --git a/x-pack/plugins/fleet/server/services/epm/elasticsearch/datastream_ilm/remove.ts b/x-pack/plugins/fleet/server/services/epm/elasticsearch/datastream_ilm/remove.ts index 6f0cd6ecc935ff..7da980e61f0ece 100644 --- a/x-pack/plugins/fleet/server/services/epm/elasticsearch/datastream_ilm/remove.ts +++ b/x-pack/plugins/fleet/server/services/epm/elasticsearch/datastream_ilm/remove.ts @@ -5,8 +5,9 @@ * 2.0. */ -import { SavedObjectsClientContract } from 'kibana/server'; -import { CallESAsCurrentUser, ElasticsearchAssetType, EsAssetReference } from '../../../../types'; +import type { SavedObjectsClientContract } from 'kibana/server'; +import { ElasticsearchAssetType } from '../../../../types'; +import type { CallESAsCurrentUser, EsAssetReference } from '../../../../types'; import { PACKAGES_SAVED_OBJECT_TYPE } from '../../../../../common/constants'; export const deleteIlms = async (callCluster: CallESAsCurrentUser, ilmPolicyIds: string[]) => { diff --git a/x-pack/plugins/fleet/server/services/epm/elasticsearch/ilm/install.ts b/x-pack/plugins/fleet/server/services/epm/elasticsearch/ilm/install.ts index 644baa3a77e7d3..b6123d190c0ebb 100644 --- a/x-pack/plugins/fleet/server/services/epm/elasticsearch/ilm/install.ts +++ b/x-pack/plugins/fleet/server/services/epm/elasticsearch/ilm/install.ts @@ -5,7 +5,8 @@ * 2.0. */ -import { CallESAsCurrentUser, ElasticsearchAssetType } from '../../../../types'; +import { ElasticsearchAssetType } from '../../../../types'; +import type { CallESAsCurrentUser } from '../../../../types'; import { getAsset, getPathParts } from '../../archive'; export async function installILMPolicy(paths: string[], callCluster: CallESAsCurrentUser) { diff --git a/x-pack/plugins/fleet/server/services/epm/elasticsearch/index.test.ts b/x-pack/plugins/fleet/server/services/epm/elasticsearch/index.test.ts index 178d0c53703f37..aa64cd7a6ed02d 100644 --- a/x-pack/plugins/fleet/server/services/epm/elasticsearch/index.test.ts +++ b/x-pack/plugins/fleet/server/services/epm/elasticsearch/index.test.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { RegistryDataStream } from '../../../types'; +import type { RegistryDataStream } from '../../../types'; import { getRegistryDataStreamAssetBaseName } from './index'; test('getBaseName', () => { diff --git a/x-pack/plugins/fleet/server/services/epm/elasticsearch/index.ts b/x-pack/plugins/fleet/server/services/epm/elasticsearch/index.ts index 95873ef0c9b29d..81e05ef7d63147 100644 --- a/x-pack/plugins/fleet/server/services/epm/elasticsearch/index.ts +++ b/x-pack/plugins/fleet/server/services/epm/elasticsearch/index.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { RegistryDataStream } from '../../../types'; +import type { RegistryDataStream } from '../../../types'; /** * Creates the base name for Elasticsearch assets in the form of diff --git a/x-pack/plugins/fleet/server/services/epm/elasticsearch/ingest_pipeline/ingest_pipelines.test.ts b/x-pack/plugins/fleet/server/services/epm/elasticsearch/ingest_pipeline/ingest_pipelines.test.ts index 001add36ea95de..0a96186339bc00 100644 --- a/x-pack/plugins/fleet/server/services/epm/elasticsearch/ingest_pipeline/ingest_pipelines.test.ts +++ b/x-pack/plugins/fleet/server/services/epm/elasticsearch/ingest_pipeline/ingest_pipelines.test.ts @@ -8,7 +8,7 @@ import { readFileSync } from 'fs'; import path from 'path'; import { rewriteIngestPipeline, getPipelineNameForInstallation } from './install'; -import { RegistryDataStream } from '../../../../types'; +import type { RegistryDataStream } from '../../../../types'; test('a json-format pipeline with pipeline references is correctly rewritten', () => { const inputStandard = readFileSync( diff --git a/x-pack/plugins/fleet/server/services/epm/elasticsearch/ingest_pipeline/install.ts b/x-pack/plugins/fleet/server/services/epm/elasticsearch/ingest_pipeline/install.ts index 983e10e15bfff1..ff3262cb654189 100644 --- a/x-pack/plugins/fleet/server/services/epm/elasticsearch/ingest_pipeline/install.ts +++ b/x-pack/plugins/fleet/server/services/epm/elasticsearch/ingest_pipeline/install.ts @@ -5,15 +5,16 @@ * 2.0. */ -import { SavedObjectsClientContract } from 'src/core/server'; -import { +import type { SavedObjectsClientContract } from 'src/core/server'; +import { ElasticsearchAssetType } from '../../../../types'; +import type { EsAssetReference, RegistryDataStream, - ElasticsearchAssetType, InstallablePackage, + CallESAsCurrentUser, } from '../../../../types'; -import { ArchiveEntry, getAsset, getPathParts } from '../../archive'; -import { CallESAsCurrentUser } from '../../../../types'; +import { getAsset, getPathParts } from '../../archive'; +import type { ArchiveEntry } from '../../archive'; import { saveInstalledEsRefs } from '../../packages/install'; import { getInstallationObject } from '../../packages'; import { deletePipelineRefs } from './remove'; diff --git a/x-pack/plugins/fleet/server/services/epm/elasticsearch/ingest_pipeline/remove.ts b/x-pack/plugins/fleet/server/services/epm/elasticsearch/ingest_pipeline/remove.ts index 4acc4767de5255..d78c9d989bd4d5 100644 --- a/x-pack/plugins/fleet/server/services/epm/elasticsearch/ingest_pipeline/remove.ts +++ b/x-pack/plugins/fleet/server/services/epm/elasticsearch/ingest_pipeline/remove.ts @@ -5,12 +5,14 @@ * 2.0. */ -import { SavedObjectsClientContract } from 'src/core/server'; +import type { SavedObjectsClientContract } from 'src/core/server'; import { appContextService } from '../../../'; -import { CallESAsCurrentUser, ElasticsearchAssetType } from '../../../../types'; +import { ElasticsearchAssetType } from '../../../../types'; +import type { CallESAsCurrentUser } from '../../../../types'; import { IngestManagerError } from '../../../../errors'; import { getInstallation } from '../../packages/get'; -import { PACKAGES_SAVED_OBJECT_TYPE, EsAssetReference } from '../../../../../common'; +import { PACKAGES_SAVED_OBJECT_TYPE } from '../../../../../common'; +import type { EsAssetReference } from '../../../../../common'; export const deletePreviousPipelines = async ( callCluster: CallESAsCurrentUser, diff --git a/x-pack/plugins/fleet/server/services/epm/elasticsearch/template/install.test.ts b/x-pack/plugins/fleet/server/services/epm/elasticsearch/template/install.test.ts index cdcd3972fd189a..42e724794b7914 100644 --- a/x-pack/plugins/fleet/server/services/epm/elasticsearch/template/install.test.ts +++ b/x-pack/plugins/fleet/server/services/epm/elasticsearch/template/install.test.ts @@ -5,9 +5,8 @@ * 2.0. */ -import { RegistryDataStream } from '../../../../types'; -import { Field } from '../../fields/field'; - +import type { RegistryDataStream } from '../../../../types'; +import type { Field } from '../../fields/field'; import { elasticsearchServiceMock } from 'src/core/server/mocks'; import { installTemplate } from './install'; diff --git a/x-pack/plugins/fleet/server/services/epm/elasticsearch/template/install.ts b/x-pack/plugins/fleet/server/services/epm/elasticsearch/template/install.ts index 70afa78e723bcf..353331528ca3c4 100644 --- a/x-pack/plugins/fleet/server/services/epm/elasticsearch/template/install.ts +++ b/x-pack/plugins/fleet/server/services/epm/elasticsearch/template/install.ts @@ -6,16 +6,17 @@ */ import Boom from '@hapi/boom'; -import { SavedObjectsClientContract } from 'src/core/server'; -import { +import type { SavedObjectsClientContract } from 'src/core/server'; +import { ElasticsearchAssetType } from '../../../../types'; +import type { RegistryDataStream, - ElasticsearchAssetType, TemplateRef, RegistryElasticsearch, InstallablePackage, + CallESAsCurrentUser, } from '../../../../types'; -import { CallESAsCurrentUser } from '../../../../types'; -import { Field, loadFieldsFromYaml, processFields } from '../../fields/field'; +import { loadFieldsFromYaml, processFields } from '../../fields/field'; +import type { Field } from '../../fields/field'; import { getPipelineNameForInstallation } from '../ingest_pipeline/install'; import { generateMappings, diff --git a/x-pack/plugins/fleet/server/services/epm/elasticsearch/template/template.test.ts b/x-pack/plugins/fleet/server/services/epm/elasticsearch/template/template.test.ts index a176805307845c..95e9e8e6d5c710 100644 --- a/x-pack/plugins/fleet/server/services/epm/elasticsearch/template/template.test.ts +++ b/x-pack/plugins/fleet/server/services/epm/elasticsearch/template/template.test.ts @@ -8,8 +8,9 @@ import { readFileSync } from 'fs'; import { safeLoad } from 'js-yaml'; import path from 'path'; -import { RegistryDataStream } from '../../../../types'; -import { Field, processFields } from '../../fields/field'; +import type { RegistryDataStream } from '../../../../types'; +import { processFields } from '../../fields/field'; +import type { Field } from '../../fields/field'; import { generateMappings, getTemplate, diff --git a/x-pack/plugins/fleet/server/services/epm/elasticsearch/template/template.ts b/x-pack/plugins/fleet/server/services/epm/elasticsearch/template/template.ts index b86c989f8c24c8..a13ad007663d8b 100644 --- a/x-pack/plugins/fleet/server/services/epm/elasticsearch/template/template.ts +++ b/x-pack/plugins/fleet/server/services/epm/elasticsearch/template/template.ts @@ -5,8 +5,8 @@ * 2.0. */ -import { Field, Fields } from '../../fields/field'; -import { +import type { Field, Fields } from '../../fields/field'; +import type { RegistryDataStream, CallESAsCurrentUser, TemplateRef, diff --git a/x-pack/plugins/fleet/server/services/epm/elasticsearch/transform/install.ts b/x-pack/plugins/fleet/server/services/epm/elasticsearch/transform/install.ts index 948a9c56746f36..e68c5070affd39 100644 --- a/x-pack/plugins/fleet/server/services/epm/elasticsearch/transform/install.ts +++ b/x-pack/plugins/fleet/server/services/epm/elasticsearch/transform/install.ts @@ -5,16 +5,12 @@ * 2.0. */ -import { SavedObjectsClientContract } from 'kibana/server'; - +import type { SavedObjectsClientContract } from 'kibana/server'; import { saveInstalledEsRefs } from '../../packages/install'; import { getPathParts } from '../../archive'; -import { - ElasticsearchAssetType, - EsAssetReference, - InstallablePackage, -} from '../../../../../common/types/models'; -import { CallESAsCurrentUser } from '../../../../types'; +import { ElasticsearchAssetType } from '../../../../../common/types/models'; +import type { EsAssetReference, InstallablePackage } from '../../../../../common/types/models'; +import type { CallESAsCurrentUser } from '../../../../types'; import { getInstallation } from '../../packages'; import { deleteTransforms, deleteTransformRefs } from './remove'; import { getAsset } from './common'; diff --git a/x-pack/plugins/fleet/server/services/epm/elasticsearch/transform/remove.test.ts b/x-pack/plugins/fleet/server/services/epm/elasticsearch/transform/remove.test.ts index 658a130d70c614..6df9f34489aeb8 100644 --- a/x-pack/plugins/fleet/server/services/epm/elasticsearch/transform/remove.test.ts +++ b/x-pack/plugins/fleet/server/services/epm/elasticsearch/transform/remove.test.ts @@ -5,11 +5,11 @@ * 2.0. */ -import { SavedObjectsClientContract } from 'kibana/server'; +import type { SavedObjectsClientContract } from 'kibana/server'; // eslint-disable-next-line @kbn/eslint/no-restricted-paths import { savedObjectsClientMock } from '../../../../../../../../src/core/server/saved_objects/service/saved_objects_client.mock'; import { deleteTransformRefs } from './remove'; -import { EsAssetReference } from '../../../../../common/types/models'; +import type { EsAssetReference } from '../../../../../common/types/models'; describe('test transform install', () => { let savedObjectsClient: jest.Mocked; diff --git a/x-pack/plugins/fleet/server/services/epm/elasticsearch/transform/remove.ts b/x-pack/plugins/fleet/server/services/epm/elasticsearch/transform/remove.ts index 0e947e0f0b90bb..510071f1199100 100644 --- a/x-pack/plugins/fleet/server/services/epm/elasticsearch/transform/remove.ts +++ b/x-pack/plugins/fleet/server/services/epm/elasticsearch/transform/remove.ts @@ -5,8 +5,9 @@ * 2.0. */ -import { SavedObjectsClientContract } from 'kibana/server'; -import { CallESAsCurrentUser, ElasticsearchAssetType, EsAssetReference } from '../../../../types'; +import type { SavedObjectsClientContract } from 'kibana/server'; +import { ElasticsearchAssetType } from '../../../../types'; +import type { CallESAsCurrentUser, EsAssetReference } from '../../../../types'; import { PACKAGES_SAVED_OBJECT_TYPE } from '../../../../../common/constants'; import { appContextService } from '../../../app_context'; diff --git a/x-pack/plugins/fleet/server/services/epm/elasticsearch/transform/transform.test.ts b/x-pack/plugins/fleet/server/services/epm/elasticsearch/transform/transform.test.ts index bd944391b5f23d..602908c5908e5e 100644 --- a/x-pack/plugins/fleet/server/services/epm/elasticsearch/transform/transform.test.ts +++ b/x-pack/plugins/fleet/server/services/epm/elasticsearch/transform/transform.test.ts @@ -19,8 +19,13 @@ jest.mock('./common', () => { import { errors as LegacyESErrors } from 'elasticsearch'; import { installTransform } from './install'; -import { ILegacyScopedClusterClient, SavedObject, SavedObjectsClientContract } from 'kibana/server'; -import { ElasticsearchAssetType, Installation, RegistryPackage } from '../../../../types'; +import type { + ILegacyScopedClusterClient, + SavedObject, + SavedObjectsClientContract, +} from 'kibana/server'; +import { ElasticsearchAssetType } from '../../../../types'; +import type { Installation, RegistryPackage } from '../../../../types'; import { getInstallation, getInstallationObject } from '../../packages'; import { getAsset } from './common'; // eslint-disable-next-line @kbn/eslint/no-restricted-paths diff --git a/x-pack/plugins/fleet/server/services/epm/fields/field.test.ts b/x-pack/plugins/fleet/server/services/epm/fields/field.test.ts index b10c4172106566..21c0fc52f6b3ff 100644 --- a/x-pack/plugins/fleet/server/services/epm/fields/field.test.ts +++ b/x-pack/plugins/fleet/server/services/epm/fields/field.test.ts @@ -9,7 +9,8 @@ import { readFileSync } from 'fs'; import glob from 'glob'; import { safeLoad } from 'js-yaml'; import path from 'path'; -import { Field, Fields, getField, processFields } from './field'; +import { getField, processFields } from './field'; +import type { Field, Fields } from './field'; // Add our own serialiser to just do JSON.stringify expect.addSnapshotSerializer({ diff --git a/x-pack/plugins/fleet/server/services/epm/fields/field.ts b/x-pack/plugins/fleet/server/services/epm/fields/field.ts index cc925bbb14ba0e..7144a4ca4e7f0d 100644 --- a/x-pack/plugins/fleet/server/services/epm/fields/field.ts +++ b/x-pack/plugins/fleet/server/services/epm/fields/field.ts @@ -6,7 +6,7 @@ */ import { safeLoad } from 'js-yaml'; -import { InstallablePackage } from '../../../types'; +import type { InstallablePackage } from '../../../types'; import { getAssetsData } from '../packages/assets'; // This should become a copy of https://github.com/elastic/beats/blob/d9a4c9c240a9820fab15002592e5bb6db318543b/libbeat/mapping/field.go#L39 diff --git a/x-pack/plugins/fleet/server/services/epm/kibana/assets/install.ts b/x-pack/plugins/fleet/server/services/epm/kibana/assets/install.ts index 64d65da2c3e140..a004bf0f21f628 100644 --- a/x-pack/plugins/fleet/server/services/epm/kibana/assets/install.ts +++ b/x-pack/plugins/fleet/server/services/epm/kibana/assets/install.ts @@ -5,20 +5,15 @@ * 2.0. */ -import { +import type { SavedObject, SavedObjectsBulkCreateObject, SavedObjectsClientContract, } from 'src/core/server'; import { PACKAGES_SAVED_OBJECT_TYPE } from '../../../../../common'; import { getAsset, getPathParts } from '../../archive'; -import { - AssetType, - KibanaAssetType, - AssetReference, - AssetParts, - KibanaSavedObjectType, -} from '../../../../types'; +import { KibanaAssetType, KibanaSavedObjectType } from '../../../../types'; +import type { AssetType, AssetReference, AssetParts } from '../../../../types'; import { savedObjectTypes } from '../../packages'; import { indexPatternTypes } from '../index_pattern/install'; diff --git a/x-pack/plugins/fleet/server/services/epm/kibana/index_pattern/install.test.ts b/x-pack/plugins/fleet/server/services/epm/kibana/index_pattern/install.test.ts index afac05f6ecaec5..e6d36235f03840 100644 --- a/x-pack/plugins/fleet/server/services/epm/kibana/index_pattern/install.test.ts +++ b/x-pack/plugins/fleet/server/services/epm/kibana/index_pattern/install.test.ts @@ -14,12 +14,12 @@ import { dedupeFields, transformField, findFieldByPath, - IndexPatternField, createFieldFormatMap, createIndexPatternFields, createIndexPattern, } from './install'; -import { Fields, Field } from '../../fields/field'; +import type { IndexPatternField } from './install'; +import type { Fields, Field } from '../../fields/field'; import { dupeFields } from './tests/test_data'; // Add our own serialiser to just do JSON.stringify diff --git a/x-pack/plugins/fleet/server/services/epm/kibana/index_pattern/install.ts b/x-pack/plugins/fleet/server/services/epm/kibana/index_pattern/install.ts index 8b8ff8b4c9d954..f45eeab8bc2baf 100644 --- a/x-pack/plugins/fleet/server/services/epm/kibana/index_pattern/install.ts +++ b/x-pack/plugins/fleet/server/services/epm/kibana/index_pattern/install.ts @@ -5,12 +5,18 @@ * 2.0. */ -import { SavedObjectsClientContract } from 'src/core/server'; +import type { SavedObjectsClientContract } from 'src/core/server'; import { INDEX_PATTERN_SAVED_OBJECT_TYPE } from '../../../../constants'; -import { loadFieldsFromYaml, Fields, Field } from '../../fields/field'; +import { loadFieldsFromYaml } from '../../fields/field'; +import type { Fields, Field } from '../../fields/field'; import { dataTypes, installationStatuses } from '../../../../../common/constants'; -import { ArchivePackage, Installation, InstallSource, ValueOf } from '../../../../../common/types'; -import { RegistryPackage, DataType } from '../../../../types'; +import type { + ArchivePackage, + Installation, + InstallSource, + ValueOf, +} from '../../../../../common/types'; +import type { RegistryPackage, DataType } from '../../../../types'; import { getInstallation, getPackageFromSource, getPackageSavedObjects } from '../../packages/get'; interface FieldFormatMap { diff --git a/x-pack/plugins/fleet/server/services/epm/kibana/index_pattern/tests/test_data.ts b/x-pack/plugins/fleet/server/services/epm/kibana/index_pattern/tests/test_data.ts index 1b17c6d812b4c1..49a32de7037763 100644 --- a/x-pack/plugins/fleet/server/services/epm/kibana/index_pattern/tests/test_data.ts +++ b/x-pack/plugins/fleet/server/services/epm/kibana/index_pattern/tests/test_data.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { IndexPatternField } from '../install'; +import type { IndexPatternField } from '../install'; export const dupeFields: IndexPatternField[] = [ { diff --git a/x-pack/plugins/fleet/server/services/epm/packages/_install_package.test.ts b/x-pack/plugins/fleet/server/services/epm/packages/_install_package.test.ts index a55b763d7b2bbd..cf928d5b80d634 100644 --- a/x-pack/plugins/fleet/server/services/epm/packages/_install_package.test.ts +++ b/x-pack/plugins/fleet/server/services/epm/packages/_install_package.test.ts @@ -5,7 +5,8 @@ * 2.0. */ -import { SavedObjectsClientContract, LegacyScopedClusterClient } from 'src/core/server'; +import { LegacyScopedClusterClient } from 'src/core/server'; +import type { SavedObjectsClientContract } from 'src/core/server'; import { savedObjectsClientMock, elasticsearchServiceMock } from 'src/core/server/mocks'; import { appContextService } from '../../app_context'; import { createAppContextStartContractMock } from '../../../mocks'; diff --git a/x-pack/plugins/fleet/server/services/epm/packages/_install_package.ts b/x-pack/plugins/fleet/server/services/epm/packages/_install_package.ts index 2a6a4c93cb8e0b..206bef75df14b1 100644 --- a/x-pack/plugins/fleet/server/services/epm/packages/_install_package.ts +++ b/x-pack/plugins/fleet/server/services/epm/packages/_install_package.ts @@ -5,20 +5,15 @@ * 2.0. */ -import { SavedObject, SavedObjectsClientContract } from 'src/core/server'; -import { - InstallablePackage, - InstallSource, - PackageAssetReference, - MAX_TIME_COMPLETE_INSTALL, - ASSETS_SAVED_OBJECT_TYPE, -} from '../../../../common'; +import type { SavedObject, SavedObjectsClientContract } from 'src/core/server'; +import { MAX_TIME_COMPLETE_INSTALL, ASSETS_SAVED_OBJECT_TYPE } from '../../../../common'; +import type { InstallablePackage, InstallSource, PackageAssetReference } from '../../../../common'; import { PACKAGES_SAVED_OBJECT_TYPE } from '../../../constants'; -import { +import { ElasticsearchAssetType } from '../../../types'; +import type { AssetReference, Installation, CallESAsCurrentUser, - ElasticsearchAssetType, InstallType, } from '../../../types'; import { installIndexPatterns } from '../kibana/index_pattern/install'; diff --git a/x-pack/plugins/fleet/server/services/epm/packages/assets.test.ts b/x-pack/plugins/fleet/server/services/epm/packages/assets.test.ts index aa35ddd2c294b3..6e5c257badef7a 100644 --- a/x-pack/plugins/fleet/server/services/epm/packages/assets.test.ts +++ b/x-pack/plugins/fleet/server/services/epm/packages/assets.test.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { InstallablePackage } from '../../../types'; +import type { InstallablePackage } from '../../../types'; import { getAssets } from './assets'; import { getArchiveFilelist } from '../archive/cache'; diff --git a/x-pack/plugins/fleet/server/services/epm/packages/assets.ts b/x-pack/plugins/fleet/server/services/epm/packages/assets.ts index a2a2bce91d8e51..c28c982f4ea4c8 100644 --- a/x-pack/plugins/fleet/server/services/epm/packages/assets.ts +++ b/x-pack/plugins/fleet/server/services/epm/packages/assets.ts @@ -5,8 +5,9 @@ * 2.0. */ -import { InstallablePackage } from '../../../types'; -import { ArchiveEntry, getArchiveFilelist, getAsset } from '../archive'; +import type { InstallablePackage } from '../../../types'; +import { getArchiveFilelist, getAsset } from '../archive'; +import type { ArchiveEntry } from '../archive'; // paths from RegistryPackage are routes to the assets on EPR // e.g. `/package/nginx/1.2.0/data_stream/access/fields/fields.yml` diff --git a/x-pack/plugins/fleet/server/services/epm/packages/bulk_install_packages.ts b/x-pack/plugins/fleet/server/services/epm/packages/bulk_install_packages.ts index ac41f550c1c726..64fd132145ffc7 100644 --- a/x-pack/plugins/fleet/server/services/epm/packages/bulk_install_packages.ts +++ b/x-pack/plugins/fleet/server/services/epm/packages/bulk_install_packages.ts @@ -5,11 +5,12 @@ * 2.0. */ -import { SavedObjectsClientContract } from 'src/core/server'; -import { CallESAsCurrentUser } from '../../../types'; +import type { SavedObjectsClientContract } from 'src/core/server'; +import type { CallESAsCurrentUser } from '../../../types'; import * as Registry from '../registry'; import { getInstallationObject } from './index'; -import { BulkInstallResponse, IBulkInstallPackageError, upgradePackage } from './install'; +import { upgradePackage } from './install'; +import type { BulkInstallResponse, IBulkInstallPackageError } from './install'; interface BulkInstallPackagesParams { savedObjectsClient: SavedObjectsClientContract; diff --git a/x-pack/plugins/fleet/server/services/epm/packages/ensure_installed_default_packages.test.ts b/x-pack/plugins/fleet/server/services/epm/packages/ensure_installed_default_packages.test.ts index aeb08bad061845..6c2a98450c1a75 100644 --- a/x-pack/plugins/fleet/server/services/epm/packages/ensure_installed_default_packages.test.ts +++ b/x-pack/plugins/fleet/server/services/epm/packages/ensure_installed_default_packages.test.ts @@ -5,8 +5,9 @@ * 2.0. */ -import { ElasticsearchAssetType, Installation, KibanaSavedObjectType } from '../../../types'; -import { SavedObject, SavedObjectsClientContract } from 'src/core/server'; +import { ElasticsearchAssetType, KibanaSavedObjectType } from '../../../types'; +import type { Installation } from '../../../types'; +import type { SavedObject, SavedObjectsClientContract } from 'src/core/server'; jest.mock('./install'); jest.mock('./bulk_install_packages'); diff --git a/x-pack/plugins/fleet/server/services/epm/packages/get.test.ts b/x-pack/plugins/fleet/server/services/epm/packages/get.test.ts index afd150c3335afd..354bcf88685cb2 100644 --- a/x-pack/plugins/fleet/server/services/epm/packages/get.test.ts +++ b/x-pack/plugins/fleet/server/services/epm/packages/get.test.ts @@ -5,9 +5,10 @@ * 2.0. */ -import { SavedObjectsClientContract, SavedObjectsFindResult } from 'kibana/server'; +import type { SavedObjectsClientContract, SavedObjectsFindResult } from 'kibana/server'; import { savedObjectsClientMock } from '../../../../../../../src/core/server/mocks'; -import { PACKAGE_POLICY_SAVED_OBJECT_TYPE, PackagePolicySOAttributes } from '../../../../common'; +import { PACKAGE_POLICY_SAVED_OBJECT_TYPE } from '../../../../common'; +import type { PackagePolicySOAttributes } from '../../../../common'; import { getPackageUsageStats } from './get'; describe('When using EPM `get` services', () => { diff --git a/x-pack/plugins/fleet/server/services/epm/packages/get.ts b/x-pack/plugins/fleet/server/services/epm/packages/get.ts index c07b88a45e6dc9..a32ac2ad4d88f6 100644 --- a/x-pack/plugins/fleet/server/services/epm/packages/get.ts +++ b/x-pack/plugins/fleet/server/services/epm/packages/get.ts @@ -5,17 +5,21 @@ * 2.0. */ -import { SavedObjectsClientContract, SavedObjectsFindOptions } from 'src/core/server'; +import type { SavedObjectsClientContract, SavedObjectsFindOptions } from 'src/core/server'; import { isPackageLimited, installationStatuses, - PackageUsageStats, - PackagePolicySOAttributes, PACKAGE_POLICY_SAVED_OBJECT_TYPE, } from '../../../../common'; +import type { PackageUsageStats, PackagePolicySOAttributes } from '../../../../common'; import { PACKAGES_SAVED_OBJECT_TYPE } from '../../../constants'; -import { ArchivePackage, RegistryPackage, EpmPackageAdditions } from '../../../../common/types'; -import { Installation, PackageInfo, KibanaAssetType } from '../../../types'; +import type { + ArchivePackage, + RegistryPackage, + EpmPackageAdditions, +} from '../../../../common/types'; +import { KibanaAssetType } from '../../../types'; +import type { Installation, PackageInfo } from '../../../types'; import { IngestManagerError } from '../../../errors'; import * as Registry from '../registry'; import { createInstallableFrom, isRequiredPackage } from './index'; diff --git a/x-pack/plugins/fleet/server/services/epm/packages/get_install_type.test.ts b/x-pack/plugins/fleet/server/services/epm/packages/get_install_type.test.ts index f7bc2ce1b07b48..ae29a1c7956cf4 100644 --- a/x-pack/plugins/fleet/server/services/epm/packages/get_install_type.test.ts +++ b/x-pack/plugins/fleet/server/services/epm/packages/get_install_type.test.ts @@ -5,9 +5,10 @@ * 2.0. */ -import { SavedObject } from 'src/core/server'; -import { ElasticsearchAssetType, Installation, KibanaSavedObjectType } from '../../../types'; import { getInstallType } from './install'; +import type { SavedObject } from 'src/core/server'; +import { ElasticsearchAssetType, KibanaSavedObjectType } from '../../../types'; +import type { Installation } from '../../../types'; const mockInstallation: SavedObject = { id: 'test-pkg', diff --git a/x-pack/plugins/fleet/server/services/epm/packages/index.ts b/x-pack/plugins/fleet/server/services/epm/packages/index.ts index b03d260e8e0804..2dc845f94991e2 100644 --- a/x-pack/plugins/fleet/server/services/epm/packages/index.ts +++ b/x-pack/plugins/fleet/server/services/epm/packages/index.ts @@ -5,14 +5,11 @@ * 2.0. */ -import { SavedObject } from 'src/core/server'; -import { - RequiredPackage, - requiredPackages, - ValueOf, - installationStatuses, -} from '../../../../common'; -import { AssetType, Installable, Installation, KibanaAssetType } from '../../../types'; +import type { SavedObject } from 'src/core/server'; +import { requiredPackages, installationStatuses } from '../../../../common'; +import type { RequiredPackage, ValueOf } from '../../../../common'; +import { KibanaAssetType } from '../../../types'; +import type { AssetType, Installable, Installation } from '../../../types'; export { bulkInstallPackages, isBulkInstallError } from './bulk_install_packages'; export { diff --git a/x-pack/plugins/fleet/server/services/epm/packages/install.ts b/x-pack/plugins/fleet/server/services/epm/packages/install.ts index ac3c0f3952127c..96b4b63312eddb 100644 --- a/x-pack/plugins/fleet/server/services/epm/packages/install.ts +++ b/x-pack/plugins/fleet/server/services/epm/packages/install.ts @@ -8,35 +8,32 @@ import semverGt from 'semver/functions/gt'; import semverLt from 'semver/functions/lt'; import Boom from '@hapi/boom'; -import { UnwrapPromise } from '@kbn/utility-types'; -import { SavedObject, SavedObjectsClientContract } from 'src/core/server'; +import type { UnwrapPromise } from '@kbn/utility-types'; +import type { SavedObject, SavedObjectsClientContract } from 'src/core/server'; import { generateESIndexPatterns } from '../elasticsearch/template/template'; -import { isRequiredPackage } from './index'; import { - BulkInstallPackageInfo, - InstallablePackage, - InstallSource, - defaultPackages, -} from '../../../../common'; + isRequiredPackage, + getInstallation, + getInstallationObject, + bulkInstallPackages, + isBulkInstallError, +} from './index'; +import { defaultPackages } from '../../../../common'; +import type { BulkInstallPackageInfo, InstallablePackage, InstallSource } from '../../../../common'; import { PACKAGES_SAVED_OBJECT_TYPE, MAX_TIME_COMPLETE_INSTALL } from '../../../constants'; -import { +import { KibanaAssetType } from '../../../types'; +import type { AssetReference, Installation, CallESAsCurrentUser, AssetType, EsAssetReference, InstallType, - KibanaAssetType, } from '../../../types'; import * as Registry from '../registry'; import { setPackageInfo, parseAndVerifyArchiveEntries, unpackBufferToCache } from '../archive'; -import { - getInstallation, - getInstallationObject, - bulkInstallPackages, - isBulkInstallError, -} from './index'; -import { toAssetReference, ArchiveAsset } from '../kibana/assets/install'; +import { toAssetReference } from '../kibana/assets/install'; +import type { ArchiveAsset } from '../kibana/assets/install'; import { removeInstallation } from './remove'; import { IngestManagerError, diff --git a/x-pack/plugins/fleet/server/services/epm/packages/remove.ts b/x-pack/plugins/fleet/server/services/epm/packages/remove.ts index 78471f70adc3ca..4d05daaf82500f 100644 --- a/x-pack/plugins/fleet/server/services/epm/packages/remove.ts +++ b/x-pack/plugins/fleet/server/services/epm/packages/remove.ts @@ -5,14 +5,14 @@ * 2.0. */ -import { SavedObjectsClientContract } from 'src/core/server'; +import type { SavedObjectsClientContract } from 'src/core/server'; import Boom from '@hapi/boom'; import { PACKAGE_POLICY_SAVED_OBJECT_TYPE, PACKAGES_SAVED_OBJECT_TYPE } from '../../../constants'; -import { +import { ElasticsearchAssetType } from '../../../types'; +import type { AssetReference, AssetType, CallESAsCurrentUser, - ElasticsearchAssetType, EsAssetReference, KibanaAssetReference, Installation, diff --git a/x-pack/plugins/fleet/server/services/epm/registry/index.test.ts b/x-pack/plugins/fleet/server/services/epm/registry/index.test.ts index ca476b4ee20337..e7ac5a0ce912ef 100644 --- a/x-pack/plugins/fleet/server/services/epm/registry/index.test.ts +++ b/x-pack/plugins/fleet/server/services/epm/registry/index.test.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { AssetParts } from '../../../types'; +import type { AssetParts } from '../../../types'; import { getBufferExtractor, getPathParts, untarBuffer, unzipBuffer } from '../archive'; import { splitPkgKey } from './index'; diff --git a/x-pack/plugins/fleet/server/services/epm/registry/index.ts b/x-pack/plugins/fleet/server/services/epm/registry/index.ts index bee979a58076bc..8c5e2c9530b61c 100644 --- a/x-pack/plugins/fleet/server/services/epm/registry/index.ts +++ b/x-pack/plugins/fleet/server/services/epm/registry/index.ts @@ -9,12 +9,12 @@ import mime from 'mime-types'; import semverValid from 'semver/functions/valid'; import { Response } from 'node-fetch'; import { URL } from 'url'; -import { +import { KibanaAssetType } from '../../../types'; +import type { AssetsGroupedByServiceByType, CategoryId, CategorySummaryList, InstallSource, - KibanaAssetType, RegistryPackage, RegistrySearchResults, RegistrySearchResult, diff --git a/x-pack/plugins/fleet/server/services/epm/registry/proxy.ts b/x-pack/plugins/fleet/server/services/epm/registry/proxy.ts index 655e1318d51340..0be25da2bca235 100644 --- a/x-pack/plugins/fleet/server/services/epm/registry/proxy.ts +++ b/x-pack/plugins/fleet/server/services/epm/registry/proxy.ts @@ -6,11 +6,10 @@ */ import HttpProxyAgent from 'http-proxy-agent'; -import HttpsProxyAgent, { - HttpsProxyAgent as IHttpsProxyAgent, - HttpsProxyAgentOptions, -} from 'https-proxy-agent'; +import HttpsProxyAgent, { HttpsProxyAgent as IHttpsProxyAgent } from 'https-proxy-agent'; +import type { HttpsProxyAgentOptions } from 'https-proxy-agent'; import { appContextService } from '../../index'; + export interface RegistryProxySettings { proxyUrl: string; proxyHeaders?: Record; diff --git a/x-pack/plugins/fleet/server/services/epm/registry/requests.ts b/x-pack/plugins/fleet/server/services/epm/registry/requests.ts index 8612e1d50d7e8e..1b4abbc7e9b710 100644 --- a/x-pack/plugins/fleet/server/services/epm/registry/requests.ts +++ b/x-pack/plugins/fleet/server/services/epm/registry/requests.ts @@ -5,7 +5,8 @@ * 2.0. */ -import fetch, { FetchError, Response, RequestInit } from 'node-fetch'; +import fetch, { FetchError, Response } from 'node-fetch'; +import type { RequestInit } from 'node-fetch'; import pRetry from 'p-retry'; import { streamToString } from '../streams'; import { appContextService } from '../../app_context'; diff --git a/x-pack/plugins/fleet/server/services/es_index_pattern.ts b/x-pack/plugins/fleet/server/services/es_index_pattern.ts index 0d5a4c888e93fb..015fb91a9660ef 100644 --- a/x-pack/plugins/fleet/server/services/es_index_pattern.ts +++ b/x-pack/plugins/fleet/server/services/es_index_pattern.ts @@ -5,9 +5,9 @@ * 2.0. */ -import { SavedObjectsClientContract } from 'kibana/server'; +import type { SavedObjectsClientContract } from 'kibana/server'; import { getInstallation } from './epm/packages'; -import { ESIndexPatternService } from '../../server'; +import type { ESIndexPatternService } from '../../server'; export class ESIndexPatternSavedObjectService implements ESIndexPatternService { public async getESIndexPattern( diff --git a/x-pack/plugins/fleet/server/services/fleet_server/elastic_index.ts b/x-pack/plugins/fleet/server/services/fleet_server/elastic_index.ts index 4b85f753740e3f..9722c28d96d235 100644 --- a/x-pack/plugins/fleet/server/services/fleet_server/elastic_index.ts +++ b/x-pack/plugins/fleet/server/services/fleet_server/elastic_index.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { ElasticsearchClient } from 'kibana/server'; +import type { ElasticsearchClient } from 'kibana/server'; import hash from 'object-hash'; import { FLEET_SERVER_INDICES, FLEET_SERVER_INDICES_VERSION } from '../../../common'; diff --git a/x-pack/plugins/fleet/server/services/fleet_server/saved_object_migrations.ts b/x-pack/plugins/fleet/server/services/fleet_server/saved_object_migrations.ts index 84e6b06e59844f..d160925544adf9 100644 --- a/x-pack/plugins/fleet/server/services/fleet_server/saved_object_migrations.ts +++ b/x-pack/plugins/fleet/server/services/fleet_server/saved_object_migrations.ts @@ -12,15 +12,16 @@ import { ENROLLMENT_API_KEYS_SAVED_OBJECT_TYPE, AGENT_POLICY_INDEX, AGENTS_INDEX, - FleetServerEnrollmentAPIKey, AGENT_SAVED_OBJECT_TYPE, + SO_SEARCH_LIMIT, +} from '../../../common'; +import type { + FleetServerEnrollmentAPIKey, AgentSOAttributes, FleetServerAgent, - SO_SEARCH_LIMIT, } from '../../../common'; import { listEnrollmentApiKeys, getEnrollmentAPIKey } from '../api_keys/enrollment_api_key_so'; import { appContextService } from '../app_context'; - import { isAgentsSetup } from '../agents'; import { agentPolicyService } from '../agent_policy'; diff --git a/x-pack/plugins/fleet/server/services/index.ts b/x-pack/plugins/fleet/server/services/index.ts index 77ce882275b6bf..3f28a3f987a8e2 100644 --- a/x-pack/plugins/fleet/server/services/index.ts +++ b/x-pack/plugins/fleet/server/services/index.ts @@ -5,13 +5,14 @@ * 2.0. */ -import { ElasticsearchClient, SavedObjectsClientContract, KibanaRequest } from 'kibana/server'; -import { AgentStatus, Agent, EsAssetReference } from '../types'; -import * as settingsService from './settings'; +import { KibanaRequest } from 'kibana/server'; +import type { ElasticsearchClient, SavedObjectsClientContract } from 'kibana/server'; +import type { AgentStatus, Agent, EsAssetReference } from '../types'; import { getAgent, listAgents } from './agents'; -export { ESIndexPatternSavedObjectService } from './es_index_pattern'; import { agentPolicyService } from './agent_policy'; +import * as settingsService from './settings'; +export { ESIndexPatternSavedObjectService } from './es_index_pattern'; export { getRegistryUrl } from './epm/registry/registry_url'; /** diff --git a/x-pack/plugins/fleet/server/services/install_script/install_templates/linux.ts b/x-pack/plugins/fleet/server/services/install_script/install_templates/linux.ts index dc04d099c4eb7a..4e31193efc0e60 100644 --- a/x-pack/plugins/fleet/server/services/install_script/install_templates/linux.ts +++ b/x-pack/plugins/fleet/server/services/install_script/install_templates/linux.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { InstallTemplateFunction } from './types'; +import type { InstallTemplateFunction } from './types'; export const linuxInstallTemplate: InstallTemplateFunction = (variables) => { const artifact = `elastic-agent-${variables.kibanaVersion}-linux-x86_64`; diff --git a/x-pack/plugins/fleet/server/services/install_script/install_templates/macos.ts b/x-pack/plugins/fleet/server/services/install_script/install_templates/macos.ts index 14043fe8647fea..abe52f64d0e5c1 100644 --- a/x-pack/plugins/fleet/server/services/install_script/install_templates/macos.ts +++ b/x-pack/plugins/fleet/server/services/install_script/install_templates/macos.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { InstallTemplateFunction } from './types'; +import type { InstallTemplateFunction } from './types'; export const macosInstallTemplate: InstallTemplateFunction = (variables) => { const artifact = `elastic-agent-${variables.kibanaVersion}-darwin-x86_64`; diff --git a/x-pack/plugins/fleet/server/services/output.ts b/x-pack/plugins/fleet/server/services/output.ts index c3e453bc0e24fd..2301570c54cd2e 100644 --- a/x-pack/plugins/fleet/server/services/output.ts +++ b/x-pack/plugins/fleet/server/services/output.ts @@ -5,8 +5,8 @@ * 2.0. */ -import { SavedObjectsClientContract } from 'src/core/server'; -import { NewOutput, Output, OutputSOAttributes } from '../types'; +import type { SavedObjectsClientContract } from 'src/core/server'; +import type { NewOutput, Output, OutputSOAttributes } from '../types'; import { DEFAULT_OUTPUT, OUTPUT_SAVED_OBJECT_TYPE } from '../constants'; import { appContextService } from './app_context'; import { decodeCloudId } from '../../common'; diff --git a/x-pack/plugins/fleet/server/services/package_policy.test.ts b/x-pack/plugins/fleet/server/services/package_policy.test.ts index 604592a0a8d878..e8991f2d66647f 100644 --- a/x-pack/plugins/fleet/server/services/package_policy.test.ts +++ b/x-pack/plugins/fleet/server/services/package_policy.test.ts @@ -5,14 +5,17 @@ * 2.0. */ -import { elasticsearchServiceMock, savedObjectsClientMock } from 'src/core/server/mocks'; +import { + elasticsearchServiceMock, + savedObjectsClientMock, + httpServerMock, +} from 'src/core/server/mocks'; import { createPackagePolicyMock } from '../../common/mocks'; import { packagePolicyService } from './package_policy'; -import { PackageInfo, PackagePolicySOAttributes } from '../types'; -import { SavedObjectsUpdateResponse } from 'src/core/server'; -import { httpServerMock } from 'src/core/server/mocks'; +import type { PackageInfo, PackagePolicySOAttributes } from '../types'; +import type { SavedObjectsUpdateResponse } from 'src/core/server'; import { KibanaRequest } from 'kibana/server'; -import { ExternalCallback } from '..'; +import type { ExternalCallback } from '..'; import { appContextService } from './app_context'; import { createAppContextStartContractMock, xpackMocks } from '../mocks'; diff --git a/x-pack/plugins/fleet/server/services/package_policy.ts b/x-pack/plugins/fleet/server/services/package_policy.ts index 335cd7c956faf9..3a350ded2d7ed1 100644 --- a/x-pack/plugins/fleet/server/services/package_policy.ts +++ b/x-pack/plugins/fleet/server/services/package_policy.ts @@ -5,15 +5,20 @@ * 2.0. */ -import { +import { KibanaRequest } from 'src/core/server'; +import type { ElasticsearchClient, - KibanaRequest, RequestHandlerContext, SavedObjectsClientContract, } from 'src/core/server'; import uuid from 'uuid'; -import { AuthenticatedUser } from '../../../security/server'; +import type { AuthenticatedUser } from '../../../security/server'; import { + packageToPackagePolicy, + isPackageLimited, + doesAgentPolicyAlreadyIncludePackage, +} from '../../common'; +import type { DeletePackagePoliciesResponse, PackagePolicyInput, NewPackagePolicyInput, @@ -21,21 +26,17 @@ import { PackageInfo, ListWithKuery, ListResult, - packageToPackagePolicy, - isPackageLimited, - doesAgentPolicyAlreadyIncludePackage, } from '../../common'; import { PACKAGE_POLICY_SAVED_OBJECT_TYPE } from '../constants'; import { IngestManagerError, ingestErrorToResponseOptions } from '../errors'; -import { +import { NewPackagePolicySchema, UpdatePackagePolicySchema } from '../types'; +import type { NewPackagePolicy, UpdatePackagePolicy, PackagePolicy, PackagePolicySOAttributes, RegistryPackage, CallESAsCurrentUser, - NewPackagePolicySchema, - UpdatePackagePolicySchema, } from '../types'; import { agentPolicyService } from './agent_policy'; import { outputService } from './output'; @@ -45,7 +46,7 @@ import { getAssetsData } from './epm/packages/assets'; import { compileTemplate } from './epm/agent/agent'; import { normalizeKuery } from './saved_object'; import { appContextService } from '.'; -import { ExternalCallback } from '..'; +import type { ExternalCallback } from '..'; const SAVED_OBJECT_TYPE = PACKAGE_POLICY_SAVED_OBJECT_TYPE; diff --git a/x-pack/plugins/fleet/server/services/saved_object.ts b/x-pack/plugins/fleet/server/services/saved_object.ts index e6a792e4179f7d..da416fa812cc49 100644 --- a/x-pack/plugins/fleet/server/services/saved_object.ts +++ b/x-pack/plugins/fleet/server/services/saved_object.ts @@ -5,9 +5,9 @@ * 2.0. */ -import { SavedObjectsClientContract, SavedObjectsFindResponse } from 'src/core/server'; +import type { SavedObjectsClientContract, SavedObjectsFindResponse } from 'src/core/server'; import { SO_SEARCH_LIMIT } from '../constants'; -import { ListWithKuery } from '../types'; +import type { ListWithKuery } from '../types'; /** * Escape a value with double quote to use with saved object search diff --git a/x-pack/plugins/fleet/server/services/settings.ts b/x-pack/plugins/fleet/server/services/settings.ts index c58d3de9db1a78..01454c6217c05c 100644 --- a/x-pack/plugins/fleet/server/services/settings.ts +++ b/x-pack/plugins/fleet/server/services/settings.ts @@ -6,15 +6,10 @@ */ import Boom from '@hapi/boom'; -import { SavedObjectsClientContract } from 'kibana/server'; +import type { SavedObjectsClientContract } from 'kibana/server'; import url from 'url'; -import { - GLOBAL_SETTINGS_SAVED_OBJECT_TYPE, - SettingsSOAttributes, - Settings, - decodeCloudId, - BaseSettings, -} from '../../common'; +import { GLOBAL_SETTINGS_SAVED_OBJECT_TYPE, decodeCloudId } from '../../common'; +import type { SettingsSOAttributes, Settings, BaseSettings } from '../../common'; import { appContextService } from './app_context'; export async function getSettings(soClient: SavedObjectsClientContract): Promise { diff --git a/x-pack/plugins/fleet/server/services/setup.ts b/x-pack/plugins/fleet/server/services/setup.ts index 2a3166e9dc7296..b90f223629b60d 100644 --- a/x-pack/plugins/fleet/server/services/setup.ts +++ b/x-pack/plugins/fleet/server/services/setup.ts @@ -6,8 +6,8 @@ */ import uuid from 'uuid'; -import { ElasticsearchClient, SavedObjectsClientContract } from 'src/core/server'; -import { CallESAsCurrentUser } from '../types'; +import type { ElasticsearchClient, SavedObjectsClientContract } from 'src/core/server'; +import type { CallESAsCurrentUser } from '../types'; import { agentPolicyService } from './agent_policy'; import { outputService } from './output'; import { @@ -17,13 +17,10 @@ import { } from './epm/packages/install'; import { packageToPackagePolicy, - PackagePolicy, - AgentPolicy, - Installation, - Output, DEFAULT_AGENT_POLICIES_PACKAGES, FLEET_SERVER_PACKAGE, } from '../../common'; +import type { PackagePolicy, AgentPolicy, Installation, Output } from '../../common'; import { SO_SEARCH_LIMIT } from '../constants'; import { getPackageInfo } from './epm/packages'; import { packagePolicyService } from './package_policy'; diff --git a/x-pack/plugins/fleet/server/types/rest_spec/common.ts b/x-pack/plugins/fleet/server/types/rest_spec/common.ts index 78af66dd50f41b..2d12bd5d7c9874 100644 --- a/x-pack/plugins/fleet/server/types/rest_spec/common.ts +++ b/x-pack/plugins/fleet/server/types/rest_spec/common.ts @@ -5,7 +5,8 @@ * 2.0. */ -import { schema, TypeOf } from '@kbn/config-schema'; +import { schema } from '@kbn/config-schema'; +import type { TypeOf } from '@kbn/config-schema'; export const ListWithKuerySchema = schema.object({ page: schema.maybe(schema.number({ defaultValue: 1 })), diff --git a/x-pack/plugins/lens/public/pie_visualization/render_function.tsx b/x-pack/plugins/lens/public/pie_visualization/render_function.tsx index 404ac99db9df78..4d6eac6a87e489 100644 --- a/x-pack/plugins/lens/public/pie_visualization/render_function.tsx +++ b/x-pack/plugins/lens/public/pie_visualization/render_function.tsx @@ -172,7 +172,6 @@ export function PieComponent( fontFamily: chartTheme.barSeriesStyle?.displayValue?.fontFamily, outerSizeRatio: 1, specialFirstInnermostSector: true, - clockwiseSectors: false, minFontSize: 10, maxFontSize: 16, // Labels are added outside the outer ring when the slice is too small diff --git a/x-pack/plugins/maps/common/descriptor_types/source_descriptor_types.ts b/x-pack/plugins/maps/common/descriptor_types/source_descriptor_types.ts index c825f148cd0ce5..7b757aa9cf10b1 100644 --- a/x-pack/plugins/maps/common/descriptor_types/source_descriptor_types.ts +++ b/x-pack/plugins/maps/common/descriptor_types/source_descriptor_types.ts @@ -174,6 +174,8 @@ export type InlineFieldDescriptor = { export type GeojsonFileSourceDescriptor = { __fields?: InlineFieldDescriptor[]; __featureCollection: FeatureCollection; + areResultsTrimmed: boolean; + tooltipContent: string | null; name: string; type: string; }; diff --git a/x-pack/plugins/maps/common/elasticsearch_util/elasticsearch_geo_utils.d.ts b/x-pack/plugins/maps/common/elasticsearch_util/elasticsearch_geo_utils.d.ts index d7d76ab8acd372..2a3741146d454e 100644 --- a/x-pack/plugins/maps/common/elasticsearch_util/elasticsearch_geo_utils.d.ts +++ b/x-pack/plugins/maps/common/elasticsearch_util/elasticsearch_geo_utils.d.ts @@ -47,8 +47,7 @@ export interface ESPolygonFilter { export function createExtentFilter( mapExtent: MapExtent, - geoFieldName: string, - geoFieldType: ES_GEO_FIELD_TYPE + geoFieldName: string ): ESPolygonFilter | ESGeoBoundingBoxFilter; export function makeESBbox({ maxLat, maxLon, minLat, minLon }: MapExtent): ESBBox; diff --git a/x-pack/plugins/maps/common/elasticsearch_util/elasticsearch_geo_utils.js b/x-pack/plugins/maps/common/elasticsearch_util/elasticsearch_geo_utils.js index c6b1c712925f01..47de8850c0e969 100644 --- a/x-pack/plugins/maps/common/elasticsearch_util/elasticsearch_geo_utils.js +++ b/x-pack/plugins/maps/common/elasticsearch_util/elasticsearch_geo_utils.js @@ -280,8 +280,8 @@ export function makeESBbox({ maxLat, maxLon, minLat, minLon }) { return esBbox; } -function createGeoBoundBoxFilter({ maxLat, maxLon, minLat, minLon }, geoFieldName) { - const boundingBox = makeESBbox({ maxLat, maxLon, minLat, minLon }); +export function createExtentFilter(mapExtent, geoFieldName) { + const boundingBox = makeESBbox(mapExtent); return { geo_bounding_box: { [geoFieldName]: boundingBox, @@ -289,28 +289,6 @@ function createGeoBoundBoxFilter({ maxLat, maxLon, minLat, minLon }, geoFieldNam }; } -export function createExtentFilter(mapExtent, geoFieldName, geoFieldType) { - ensureGeoField(geoFieldType); - - // Extent filters are used to dynamically filter data for the current map view port. - // Continue to use geo_bounding_box queries for extent filters - // 1) geo_bounding_box queries are faster than polygon queries - // 2) geo_shape benefits of pre-indexed shapes and - // compatability across multi-indices with geo_point and geo_shape do not apply to this use case. - if (geoFieldType === ES_GEO_FIELD_TYPE.GEO_POINT) { - return createGeoBoundBoxFilter(mapExtent, geoFieldName); - } - - return { - geo_shape: { - [geoFieldName]: { - shape: formatEnvelopeAsPolygon(mapExtent), - relation: ES_SPATIAL_RELATIONS.INTERSECTS, - }, - }, - }; -} - export function createSpatialFilterWithGeometry({ preIndexedShape, geometry, diff --git a/x-pack/plugins/maps/common/elasticsearch_util/elasticsearch_geo_utils.test.js b/x-pack/plugins/maps/common/elasticsearch_util/elasticsearch_geo_utils.test.js index aed9ccbb96c3bc..9983bb9b845882 100644 --- a/x-pack/plugins/maps/common/elasticsearch_util/elasticsearch_geo_utils.test.js +++ b/x-pack/plugins/maps/common/elasticsearch_util/elasticsearch_geo_utils.test.js @@ -389,143 +389,99 @@ describe('geoShapeToGeometry', () => { }); describe('createExtentFilter', () => { - describe('geo_point field', () => { - it('should return elasticsearch geo_bounding_box filter for geo_point field', () => { - const mapExtent = { - maxLat: 39, - maxLon: -83, - minLat: 35, - minLon: -89, - }; - const filter = createExtentFilter(mapExtent, geoFieldName, 'geo_point'); - expect(filter).toEqual({ - geo_bounding_box: { - location: { - top_left: [-89, 39], - bottom_right: [-83, 35], - }, - }, - }); - }); - - it('should clamp longitudes to -180 to 180 and latitudes to -90 to 90', () => { - const mapExtent = { - maxLat: 120, - maxLon: 200, - minLat: -100, - minLon: -190, - }; - const filter = createExtentFilter(mapExtent, geoFieldName, 'geo_point'); - expect(filter).toEqual({ - geo_bounding_box: { - location: { - top_left: [-180, 89], - bottom_right: [180, -89], - }, + it('should return elasticsearch geo_bounding_box filter', () => { + const mapExtent = { + maxLat: 39, + maxLon: -83, + minLat: 35, + minLon: -89, + }; + const filter = createExtentFilter(mapExtent, geoFieldName); + expect(filter).toEqual({ + geo_bounding_box: { + location: { + top_left: [-89, 39], + bottom_right: [-83, 35], }, - }); + }, }); + }); - it('should make left longitude greater then right longitude when area crosses 180 meridian east to west', () => { - const mapExtent = { - maxLat: 39, - maxLon: 200, - minLat: 35, - minLon: 100, - }; - const filter = createExtentFilter(mapExtent, geoFieldName, 'geo_point'); - const leftLon = filter.geo_bounding_box.location.top_left[0]; - const rightLon = filter.geo_bounding_box.location.bottom_right[0]; - expect(leftLon).toBeGreaterThan(rightLon); - expect(filter).toEqual({ - geo_bounding_box: { - location: { - top_left: [100, 39], - bottom_right: [-160, 35], - }, + it('should clamp longitudes to -180 to 180 and latitudes to -90 to 90', () => { + const mapExtent = { + maxLat: 120, + maxLon: 200, + minLat: -100, + minLon: -190, + }; + const filter = createExtentFilter(mapExtent, geoFieldName); + expect(filter).toEqual({ + geo_bounding_box: { + location: { + top_left: [-180, 89], + bottom_right: [180, -89], }, - }); + }, }); + }); - it('should make left longitude greater then right longitude when area crosses 180 meridian west to east', () => { - const mapExtent = { - maxLat: 39, - maxLon: -100, - minLat: 35, - minLon: -200, - }; - const filter = createExtentFilter(mapExtent, geoFieldName, 'geo_point'); - const leftLon = filter.geo_bounding_box.location.top_left[0]; - const rightLon = filter.geo_bounding_box.location.bottom_right[0]; - expect(leftLon).toBeGreaterThan(rightLon); - expect(filter).toEqual({ - geo_bounding_box: { - location: { - top_left: [160, 39], - bottom_right: [-100, 35], - }, + it('should make left longitude greater then right longitude when area crosses 180 meridian east to west', () => { + const mapExtent = { + maxLat: 39, + maxLon: 200, + minLat: 35, + minLon: 100, + }; + const filter = createExtentFilter(mapExtent, geoFieldName); + const leftLon = filter.geo_bounding_box.location.top_left[0]; + const rightLon = filter.geo_bounding_box.location.bottom_right[0]; + expect(leftLon).toBeGreaterThan(rightLon); + expect(filter).toEqual({ + geo_bounding_box: { + location: { + top_left: [100, 39], + bottom_right: [-160, 35], }, - }); + }, }); }); - describe('geo_shape field', () => { - it('should return elasticsearch geo_shape filter', () => { - const mapExtent = { - maxLat: 39, - maxLon: -83, - minLat: 35, - minLon: -89, - }; - const filter = createExtentFilter(mapExtent, geoFieldName, 'geo_shape'); - expect(filter).toEqual({ - geo_shape: { - location: { - relation: 'INTERSECTS', - shape: { - coordinates: [ - [ - [-89, 39], - [-89, 35], - [-83, 35], - [-83, 39], - [-89, 39], - ], - ], - type: 'Polygon', - }, - }, + it('should make left longitude greater then right longitude when area crosses 180 meridian west to east', () => { + const mapExtent = { + maxLat: 39, + maxLon: -100, + minLat: 35, + minLon: -200, + }; + const filter = createExtentFilter(mapExtent, geoFieldName); + const leftLon = filter.geo_bounding_box.location.top_left[0]; + const rightLon = filter.geo_bounding_box.location.bottom_right[0]; + expect(leftLon).toBeGreaterThan(rightLon); + expect(filter).toEqual({ + geo_bounding_box: { + location: { + top_left: [160, 39], + bottom_right: [-100, 35], }, - }); + }, }); + }); - it('should clamp longitudes to -180 to 180 when lonitude wraps globe', () => { - const mapExtent = { - maxLat: 39, - maxLon: 209, - minLat: 35, - minLon: -191, - }; - const filter = createExtentFilter(mapExtent, geoFieldName, 'geo_shape'); - expect(filter).toEqual({ - geo_shape: { - location: { - relation: 'INTERSECTS', - shape: { - coordinates: [ - [ - [-180, 39], - [-180, 35], - [180, 35], - [180, 39], - [-180, 39], - ], - ], - type: 'Polygon', - }, - }, + it('should clamp longitudes to -180 to 180 when longitude wraps globe', () => { + const mapExtent = { + maxLat: 39, + maxLon: 209, + minLat: 35, + minLon: -191, + }; + const filter = createExtentFilter(mapExtent, geoFieldName); + expect(filter).toEqual({ + geo_bounding_box: { + location: { + top_left: [-180, 39], + bottom_right: [180, 35], }, - }); + }, }); }); }); diff --git a/x-pack/plugins/maps/public/classes/layers/file_upload_wizard/wizard.tsx b/x-pack/plugins/maps/public/classes/layers/file_upload_wizard/wizard.tsx index 138ed7a8cd0b14..30e3317a3a3cf3 100644 --- a/x-pack/plugins/maps/public/classes/layers/file_upload_wizard/wizard.tsx +++ b/x-pack/plugins/maps/public/classes/layers/file_upload_wizard/wizard.tsx @@ -5,6 +5,7 @@ * 2.0. */ +import { i18n } from '@kbn/i18n'; import React, { Component } from 'react'; import { FeatureCollection } from 'geojson'; import { EuiPanel } from '@elastic/eui'; @@ -70,7 +71,7 @@ export class ClientFileCreateSourceEditor extends Component { + _onFileUpload = (geojsonFile: FeatureCollection, name: string, previewCoverage: number) => { if (!this._isMounted) { return; } @@ -80,8 +81,19 @@ export class ClientFileCreateSourceEditor extends Component { try { const tileBounds: ESBounds = tileToESBbox(x, y, z); @@ -72,6 +78,7 @@ export async function getGridTile({ }, { sessionId: searchSessionId, + abortSignal, } ) .toPromise(); @@ -83,7 +90,9 @@ export async function getGridTile({ return createMvtTile(featureCollection, z, x, y); } catch (e) { - logger.warn(`Cannot generate grid-tile for ${z}/${x}/${y}: ${e.message}`); + if (!isAbortError(e)) { + logger.warn(`Cannot generate grid-tile for ${z}/${x}/${y}: ${e.message}`); + } return null; } } @@ -99,6 +108,7 @@ export async function getTile({ requestBody = {}, geoFieldType, searchSessionId, + abortSignal, }: { x: number; y: number; @@ -110,6 +120,7 @@ export async function getTile({ requestBody: any; geoFieldType: ES_GEO_FIELD_TYPE; searchSessionId?: string; + abortSignal: AbortSignal; }): Promise { let features: Feature[]; try { @@ -119,6 +130,7 @@ export async function getTile({ const searchOptions = { sessionId: searchSessionId, + abortSignal, }; const countResponse = await context @@ -214,7 +226,9 @@ export async function getTile({ return createMvtTile(featureCollection, z, x, y); } catch (e) { - logger.warn(`Cannot generate tile for ${z}/${x}/${y}: ${e.message}`); + if (!isAbortError(e)) { + logger.warn(`Cannot generate tile for ${z}/${x}/${y}: ${e.message}`); + } return null; } } diff --git a/x-pack/plugins/maps/server/mvt/mvt_routes.ts b/x-pack/plugins/maps/server/mvt/mvt_routes.ts index 3e161765795864..1423e4ef5a20d6 100644 --- a/x-pack/plugins/maps/server/mvt/mvt_routes.ts +++ b/x-pack/plugins/maps/server/mvt/mvt_routes.ts @@ -10,6 +10,8 @@ import { schema } from '@kbn/config-schema'; import { KibanaRequest, KibanaResponseFactory, Logger } from 'src/core/server'; import { IRouter } from 'src/core/server'; import type { DataRequestHandlerContext } from 'src/plugins/data/server'; +// @ts-ignore not typed +import { AbortController } from 'abortcontroller-polyfill/dist/cjs-ponyfill'; import { MVT_GETTILE_API_PATH, API_ROOT_PATH, @@ -50,6 +52,12 @@ export function initMVTRoutes({ response: KibanaResponseFactory ) => { const { query } = request; + + const abortController = new AbortController(); + request.events.aborted$.subscribe(() => { + abortController.abort(); + }); + const requestBodyDSL = rison.decode(query.requestBody as string); const tile = await getTile({ @@ -63,6 +71,7 @@ export function initMVTRoutes({ requestBody: requestBodyDSL as any, geoFieldType: query.geoFieldType as ES_GEO_FIELD_TYPE, searchSessionId: query.searchSessionId, + abortSignal: abortController.signal, }); return sendResponse(response, tile); @@ -92,6 +101,11 @@ export function initMVTRoutes({ response: KibanaResponseFactory ) => { const { query } = request; + const abortController = new AbortController(); + request.events.aborted$.subscribe(() => { + abortController.abort(); + }); + const requestBodyDSL = rison.decode(query.requestBody as string); const tile = await getGridTile({ @@ -106,6 +120,7 @@ export function initMVTRoutes({ requestType: query.requestType as RENDER_AS, geoFieldType: query.geoFieldType as ES_GEO_FIELD_TYPE, searchSessionId: query.searchSessionId, + abortSignal: abortController.signal, }); return sendResponse(response, tile); diff --git a/x-pack/plugins/ml/common/constants/settings.ts b/x-pack/plugins/ml/common/constants/settings.ts index 30e0e0a57afefc..5a9b18a232dcef 100644 --- a/x-pack/plugins/ml/common/constants/settings.ts +++ b/x-pack/plugins/ml/common/constants/settings.ts @@ -5,7 +5,6 @@ * 2.0. */ -export const FILE_DATA_VISUALIZER_MAX_FILE_SIZE = 'ml:fileDataVisualizerMaxFileSize'; export const ANOMALY_DETECTION_ENABLE_TIME_RANGE = 'ml:anomalyDetection:results:enableTimeDefaults'; export const ANOMALY_DETECTION_DEFAULT_TIME_RANGE = 'ml:anomalyDetection:results:timeDefaults'; diff --git a/x-pack/plugins/ml/public/application/app.tsx b/x-pack/plugins/ml/public/application/app.tsx index 107bbda23ecb90..5f72d49e4672e9 100644 --- a/x-pack/plugins/ml/public/application/app.tsx +++ b/x-pack/plugins/ml/public/application/app.tsx @@ -82,6 +82,7 @@ const App: FC = ({ coreStart, deps, appMountParams }) => { embeddable: deps.embeddable, maps: deps.maps, triggersActionsUi: deps.triggersActionsUi, + fileUpload: deps.fileUpload, ...coreStart, }; diff --git a/x-pack/plugins/ml/public/application/contexts/kibana/kibana_context.ts b/x-pack/plugins/ml/public/application/contexts/kibana/kibana_context.ts index 99d4b77547d9d0..3c86bb520600f3 100644 --- a/x-pack/plugins/ml/public/application/contexts/kibana/kibana_context.ts +++ b/x-pack/plugins/ml/public/application/contexts/kibana/kibana_context.ts @@ -18,6 +18,7 @@ import { MlServicesContext } from '../../app'; import { IStorageWrapper } from '../../../../../../../src/plugins/kibana_utils/public'; import type { EmbeddableStart } from '../../../../../../../src/plugins/embeddable/public'; import type { MapsStartApi } from '../../../../../maps/public'; +import type { FileUploadPluginStart } from '../../../../../file_upload/public'; import type { LensPublicStart } from '../../../../../lens/public'; import { TriggersAndActionsUIPublicPluginStart } from '../../../../../triggers_actions_ui/public'; @@ -30,6 +31,7 @@ interface StartPlugins { maps?: MapsStartApi; lens?: LensPublicStart; triggersActionsUi?: TriggersAndActionsUIPublicPluginStart; + fileUpload?: FileUploadPluginStart; } export type StartServices = CoreStart & StartPlugins & { diff --git a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/exploration_query_bar/exploration_query_bar.tsx b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/exploration_query_bar/exploration_query_bar.tsx index dd451958e26465..3ef6dbc292c080 100644 --- a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/exploration_query_bar/exploration_query_bar.tsx +++ b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/exploration_query_bar/exploration_query_bar.tsx @@ -60,7 +60,7 @@ export const ExplorationQueryBar: FC = ({ const searchChangeHandler = (q: Query) => setSearchInput(q); - const regex = useMemo(() => new RegExp(`${filters?.columnId}\s?:\s?(true|false)`, 'g'), [ + const regex = useMemo(() => new RegExp(`${filters?.columnId}\\s*:\\s*(true|false)`, 'g'), [ filters?.columnId, ]); diff --git a/x-pack/plugins/ml/public/application/datavisualizer/datavisualizer_selector.tsx b/x-pack/plugins/ml/public/application/datavisualizer/datavisualizer_selector.tsx index 79d17a7846b8c9..fc03ff475e05a6 100644 --- a/x-pack/plugins/ml/public/application/datavisualizer/datavisualizer_selector.tsx +++ b/x-pack/plugins/ml/public/application/datavisualizer/datavisualizer_selector.tsx @@ -25,9 +25,7 @@ import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n/react'; import { isFullLicense } from '../license'; import { useTimefilter, useMlKibana, useNavigateToPath } from '../contexts/kibana'; - import { NavigationMenu } from '../components/navigation_menu'; -import { getMaxBytesFormatted } from './file_based/components/utils'; import { HelpMenu } from '../components/help_menu'; function startTrialDescription() { @@ -58,8 +56,10 @@ export const DatavisualizerSelector: FC = () => { licenseManagement, http: { basePath }, docLinks, + fileUpload, }, } = useMlKibana(); + const helpLink = docLinks.links.ml.guide; const navigateToPath = useNavigateToPath(); @@ -68,7 +68,12 @@ export const DatavisualizerSelector: FC = () => { licenseManagement.enabled === true && isFullLicense() === false; - const maxFileSize = getMaxBytesFormatted(); + if (fileUpload === undefined) { + // eslint-disable-next-line no-console + console.error('File upload plugin not available'); + return null; + } + const maxFileSize = fileUpload.getMaxBytesFormatted(); return ( diff --git a/x-pack/plugins/ml/public/application/datavisualizer/file_based/components/about_panel/welcome_content.tsx b/x-pack/plugins/ml/public/application/datavisualizer/file_based/components/about_panel/welcome_content.tsx index f20319e6066813..2c441e42dea2fe 100644 --- a/x-pack/plugins/ml/public/application/datavisualizer/file_based/components/about_panel/welcome_content.tsx +++ b/x-pack/plugins/ml/public/application/datavisualizer/file_based/components/about_panel/welcome_content.tsx @@ -20,7 +20,8 @@ import { } from '@elastic/eui'; import { ExperimentalBadge } from '../experimental_badge'; -import { getMaxBytesFormatted } from '../utils'; + +import { useMlKibana } from '../../../../contexts/kibana'; export const WelcomeContent: FC = () => { const toolTipContent = i18n.translate( @@ -30,7 +31,16 @@ export const WelcomeContent: FC = () => { } ); - const maxFileSize = getMaxBytesFormatted(); + const { + services: { fileUpload }, + } = useMlKibana(); + + if (fileUpload === undefined) { + // eslint-disable-next-line no-console + console.error('File upload plugin not available'); + return null; + } + const maxFileSize = fileUpload.getMaxBytesFormatted(); return ( diff --git a/x-pack/plugins/ml/public/application/datavisualizer/file_based/components/file_datavisualizer_view/file_datavisualizer_view.js b/x-pack/plugins/ml/public/application/datavisualizer/file_based/components/file_datavisualizer_view/file_datavisualizer_view.js index 8b683a154519ef..90c2b2bf186393 100644 --- a/x-pack/plugins/ml/public/application/datavisualizer/file_based/components/file_datavisualizer_view/file_datavisualizer_view.js +++ b/x-pack/plugins/ml/public/application/datavisualizer/file_based/components/file_datavisualizer_view/file_datavisualizer_view.js @@ -22,12 +22,12 @@ import { ExplanationFlyout } from '../explanation_flyout'; import { ImportView } from '../import_view'; import { DEFAULT_LINES_TO_SAMPLE, - getMaxBytes, readFile, createUrlOverrides, processResults, hasImportPermission, } from '../utils'; +import { getFileUpload } from '../../../../util/dependency_cache'; import { MODE } from './constants'; @@ -60,7 +60,7 @@ export class FileDataVisualizerView extends Component { this.originalSettings = { linesToSample: DEFAULT_LINES_TO_SAMPLE, }; - this.maxFileUploadBytes = getMaxBytes(); + this.maxFileUploadBytes = getFileUpload().getMaxBytes(); } async componentDidMount() { diff --git a/x-pack/plugins/ml/public/application/datavisualizer/file_based/components/utils/index.ts b/x-pack/plugins/ml/public/application/datavisualizer/file_based/components/utils/index.ts index 41ea5582a7de5c..209f2ef5ad174f 100644 --- a/x-pack/plugins/ml/public/application/datavisualizer/file_based/components/utils/index.ts +++ b/x-pack/plugins/ml/public/application/datavisualizer/file_based/components/utils/index.ts @@ -10,7 +10,5 @@ export { hasImportPermission, processResults, readFile, - getMaxBytes, - getMaxBytesFormatted, DEFAULT_LINES_TO_SAMPLE, } from './utils'; diff --git a/x-pack/plugins/ml/public/application/datavisualizer/file_based/components/utils/utils.ts b/x-pack/plugins/ml/public/application/datavisualizer/file_based/components/utils/utils.ts index 2c1b02b53354aa..ebde771603fcfb 100644 --- a/x-pack/plugins/ml/public/application/datavisualizer/file_based/components/utils/utils.ts +++ b/x-pack/plugins/ml/public/application/datavisualizer/file_based/components/utils/utils.ts @@ -6,19 +6,9 @@ */ import { isEqual } from 'lodash'; -// @ts-ignore -import numeral from '@elastic/numeral'; import { ml } from '../../../../services/ml_api_service'; import { AnalysisResult, InputOverrides } from '../../../../../../common/types/file_datavisualizer'; -import { - MB, - MAX_FILE_SIZE, - MAX_FILE_SIZE_BYTES, - ABSOLUTE_MAX_FILE_SIZE_BYTES, - FILE_SIZE_DISPLAY_FORMAT, -} from '../../../../../../../file_upload/public'; -import { getUiSettings } from '../../../../util/dependency_cache'; -import { FILE_DATA_VISUALIZER_MAX_FILE_SIZE } from '../../../../../../common/constants/settings'; +import { MB } from '../../../../../../../file_upload/public'; export const DEFAULT_LINES_TO_SAMPLE = 1000; const UPLOAD_SIZE_MB = 5; @@ -66,20 +56,6 @@ export function readFile(file: File) { }); } -export function getMaxBytes() { - const maxFileSize = getUiSettings().get(FILE_DATA_VISUALIZER_MAX_FILE_SIZE, MAX_FILE_SIZE); - // @ts-ignore - const maxBytes = numeral(maxFileSize.toUpperCase()).value(); - if (maxBytes < MAX_FILE_SIZE_BYTES) { - return MAX_FILE_SIZE_BYTES; - } - return maxBytes <= ABSOLUTE_MAX_FILE_SIZE_BYTES ? maxBytes : ABSOLUTE_MAX_FILE_SIZE_BYTES; -} - -export function getMaxBytesFormatted() { - return numeral(getMaxBytes()).format(FILE_SIZE_DISPLAY_FORMAT); -} - export function createUrlOverrides(overrides: InputOverrides, originalSettings: InputOverrides) { const formattedOverrides: InputOverrides = {}; for (const o in overrideDefaults) { diff --git a/x-pack/plugins/ml/server/lib/register_settings.ts b/x-pack/plugins/ml/server/lib/register_settings.ts index 5f9107bd29815e..8f279114344e49 100644 --- a/x-pack/plugins/ml/server/lib/register_settings.ts +++ b/x-pack/plugins/ml/server/lib/register_settings.ts @@ -9,34 +9,14 @@ import { CoreSetup } from 'kibana/server'; import { i18n } from '@kbn/i18n'; import { schema } from '@kbn/config-schema'; import { - FILE_DATA_VISUALIZER_MAX_FILE_SIZE, ANOMALY_DETECTION_DEFAULT_TIME_RANGE, ANOMALY_DETECTION_ENABLE_TIME_RANGE, DEFAULT_AD_RESULTS_TIME_FILTER, DEFAULT_ENABLE_AD_RESULTS_TIME_FILTER, } from '../../common/constants/settings'; -import { MAX_FILE_SIZE } from '../../../file_upload/common'; export function registerKibanaSettings(coreSetup: CoreSetup) { coreSetup.uiSettings.register({ - [FILE_DATA_VISUALIZER_MAX_FILE_SIZE]: { - name: i18n.translate('xpack.ml.maxFileSizeSettingsName', { - defaultMessage: 'File Data Visualizer maximum file upload size', - }), - value: MAX_FILE_SIZE, - description: i18n.translate('xpack.ml.maxFileSizeSettingsDescription', { - defaultMessage: - 'Sets the file size limit when importing data in the File Data Visualizer. The highest supported value for this setting is 1GB.', - }), - category: ['machineLearning'], - schema: schema.string(), - validation: { - regexString: '\\d+[mMgG][bB]', - message: i18n.translate('xpack.ml.maxFileSizeSettingsError', { - defaultMessage: 'Should be a valid data size. e.g. 200MB, 1GB', - }), - }, - }, [ANOMALY_DETECTION_ENABLE_TIME_RANGE]: { name: i18n.translate('xpack.ml.advancedSettings.enableAnomalyDetectionDefaultTimeRangeName', { defaultMessage: 'Enable time filter defaults for anomaly detection results', diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/signal_rule_alert_type.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/signals/signal_rule_alert_type.ts index f81f4c5a2c537a..45d3986a1c115e 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/signal_rule_alert_type.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/signals/signal_rule_alert_type.ts @@ -12,6 +12,7 @@ import isEmpty from 'lodash/isEmpty'; import { chain, tryCatch } from 'fp-ts/lib/TaskEither'; import { flow } from 'fp-ts/lib/function'; +import { performance } from 'perf_hooks'; import { toError, toPromise } from '../../../../common/fp_utils'; import { @@ -50,6 +51,7 @@ import { hasTimestampFields, hasReadIndexPrivileges, getRuleRangeTuples, + makeFloatString, } from './utils'; import { signalParamsSchema } from './signal_params_schema'; import { siemRuleActionGroups } from './siem_rule_action_groups'; @@ -402,7 +404,11 @@ export const signalRulesAlertType = ({ lists: exceptionItems ?? [], }); - const { searchResult: thresholdResults, searchErrors } = await findThresholdSignals({ + const { + searchResult: thresholdResults, + searchErrors, + searchDuration: thresholdSearchDuration, + } = await findThresholdSignals({ inputIndexPattern: inputIndex, from, to, @@ -457,6 +463,7 @@ export const signalRulesAlertType = ({ createdSignalsCount: createdItemsCount, createdSignals: createdItems, bulkCreateTimes: bulkCreateDuration ? [bulkCreateDuration] : [], + searchAfterTimes: [thresholdSearchDuration], }), ]); } else if (isThreatMatchRule(type)) { @@ -590,10 +597,14 @@ export const signalRulesAlertType = ({ exceptionItems ?? [], eventCategoryOverride ); + const eqlSignalSearchStart = performance.now(); const response: EqlSignalSearchResponse = await services.callCluster( 'transport.request', request ); + const eqlSignalSearchEnd = performance.now(); + const eqlSearchDuration = makeFloatString(eqlSignalSearchEnd - eqlSignalSearchStart); + result.searchAfterTimes = [eqlSearchDuration]; let newSignals: WrappedSignalHit[] | undefined; if (response.hits.sequences !== undefined) { newSignals = response.hits.sequences.reduce( @@ -634,7 +645,6 @@ export const signalRulesAlertType = ({ const fromInMs = parseScheduleDates(`now-${interval}`)?.format('x'); const toInMs = parseScheduleDates('now')?.format('x'); - const resultsLink = getNotificationResultsLink({ from: fromInMs, to: toInMs, diff --git a/x-pack/plugins/security_solution/server/lib/telemetry/sender.ts b/x-pack/plugins/security_solution/server/lib/telemetry/sender.ts index 6ce42eabeca5ee..e169c036419c52 100644 --- a/x-pack/plugins/security_solution/server/lib/telemetry/sender.ts +++ b/x-pack/plugins/security_solution/server/lib/telemetry/sender.ts @@ -395,27 +395,45 @@ const allowlistEventFields: AllowlistFields = { Ext: { call_stack: true, start_address: true, + start_address_allocation_offset: true, + start_address_bytes: true, + start_address_bytes_disasm: true, + start_address_bytes_disasm_hash: true, start_address_details: { - address_offset: true, allocation_base: true, allocation_protection: true, allocation_size: true, allocation_type: true, - base_address: true, - bytes_start_address: true, - compressed_bytes: true, - dest_bytes: true, - dest_bytes_disasm: true, - dest_bytes_disasm_hash: true, - pe: { + bytes_address: true, + bytes_allocation_offset: true, + bytes_compressed: true, + mapped_pe: { Ext: { + code_signature: { + status: true, + subject_name: true, + trusted: true, + }, legal_copyright: true, product_version: true, + }, + company: true, + description: true, + file_version: true, + imphash: true, + original_file_name: true, + product: true, + }, + mapped_pe_path: true, + memory_pe: { + Ext: { code_signature: { status: true, subject_name: true, trusted: true, }, + legal_copyright: true, + product_version: true, }, company: true, description: true, @@ -424,7 +442,8 @@ const allowlistEventFields: AllowlistFields = { original_file_name: true, product: true, }, - pe_detected: true, + memory_pe_detected: true, + region_base: true, region_protection: true, region_size: true, region_state: true, diff --git a/x-pack/plugins/stack_alerts/public/alert_types/es_query/expression.test.tsx b/x-pack/plugins/stack_alerts/public/alert_types/es_query/expression.test.tsx index f475d97e2f39d3..51c2f0471d486f 100644 --- a/x-pack/plugins/stack_alerts/public/alert_types/es_query/expression.test.tsx +++ b/x-pack/plugins/stack_alerts/public/alert_types/es_query/expression.test.tsx @@ -116,6 +116,11 @@ describe('EsQueryAlertTypeExpression', () => { docLinks: { ELASTIC_WEBSITE_URL: '', DOC_LINK_VERSION: '', + links: { + query: { + queryDsl: 'query-dsl.html', + }, + }, }, }, }); diff --git a/x-pack/plugins/stack_alerts/public/alert_types/es_query/expression.tsx b/x-pack/plugins/stack_alerts/public/alert_types/es_query/expression.tsx index 37c64688ec49af..6adcada9b273af 100644 --- a/x-pack/plugins/stack_alerts/public/alert_types/es_query/expression.tsx +++ b/x-pack/plugins/stack_alerts/public/alert_types/es_query/expression.tsx @@ -287,10 +287,7 @@ export const EsQueryAlertTypeExpression: React.FunctionComponent< isInvalid={errors.esQuery.length > 0} error={errors.esQuery} helpText={ - + { defaultMessage: 'Alert on matches against an ES query.', }), iconClass: 'logoElastic', - documentationUrl(docLinks) { - return `${docLinks.ELASTIC_WEBSITE_URL}guide/en/kibana/${docLinks.DOC_LINK_VERSION}/alert-types.html#alert-type-es-query`; - }, + documentationUrl: (docLinks) => docLinks.links.alerting.esQuery, alertParamsExpression: lazy(() => import('./expression')), validate: validateExpression, defaultActionMessage: i18n.translate( diff --git a/x-pack/plugins/stack_alerts/public/alert_types/threshold/index.ts b/x-pack/plugins/stack_alerts/public/alert_types/threshold/index.ts index 95ecd121cf5a28..1b229bb4a9d0a1 100644 --- a/x-pack/plugins/stack_alerts/public/alert_types/threshold/index.ts +++ b/x-pack/plugins/stack_alerts/public/alert_types/threshold/index.ts @@ -18,9 +18,7 @@ export function getAlertType(): AlertTypeModel { defaultMessage: 'Alert when an aggregated query meets the threshold.', }), iconClass: 'alert', - documentationUrl(docLinks) { - return `${docLinks.ELASTIC_WEBSITE_URL}guide/en/kibana/${docLinks.DOC_LINK_VERSION}/alert-types.html#alert-type-index-threshold`; - }, + documentationUrl: (docLinks) => docLinks.links.alerting.indexThreshold, alertParamsExpression: lazy(() => import('./expression')), validate: validateExpression, defaultActionMessage: i18n.translate( diff --git a/x-pack/plugins/telemetry_collection_xpack/schema/xpack_plugins.json b/x-pack/plugins/telemetry_collection_xpack/schema/xpack_plugins.json index 527fb0fc040ae6..4a0ab555f8f40f 100644 --- a/x-pack/plugins/telemetry_collection_xpack/schema/xpack_plugins.json +++ b/x-pack/plugins/telemetry_collection_xpack/schema/xpack_plugins.json @@ -1667,6 +1667,19 @@ } } }, + "search-session": { + "properties": { + "transientCount": { + "type": "long" + }, + "persistedCount": { + "type": "long" + }, + "totalCount": { + "type": "long" + } + } + }, "discoverEnhanced": { "properties": { "exploreDataInChartActionEnabled": { @@ -3194,19 +3207,6 @@ } } }, - "search-session": { - "properties": { - "transientCount": { - "type": "long" - }, - "persistedCount": { - "type": "long" - }, - "totalCount": { - "type": "long" - } - } - }, "security_solution": { "properties": { "detections": { diff --git a/x-pack/plugins/translations/translations/ja-JP.json b/x-pack/plugins/translations/translations/ja-JP.json index dd628134c521e0..6e1f96e80b5737 100644 --- a/x-pack/plugins/translations/translations/ja-JP.json +++ b/x-pack/plugins/translations/translations/ja-JP.json @@ -7424,8 +7424,6 @@ "xpack.features.savedObjectsManagementFeatureName": "保存されたオブジェクトの管理", "xpack.features.visualizeFeatureName": "可視化", "xpack.fileUpload.enterIndexName": "インデックス名を入力", - "xpack.fileUpload.fileParser.noFeaturesDetected": "エラー、機能が検出されませんでした", - "xpack.fileUpload.fileParser.noFileProvided": "エラー、ファイルが提供されていません", "xpack.fileUpload.httpService.fetchError": "フェッチ実行エラー:{error}", "xpack.fileUpload.httpService.noUrl": "URLが指定されていません", "xpack.fileUpload.indexNameReqField": "インデックス名、必須フィールド", @@ -7441,29 +7439,11 @@ "xpack.fileUpload.indexSettings.indexNameContainsIllegalCharactersErrorMessage": "インデックス名に許可されていない文字が含まれています", "xpack.fileUpload.indexSettings.indexNameGuidelines": "インデックス名ガイドライン", "xpack.fileUpload.jsonImport.indexingResponse": "インデックス応答", - "xpack.fileUpload.jsonImport.indexingStatus": "インデックスステータス", "xpack.fileUpload.jsonImport.indexMgmtLink": "インデックス管理", "xpack.fileUpload.jsonImport.indexModsMsg": "次を使用すると、その他のインデックス修正を行うことができます。\n", "xpack.fileUpload.jsonImport.indexPatternResponse": "インデックスパターン応答", - "xpack.fileUpload.jsonIndexFilePicker.acceptableFileSize": "ファイルサイズ {fileSize} は最大ファイルサイズの{maxFileSize} を超えています", - "xpack.fileUpload.jsonIndexFilePicker.acceptableTypesError": "ファイルは使用可能なタイプのいずれかではありません。{types}", - "xpack.fileUpload.jsonIndexFilePicker.coordinateSystemAccepted": "座標は EPSG:4326 座標参照系でなければなりません。", - "xpack.fileUpload.jsonIndexFilePicker.fileParseError": "ファイル解析エラーが検出されました:{error}", - "xpack.fileUpload.jsonIndexFilePicker.filePicker": "ファイルをアップロード", - "xpack.fileUpload.jsonIndexFilePicker.filePickerLabel": "アップロードするファイルを選択", - "xpack.fileUpload.jsonIndexFilePicker.fileProcessingError": "ファイル処理エラー: {errorMessage}", - "xpack.fileUpload.jsonIndexFilePicker.formatsAccepted": "許可されているフォーマット:{acceptedFileTypeStringMessage}", - "xpack.fileUpload.jsonIndexFilePicker.maxSize": "最大サイズ:{maxFileSize}", - "xpack.fileUpload.jsonIndexFilePicker.noFileNameError": "ファイル名が指定されていません", - "xpack.fileUpload.jsonIndexFilePicker.parsingFile": "{featuresProcessed} 機能が解析されました...", - "xpack.fileUpload.jsonIndexFilePicker.unableParseFile": "ファイルをパースできません。{error}", - "xpack.fileUpload.jsonUploadAndParse.creatingIndexPattern": "インデックスパターンを作成中です", "xpack.fileUpload.jsonUploadAndParse.dataIndexingError": "データインデックスエラー", - "xpack.fileUpload.jsonUploadAndParse.dataIndexingStarted": "データインデックスが開始しました", - "xpack.fileUpload.jsonUploadAndParse.indexingComplete": "インデックス完了", - "xpack.fileUpload.jsonUploadAndParse.indexPatternComplete": "インデックスパターンの完了", "xpack.fileUpload.jsonUploadAndParse.indexPatternError": "インデックスパターンエラー", - "xpack.fileUpload.jsonUploadAndParse.writingToIndex": "インデックスに書き込み中", "xpack.fleet.agentBulkActions.agentsSelected": "{count, plural, other {#個のエージェント}}が選択されました", "xpack.fleet.agentBulkActions.clearSelection": "選択した項目をクリア", "xpack.fleet.agentBulkActions.reassignPolicy": "新しいポリシーに割り当てる", @@ -13417,9 +13397,6 @@ "xpack.ml.management.syncSavedObjectsFlyout.sync.error": "一部のジョブを同期できません。", "xpack.ml.management.syncSavedObjectsFlyout.sync.success": "{successCount} {successCount, plural, other {件のジョブ}}が同期されました", "xpack.ml.management.syncSavedObjectsFlyout.syncButton": "同期", - "xpack.ml.maxFileSizeSettingsDescription": "ファイルデータビジュアライザーでデータをインポートするときのファイルサイズ上限を設定します。この設定でサポートされている最大値は1 GBです。", - "xpack.ml.maxFileSizeSettingsError": "200 MB、1 GBなどの有効なデータサイズにしてください。", - "xpack.ml.maxFileSizeSettingsName": "ファイルデータビジュアライザーの最大ファイルアップロードサイズ", "xpack.ml.models.jobService.allOtherRequestsCancelledDescription": " 他のすべてのリクエストはキャンセルされました。", "xpack.ml.models.jobService.categorization.messages.failureToGetTokens": "フィールド値の例のサンプルをトークン化することができませんでした。{message}", "xpack.ml.models.jobService.categorization.messages.insufficientPrivileges": "権限が不十分なため、フィールド値の例のトークン化を実行できませんでした。そのため、フィールド値を確認し、カテゴリー分けジョブでの使用が適当かを確認することができません。", diff --git a/x-pack/plugins/translations/translations/zh-CN.json b/x-pack/plugins/translations/translations/zh-CN.json index c733f214be5547..b5a4b8a7085133 100644 --- a/x-pack/plugins/translations/translations/zh-CN.json +++ b/x-pack/plugins/translations/translations/zh-CN.json @@ -7443,8 +7443,6 @@ "xpack.features.savedObjectsManagementFeatureName": "已保存对象管理", "xpack.features.visualizeFeatureName": "Visualize", "xpack.fileUpload.enterIndexName": "输入索引名称", - "xpack.fileUpload.fileParser.noFeaturesDetected": "错误,未检测到特征", - "xpack.fileUpload.fileParser.noFileProvided": "错误,未提供任何文件", "xpack.fileUpload.httpService.fetchError": "执行提取时出错:{error}", "xpack.fileUpload.httpService.noUrl": "未提供 URL", "xpack.fileUpload.indexNameReqField": "索引名称,必填字段", @@ -7460,29 +7458,11 @@ "xpack.fileUpload.indexSettings.indexNameContainsIllegalCharactersErrorMessage": "索引名称包含非法字符。", "xpack.fileUpload.indexSettings.indexNameGuidelines": "索引名称指引", "xpack.fileUpload.jsonImport.indexingResponse": "索引响应", - "xpack.fileUpload.jsonImport.indexingStatus": "索引状态", "xpack.fileUpload.jsonImport.indexMgmtLink": "索引管理", "xpack.fileUpload.jsonImport.indexModsMsg": "要进一步做索引修改,可以使用\n", "xpack.fileUpload.jsonImport.indexPatternResponse": "索引模式响应", - "xpack.fileUpload.jsonIndexFilePicker.acceptableFileSize": "文件大小 {fileSize} 超过最大文件大小 {maxFileSize}", - "xpack.fileUpload.jsonIndexFilePicker.acceptableTypesError": "文件不是可接受类型之一:{types}", - "xpack.fileUpload.jsonIndexFilePicker.coordinateSystemAccepted": "坐标必须在 EPSG:4326 坐标参考系中。", - "xpack.fileUpload.jsonIndexFilePicker.fileParseError": "检测到文件解析错误:{error}", - "xpack.fileUpload.jsonIndexFilePicker.filePicker": "上传文件", - "xpack.fileUpload.jsonIndexFilePicker.filePickerLabel": "选择文件进行上传", - "xpack.fileUpload.jsonIndexFilePicker.fileProcessingError": "文件处理错误:{errorMessage}", - "xpack.fileUpload.jsonIndexFilePicker.formatsAccepted": "接受的格式:{acceptedFileTypeStringMessage}", - "xpack.fileUpload.jsonIndexFilePicker.maxSize": "最大大小:{maxFileSize}", - "xpack.fileUpload.jsonIndexFilePicker.noFileNameError": "未提供任何文件名称", - "xpack.fileUpload.jsonIndexFilePicker.parsingFile": "已处理 {featuresProcessed} 个特征......", - "xpack.fileUpload.jsonIndexFilePicker.unableParseFile": "无法解析文件:{error}", - "xpack.fileUpload.jsonUploadAndParse.creatingIndexPattern": "正在创建索引模式", "xpack.fileUpload.jsonUploadAndParse.dataIndexingError": "数据索引错误", - "xpack.fileUpload.jsonUploadAndParse.dataIndexingStarted": "数据索引已启动", - "xpack.fileUpload.jsonUploadAndParse.indexingComplete": "索引完成", - "xpack.fileUpload.jsonUploadAndParse.indexPatternComplete": "索引模式完成", "xpack.fileUpload.jsonUploadAndParse.indexPatternError": "索引模式错误", - "xpack.fileUpload.jsonUploadAndParse.writingToIndex": "正在写入索引", "xpack.fleet.agentBulkActions.agentsSelected": "已选择 {count, plural, other {# 个代理}}", "xpack.fleet.agentBulkActions.clearSelection": "清除所选内容", "xpack.fleet.agentBulkActions.reassignPolicy": "分配到新策略", @@ -13449,9 +13429,6 @@ "xpack.ml.management.syncSavedObjectsFlyout.sync.error": "一些作业无法同步。", "xpack.ml.management.syncSavedObjectsFlyout.sync.success": "{successCount} 个{successCount, plural, other {作业}}已同步", "xpack.ml.management.syncSavedObjectsFlyout.syncButton": "同步", - "xpack.ml.maxFileSizeSettingsDescription": "设置在文件数据可视化工具中导入数据时的文件大小限制。此设置支持的最高值为 1GB。", - "xpack.ml.maxFileSizeSettingsError": "应为有效的数据大小。如 200MB、1GB", - "xpack.ml.maxFileSizeSettingsName": "文件数据可视化工具最大文件上传大小", "xpack.ml.models.jobService.allOtherRequestsCancelledDescription": " 所有其他请求已取消。", "xpack.ml.models.jobService.categorization.messages.failureToGetTokens": "无法对示例字段值样本进行分词。{message}", "xpack.ml.models.jobService.categorization.messages.insufficientPrivileges": "由于权限不足,无法对字段值示例执行分词。因此,无法检查字段值是否适合用于归类作业。", diff --git a/x-pack/plugins/triggers_actions_ui/kibana.json b/x-pack/plugins/triggers_actions_ui/kibana.json index 0487c58e662692..2938d94bf426a7 100644 --- a/x-pack/plugins/triggers_actions_ui/kibana.json +++ b/x-pack/plugins/triggers_actions_ui/kibana.json @@ -3,7 +3,7 @@ "version": "kibana", "server": true, "ui": true, - "optionalPlugins": ["alerts", "features", "home"], + "optionalPlugins": ["alerts", "features", "home", "spaces"], "requiredPlugins": ["management", "charts", "data", "kibanaReact", "kibanaUtils", "savedObjects"], "configPath": ["xpack", "trigger_actions_ui"], "extraPublicDirs": ["public/common", "public/common/constants"], diff --git a/x-pack/plugins/triggers_actions_ui/public/application/app.tsx b/x-pack/plugins/triggers_actions_ui/public/application/app.tsx index 0a59cff98ce26b..0afb81031e3bc7 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/app.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/app.tsx @@ -17,6 +17,8 @@ import { ActionTypeRegistryContract, AlertTypeRegistryContract } from '../types' import { ChartsPluginStart } from '../../../../../src/plugins/charts/public'; import { DataPublicPluginStart } from '../../../../../src/plugins/data/public'; import { PluginStartContract as AlertingStart } from '../../../alerts/public'; +import type { SpacesPluginStart } from '../../../spaces/public'; + import { suspendedComponentWithProps } from './lib/suspended_component_with_props'; import { Storage } from '../../../../../src/plugins/kibana_utils/public'; import { EuiThemeProvider } from '../../../../../src/plugins/kibana_react/common'; @@ -33,6 +35,7 @@ export interface TriggersAndActionsUiServices extends CoreStart { data: DataPublicPluginStart; charts: ChartsPluginStart; alerts?: AlertingStart; + spaces?: SpacesPluginStart; storage?: Storage; setBreadcrumbs: (crumbs: ChromeBreadcrumb[]) => void; actionTypeRegistry: ActionTypeRegistryContract; diff --git a/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_action_types/email/email_connector.tsx b/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_action_types/email/email_connector.tsx index 2f518780c9f6bf..df6822c85340a7 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_action_types/email/email_connector.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_action_types/email/email_connector.tsx @@ -55,10 +55,7 @@ export const EmailActionConnectorFields: React.FunctionComponent< } )} helpText={ - + - + + + + + + = ({ }; interface PromptErrorProps { - docLinks: Pick; + docLinks: DocLinksStart; className?: string; } -const EncryptionError = ({ - // eslint-disable-next-line @typescript-eslint/naming-convention - docLinks: { ELASTIC_WEBSITE_URL, DOC_LINK_VERSION }, - className, -}: PromptErrorProps) => ( +const EncryptionError = ({ docLinks, className }: PromptErrorProps) => ( + {i18n.translate( 'xpack.triggersActionsUI.components.healthCheck.encryptionErrorAction', { @@ -151,11 +143,7 @@ const EncryptionError = ({ /> ); -const TlsError = ({ - // eslint-disable-next-line @typescript-eslint/naming-convention - docLinks: { ELASTIC_WEBSITE_URL, DOC_LINK_VERSION }, - className, -}: PromptErrorProps) => ( +const TlsError = ({ docLinks, className }: PromptErrorProps) => ( + {i18n.translate('xpack.triggersActionsUI.components.healthCheck.tlsErrorAction', { defaultMessage: 'Learn how to enable TLS.', })} @@ -191,11 +175,7 @@ const TlsError = ({ /> ); -const AlertsError = ({ - // eslint-disable-next-line @typescript-eslint/naming-convention - docLinks: { ELASTIC_WEBSITE_URL, DOC_LINK_VERSION }, - className, -}: PromptErrorProps) => ( +const AlertsError = ({ docLinks, className }: PromptErrorProps) => ( + {i18n.translate('xpack.triggersActionsUI.components.healthCheck.alertsErrorAction', { defaultMessage: 'Learn how to enable Alerts and Actions.', })} @@ -230,11 +206,7 @@ const AlertsError = ({ /> ); -const TlsAndEncryptionError = ({ - // eslint-disable-next-line @typescript-eslint/naming-convention - docLinks: { ELASTIC_WEBSITE_URL, DOC_LINK_VERSION }, - className, -}: PromptErrorProps) => ( +const TlsAndEncryptionError = ({ docLinks, className }: PromptErrorProps) => ( + {i18n.translate( 'xpack.triggersActionsUI.components.healthCheck.tlsAndEncryptionErrorAction', { diff --git a/x-pack/plugins/triggers_actions_ui/public/application/home.tsx b/x-pack/plugins/triggers_actions_ui/public/application/home.tsx index 1e7fa3c51e6891..c251a1d597f27c 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/home.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/home.tsx @@ -99,7 +99,7 @@ export const TriggersActionsUIHome: React.FunctionComponent + - + job.environment)).to.eql(['production', 'staging']); + expect(countBy(body.jobs, 'environment')).to.eql({ + production: 1, + staging: 1, + }); + }); + + describe('with existing ML jobs', () => { + before(async () => { + await createJobs(['production', 'staging']); + }); + it('skips duplicate job creation', async () => { + await createJobs(['production', 'test']); + + const { body } = await getJobs(); + expect(countBy(body.jobs, 'environment')).to.eql({ + production: 1, + staging: 1, + test: 1, + }); + }); }); }); }); diff --git a/x-pack/test/functional/apps/lens/dashboard.ts b/x-pack/test/functional/apps/lens/dashboard.ts index 0d2db53ba73af7..a15176d76f9538 100644 --- a/x-pack/test/functional/apps/lens/dashboard.ts +++ b/x-pack/test/functional/apps/lens/dashboard.ts @@ -120,7 +120,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { '[data-test-subj="embeddablePanelHeading-lnsPieVis"]', 'lnsPieVis' ); - const hasGeoDestFilter = await filterBar.hasFilter('geo.dest', 'LS'); + const hasGeoDestFilter = await filterBar.hasFilter('geo.dest', 'AL'); expect(hasGeoDestFilter).to.be(true); await filterBar.addFilter('geo.src', 'is', 'US'); await filterBar.toggleFilterPinned('geo.src'); diff --git a/x-pack/test/functional/apps/maps/import_geojson/file_indexing_panel.js b/x-pack/test/functional/apps/maps/import_geojson/file_indexing_panel.js index 0ce9b7022b38d6..a5b376cbb33a50 100644 --- a/x-pack/test/functional/apps/maps/import_geojson/file_indexing_panel.js +++ b/x-pack/test/functional/apps/maps/import_geojson/file_indexing_panel.js @@ -13,6 +13,7 @@ export default function ({ getService, getPageObjects }) { const PageObjects = getPageObjects(['maps', 'common']); const log = getService('log'); const security = getService('security'); + const browser = getService('browser'); const IMPORT_FILE_PREVIEW_NAME = 'Import File'; const FILE_LOAD_DIR = 'test_upload_files'; @@ -102,6 +103,9 @@ export default function ({ getService, getPageObjects }) { const pointGeojsonFiles = ['point.json', 'multi_point.json']; pointGeojsonFiles.forEach(async (pointFile) => { it(`should index with type geo_point for file: ${pointFile}`, async () => { + if (!(await browser.checkBrowserPermission('clipboard-read'))) { + return; + } await loadFileAndIndex(pointFile); const indexPatternResults = await PageObjects.maps.getIndexPatternResults(); const coordinatesField = indexPatternResults.fields.find( @@ -120,6 +124,9 @@ export default function ({ getService, getPageObjects }) { ]; nonPointGeojsonFiles.forEach(async (shapeFile) => { it(`should index with type geo_shape for file: ${shapeFile}`, async () => { + if (!(await browser.checkBrowserPermission('clipboard-read'))) { + return; + } await loadFileAndIndex(shapeFile); const indexPatternResults = await PageObjects.maps.getIndexPatternResults(); const coordinatesField = indexPatternResults.fields.find( diff --git a/x-pack/test/functional/es_archives/reporting/ecommerce_kibana/data.json b/x-pack/test/functional/es_archives/reporting/ecommerce_kibana/data.json new file mode 100644 index 00000000000000..a0f384a96e6b45 --- /dev/null +++ b/x-pack/test/functional/es_archives/reporting/ecommerce_kibana/data.json @@ -0,0 +1,31 @@ +{ "type": "doc", "value": { "id": "config:7.0.0", "index": ".kibana_1", "source": { "config": { "buildNum": 9007199254740991, "dateFormat:tz": "UTC", "defaultIndex": "5193f870-d861-11e9-a311-0fa548c5f953" }, "migrationVersion": { "config": "7.13.0" }, "references": [ ], "type": "config", "updated_at": "2019-09-16T09:06:51.201Z" } } } + +{ "type": "doc", "value": { "id": "config:8.0.0", "index": ".kibana_1", "source": { "config": { "buildNum": 9007199254740991, "dateFormat:tz": "UTC", "defaultIndex": "5193f870-d861-11e9-a311-0fa548c5f953" }, "migrationVersion": { "config": "7.13.0" }, "references": [ ], "type": "config", "updated_at": "2019-12-11T23:22:12.698Z" } } } + +{ "type": "doc", "value": { "id": "index-pattern:5193f870-d861-11e9-a311-0fa548c5f953", "index": ".kibana_1", "source": { "index-pattern": { "fields": "[{\"name\":\"_id\",\"type\":\"string\",\"esTypes\":[\"_id\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":false},{\"name\":\"_index\",\"type\":\"string\",\"esTypes\":[\"_index\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":false},{\"name\":\"_score\",\"type\":\"number\",\"count\":0,\"scripted\":false,\"searchable\":false,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"_source\",\"type\":\"_source\",\"esTypes\":[\"_source\"],\"count\":0,\"scripted\":false,\"searchable\":false,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"_type\",\"type\":\"string\",\"esTypes\":[\"_type\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":false},{\"name\":\"category\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":1,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"category.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"category\"}}},{\"name\":\"currency\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":1,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"customer_birth_date\",\"type\":\"date\",\"esTypes\":[\"date\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"customer_first_name\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"customer_first_name.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"customer_first_name\"}}},{\"name\":\"customer_full_name\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"customer_full_name.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"customer_full_name\"}}},{\"name\":\"customer_gender\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"customer_id\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":1,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"customer_last_name\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"customer_last_name.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"customer_last_name\"}}},{\"name\":\"customer_phone\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"day_of_week\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"day_of_week_i\",\"type\":\"number\",\"esTypes\":[\"integer\"],\"count\":1,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"email\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"geoip.city_name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"geoip.continent_name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"geoip.country_iso_code\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"geoip.location\",\"type\":\"geo_point\",\"esTypes\":[\"geo_point\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"geoip.region_name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"manufacturer\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"manufacturer.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"manufacturer\"}}},{\"name\":\"order_date\",\"type\":\"date\",\"esTypes\":[\"date\"],\"count\":1,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"order_id\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":1,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"products._id\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"products._id.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"products._id\"}}},{\"name\":\"products.base_price\",\"type\":\"number\",\"esTypes\":[\"half_float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"products.base_unit_price\",\"type\":\"number\",\"esTypes\":[\"half_float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"products.category\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"products.category.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"products.category\"}}},{\"name\":\"products.created_on\",\"type\":\"date\",\"esTypes\":[\"date\"],\"count\":1,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"products.discount_amount\",\"type\":\"number\",\"esTypes\":[\"half_float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"products.discount_percentage\",\"type\":\"number\",\"esTypes\":[\"half_float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"products.manufacturer\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"products.manufacturer.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"products.manufacturer\"}}},{\"name\":\"products.min_price\",\"type\":\"number\",\"esTypes\":[\"half_float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"products.price\",\"type\":\"number\",\"esTypes\":[\"half_float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"products.product_id\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"products.product_name\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"products.product_name.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"products.product_name\"}}},{\"name\":\"products.quantity\",\"type\":\"number\",\"esTypes\":[\"integer\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"products.sku\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"products.tax_amount\",\"type\":\"number\",\"esTypes\":[\"half_float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"products.taxful_price\",\"type\":\"number\",\"esTypes\":[\"half_float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"products.taxless_price\",\"type\":\"number\",\"esTypes\":[\"half_float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"products.unit_discount_amount\",\"type\":\"number\",\"esTypes\":[\"half_float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"sku\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":1,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"taxful_total_price\",\"type\":\"number\",\"esTypes\":[\"half_float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"taxless_total_price\",\"type\":\"number\",\"esTypes\":[\"half_float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"total_quantity\",\"type\":\"number\",\"esTypes\":[\"integer\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"total_unique_products\",\"type\":\"number\",\"esTypes\":[\"integer\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"type\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"user\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true}]", "timeFieldName": "order_date", "title": "ecommerce" }, "migrationVersion": { "index-pattern": "7.11.0" }, "references": [ ], "type": "index-pattern", "updated_at": "2019-12-11T23:24:13.381Z" } } } + +{ "type": "doc", "value": { "id": "search:6091ead0-1c6d-11ea-a100-8589bb9d7c6b", "index": ".kibana_1", "source": { "migrationVersion": { "search": "7.9.3" }, "references": [ { "id": "5193f870-d861-11e9-a311-0fa548c5f953", "name": "kibanaSavedObjectMeta.searchSourceJSON.index", "type": "index-pattern" } ], "search": { "columns": [ "category", "currency", "customer_id", "order_id", "day_of_week_i", "order_date", "products.created_on", "sku" ], "description": "", "hits": 0, "kibanaSavedObjectMeta": { "searchSourceJSON": "{\"highlightAll\":true,\"version\":true,\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filter\":[],\"indexRefName\":\"kibanaSavedObjectMeta.searchSourceJSON.index\"}" }, "sort": [ [ "order_date", "desc" ] ], "title": "Ecommerce Data", "version": 1 }, "type": "search", "updated_at": "2019-12-11T23:24:28.540Z" } } } + +{ "type": "doc", "value": { "id": "dashboard:constructed-sample-saved-object-id", "index": ".kibana_1", "source": { "dashboard": { "description": "", "hits": 0, "kibanaSavedObjectMeta": { "searchSourceJSON": "{\"query\":{\"language\":\"kuery\",\"query\":\"\"},\"filter\":[]}" }, "optionsJSON": "{\"hidePanelTitles\":true,\"useMargins\":true}", "panelsJSON": "[{\"version\":\"8.0.0\",\"gridData\":{\"x\":0,\"y\":0,\"w\":24,\"h\":15,\"i\":\"1c12c2f2-80c2-4d5c-b722-55b2415006e1\"},\"panelIndex\":\"1c12c2f2-80c2-4d5c-b722-55b2415006e1\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_0\"},{\"version\":\"8.0.0\",\"gridData\":{\"x\":24,\"y\":0,\"w\":24,\"h\":15,\"i\":\"1c4b99e1-7785-444f-a1c5-f592893b1a96\"},\"panelIndex\":\"1c4b99e1-7785-444f-a1c5-f592893b1a96\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_1\"},{\"version\":\"8.0.0\",\"gridData\":{\"x\":0,\"y\":15,\"w\":48,\"h\":18,\"i\":\"94eab06f-60ac-4a85-b771-3a8ed475c9bb\"},\"panelIndex\":\"94eab06f-60ac-4a85-b771-3a8ed475c9bb\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_2\"},{\"version\":\"8.0.0\",\"gridData\":{\"x\":0,\"y\":33,\"w\":48,\"h\":8,\"i\":\"52c19b6b-7117-42ac-a74e-c507a1c3ffc0\"},\"panelIndex\":\"52c19b6b-7117-42ac-a74e-c507a1c3ffc0\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_3\"},{\"version\":\"8.0.0\",\"gridData\":{\"x\":0,\"y\":41,\"w\":11,\"h\":10,\"i\":\"a1e889dc-b80e-4937-a576-979f34d1859b\"},\"panelIndex\":\"a1e889dc-b80e-4937-a576-979f34d1859b\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_4\"},{\"version\":\"8.0.0\",\"gridData\":{\"x\":11,\"y\":41,\"w\":5,\"h\":10,\"i\":\"4930b035-d756-4cc5-9a18-1af9e67d6f31\"},\"panelIndex\":\"4930b035-d756-4cc5-9a18-1af9e67d6f31\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_5\"}]", "refreshInterval": { "pause": true, "value": 0 }, "timeFrom": "2019-06-26T06:20:28.066Z", "timeRestore": true, "timeTo": "2019-06-26T07:27:58.573Z", "title": "Ecom Dashboard Hidden Panel Titles", "version": 1 }, "migrationVersion": { "dashboard": "7.11.0" }, "references": [ { "id": "0a464230-79f0-11ea-ae7f-13c5d6e410a0", "name": "panel_0", "type": "visualization" }, { "id": "200609c0-79f0-11ea-ae7f-13c5d6e410a0", "name": "panel_1", "type": "visualization" }, { "id": "6091ead0-1c6d-11ea-a100-8589bb9d7c6b", "name": "panel_2", "type": "search" }, { "id": "4a36acd0-7ac3-11ea-b69c-cf0d7935cd67", "name": "panel_3", "type": "visualization" }, { "id": "ef8757d0-7ac2-11ea-b69c-cf0d7935cd67", "name": "panel_4", "type": "visualization" }, { "id": "132ab9c0-7ac3-11ea-b69c-cf0d7935cd67", "name": "panel_5", "type": "visualization" } ], "type": "dashboard", "updated_at": "2020-04-10T00:37:48.462Z" } } } + +{ "type": "doc", "value": { "id": "visualization:0a464230-79f0-11ea-ae7f-13c5d6e410a0", "index": ".kibana_1", "source": { "migrationVersion": { "visualization": "7.12.0" }, "references": [ { "id": "5193f870-d861-11e9-a311-0fa548c5f953", "name": "kibanaSavedObjectMeta.searchSourceJSON.index", "type": "index-pattern" } ], "type": "visualization", "updated_at": "2020-04-08T23:24:05.971Z", "visualization": { "description": "", "kibanaSavedObjectMeta": { "searchSourceJSON": "{\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filter\":[],\"indexRefName\":\"kibanaSavedObjectMeta.searchSourceJSON.index\"}" }, "title": "e-commerce area chart", "uiStateJSON": "{}", "version": 1, "visState": "{\"type\":\"area\",\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"count\",\"schema\":\"metric\",\"params\":{}},{\"id\":\"2\",\"enabled\":true,\"type\":\"date_histogram\",\"schema\":\"segment\",\"params\":{\"field\":\"order_date\",\"timeRange\":{\"from\":\"2019-06-26T06:20:28.066Z\",\"to\":\"2019-06-26T07:27:58.573Z\"},\"useNormalizedEsInterval\":true,\"scaleMetricValues\":false,\"interval\":\"auto\",\"drop_partials\":false,\"min_doc_count\":1,\"extended_bounds\":{}}}],\"params\":{\"type\":\"area\",\"grid\":{\"categoryLines\":false},\"categoryAxes\":[{\"id\":\"CategoryAxis-1\",\"type\":\"category\",\"position\":\"bottom\",\"show\":true,\"style\":{},\"scale\":{\"type\":\"linear\"},\"labels\":{\"show\":true,\"filter\":true,\"truncate\":100},\"title\":{}}],\"valueAxes\":[{\"id\":\"ValueAxis-1\",\"name\":\"LeftAxis-1\",\"type\":\"value\",\"position\":\"left\",\"show\":true,\"style\":{},\"scale\":{\"type\":\"linear\",\"mode\":\"normal\"},\"labels\":{\"show\":true,\"rotate\":0,\"filter\":false,\"truncate\":100},\"title\":{\"text\":\"Count\"}}],\"seriesParams\":[{\"show\":true,\"type\":\"area\",\"mode\":\"stacked\",\"data\":{\"label\":\"Count\",\"id\":\"1\"},\"drawLinesBetweenPoints\":true,\"lineWidth\":2,\"showCircles\":true,\"interpolate\":\"linear\",\"valueAxis\":\"ValueAxis-1\"}],\"addTooltip\":true,\"addLegend\":true,\"legendPosition\":\"right\",\"times\":[],\"addTimeMarker\":false,\"thresholdLine\":{\"show\":false,\"value\":10,\"width\":1,\"style\":\"full\",\"color\":\"#E7664C\"},\"labels\":{},\"isVislibVis\":true,\"detailedTooltip\":true,\"fittingFunction\":\"zero\"},\"title\":\"e-commerce area chart\"}" } } } } + +{ "type": "doc", "value": { "id": "visualization:200609c0-79f0-11ea-ae7f-13c5d6e410a0", "index": ".kibana_1", "source": { "migrationVersion": { "visualization": "7.12.0" }, "references": [ { "id": "5193f870-d861-11e9-a311-0fa548c5f953", "name": "kibanaSavedObjectMeta.searchSourceJSON.index", "type": "index-pattern" } ], "type": "visualization", "updated_at": "2020-04-08T23:24:42.460Z", "visualization": { "description": "", "kibanaSavedObjectMeta": { "searchSourceJSON": "{\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filter\":[],\"indexRefName\":\"kibanaSavedObjectMeta.searchSourceJSON.index\"}" }, "title": "e-commerce pie chart", "uiStateJSON": "{}", "version": 1, "visState": "{\"type\":\"pie\",\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"count\",\"schema\":\"metric\",\"params\":{}},{\"id\":\"2\",\"enabled\":true,\"type\":\"date_histogram\",\"schema\":\"segment\",\"params\":{\"field\":\"order_date\",\"timeRange\":{\"from\":\"2019-06-26T06:20:28.066Z\",\"to\":\"2019-06-26T07:27:58.573Z\"},\"useNormalizedEsInterval\":true,\"scaleMetricValues\":false,\"interval\":\"auto\",\"drop_partials\":false,\"min_doc_count\":1,\"extended_bounds\":{}}}],\"params\":{\"type\":\"pie\",\"addTooltip\":true,\"addLegend\":true,\"legendPosition\":\"right\",\"isDonut\":true,\"labels\":{\"show\":false,\"values\":true,\"last_level\":true,\"truncate\":100}},\"title\":\"e-commerce pie chart\"}" } } } } + +{ "type": "doc", "value": { "id": "visualization:ef8757d0-7ac2-11ea-b69c-cf0d7935cd67", "index": ".kibana_1", "source": { "migrationVersion": { "visualization": "7.12.0" }, "references": [ { "id": "5193f870-d861-11e9-a311-0fa548c5f953", "name": "kibanaSavedObjectMeta.searchSourceJSON.index", "type": "index-pattern" } ], "type": "visualization", "updated_at": "2020-04-10T00:33:44.909Z", "visualization": { "description": "", "kibanaSavedObjectMeta": { "searchSourceJSON": "{\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"indexRefName\":\"kibanaSavedObjectMeta.searchSourceJSON.index\",\"filter\":[]}" }, "title": "게이지", "uiStateJSON": "{}", "version": 1, "visState": "{\"type\":\"gauge\",\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"count\",\"schema\":\"metric\",\"params\":{}}],\"params\":{\"type\":\"gauge\",\"addTooltip\":true,\"addLegend\":true,\"isDisplayWarning\":false,\"gauge\":{\"alignment\":\"automatic\",\"extendRange\":true,\"percentageMode\":false,\"gaugeType\":\"Arc\",\"gaugeStyle\":\"Full\",\"backStyle\":\"Full\",\"orientation\":\"vertical\",\"colorSchema\":\"Green to Red\",\"gaugeColorMode\":\"Labels\",\"colorsRange\":[{\"from\":0,\"to\":50},{\"from\":50,\"to\":75},{\"from\":75,\"to\":100}],\"invertColors\":false,\"labels\":{\"show\":true,\"color\":\"black\"},\"scale\":{\"show\":true,\"labels\":false,\"color\":\"rgba(105,112,125,0.2)\"},\"type\":\"meter\",\"style\":{\"bgWidth\":0.9,\"width\":0.9,\"mask\":false,\"bgMask\":false,\"maskBars\":50,\"bgFill\":\"rgba(105,112,125,0.2)\",\"bgColor\":true,\"subText\":\"\",\"fontSize\":60}}},\"title\":\"게이지\"}" } } } } + +{ "type": "doc", "value": { "id": "visualization:132ab9c0-7ac3-11ea-b69c-cf0d7935cd67", "index": ".kibana_1", "source": { "migrationVersion": { "visualization": "7.12.0" }, "references": [ { "id": "5193f870-d861-11e9-a311-0fa548c5f953", "name": "kibanaSavedObjectMeta.searchSourceJSON.index", "type": "index-pattern" } ], "type": "visualization", "updated_at": "2020-04-10T00:34:44.700Z", "visualization": { "description": "", "kibanaSavedObjectMeta": { "searchSourceJSON": "{\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"indexRefName\":\"kibanaSavedObjectMeta.searchSourceJSON.index\",\"filter\":[]}" }, "title": "Українська", "uiStateJSON": "{}", "version": 1, "visState": "{\"type\":\"metric\",\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"count\",\"schema\":\"metric\",\"params\":{}}],\"params\":{\"addTooltip\":true,\"addLegend\":false,\"type\":\"metric\",\"metric\":{\"percentageMode\":false,\"useRanges\":false,\"colorSchema\":\"Green to Red\",\"metricColorMode\":\"None\",\"colorsRange\":[{\"from\":0,\"to\":10000}],\"labels\":{\"show\":true},\"invertColors\":false,\"style\":{\"bgFill\":\"#000\",\"bgColor\":false,\"labelColor\":false,\"subText\":\"\",\"fontSize\":60}}},\"title\":\"Українська\"}" } } } } + +{ "type": "doc", "value": { "id": "visualization:4a36acd0-7ac3-11ea-b69c-cf0d7935cd67", "index": ".kibana_1", "source": { "migrationVersion": { "visualization": "7.12.0" }, "references": [ ], "type": "visualization", "updated_at": "2020-04-10T00:36:17.053Z", "visualization": { "description": "", "kibanaSavedObjectMeta": { "searchSourceJSON": "{\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filter\":[]}" }, "title": "Tiểu thuyết", "uiStateJSON": "{}", "version": 1, "visState": "{\"type\":\"markdown\",\"aggs\":[],\"params\":{\"fontSize\":12,\"openLinksInNewTab\":false,\"markdown\":\"Tiểu thuyết là một thể loại văn xuôi có hư cấu, thông qua nhân vật, hoàn cảnh, sự việc để phản ánh bức tranh xã hội rộng lớn và những vấn đề của cuộc sống con người, biểu hiện tính chất tường thuật, tính chất kể chuyện bằng ngôn ngữ văn xuôi theo những chủ đề xác định.\\n\\nTrong một cách hiểu khác, nhận định của Belinski: \\\"tiểu thuyết là sử thi của đời tư\\\" chỉ ra khái quát nhất về một dạng thức tự sự, trong đó sự trần thuật tập trung vào số phận của một cá nhân trong quá trình hình thành và phát triển của nó. Sự trần thuật ở đây được khai triển trong không gian và thời gian nghệ thuật đến mức đủ để truyền đạt cơ cấu của nhân cách[1].\\n\\n\\n[1]^ Mục từ Tiểu thuyết trong cuốn 150 thuật ngữ văn học, Lại Nguyên Ân biên soạn, Nhà xuất bản Đại học Quốc gia Hà Nội, in lần thứ 2 có sửa đổi bổ sung. H. 2003. Trang 326.\"},\"title\":\"Tiểu thuyết\"}" } } } } + +{ "type": "doc", "value": { "id": "space:default", "index": ".kibana_1", "source": { "space": { "_reserved": true, "description": "This is the default space", "disabledFeatures": [ ], "name": "Default Space" }, "type": "space", "updated_at": "2021-01-07T00:17:12.785Z" } } } + +{ "type": "doc", "value": { "id": "ui-counter:visualize:06012021:click:tagcloud", "index": ".kibana_1", "source": { "type": "ui-counter", "ui-counter": { "count": 1 }, "updated_at": "2021-01-07T00:18:52.592Z" } } } + +{ "type": "doc", "value": { "id": "ui-counter:data_plugin:06012021:click:discover:query_submitted", "index": ".kibana_1", "source": { "type": "ui-counter", "ui-counter": { "count": 1 }, "updated_at": "2021-01-07T00:18:52.592Z" } } } + +{ "type": "doc", "value": { "id": "dashboard:6c263e00-1c6d-11ea-a100-8589bb9d7c6b", "index": ".kibana_1", "source": { "dashboard": { "description": "", "hits": 0, "kibanaSavedObjectMeta": { "searchSourceJSON": "{\"query\":{\"language\":\"kuery\",\"query\":\"\"},\"filter\":[]}" }, "optionsJSON": "{\"hidePanelTitles\":false,\"useMargins\":true}", "panelsJSON": "[{\"version\":\"8.0.0\",\"gridData\":{\"x\":0,\"y\":0,\"w\":24,\"h\":15,\"i\":\"1c12c2f2-80c2-4d5c-b722-55b2415006e1\"},\"panelIndex\":\"1c12c2f2-80c2-4d5c-b722-55b2415006e1\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_0\"},{\"version\":\"8.0.0\",\"gridData\":{\"x\":24,\"y\":0,\"w\":24,\"h\":15,\"i\":\"1c4b99e1-7785-444f-a1c5-f592893b1a96\"},\"panelIndex\":\"1c4b99e1-7785-444f-a1c5-f592893b1a96\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_1\"},{\"version\":\"8.0.0\",\"gridData\":{\"x\":0,\"y\":35,\"w\":48,\"h\":18,\"i\":\"94eab06f-60ac-4a85-b771-3a8ed475c9bb\"},\"panelIndex\":\"94eab06f-60ac-4a85-b771-3a8ed475c9bb\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_2\"},{\"version\":\"8.0.0\",\"gridData\":{\"x\":0,\"y\":15,\"w\":48,\"h\":8,\"i\":\"52c19b6b-7117-42ac-a74e-c507a1c3ffc0\"},\"panelIndex\":\"52c19b6b-7117-42ac-a74e-c507a1c3ffc0\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_3\"},{\"version\":\"8.0.0\",\"gridData\":{\"x\":0,\"y\":23,\"w\":16,\"h\":12,\"i\":\"a1e889dc-b80e-4937-a576-979f34d1859b\"},\"panelIndex\":\"a1e889dc-b80e-4937-a576-979f34d1859b\",\"embeddableConfig\":{\"enhancements\":{},\"vis\":null},\"panelRefName\":\"panel_4\"},{\"version\":\"8.0.0\",\"gridData\":{\"x\":16,\"y\":23,\"w\":12,\"h\":12,\"i\":\"4930b035-d756-4cc5-9a18-1af9e67d6f31\"},\"panelIndex\":\"4930b035-d756-4cc5-9a18-1af9e67d6f31\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_5\"},{\"version\":\"8.0.0\",\"gridData\":{\"x\":28,\"y\":23,\"w\":20,\"h\":12,\"i\":\"55112375-d6f0-44f7-a8fb-867c8f7d464d\"},\"panelIndex\":\"55112375-d6f0-44f7-a8fb-867c8f7d464d\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_6\"}]", "refreshInterval": { "pause": true, "value": 0 }, "timeFrom": "2019-03-23T03:06:17.785Z", "timeRestore": true, "timeTo": "2019-10-04T02:33:16.708Z", "title": "Ecom Dashboard", "version": 1 }, "migrationVersion": { "dashboard": "7.11.0" }, "references": [ { "id": "0a464230-79f0-11ea-ae7f-13c5d6e410a0", "name": "panel_0", "type": "visualization" }, { "id": "200609c0-79f0-11ea-ae7f-13c5d6e410a0", "name": "panel_1", "type": "visualization" }, { "id": "6091ead0-1c6d-11ea-a100-8589bb9d7c6b", "name": "panel_2", "type": "search" }, { "id": "4a36acd0-7ac3-11ea-b69c-cf0d7935cd67", "name": "panel_3", "type": "visualization" }, { "id": "ef8757d0-7ac2-11ea-b69c-cf0d7935cd67", "name": "panel_4", "type": "visualization" }, { "id": "132ab9c0-7ac3-11ea-b69c-cf0d7935cd67", "name": "panel_5", "type": "visualization" }, { "id": "1bba55f0-507e-11eb-9c0d-97106882b997", "name": "panel_6", "type": "visualization" } ], "type": "dashboard", "updated_at": "2021-01-07T00:22:16.102Z" } } } + +{ "type": "doc", "value": { "id": "visualization:1bba55f0-507e-11eb-9c0d-97106882b997", "index": ".kibana_1", "source": { "migrationVersion": { "visualization": "7.12.0" }, "references": [ { "id": "6091ead0-1c6d-11ea-a100-8589bb9d7c6b", "name": "search_0", "type": "search" } ], "type": "visualization", "updated_at": "2021-01-07T00:23:04.624Z", "visualization": { "description": "", "kibanaSavedObjectMeta": { "searchSourceJSON": "{\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filter\":[]}" }, "savedSearchRefName": "search_0", "title": "Tag Cloud of Names", "uiStateJSON": "{}", "version": 1, "visState": "{\"title\":\"Tag Cloud of Names\",\"type\":\"tagcloud\",\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"count\",\"params\":{},\"schema\":\"metric\"},{\"id\":\"2\",\"enabled\":true,\"type\":\"terms\",\"params\":{\"field\":\"customer_first_name.keyword\",\"orderBy\":\"1\",\"order\":\"desc\",\"size\":10,\"otherBucket\":false,\"otherBucketLabel\":\"Other\",\"missingBucket\":false,\"missingBucketLabel\":\"Missing\"},\"schema\":\"segment\"}],\"params\":{\"scale\":\"linear\",\"orientation\":\"single\",\"minFontSize\":18,\"maxFontSize\":72,\"showLabel\":true}}" } } } } + +{ "type": "doc", "value": { "id": "ui-counter:DashboardPanelVersionInUrl:06012021:loaded:8.0.0", "index": ".kibana_1", "source": { "type": "ui-counter", "ui-counter": { "count": 85 }, "updated_at": "2021-01-07T00:23:25.741Z" } } } diff --git a/x-pack/test/functional/es_archives/reporting/ecommerce_kibana/data.json.gz b/x-pack/test/functional/es_archives/reporting/ecommerce_kibana/data.json.gz deleted file mode 100644 index 8b2b8f9c114de2..00000000000000 Binary files a/x-pack/test/functional/es_archives/reporting/ecommerce_kibana/data.json.gz and /dev/null differ diff --git a/x-pack/test/functional/es_archives/reporting/ecommerce_kibana_spaces/data.json b/x-pack/test/functional/es_archives/reporting/ecommerce_kibana_spaces/data.json new file mode 100644 index 00000000000000..98bbbde8b83b71 --- /dev/null +++ b/x-pack/test/functional/es_archives/reporting/ecommerce_kibana_spaces/data.json @@ -0,0 +1,362 @@ +{ + "type": "doc", + "value": { + "id": "non_default_space:index-pattern:067dec90-e7ee-11ea-a730-d58e9ea7581b", + "index": ".kibana_1", + "source": { + "index-pattern": { + "fields": "[{\"count\":0,\"name\":\"_id\",\"type\":\"string\",\"esTypes\":[\"_id\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":false},{\"count\":0,\"name\":\"_index\",\"type\":\"string\",\"esTypes\":[\"_index\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":false},{\"count\":0,\"name\":\"_score\",\"type\":\"number\",\"scripted\":false,\"searchable\":false,\"aggregatable\":false,\"readFromDocValues\":false},{\"count\":0,\"name\":\"_source\",\"type\":\"_source\",\"esTypes\":[\"_source\"],\"scripted\":false,\"searchable\":false,\"aggregatable\":false,\"readFromDocValues\":false},{\"count\":0,\"name\":\"_type\",\"type\":\"string\",\"esTypes\":[\"_type\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":false},{\"count\":1,\"name\":\"category\",\"type\":\"string\",\"esTypes\":[\"text\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"count\":0,\"name\":\"category.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"category\"}}},{\"count\":1,\"name\":\"currency\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"count\":0,\"name\":\"customer_birth_date\",\"type\":\"date\",\"esTypes\":[\"date\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"count\":1,\"name\":\"customer_first_name\",\"type\":\"string\",\"esTypes\":[\"text\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"count\":0,\"name\":\"customer_first_name.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"customer_first_name\"}}},{\"count\":1,\"name\":\"customer_full_name\",\"type\":\"string\",\"esTypes\":[\"text\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"count\":0,\"name\":\"customer_full_name.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"customer_full_name\"}}},{\"count\":0,\"name\":\"customer_gender\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"count\":0,\"name\":\"customer_id\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"count\":0,\"name\":\"customer_last_name\",\"type\":\"string\",\"esTypes\":[\"text\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"count\":0,\"name\":\"customer_last_name.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"customer_last_name\"}}},{\"count\":0,\"name\":\"customer_phone\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"count\":0,\"name\":\"day_of_week\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"count\":0,\"name\":\"day_of_week_i\",\"type\":\"number\",\"esTypes\":[\"integer\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"count\":0,\"name\":\"email\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"count\":0,\"name\":\"geoip.city_name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"count\":0,\"name\":\"geoip.continent_name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"count\":0,\"name\":\"geoip.country_iso_code\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"count\":0,\"name\":\"geoip.location\",\"type\":\"geo_point\",\"esTypes\":[\"geo_point\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"count\":0,\"name\":\"geoip.region_name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"count\":0,\"name\":\"manufacturer\",\"type\":\"string\",\"esTypes\":[\"text\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"count\":0,\"name\":\"manufacturer.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"manufacturer\"}}},{\"count\":0,\"name\":\"order_date\",\"type\":\"date\",\"esTypes\":[\"date\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"count\":0,\"name\":\"order_id\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"count\":0,\"name\":\"products._id\",\"type\":\"string\",\"esTypes\":[\"text\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"count\":0,\"name\":\"products._id.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"products._id\"}}},{\"count\":0,\"name\":\"products.base_price\",\"type\":\"number\",\"esTypes\":[\"half_float\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"count\":0,\"name\":\"products.base_unit_price\",\"type\":\"number\",\"esTypes\":[\"half_float\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"count\":0,\"name\":\"products.category\",\"type\":\"string\",\"esTypes\":[\"text\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"count\":0,\"name\":\"products.category.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"products.category\"}}},{\"count\":0,\"name\":\"products.created_on\",\"type\":\"date\",\"esTypes\":[\"date\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"count\":0,\"name\":\"products.discount_amount\",\"type\":\"number\",\"esTypes\":[\"half_float\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"count\":0,\"name\":\"products.discount_percentage\",\"type\":\"number\",\"esTypes\":[\"half_float\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"count\":0,\"name\":\"products.manufacturer\",\"type\":\"string\",\"esTypes\":[\"text\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"count\":0,\"name\":\"products.manufacturer.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"products.manufacturer\"}}},{\"count\":0,\"name\":\"products.min_price\",\"type\":\"number\",\"esTypes\":[\"half_float\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"count\":0,\"name\":\"products.price\",\"type\":\"number\",\"esTypes\":[\"half_float\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"count\":0,\"name\":\"products.product_id\",\"type\":\"number\",\"esTypes\":[\"long\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"count\":0,\"name\":\"products.product_name\",\"type\":\"string\",\"esTypes\":[\"text\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"count\":0,\"name\":\"products.product_name.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"products.product_name\"}}},{\"count\":0,\"name\":\"products.quantity\",\"type\":\"number\",\"esTypes\":[\"integer\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"count\":0,\"name\":\"products.sku\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"count\":0,\"name\":\"products.tax_amount\",\"type\":\"number\",\"esTypes\":[\"half_float\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"count\":0,\"name\":\"products.taxful_price\",\"type\":\"number\",\"esTypes\":[\"half_float\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"count\":0,\"name\":\"products.taxless_price\",\"type\":\"number\",\"esTypes\":[\"half_float\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"count\":0,\"name\":\"products.unit_discount_amount\",\"type\":\"number\",\"esTypes\":[\"half_float\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"count\":0,\"name\":\"sku\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"count\":1,\"name\":\"taxful_total_price\",\"type\":\"number\",\"esTypes\":[\"half_float\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"count\":1,\"name\":\"taxless_total_price\",\"type\":\"number\",\"esTypes\":[\"half_float\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"count\":1,\"name\":\"total_quantity\",\"type\":\"number\",\"esTypes\":[\"integer\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"count\":1,\"name\":\"total_unique_products\",\"type\":\"number\",\"esTypes\":[\"integer\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"count\":0,\"name\":\"type\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"count\":0,\"name\":\"user\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true}]", + "timeFieldName": "order_date", + "title": "ecommerce*" + }, + "migrationVersion": { + "index-pattern": "7.6.0" + }, + "namespace": "non_default_space", + "references": [ + ], + "type": "index-pattern", + "updated_at": "2020-08-26T22:49:22.080Z" + } + } +} + +{ + "type": "doc", + "value": { + "id": "index-pattern:aac3e500-f2c7-11ea-8250-fb138aa491e7", + "index": ".kibana_1", + "source": { + "index-pattern": { + "fields": "[{\"count\":0,\"name\":\"_id\",\"type\":\"string\",\"esTypes\":[\"_id\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":false},{\"count\":0,\"name\":\"_index\",\"type\":\"string\",\"esTypes\":[\"_index\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":false},{\"count\":0,\"name\":\"_score\",\"type\":\"number\",\"scripted\":false,\"searchable\":false,\"aggregatable\":false,\"readFromDocValues\":false},{\"count\":0,\"name\":\"_source\",\"type\":\"_source\",\"esTypes\":[\"_source\"],\"scripted\":false,\"searchable\":false,\"aggregatable\":false,\"readFromDocValues\":false},{\"count\":0,\"name\":\"_type\",\"type\":\"string\",\"esTypes\":[\"_type\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":false},{\"count\":0,\"name\":\"category\",\"type\":\"string\",\"esTypes\":[\"text\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"count\":0,\"name\":\"category.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"category\"}}},{\"count\":0,\"name\":\"currency\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"count\":0,\"name\":\"customer_birth_date\",\"type\":\"date\",\"esTypes\":[\"date\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"count\":1,\"name\":\"customer_first_name\",\"type\":\"string\",\"esTypes\":[\"text\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"count\":0,\"name\":\"customer_first_name.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"customer_first_name\"}}},{\"count\":1,\"name\":\"customer_full_name\",\"type\":\"string\",\"esTypes\":[\"text\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"count\":0,\"name\":\"customer_full_name.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"customer_full_name\"}}},{\"count\":0,\"name\":\"customer_gender\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"count\":0,\"name\":\"customer_id\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"count\":0,\"name\":\"customer_last_name\",\"type\":\"string\",\"esTypes\":[\"text\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"count\":0,\"name\":\"customer_last_name.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"customer_last_name\"}}},{\"count\":0,\"name\":\"customer_phone\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"count\":0,\"name\":\"day_of_week\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"count\":0,\"name\":\"day_of_week_i\",\"type\":\"number\",\"esTypes\":[\"integer\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"count\":0,\"name\":\"email\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"count\":0,\"name\":\"geoip.city_name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"count\":0,\"name\":\"geoip.continent_name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"count\":0,\"name\":\"geoip.country_iso_code\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"count\":0,\"name\":\"geoip.location\",\"type\":\"geo_point\",\"esTypes\":[\"geo_point\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"count\":0,\"name\":\"geoip.region_name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"count\":0,\"name\":\"manufacturer\",\"type\":\"string\",\"esTypes\":[\"text\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"count\":0,\"name\":\"manufacturer.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"manufacturer\"}}},{\"count\":1,\"name\":\"order_date\",\"type\":\"date\",\"esTypes\":[\"date\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"count\":0,\"name\":\"order_id\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"count\":0,\"name\":\"products._id\",\"type\":\"string\",\"esTypes\":[\"text\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"count\":0,\"name\":\"products._id.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"products._id\"}}},{\"count\":0,\"name\":\"products.base_price\",\"type\":\"number\",\"esTypes\":[\"half_float\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"count\":0,\"name\":\"products.base_unit_price\",\"type\":\"number\",\"esTypes\":[\"half_float\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"count\":0,\"name\":\"products.category\",\"type\":\"string\",\"esTypes\":[\"text\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"count\":0,\"name\":\"products.category.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"products.category\"}}},{\"count\":0,\"name\":\"products.created_on\",\"type\":\"date\",\"esTypes\":[\"date\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"count\":0,\"name\":\"products.discount_amount\",\"type\":\"number\",\"esTypes\":[\"half_float\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"count\":0,\"name\":\"products.discount_percentage\",\"type\":\"number\",\"esTypes\":[\"half_float\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"count\":0,\"name\":\"products.manufacturer\",\"type\":\"string\",\"esTypes\":[\"text\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"count\":0,\"name\":\"products.manufacturer.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"products.manufacturer\"}}},{\"count\":0,\"name\":\"products.min_price\",\"type\":\"number\",\"esTypes\":[\"half_float\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"count\":0,\"name\":\"products.price\",\"type\":\"number\",\"esTypes\":[\"half_float\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"count\":0,\"name\":\"products.product_id\",\"type\":\"number\",\"esTypes\":[\"long\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"count\":0,\"name\":\"products.product_name\",\"type\":\"string\",\"esTypes\":[\"text\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"count\":0,\"name\":\"products.product_name.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"products.product_name\"}}},{\"count\":0,\"name\":\"products.quantity\",\"type\":\"number\",\"esTypes\":[\"integer\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"count\":0,\"name\":\"products.sku\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"count\":0,\"name\":\"products.tax_amount\",\"type\":\"number\",\"esTypes\":[\"half_float\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"count\":0,\"name\":\"products.taxful_price\",\"type\":\"number\",\"esTypes\":[\"half_float\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"count\":0,\"name\":\"products.taxless_price\",\"type\":\"number\",\"esTypes\":[\"half_float\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"count\":0,\"name\":\"products.unit_discount_amount\",\"type\":\"number\",\"esTypes\":[\"half_float\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"count\":0,\"name\":\"sku\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"count\":1,\"name\":\"taxful_total_price\",\"type\":\"number\",\"esTypes\":[\"half_float\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"count\":1,\"name\":\"taxless_total_price\",\"type\":\"number\",\"esTypes\":[\"half_float\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"count\":1,\"name\":\"total_quantity\",\"type\":\"number\",\"esTypes\":[\"integer\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"count\":1,\"name\":\"total_unique_products\",\"type\":\"number\",\"esTypes\":[\"integer\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"count\":0,\"name\":\"type\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"count\":0,\"name\":\"user\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true}]", + "timeFieldName": "order_date", + "title": "ec*" + }, + "migrationVersion": { + "index-pattern": "7.6.0" + }, + "references": [ + ], + "type": "index-pattern", + "updated_at": "2020-09-09T18:10:54.007Z" + } + } +} + +{ + "type": "doc", + "value": { + "id": "non_default_space:config:8.0.0", + "index": ".kibana_1", + "source": { + "config": { + "buildNum": 9007199254740991, + "csv:separator": ";", + "dateFormat:tz": "US/Alaska", + "defaultIndex": "067dec90-e7ee-11ea-a730-d58e9ea7581b" + }, + "migrationVersion": { + "config": "7.13.0" + }, + "namespace": "non_default_space", + "references": [ + ], + "type": "config", + "updated_at": "2020-08-26T22:46:48.711Z" + } + } +} + +{ + "type": "doc", + "value": { + "id": "config:8.0.0", + "index": ".kibana_1", + "source": { + "config": { + "buildNum": 9007199254740991, + "dateFormat:tz": "UTC", + "defaultIndex": "aac3e500-f2c7-11ea-8250-fb138aa491e7" + }, + "migrationVersion": { + "config": "7.13.0" + }, + "namespace": "default", + "references": [ + ], + "type": "config", + "updated_at": "2020-08-26T22:46:48.711Z" + } + } +} + +{ + "type": "doc", + "value": { + "id": "space:non_default_space", + "index": ".kibana_1", + "source": { + "migrationVersion": { + "space": "6.6.0" + }, + "references": [ + ], + "space": { + "disabledFeatures": [ + ], + "name": "non_default_space" + }, + "type": "space", + "updated_at": "2020-08-26T22:45:32.322Z" + } + } +} + +{ + "type": "doc", + "value": { + "id": "space:non_timezone_space", + "index": ".kibana_1", + "source": { + "migrationVersion": { + "space": "6.6.0" + }, + "references": [ + ], + "space": { + "disabledFeatures": [ + ], + "name": "non_timezone_space" + }, + "type": "space", + "updated_at": "2020-08-26T22:45:32.322Z" + } + } +} + +{ + "type": "doc", + "value": { + "id": "space:default", + "index": ".kibana_1", + "source": { + "migrationVersion": { + "space": "6.6.0" + }, + "references": [ + ], + "space": { + "_reserved": true, + "description": "This is the default space", + "disabledFeatures": [ + ], + "name": "Default Space" + }, + "type": "space", + "updated_at": "2020-08-26T22:44:31.883Z" + } + } +} + +{ + "type": "doc", + "value": { + "id": "non_default_space:dashboard:3c9ee360-e7ee-11ea-a730-d58e9ea7581b", + "index": ".kibana_1", + "source": { + "dashboard": { + "description": "", + "hits": 0, + "kibanaSavedObjectMeta": { + "searchSourceJSON": "{\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filter\":[]}" + }, + "optionsJSON": "{\"useMargins\":true,\"hidePanelTitles\":false}", + "panelsJSON": "[{\"version\":\"8.0.0\",\"gridData\":{\"x\":0,\"y\":0,\"w\":48,\"h\":18,\"i\":\"3021441a-54e1-44b7-9a08-d970aa929d4c\"},\"panelIndex\":\"3021441a-54e1-44b7-9a08-d970aa929d4c\",\"embeddableConfig\":{},\"panelRefName\":\"panel_0\"}]", + "refreshInterval": { + "pause": true, + "value": 0 + }, + "timeFrom": "2019-06-10T03:17:28.800Z", + "timeRestore": true, + "timeTo": "2019-07-14T19:25:06.385Z", + "title": "Ecom Dashboard Non Default Space", + "version": 1 + }, + "migrationVersion": { + "dashboard": "7.3.0" + }, + "namespace": "non_default_space", + "references": [ + { + "id": "22bebe20-e7ee-11ea-a730-d58e9ea7581b", + "name": "panel_0", + "type": "search" + } + ], + "type": "dashboard", + "updated_at": "2020-08-26T22:48:19.349Z" + } + } +} + +{ + "type": "doc", + "value": { + "id": "search:bbe45ae0-f2c7-11ea-8250-fb138aa491e7", + "index": ".kibana_1", + "source": { + "migrationVersion": { + "search": "7.4.0" + }, + "references": [ + { + "id": "aac3e500-f2c7-11ea-8250-fb138aa491e7", + "name": "kibanaSavedObjectMeta.searchSourceJSON.index", + "type": "index-pattern" + } + ], + "search": { + "columns": [ + "category", + "customer_full_name", + "taxful_total_price", + "currency" + ], + "description": "", + "hits": 0, + "kibanaSavedObjectMeta": { + "searchSourceJSON": "{\"highlightAll\":true,\"version\":true,\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filter\":[],\"indexRefName\":\"kibanaSavedObjectMeta.searchSourceJSON.index\"}" + }, + "sort": [ + ], + "title": "EC SEARCH from DEFAULT", + "version": 1 + }, + "type": "search", + "updated_at": "2020-09-09T18:10:58.011Z" + } + } +} + +{ + "type": "doc", + "value": { + "id": "non_default_space:search:22bebe20-e7ee-11ea-a730-d58e9ea7581b", + "index": ".kibana_1", + "source": { + "migrationVersion": { + "search": "7.4.0" + }, + "namespace": "non_default_space", + "references": [ + { + "id": "067dec90-e7ee-11ea-a730-d58e9ea7581b", + "name": "kibanaSavedObjectMeta.searchSourceJSON.index", + "type": "index-pattern" + } + ], + "search": { + "columns": [ + "category", + "customer_full_name", + "taxful_total_price", + "currency" + ], + "description": "", + "hits": 0, + "kibanaSavedObjectMeta": { + "searchSourceJSON": "{\"highlightAll\":true,\"version\":true,\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filter\":[],\"indexRefName\":\"kibanaSavedObjectMeta.searchSourceJSON.index\"}" + }, + "sort": [ + ], + "title": "Ecom Search from Non-Default", + "version": 1 + }, + "type": "search", + "updated_at": "2020-09-09T18:38:26.314Z" + } + } +} + +{ + "type": "doc", + "value": { + "id": "non_timezone_space:config:8.0.0", + "index": ".kibana_1", + "source": { + "config": { + "buildNum": 9007199254740991, + "defaultIndex": "526cf200-f774-11ea-93eb-cf722c4a3092" + }, + "migrationVersion": { + "config": "7.13.0" + }, + "namespace": "non_timezone_space", + "references": [ + ], + "type": "config", + "updated_at": "2020-09-15T16:55:56.998Z" + } + } +} + +{ + "type": "doc", + "value": { + "id": "non_timezone_space:index-pattern:526cf200-f774-11ea-93eb-cf722c4a3092", + "index": ".kibana_1", + "source": { + "index-pattern": { + "fields": "[{\"count\":0,\"name\":\"_id\",\"type\":\"string\",\"esTypes\":[\"_id\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":false},{\"count\":0,\"name\":\"_index\",\"type\":\"string\",\"esTypes\":[\"_index\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":false},{\"count\":0,\"name\":\"_score\",\"type\":\"number\",\"scripted\":false,\"searchable\":false,\"aggregatable\":false,\"readFromDocValues\":false},{\"count\":0,\"name\":\"_source\",\"type\":\"_source\",\"esTypes\":[\"_source\"],\"scripted\":false,\"searchable\":false,\"aggregatable\":false,\"readFromDocValues\":false},{\"count\":0,\"name\":\"_type\",\"type\":\"string\",\"esTypes\":[\"_type\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":false},{\"count\":1,\"name\":\"category\",\"type\":\"string\",\"esTypes\":[\"text\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"count\":0,\"name\":\"category.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"category\"}}},{\"count\":0,\"name\":\"currency\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"count\":0,\"name\":\"customer_birth_date\",\"type\":\"date\",\"esTypes\":[\"date\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"count\":0,\"name\":\"customer_first_name\",\"type\":\"string\",\"esTypes\":[\"text\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"count\":0,\"name\":\"customer_first_name.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"customer_first_name\"}}},{\"count\":1,\"name\":\"customer_full_name\",\"type\":\"string\",\"esTypes\":[\"text\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"count\":0,\"name\":\"customer_full_name.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"customer_full_name\"}}},{\"count\":0,\"name\":\"customer_gender\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"count\":0,\"name\":\"customer_id\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"count\":0,\"name\":\"customer_last_name\",\"type\":\"string\",\"esTypes\":[\"text\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"count\":0,\"name\":\"customer_last_name.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"customer_last_name\"}}},{\"count\":0,\"name\":\"customer_phone\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"count\":0,\"name\":\"day_of_week\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"count\":0,\"name\":\"day_of_week_i\",\"type\":\"number\",\"esTypes\":[\"integer\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"count\":0,\"name\":\"email\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"count\":0,\"name\":\"geoip.city_name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"count\":0,\"name\":\"geoip.continent_name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"count\":0,\"name\":\"geoip.country_iso_code\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"count\":0,\"name\":\"geoip.location\",\"type\":\"geo_point\",\"esTypes\":[\"geo_point\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"count\":0,\"name\":\"geoip.region_name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"count\":0,\"name\":\"manufacturer\",\"type\":\"string\",\"esTypes\":[\"text\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"count\":0,\"name\":\"manufacturer.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"manufacturer\"}}},{\"count\":2,\"name\":\"order_date\",\"type\":\"date\",\"esTypes\":[\"date\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"count\":0,\"name\":\"order_id\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"count\":0,\"name\":\"products._id\",\"type\":\"string\",\"esTypes\":[\"text\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"count\":0,\"name\":\"products._id.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"products._id\"}}},{\"count\":0,\"name\":\"products.base_price\",\"type\":\"number\",\"esTypes\":[\"half_float\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"count\":0,\"name\":\"products.base_unit_price\",\"type\":\"number\",\"esTypes\":[\"half_float\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"count\":0,\"name\":\"products.category\",\"type\":\"string\",\"esTypes\":[\"text\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"count\":0,\"name\":\"products.category.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"products.category\"}}},{\"count\":0,\"name\":\"products.created_on\",\"type\":\"date\",\"esTypes\":[\"date\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"count\":0,\"name\":\"products.discount_amount\",\"type\":\"number\",\"esTypes\":[\"half_float\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"count\":0,\"name\":\"products.discount_percentage\",\"type\":\"number\",\"esTypes\":[\"half_float\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"count\":0,\"name\":\"products.manufacturer\",\"type\":\"string\",\"esTypes\":[\"text\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"count\":0,\"name\":\"products.manufacturer.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"products.manufacturer\"}}},{\"count\":0,\"name\":\"products.min_price\",\"type\":\"number\",\"esTypes\":[\"half_float\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"count\":0,\"name\":\"products.price\",\"type\":\"number\",\"esTypes\":[\"half_float\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"count\":0,\"name\":\"products.product_id\",\"type\":\"number\",\"esTypes\":[\"long\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"count\":0,\"name\":\"products.product_name\",\"type\":\"string\",\"esTypes\":[\"text\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"count\":0,\"name\":\"products.product_name.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"products.product_name\"}}},{\"count\":0,\"name\":\"products.quantity\",\"type\":\"number\",\"esTypes\":[\"integer\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"count\":0,\"name\":\"products.sku\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"count\":0,\"name\":\"products.tax_amount\",\"type\":\"number\",\"esTypes\":[\"half_float\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"count\":0,\"name\":\"products.taxful_price\",\"type\":\"number\",\"esTypes\":[\"half_float\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"count\":0,\"name\":\"products.taxless_price\",\"type\":\"number\",\"esTypes\":[\"half_float\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"count\":0,\"name\":\"products.unit_discount_amount\",\"type\":\"number\",\"esTypes\":[\"half_float\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"count\":0,\"name\":\"sku\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"count\":0,\"name\":\"taxful_total_price\",\"type\":\"number\",\"esTypes\":[\"half_float\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"count\":0,\"name\":\"taxless_total_price\",\"type\":\"number\",\"esTypes\":[\"half_float\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"count\":0,\"name\":\"total_quantity\",\"type\":\"number\",\"esTypes\":[\"integer\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"count\":0,\"name\":\"total_unique_products\",\"type\":\"number\",\"esTypes\":[\"integer\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"count\":0,\"name\":\"type\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"count\":0,\"name\":\"user\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true}]", + "timeFieldName": "order_date", + "title": "ecom*" + }, + "migrationVersion": { + "index-pattern": "7.6.0" + }, + "namespace": "non_timezone_space", + "references": [ + ], + "type": "index-pattern", + "updated_at": "2020-09-15T16:57:09.594Z" + } + } +} + +{ + "type": "doc", + "value": { + "id": "non_timezone_space:search:89c864a0-f774-11ea-93eb-cf722c4a3092", + "index": ".kibana_1", + "source": { + "migrationVersion": { + "search": "7.4.0" + }, + "namespace": "non_timezone_space", + "references": [ + { + "id": "526cf200-f774-11ea-93eb-cf722c4a3092", + "name": "kibanaSavedObjectMeta.searchSourceJSON.index", + "type": "index-pattern" + } + ], + "search": { + "columns": [ + "category", + "customer_full_name" + ], + "description": "", + "hits": 0, + "kibanaSavedObjectMeta": { + "searchSourceJSON": "{\"highlightAll\":true,\"version\":true,\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filter\":[],\"indexRefName\":\"kibanaSavedObjectMeta.searchSourceJSON.index\"}" + }, + "sort": [ + ], + "title": "Browser Timezone Search", + "version": 1 + }, + "type": "search", + "updated_at": "2020-09-15T16:57:28.809Z" + } + } +} diff --git a/x-pack/test/functional/es_archives/reporting/ecommerce_kibana_spaces/data.json.gz b/x-pack/test/functional/es_archives/reporting/ecommerce_kibana_spaces/data.json.gz deleted file mode 100644 index 0cec8a44dea8d9..00000000000000 Binary files a/x-pack/test/functional/es_archives/reporting/ecommerce_kibana_spaces/data.json.gz and /dev/null differ diff --git a/x-pack/test/functional/page_objects/gis_page.ts b/x-pack/test/functional/page_objects/gis_page.ts index 097176b72579c4..6694a494cf8533 100644 --- a/x-pack/test/functional/page_objects/gis_page.ts +++ b/x-pack/test/functional/page_objects/gis_page.ts @@ -423,7 +423,7 @@ export function GisPageProvider({ getService, getPageObjects }: FtrProviderConte async importLayerReadyForAdd() { log.debug(`Wait until import complete`); - await testSubjects.find('indexRespCodeBlock', 5000); + await testSubjects.find('indexRespCopyButton', 5000); let layerAddReady = false; await retry.waitForWithTimeout('Add layer button ready', 2000, async () => { layerAddReady = await this.importFileButtonEnabled(); @@ -454,21 +454,20 @@ export function GisPageProvider({ getService, getPageObjects }: FtrProviderConte ); } - async getCodeBlockParsedJson(dataTestSubjName: string) { - log.debug(`Get parsed code block for ${dataTestSubjName}`); - const indexRespCodeBlock = await testSubjects.find(`${dataTestSubjName}`); - const indexRespJson = await indexRespCodeBlock.getAttribute('innerText'); - return JSON.parse(indexRespJson); + async clickCopyButton(dataTestSubj: string): Promise { + log.debug(`Click ${dataTestSubj} copy button`); + + await testSubjects.click(dataTestSubj); + + return await browser.getClipboardValue(); } async getIndexResults() { - log.debug('Get index results'); - return await this.getCodeBlockParsedJson('indexRespCodeBlock'); + return JSON.parse(await this.clickCopyButton('indexRespCopyButton')); } async getIndexPatternResults() { - log.debug('Get index pattern results'); - return await this.getCodeBlockParsedJson('indexPatternRespCodeBlock'); + return JSON.parse(await this.clickCopyButton('indexPatternRespCopyButton')); } async setLayerQuery(layerName: string, query: string) { diff --git a/yarn.lock b/yarn.lock index 6c706cffebaaf3..52945b884ab231 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2146,10 +2146,10 @@ dependencies: object-hash "^1.3.0" -"@elastic/charts@25.0.1": - version "25.0.1" - resolved "https://registry.yarnpkg.com/@elastic/charts/-/charts-25.0.1.tgz#7c61fc22887b7b1feba3e52fc1b44f21a9c1d0bc" - integrity sha512-UYGO9Yg2+cdJOOs9DjlYeB2Oy/3UMXTtF6/yWZt2iXh7mmW9jI5DqfjgG/9BFSCwQZHUKBZ58d5ZCQfe72maGA== +"@elastic/charts@25.1.0": + version "25.1.0" + resolved "https://registry.yarnpkg.com/@elastic/charts/-/charts-25.1.0.tgz#8859e07c9822696b3f9b12ae46a18e3316f623fd" + integrity sha512-4IFmyhg3dG7VjP0C9DbMBBAxAtai/HPdG/4Z5UMdGYGoZiJwS+fo50irQtvD3H5Lm6OSS8Xk9hmCVPx8KmdiUg== dependencies: "@popperjs/core" "^2.4.0" chroma-js "^2.1.0"