diff --git a/docs/management/alerting/alert-details.asciidoc b/docs/management/alerting/alert-details.asciidoc new file mode 100644 index 0000000000000..b108f79fe5bad --- /dev/null +++ b/docs/management/alerting/alert-details.asciidoc @@ -0,0 +1,34 @@ +[role="xpack"] +[[alert-details]] +=== Alert details + +beta[] + +The *Alert details* page tells you about the state of the alert and provides granular control over the actions it is taking. + +[role="screenshot"] +image::images/alerts-details-instances-active.png[Alert details page with three alert instances] + +In this example, alerts detect when a site serves more than a threshold number of bytes in a 24 hour period. Three sites are above the threshold. These are called alert instances - occurrences of the condition being detected - and the instance name, status, time of detection, and duration of the condition are shown in this view. + +Upon detection, each instance can trigger one or more actions. If the condition persists, the same actions will trigger either on the next scheduled alert check, or (if defined) after the re-notify period on the alert has passed. To prevent re-notification, you can suppress future actions by clicking on the eye icon to mute an individual alert instance. Muting means that the alert checks continue to run on a schedule, but that instance will not trigger any action. + +[role="screenshot"] +image::images/alerts-details-instance-muting.png[Muting an alert instance] + +Alert instances will come and go from the list depending on whether they meet the alert conditions or not - unless they are muted. If a muted instance no longer meets the alert conditions, it will appear as inactive in the list. This prevents an instance from triggering actions if it reappears in the future. + +[role="screenshot"] +image::images/alerts-details-instances-inactive.png[Alert details page with three inactive alert instances] + +If you want to suppress actions on all current and future instances, you can mute the entire alert. Alert checks continue to run and the instance list will update as instances activate or deactivate, but no actions will be triggered. + +[role="screenshot"] +image::images/alerts-details-muting.png[Use the mute toggle to suppress all action on current and future instances] + +You can also disable an alert altogether. When disabled, the alert stops running checks altogether and will clear any instances it is tracking. You may want to disable alerts that are not currently needed to reduce the load on {kib} and {es}. + +[role="screenshot"] +image::images/alerts-details-disabling.png[Use the disable toggle to turn off alert checks and clear instances tracked] + +* For further information on alerting concepts and examples, see <>. diff --git a/docs/management/alerting/alert-management.asciidoc b/docs/management/alerting/alert-management.asciidoc new file mode 100644 index 0000000000000..caf260937b7be --- /dev/null +++ b/docs/management/alerting/alert-management.asciidoc @@ -0,0 +1,59 @@ +[role="xpack"] +[[alert-management]] +=== Managing Alerts + +beta[] + +The *Alerts* tab provides a cross-app view of alerting. Different {kib} apps like <>, <>, <>, and <> can offer their own alerts, and the *Alerts* tab provides a central place to: + +* <> alerts +* <> including enabling/disabling, muting/unmuting, and deleting +* Drill-down to <> + +[role="screenshot"] +image:management/alerting/images/alerts-and-actions-ui.png[Example alert listing in the Alerts and Actions UI] + +For more information on alerting concepts and the types of alerts and actions available, see <>. + +[float] +==== Finding alerts + +The *Alerts* tab lists all alerts in the current space, including summary information about their execution frequency, tags, and type. + +The *search bar* can be used to quickly find alerts by name or tag. + +[role="screenshot"] +image::images/alerts-filter-by-search.png[Filtering the alerts list using the search bar] + +The *type* dropdown lets you filter to a subset of alert types. + +[role="screenshot"] +image::images/alerts-filter-by-type.png[Filtering the alerts list by types of alert] + +The *Action type* dropdown lets you filter by the type of action used in the alert. + +[role="screenshot"] +image::images/alerts-filter-by-action-type.png[Filtering the alert list by type of action] + +[float] +[[create-edit-alerts]] +==== Creating and editing alerts + +Many alerts must be created within the context of a {kib} app like <>, <>, or <>, but others are generic. Generic alert types can be created in the *Alerts* management UI by clicking the *Create* button. This will launch a flyout that guides you through selecting an alert type and configuring it's properties. Refer to <> for details on what types of alerts are available and how to configure them. + +After an alert is created, you can re-open the flyout and change an alerts properties by clicking the *Edit* button shown on each row of the alert listing. + + +[float] +[[controlling-alerts]] +==== Controlling alerts + +The alert listing allows you to quickly mute/unmute, disable/enable, and delete individual alerts by clicking the action button at the right of each row. + +[role="screenshot"] +image:management/alerting/images/individual-mute-disable.png[The actions button allows an individual alert to be muted, disabled, or deleted] + +These operations can also be performed in bulk by multi-selecting alerts and clicking the *Manage alerts* button: + +[role="screenshot"] +image:management/alerting/images/bulk-mute-disable.png[The Manage alerts button lets you mute/unmute, enable/disable, and delete in bulk] \ No newline at end of file diff --git a/docs/management/alerting/alerts-and-actions-intro.asciidoc b/docs/management/alerting/alerts-and-actions-intro.asciidoc new file mode 100644 index 0000000000000..4674c9ba902be --- /dev/null +++ b/docs/management/alerting/alerts-and-actions-intro.asciidoc @@ -0,0 +1,25 @@ +[role="xpack"] +[[managing-alerts-and-actions]] +== Alerts and Actions + +beta[] + +The *Alerts and Actions* UI lets you <> in a space, and provides tools to <> so that alerts can trigger actions like notification, indexing, and ticketing. + +To manage alerting and connectors, go to *Management > {kib} > Alerts and Actions*. + +[role="screenshot"] +image:management/alerting/images/alerts-and-actions-ui.png[Example alert listing in the Alerts and Actions UI] + +[NOTE] +============================================================================ +Similar to dashboards, alerts and connectors reside in a <>. +The *Alerts and Actions* UI only shows alerts and connectors for the current space. +============================================================================ + +[NOTE] +============================================================================ +{es} also offers alerting capabilities through Watcher, which +can be managed through the <>. See +<> for more information. +============================================================================ \ No newline at end of file diff --git a/docs/management/alerting/connector-management.asciidoc b/docs/management/alerting/connector-management.asciidoc new file mode 100644 index 0000000000000..1002a372f9460 --- /dev/null +++ b/docs/management/alerting/connector-management.asciidoc @@ -0,0 +1,47 @@ +[role="xpack"] +[[connector-management]] +=== Managing Connectors + +beta[] + +Alerts use *Connectors* to route actions to different destinations like log files, ticketing systems, and messaging tools. While each {kib} app can offer their own types of alerts, they typically share connectors. The *Connectors* tab offers a central place to view and manage all the connectors in the current space. + +For more information on connectors and the types of actions available see <>. + +[role="screenshot"] +image::images/connector-listing.png[Example connector listing in the Alerts and Actions UI] + + +[float] +==== Connector list + +The *Connectors* tab lists all connectors in the current space. The *search bar* can be used to find specific connectors by name and/or type. + +[role="screenshot"] +image::images/connector-filter-by-search.png[Filtering the connector list using the search bar] + + +The *type* dropdown also lets you filter to a subset of action types. + +[role="screenshot"] +image::images/connector-filter-by-type.png[Filtering the connector list by types of actions] + +The *Actions* column indicates the number of actions that reference the connector. This count helps you confirm a connector is unused before you delete it, and tells you how many actions will be affected when a connector is modified. + +[role="screenshot"] +image::images/connector-action-count.png[Filtering the connector list by types of actions] + +You can delete individual connectors using the trash icon on the right of each row. Connectors can also be deleted in bulk by multi-selecting them and clicking the *Delete* button to the left of the search box. + +[role="screenshot"] +image::images/connector-delete.png[Deleting connectors individually or in bulk] + +[NOTE] +============================================================================ +You can delete a connector even if there are still actions referencing it. +When this happens the action will fail to execute, and appear as errors in the {kib} logs. +============================================================================ + +==== Creating a new connector + +New connectors can be created by clicking the *Create connector* button, which will guide you to select the type of connector and configure it's properties. Refer to <> for the types of connectors available and how to configure them. Once you create a connector it will be made available to you anytime you set up an action in the current space. \ No newline at end of file diff --git a/docs/management/alerting/images/alerts-and-actions-ui.png b/docs/management/alerting/images/alerts-and-actions-ui.png new file mode 100644 index 0000000000000..acf3f3b1f0be9 Binary files /dev/null and b/docs/management/alerting/images/alerts-and-actions-ui.png differ diff --git a/docs/management/alerting/images/alerts-details-disabling.png b/docs/management/alerting/images/alerts-details-disabling.png new file mode 100644 index 0000000000000..7057afc8ad07d Binary files /dev/null and b/docs/management/alerting/images/alerts-details-disabling.png differ diff --git a/docs/management/alerting/images/alerts-details-instance-muting.png b/docs/management/alerting/images/alerts-details-instance-muting.png new file mode 100644 index 0000000000000..9d26fad419e4f Binary files /dev/null and b/docs/management/alerting/images/alerts-details-instance-muting.png differ diff --git a/docs/management/alerting/images/alerts-details-instances-active.png b/docs/management/alerting/images/alerts-details-instances-active.png new file mode 100644 index 0000000000000..d6895bd4952b8 Binary files /dev/null and b/docs/management/alerting/images/alerts-details-instances-active.png differ diff --git a/docs/management/alerting/images/alerts-details-instances-inactive.png b/docs/management/alerting/images/alerts-details-instances-inactive.png new file mode 100644 index 0000000000000..b049b4ba082f6 Binary files /dev/null and b/docs/management/alerting/images/alerts-details-instances-inactive.png differ diff --git a/docs/management/alerting/images/alerts-details-muting.png b/docs/management/alerting/images/alerts-details-muting.png new file mode 100644 index 0000000000000..9b47d82a74639 Binary files /dev/null and b/docs/management/alerting/images/alerts-details-muting.png differ diff --git a/docs/management/alerting/images/alerts-filter-by-action-type.png b/docs/management/alerting/images/alerts-filter-by-action-type.png new file mode 100644 index 0000000000000..94336a20e1d6c Binary files /dev/null and b/docs/management/alerting/images/alerts-filter-by-action-type.png differ diff --git a/docs/management/alerting/images/alerts-filter-by-search.png b/docs/management/alerting/images/alerts-filter-by-search.png new file mode 100644 index 0000000000000..df4b6d7d9d9aa Binary files /dev/null and b/docs/management/alerting/images/alerts-filter-by-search.png differ diff --git a/docs/management/alerting/images/alerts-filter-by-type.png b/docs/management/alerting/images/alerts-filter-by-type.png new file mode 100644 index 0000000000000..75ffb3ff69bab Binary files /dev/null and b/docs/management/alerting/images/alerts-filter-by-type.png differ diff --git a/docs/management/alerting/images/bulk-mute-disable.png b/docs/management/alerting/images/bulk-mute-disable.png new file mode 100644 index 0000000000000..04cdc3f03f34d Binary files /dev/null and b/docs/management/alerting/images/bulk-mute-disable.png differ diff --git a/docs/management/alerting/images/connector-action-count.png b/docs/management/alerting/images/connector-action-count.png new file mode 100644 index 0000000000000..b792ae2cc11c8 Binary files /dev/null and b/docs/management/alerting/images/connector-action-count.png differ diff --git a/docs/management/alerting/images/connector-delete.png b/docs/management/alerting/images/connector-delete.png new file mode 100644 index 0000000000000..ccb6bcea4bade Binary files /dev/null and b/docs/management/alerting/images/connector-delete.png differ diff --git a/docs/management/alerting/images/connector-filter-by-search.png b/docs/management/alerting/images/connector-filter-by-search.png new file mode 100644 index 0000000000000..1f052ea23a577 Binary files /dev/null and b/docs/management/alerting/images/connector-filter-by-search.png differ diff --git a/docs/management/alerting/images/connector-filter-by-type.png b/docs/management/alerting/images/connector-filter-by-type.png new file mode 100644 index 0000000000000..06c7d6f4dad47 Binary files /dev/null and b/docs/management/alerting/images/connector-filter-by-type.png differ diff --git a/docs/management/alerting/images/connector-listing.png b/docs/management/alerting/images/connector-listing.png new file mode 100644 index 0000000000000..43014ff88057f Binary files /dev/null and b/docs/management/alerting/images/connector-listing.png differ diff --git a/docs/management/alerting/images/individual-mute-disable.png b/docs/management/alerting/images/individual-mute-disable.png new file mode 100644 index 0000000000000..ca00240a4af61 Binary files /dev/null and b/docs/management/alerting/images/individual-mute-disable.png differ diff --git a/docs/settings/alert-action-settings.asciidoc b/docs/settings/alert-action-settings.asciidoc index e3b9e61667bdf..d7f1ec637d1df 100644 --- a/docs/settings/alert-action-settings.asciidoc +++ b/docs/settings/alert-action-settings.asciidoc @@ -27,7 +27,7 @@ If not set, {kib} will generate a random key on startup, but all alert and actio Although the key can be specified in clear text in `kibana.yml`, it's recommended to store this key securely in the <>. [float] -[[alert-settings]] +[[action-settings]] ==== Action settings `xpack.actions.whitelistedHosts`:: @@ -41,7 +41,7 @@ A list of action types that are enabled. It defaults to `[*]`, enabling all type Disabled action types will not appear as an option when creating new connectors, but existing connectors and actions of that type will remain in {kib} and will not function. [float] -[[action-settings]] +[[alert-settings]] ==== Alert settings You do not need to configure any additional settings to use alerting in {kib}. diff --git a/docs/user/alerting/action-types.asciidoc b/docs/user/alerting/action-types.asciidoc new file mode 100644 index 0000000000000..02c09736e1fa0 --- /dev/null +++ b/docs/user/alerting/action-types.asciidoc @@ -0,0 +1,182 @@ +[role="xpack"] +[[action-types]] +== Action and connector types + +{kib} provides the following types of actions: + +* <> +* <> +* <> +* <> +* <> +* <> + +This section describes how to configure connectors and actions for each type. + +[NOTE] +============================================== +Some action types are paid commercial features, while others are free. +For a comparison of the Elastic license levels, +see https://www.elastic.co/subscriptions[the subscription page]. +============================================== + +[float] +[[email-action-type]] +=== 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. + +[float] +[[email-connector-configuration]] +==== Connector configuration + +Email 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. +Sender:: The from address for all emails sent with this connector, specified in `user@host-name` format. +Host:: Host name of the service provider. If you are using the <> setting, make sure this hostname is whitelisted. +Port:: The port to connect to on the service provider. +Secure:: If true the connection will use TLS when connecting to the service provider. See https://nodemailer.com/smtp/#tls-options[nodemailer TLS documentation] for more information. +Username:: username for 'login' type authentication. +Password:: password for 'login' type authentication. + +[float] +[[email-action-configuration]] +==== Action configuration + +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. +Subject:: The subject line of the email. +Message:: The message text of the email. Markdown format is supported. + +[float] +[[index-action-type]] +=== Index + +The index action type will index a document into {es}. + +[float] +[[index-connector-configuration]] +==== Connector configuration + +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. +Refresh:: Setting for the {ref}/docs-refresh.html[refresh] policy for the write request. +Execution time field:: This field will be automatically set to the time the alert condition was detected. + +[float] +[[index-action-configuration]] +==== Action configuration + +Index actions have the following properties: + +Document:: The document to index in json format. + +[float] +[[pagerduty-action-type]] +=== 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-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 whitelisted. +Routing Key:: A 32 character PagerDuty Integration Key for an integration on a service or on a global ruleset. + +[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 unset defaults to `action:`. 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]. + +[float] +[[server-log-action-type]] +=== Server log + +This action type writes and entry to the {kib} server log. + +[float] +[[server-log-connector-configuration]] +==== Connector configuration + +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. + +[float] +[[server-log-action-configuration]] +==== Action configuration + +Server log actions have the following properties: + +Message:: The message to log. + +[float] +[[slack-action-type]] +=== Slack + +The Slack action type uses https://api.slack.com/incoming-webhooks[Slack Incoming Webhooks]. + +[float] +[[slack-connector-configuration]] +==== Connector configuration + +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 whitelisted. + +[float] +[[slack-action-configuration]] +==== Action configuration + +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. + +[float] +[[webhook-action-type]] +=== Webhook + +The Webhook action type uses https://github.com/axios/axios[axios] to send a POST or PUT request to a web service. + +[float] +[[webhook-connector-configuration]] +==== Connector configuration + +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 whitelisted. +Method:: HTTP request method, either `post`(default) or `put`. +Headers:: A set of key-value pairs sent as headers with the request +User:: An optional username. If set, HTTP basic authentication is used. Currently only basic authentication is supported. +Password:: An optional password. If set, HTTP basic authentication is used. Currently only basic authentication is supported. + +[float] +[[webhook-action-configuration]] +==== Action configuration + +Webhook actions have the following properties: + +Body:: A json payload sent to the request URL. \ No newline at end of file diff --git a/docs/user/alerting/alert-types.asciidoc b/docs/user/alerting/alert-types.asciidoc new file mode 100644 index 0000000000000..4a99c70f9d961 --- /dev/null +++ b/docs/user/alerting/alert-types.asciidoc @@ -0,0 +1,115 @@ +[role="xpack"] +[[alert-types]] +== Alert types + +{kib} supplies alerts types in two ways: some are built into {kib}, while domain-specific alert types are registered by {kib} apps such as <>, <>, and <>. + +This section covers built-in alert types. For domain-specific alert types, refer to the documentation for that app. + +Currently {kib} provides one built-in alert type: the <> type. + +[float] +[[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. + +[float] +==== Creating 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::images/alert-types-index-threshold-select.png[Choosing an index threshold alert type] + +[float] +==== Defining the conditions + +The index threshold has 5 clauses that define the condition to detect. + +[role="screenshot"] +image::images/alert-types-index-threshold-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*. +When:: This clause specifies how the value to be compared to the threshold is calculated. The value is calculated by aggregating a numeric field a the *time window*. The aggregation options are: `count`, `average`, `sum`, `min`, and `max`. When using `count` the document count is used, and an aggregation field is not necessary. +Over/Grouped Over:: This clause lets you configure whether the aggregation is applied over all documents, or should be split into groups using a grouping field. If grouping is used, an <> will be created for each group when it exceeds the threshold. To limit the number of instances on high cardinality fields, you must specify the number of groups to check against the threshold. Only the *top* groups are checked. +Threshold:: This clause defines a threshold value and a comparison operator (one of `is above`, `is above or equals`, `is below`, `is below or equals`, or `is between`). The result of the aggregation is compared to this threshold. +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 to a value higher than the *check every* value in the <>, to avoid gaps in detection. + +If data is available and all clauses have been defined, a preview chart will render the threshold value and display a line chart showing the value for the last 30 intervals. This can provide an indication of recent values and their proximity to the threshold, and help you tune the clauses. + +[role="screenshot"] +image::images/alert-types-index-threshold-preview.png[Five clauses define the condition to detect] + +[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. + +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. + +[role="screenshot"] +image::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* + +[role="screenshot"] +image::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*. + +[role="screenshot"] +image::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. + +[role="screenshot"] +image::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. + +[role="screenshot"] +image::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. + +[role="screenshot"] +image::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. + +[role="screenshot"] +image::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). + +[role="screenshot"] +image::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. + +[role="screenshot"] +image::images/alert-types-index-threshold-example-comparison.png[Comparing two time windows] + + + + diff --git a/docs/user/alerting/alerting-scale-performance.asciidoc b/docs/user/alerting/alerting-scale-performance.asciidoc new file mode 100644 index 0000000000000..644a7143f8278 --- /dev/null +++ b/docs/user/alerting/alerting-scale-performance.asciidoc @@ -0,0 +1,28 @@ +[role="xpack"] +[[alerting-scale-performance]] +== Scale and performance + +{kib} alerting run both alert checks and actions as persistent background tasks. This has two major benefits: + +* *Persistence*: all task state and scheduling is stored in {es}, so if {kib} is restarted, alerts and actions will pick up where they left off. +* *Scaling*: multiple {kib} instances can read from and update the same task queue in {es}, allowing the alerting and action load to be distributed across instances. In cases where a {kib} instance no longer has capacity to run alert checks or actions, capacity can be increased by adding additional {kib} instances. + +[float] +=== Running background alert checks and actions + +{kib} background tasks are managed by: + +* Polling an {es} task index for overdue tasks at 3 second intervals. +* Tasks are then claiming them by updating them in the {es} index, using optimistic concurrency control to prevent conflicts. Each {kib} instance can run a maximum of 10 concurrent tasks, so a maximum of 10 tasks are claimed each interval. +* Tasks are run on the {kib} server. +* In the case of alerts which are recurring background checks, upon completion the task is scheduled again according to the <>. + +[IMPORTANT] +============================================== +Because tasks are polled at 3 second intervals and only 10 tasks can run concurrently per {kib} instance, it is possible for alert and action tasks to be run late. This can happen if: + +* Alerts use a small *check interval*. The lowest interval possible is 3 seconds, though intervals of 30 seconds or higher are recommended. +* Many alerts or actions must be *run at once*. In this case pending tasks will queue in {es}, and be pulled 10 at a time from the queue at 3 second intervals. +* *Long running tasks* occupy slots for an extended time, leaving fewer slots for other tasks. + +============================================== \ No newline at end of file diff --git a/docs/user/alerting/defining-alerts.asciidoc b/docs/user/alerting/defining-alerts.asciidoc new file mode 100644 index 0000000000000..89c4c88708d58 --- /dev/null +++ b/docs/user/alerting/defining-alerts.asciidoc @@ -0,0 +1,80 @@ +[role="xpack"] +[[defining-alerts]] +== Defining alerts + +{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 + +When an alert is created in an app, the app will display a flyout panel with three main sections to configure: + +. <> +. <> +. <> + +image::images/alert-flyout-sections.png[The three sections of an alert definition] + +[float] +[[defining-alerts-general-details]] +=== General alert details + +All alert share the following four properties in common: + +[role="screenshot"] +image::images/alert-flyout-general-details.png[All alerts have name, tags, check every, and re-notify every properties in common] + +Name:: The name of the alert. While this name does not have to be unique, the name can be referenced in actions and also appears in the searchable alert listing in the management UI. A distinctive name can help identify and find an alert. +Tags:: A list of tag names that can be applied to an alert. Tags can help you organize and find alerts, because tags appear in the alert listing in the management UI which is searchable by tag. +Check every:: This value determines how frequently the alert conditions below are checked. Note that the timing of background alert checks are not guaranteed, particularly for intervals of less than 10 seconds. See <> for more information. +Re-notify every:: This value limits how often actions are repeated when an alert instance remains active across alert checks. See <> for more information. + +[float] +[[defining-alerts-type-conditions]] +=== Alert type and conditions + +Depending upon the {kib} app and context, you may be prompted to choose the type of alert you wish to create. Some apps will pre-select the type of alert for you. + +[role="screenshot"] +image::images/alert-flyout-alert-type-selection.png[Choosing the type of alert to create] + +Each alert type provides its own way of defining the conditions to detect, but an expression formed by a series of clauses is a common pattern. Each clause has a UI control that allows you to define the clause. For example, in an index threshold alert the `WHEN` clause allows you to select an aggregation operation to apply to a numeric field. + +[role="screenshot"] +image::images/alert-flyout-alert-conditions.png[UI for defining alert conditions on an index threshold alert] + +[float] +[[defining-alerts-actions-details]] +=== Action type and action details + +To add an action to an alert, you first select the type of action: + +[role="screenshot"] +image::images/alert-flyout-action-type-selection.png[UI for selecting an action type] + +Each action must specify a <> instance. If no connectors exist for that action type, click "Add new" to create one. + +Each action type exposes different properties. For example an email action allows you to set the recipients, the subject, and a message body in markdown format. See <> for details on the types of actions provided by {kib} and their properties. + +[role="screenshot"] +image::images/alert-flyout-action-details.png[UI for defining an email action] + +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. Available variables differ by alert type, and a list can be accessed using the "add variable" button at the right of the text box. + +[role="screenshot"] +image::images/alert-flyout-action-variables.png[Passing alert values to an action] + +You can attach more than one action. Clicking the "Add action" button will prompt you to select another alert type and repeat the above steps again. + +[role="screenshot"] +image::images/alert-flyout-add-action.png[You can add multiple actions on an alert] + +[NOTE] +============================================== +Actions are not required on alerts. In some cases you may want to run an alert without actions first to understand its behavior, and configure actions later. +============================================== + +[float] +=== Managing alerts + +To modify an alert after it was created, including muting or disabling it, use the <>. \ No newline at end of file diff --git a/docs/user/alerting/images/alert-concepts-connectors.svg b/docs/user/alerting/images/alert-concepts-connectors.svg new file mode 100644 index 0000000000000..9ae4c21ee5870 --- /dev/null +++ b/docs/user/alerting/images/alert-concepts-connectors.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/docs/user/alerting/images/alert-concepts-summary.svg b/docs/user/alerting/images/alert-concepts-summary.svg new file mode 100644 index 0000000000000..d11023b706418 --- /dev/null +++ b/docs/user/alerting/images/alert-concepts-summary.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/docs/user/alerting/images/alert-flyout-action-details.png b/docs/user/alerting/images/alert-flyout-action-details.png new file mode 100644 index 0000000000000..06287ed1837d2 Binary files /dev/null and b/docs/user/alerting/images/alert-flyout-action-details.png differ diff --git a/docs/user/alerting/images/alert-flyout-action-type-selection.png b/docs/user/alerting/images/alert-flyout-action-type-selection.png new file mode 100644 index 0000000000000..e4448ca5f3fcd Binary files /dev/null and b/docs/user/alerting/images/alert-flyout-action-type-selection.png differ diff --git a/docs/user/alerting/images/alert-flyout-action-variables.png b/docs/user/alerting/images/alert-flyout-action-variables.png new file mode 100644 index 0000000000000..73fc1fe9dea63 Binary files /dev/null and b/docs/user/alerting/images/alert-flyout-action-variables.png differ diff --git a/docs/user/alerting/images/alert-flyout-add-action.png b/docs/user/alerting/images/alert-flyout-add-action.png new file mode 100644 index 0000000000000..159dbd5c1e449 Binary files /dev/null and b/docs/user/alerting/images/alert-flyout-add-action.png differ diff --git a/docs/user/alerting/images/alert-flyout-alert-conditions.png b/docs/user/alerting/images/alert-flyout-alert-conditions.png new file mode 100644 index 0000000000000..f3e8f42ff0f37 Binary files /dev/null and b/docs/user/alerting/images/alert-flyout-alert-conditions.png differ diff --git a/docs/user/alerting/images/alert-flyout-alert-type-selection.png b/docs/user/alerting/images/alert-flyout-alert-type-selection.png new file mode 100644 index 0000000000000..a0a25dc5f1bbc Binary files /dev/null and b/docs/user/alerting/images/alert-flyout-alert-type-selection.png differ diff --git a/docs/user/alerting/images/alert-flyout-general-details.png b/docs/user/alerting/images/alert-flyout-general-details.png new file mode 100644 index 0000000000000..db56c16c1c308 Binary files /dev/null and b/docs/user/alerting/images/alert-flyout-general-details.png differ diff --git a/docs/user/alerting/images/alert-flyout-sections.png b/docs/user/alerting/images/alert-flyout-sections.png new file mode 100644 index 0000000000000..8fa4bfffe39a3 Binary files /dev/null and b/docs/user/alerting/images/alert-flyout-sections.png differ diff --git a/docs/user/alerting/images/alert-instances.svg b/docs/user/alerting/images/alert-instances.svg new file mode 100644 index 0000000000000..b7b0bd4996053 --- /dev/null +++ b/docs/user/alerting/images/alert-instances.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/docs/user/alerting/images/alert-types-index-threshold-conditions.png b/docs/user/alerting/images/alert-types-index-threshold-conditions.png new file mode 100644 index 0000000000000..356732dfb9777 Binary files /dev/null and b/docs/user/alerting/images/alert-types-index-threshold-conditions.png differ diff --git a/docs/user/alerting/images/alert-types-index-threshold-example-aggregation.png b/docs/user/alerting/images/alert-types-index-threshold-example-aggregation.png new file mode 100644 index 0000000000000..fc40da7436547 Binary files /dev/null and b/docs/user/alerting/images/alert-types-index-threshold-example-aggregation.png differ diff --git a/docs/user/alerting/images/alert-types-index-threshold-example-comparison.png b/docs/user/alerting/images/alert-types-index-threshold-example-comparison.png new file mode 100644 index 0000000000000..5e7c65e1247d8 Binary files /dev/null and b/docs/user/alerting/images/alert-types-index-threshold-example-comparison.png differ diff --git a/docs/user/alerting/images/alert-types-index-threshold-example-grouping.png b/docs/user/alerting/images/alert-types-index-threshold-example-grouping.png new file mode 100644 index 0000000000000..ea3a3849c8927 Binary files /dev/null and b/docs/user/alerting/images/alert-types-index-threshold-example-grouping.png differ diff --git a/docs/user/alerting/images/alert-types-index-threshold-example-index.png b/docs/user/alerting/images/alert-types-index-threshold-example-index.png new file mode 100644 index 0000000000000..8f818f7001278 Binary files /dev/null and b/docs/user/alerting/images/alert-types-index-threshold-example-index.png differ diff --git a/docs/user/alerting/images/alert-types-index-threshold-example-preview.png b/docs/user/alerting/images/alert-types-index-threshold-example-preview.png new file mode 100644 index 0000000000000..b5d9c38d99810 Binary files /dev/null and b/docs/user/alerting/images/alert-types-index-threshold-example-preview.png differ diff --git a/docs/user/alerting/images/alert-types-index-threshold-example-threshold.png b/docs/user/alerting/images/alert-types-index-threshold-example-threshold.png new file mode 100644 index 0000000000000..9c51807b8d219 Binary files /dev/null and b/docs/user/alerting/images/alert-types-index-threshold-example-threshold.png differ diff --git a/docs/user/alerting/images/alert-types-index-threshold-example-timefield.png b/docs/user/alerting/images/alert-types-index-threshold-example-timefield.png new file mode 100644 index 0000000000000..24e4e03f829ce Binary files /dev/null and b/docs/user/alerting/images/alert-types-index-threshold-example-timefield.png differ diff --git a/docs/user/alerting/images/alert-types-index-threshold-example-window.png b/docs/user/alerting/images/alert-types-index-threshold-example-window.png new file mode 100644 index 0000000000000..5405415958485 Binary files /dev/null and b/docs/user/alerting/images/alert-types-index-threshold-example-window.png differ diff --git a/docs/user/alerting/images/alert-types-index-threshold-preview.png b/docs/user/alerting/images/alert-types-index-threshold-preview.png new file mode 100644 index 0000000000000..3709f162b612b Binary files /dev/null and b/docs/user/alerting/images/alert-types-index-threshold-preview.png differ diff --git a/docs/user/alerting/images/alert-types-index-threshold-select.png b/docs/user/alerting/images/alert-types-index-threshold-select.png new file mode 100644 index 0000000000000..0c2776e01b962 Binary files /dev/null and b/docs/user/alerting/images/alert-types-index-threshold-select.png differ diff --git a/docs/user/alerting/images/alerting-overview.png b/docs/user/alerting/images/alerting-overview.png new file mode 100644 index 0000000000000..383bc8c2ce015 Binary files /dev/null and b/docs/user/alerting/images/alerting-overview.png differ diff --git a/docs/user/alerting/images/what-is-an-action.svg b/docs/user/alerting/images/what-is-an-action.svg new file mode 100644 index 0000000000000..7675f717a6c84 --- /dev/null +++ b/docs/user/alerting/images/what-is-an-action.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/docs/user/alerting/images/what-is-an-alert.svg b/docs/user/alerting/images/what-is-an-alert.svg new file mode 100644 index 0000000000000..b4dc02fae39a5 --- /dev/null +++ b/docs/user/alerting/images/what-is-an-alert.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/docs/user/alerting/index.asciidoc b/docs/user/alerting/index.asciidoc new file mode 100644 index 0000000000000..b4f7e6af3d61c --- /dev/null +++ b/docs/user/alerting/index.asciidoc @@ -0,0 +1,202 @@ +[role="xpack"] +[[alerting-getting-started]] += Alerting and Actions + +beta[] + +-- + +Alerting allows you to detect complex conditions within different {kib} apps and trigger actions when those conditions are met. Alerting is integrated with <>, <>, <>, <>, can be centrally managed from the <> UI, and provides a set of built-in <> and <> for you to use. + +image::images/alerting-overview.png[Alerts and actions UI] + +[IMPORTANT] +============================================== +To make sure you can access alerting and actions, see the <> section. +============================================== + +[float] +== Concepts and terminology + +*Alerts* work by running checks on a schedule to detect conditions. When a condition is met, the alert tracks it as an *alert instance* and responds by triggering one or more *actions*. +Actions typically involve interaction with {kib} services or third party integrations. *Connectors* allow actions to talk to these services and integrations. +This section describes all of these elements and how they operate together. + +[float] +=== What is an alert? + +An alert specifies a background task that runs on the {kib} server to check for specific conditions. It consists of three main parts: + +* *Conditions*: what needs to be detected? +* *Schedule*: when/how often should detection checks run? +* *Actions*: what happens when a condition is detected? + +For example, when monitoring a set of servers, an alert might check for average CPU usage > 0.9 on each server for the two minutes (condition), checked every minute (schedule), sending a warning email message via SMTP with subject `CPU on {{server}} is high` (action). + +image::images/what-is-an-alert.svg[Three components of an alert] + +The following sections each part of the alert is described in more detail. + +[float] +[[alerting-concepts-conditions]] +==== Conditions + +Under the hood, {kib} alerts detect conditions by running javascript function on the {kib} server, which gives it flexibility to support a wide range of detections, anything from the results of a simple {es} query to heavy computations involving data from multiple sources or external systems. + +These detections are packaged and exposed as *alert types*. An alert type hides the underlying details of the detection, and exposes a set of parameters +to control the details of the conditions to detect. + +For example, an <> lets you specify the index to query, an aggregation field, and a time window, but the details of the underlying {es} query are hidden. + +See <> for the types of alerts provided by {kib} and how they express their conditions. + +[float] +[[alerting-concepts-scheduling]] +==== Schedule + +Alert schedules are defined as an interval between subsequent checks, and can range from a few seconds to months. + +[IMPORTANT] +============================================== +The intervals of alert checks in {kib} are approximate, their timing of their execution is affected by factors such as the frequency at which tasks are claimed and the task load on the system. See <> for more information. +============================================== + +[float] +[[alerting-concepts-actions]] +==== Actions + +Actions are invocations of {kib} services or integrations with third-party systems, that run as background tasks on the {kib} server when alert conditions are met. + +When defining actions in an alert, you specify +* the *action type*: the type of service or integration to use> +* the connection for that type by referencing a <>. +* a mapping of alert values to properties exposed for that type of action. + +The result is a template: all the parameters needed to invoke a service are supplied except for specific values that are only known at the time the alert condition is detected. + +In the server monitoring example, the `email` action type is used, and `server` is mapped to the body of the email, using the template string `CPU on {{server}} is high`. + +When the alert detects the condition, it creates an <> containing the details of the condition, renders the template with these details such as server name, and executes the action on the {kib} server by invoking the `email` action type. + +image::images/what-is-an-action.svg[Actions are like templates that are rendered when an alert detects a condition] + +See <> for details on the types of actions provided by {kib}. + +[float] +[[alerting-concepts-alert-instances]] +=== Alert instances + +When checking for a condition, an alert might identify multiple occurrences of the condition. {kib} tracks each of these *alert instances* separately and takes action per instance. + +Using the server monitoring example, each server with average CPU > 0.9 is tracked as an alert instance. This means a separate email is sent for each server that exceeds the threshold. + +image::images/alert-instances.svg[{kib} tracks each detected condition as an alert instance and takes action on each instance] + +[float] +[[alerting-concepts-suppressing-duplicate-notifications]] +=== Suppressing duplicate notifications + +Since actions are taken per instance, alerts can end up generating a large number of actions. Take the following example where an alert is monitoring three servers every minute for CPU usage > 0.9: + +* Minute 1: server X123 > 0.9. *One email* is sent for server X123. +* Minute 2: X123 and Y456 > 0.9. *Two emails* are sent, on for X123 and one for Y456. +* Minute 3: X123, Y456, Z789 > 0.9. *Three emails* are sent, one for each of X123, Y456, Z789. + +In the above example, three emails are sent for server X123 in the span of 3 minutes for the same condition. Often it's desirable to suppress frequent re-notification. Operations like muting and re-notification throttling can be applied at the instance level. If we set the alert re-notify interval to 5 minutes, we reduce noise by only getting emails for new servers that exceed the threshold: + +* Minute 1: server X123 > 0.9. *One email* is sent for server X123. +* Minute 2: X123 and Y456 > 0.9. *One email* is sent for Y456 +* Minute 3: X123, Y456, Z789 > 0.9. *One email* is sent for Z789. + +[float] +[[alerting-concepts-connectors]] +=== Connectors + +Actions often involve connecting with services inside {kib} or integrations with third-party systems. +Rather than repeatedly entering connection information and credentials for each action, {kib} simplifies action setup using *connectors*. + +*Connectors* provide a central place to store connection information for services and integrations. For example if four alerts send email notifications via the same SMTP service, +they all reference the same SMTP connector. When the SMTP settings change they are updated once in the connector, instead of having to update four alerts. + +image::images/alert-concepts-connectors.svg[Connectors provide a central place to store service connection settings] + +[float] +=== Summary + +An _alert_ consists of conditions, _actions_, and a schedule. When conditions are met, _alert instances_ are created that render _actions_ and invoke them. To make action setup and update easier, actions refer to _connectors_ that centralize the information used to connect with {kib} services and third-party integrations. + +image::images/alert-concepts-summary.svg[Alerts, actions, alert instances and connectors work together to convert detection into action] + +* *Alert*: a specification of the conditions to be detected, the schedule for detection, and the response when detection occurs. +* *Action*: the response to a detected condition defined in the alert. Typically actions specify a service or third party integration along with alert details that will be sent to it. +* *Alert instance*: state tracked by {kib} for every occurrence of a detected condition. Actions as well as controls like muting and re-notification are controlled at the instance level. +* *Connector*: centralized configurations for services and third party integration that are referenced by actions. + +[float] +[[alerting-concepts-differences]] +== Differences from Watcher + +{kib} alerting and <> are both used to detect conditions and can trigger actions in response, but they are completely independent alerting systems. + +This section will clarify some of the important differences in the function and intent of the two systems. + +Functionally, {kib} alerting differs in that: + +* Scheduled checks are run on {kib} instead of {es} +* {kib} <> through *alert types*, whereas watches provide low-level control over inputs, conditions, and transformations. +* {kib} alerts tracks and persists the state of each detected condition through *alert instances*. This makes it possible to mute and throttle individual instances, and detect changes in state such as resolution. +* Actions are linked to *alert instances* in {kib} alerting. Actions are fired for each occurrence of a detected condition, rather than for the entire alert. + +At a higher level, {kib} alerts allow rich integrations across use cases like <>, <>, <>, and <>. +Pre-packaged *alert types* simplify setup, hide the details complex domain-specific detections, while providing a consistent interface across {kib}. + +[float] +[[alerting-setup-prerequisites]] +== Setup and prerequisites + +If you are using an *on-premises* Elastic Stack deployment with <>: + +* TLS must be configured for communication <>. {kib} alerting uses <> to secure background alert checks and actions, and API keys require {ref}/configuring-tls.html#tls-http[TLS on the HTTP interface]. +* In the kibana.yml configuration file, add the <> + +[float] +[[alerting-security]] +== Security + +To access alerting in a space, a user must have access to one of the following features: +* <> +* <> +* <> +* <> + +See <> for more information on configuring roles that provide access to these features. + +[float] +[[alerting-spaces]] +=== Space isolation + +Alerts and connectors are isolated to the {kib} space in which they were created. An alert or connector created in one space will not be visible in another. + +[float] +[[alerting-authorization]] +=== Authorization + +Alerts, including all background detection and the actions they generate are authorized using an <> associated with the last user to edit the alert. Upon creating or modifying an alert, an API key is generated for that user, capturing a snapshot of their privileges at that moment in time. The API key is then used to run all background tasks associated with the alert including detection checks and executing actions. + +[IMPORTANT] +============================================== +If an alert requires certain privileges to run such as index privileges, keep in mind that if a user without those privileges updates the alert, the alert will no longer function. +============================================== + +[float] +[[alerting-restricting-actions]] +=== Restricting actions + +For security reasons you may wish to limit the extent to which {kib} can connect to external services. <> allows you to disable certain <> and whitelist the hostnames that {kib} can connect with. + +-- + +include::defining-alerts.asciidoc[] +include::action-types.asciidoc[] +include::alert-types.asciidoc[] +include::alerting-scale-performance.asciidoc[] diff --git a/docs/user/index.asciidoc b/docs/user/index.asciidoc index ff100d0763368..0f53497716552 100644 --- a/docs/user/index.asciidoc +++ b/docs/user/index.asciidoc @@ -40,6 +40,8 @@ include::management.asciidoc[] include::reporting/index.asciidoc[] +include::alerting/index.asciidoc[] + include::api.asciidoc[] include::plugins.asciidoc[] diff --git a/docs/user/management.asciidoc b/docs/user/management.asciidoc index 34a3790529ca3..fa34802abe2a9 100644 --- a/docs/user/management.asciidoc +++ b/docs/user/management.asciidoc @@ -83,6 +83,10 @@ a| <> Customize {kib} to suit your needs. Change the format for displaying dates, turn on dark mode, set the timespan for notification messages, and much more. +| <> + +Centrally manage your alerts from across {kib}. Create and manage re-usable connectors for triggering actions. + | <> Create and manage the index patterns that help you retrieve your data from {es}. @@ -111,6 +115,14 @@ so you can tailor it to your needs without impacting others. include::{kib-repo-dir}/management/advanced-options.asciidoc[] +include::{kib-repo-dir}/management/alerting/alerts-and-actions-intro.asciidoc[] + +include::{kib-repo-dir}/management/alerting/alert-management.asciidoc[] + +include::{kib-repo-dir}/management/alerting/alert-details.asciidoc[] + +include::{kib-repo-dir}/management/alerting/connector-management.asciidoc[] + include::{kib-repo-dir}/management/managing-beats.asciidoc[] include::{kib-repo-dir}/management/index-lifecycle-policies/intro-to-lifecycle-policies.asciidoc[] diff --git a/src/legacy/core_plugins/kibana/public/home/tutorial_resources/logos/activemq.svg b/src/legacy/core_plugins/kibana/public/home/tutorial_resources/logos/activemq.svg index 20694ba6e62c7..8d525c23e6801 100644 --- a/src/legacy/core_plugins/kibana/public/home/tutorial_resources/logos/activemq.svg +++ b/src/legacy/core_plugins/kibana/public/home/tutorial_resources/logos/activemq.svg @@ -1,31 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/src/legacy/core_plugins/kibana/public/home/tutorial_resources/logos/azure.svg b/src/legacy/core_plugins/kibana/public/home/tutorial_resources/logos/azure.svg index f8df12ba05c50..a93c83b4b4ae0 100644 --- a/src/legacy/core_plugins/kibana/public/home/tutorial_resources/logos/azure.svg +++ b/src/legacy/core_plugins/kibana/public/home/tutorial_resources/logos/azure.svg @@ -1,17 +1 @@ - - - - - - - - - + \ No newline at end of file diff --git a/src/legacy/core_plugins/kibana/public/home/tutorial_resources/logos/cisco.svg b/src/legacy/core_plugins/kibana/public/home/tutorial_resources/logos/cisco.svg new file mode 100644 index 0000000000000..20ebebf19741e --- /dev/null +++ b/src/legacy/core_plugins/kibana/public/home/tutorial_resources/logos/cisco.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/legacy/core_plugins/kibana/public/home/tutorial_resources/logos/cockroachdb.svg b/src/legacy/core_plugins/kibana/public/home/tutorial_resources/logos/cockroachdb.svg index 72f0958f52824..08a4bdabb380f 100644 --- a/src/legacy/core_plugins/kibana/public/home/tutorial_resources/logos/cockroachdb.svg +++ b/src/legacy/core_plugins/kibana/public/home/tutorial_resources/logos/cockroachdb.svg @@ -1,666 +1 @@ - - - -image/svg+xml - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/src/legacy/core_plugins/kibana/public/home/tutorial_resources/logos/consul.svg b/src/legacy/core_plugins/kibana/public/home/tutorial_resources/logos/consul.svg index 28bbadd24c8a6..5ef8feaded689 100644 --- a/src/legacy/core_plugins/kibana/public/home/tutorial_resources/logos/consul.svg +++ b/src/legacy/core_plugins/kibana/public/home/tutorial_resources/logos/consul.svg @@ -1 +1 @@ -Asset 1 \ No newline at end of file + \ No newline at end of file diff --git a/src/legacy/core_plugins/kibana/public/home/tutorial_resources/logos/coredns.svg b/src/legacy/core_plugins/kibana/public/home/tutorial_resources/logos/coredns.svg index 863a81e0f40e7..e38616a15a11c 100644 --- a/src/legacy/core_plugins/kibana/public/home/tutorial_resources/logos/coredns.svg +++ b/src/legacy/core_plugins/kibana/public/home/tutorial_resources/logos/coredns.svg @@ -1 +1 @@ -CoreDNS_Colour_Icon + \ No newline at end of file diff --git a/src/legacy/core_plugins/kibana/public/home/tutorial_resources/logos/couchdb.svg b/src/legacy/core_plugins/kibana/public/home/tutorial_resources/logos/couchdb.svg index 2512c2eb2a011..3c3ecb66d8c87 100644 --- a/src/legacy/core_plugins/kibana/public/home/tutorial_resources/logos/couchdb.svg +++ b/src/legacy/core_plugins/kibana/public/home/tutorial_resources/logos/couchdb.svg @@ -1,86 +1 @@ - - - -image/svg+xml \ No newline at end of file + \ No newline at end of file diff --git a/src/legacy/core_plugins/kibana/public/home/tutorial_resources/logos/envoyproxy.svg b/src/legacy/core_plugins/kibana/public/home/tutorial_resources/logos/envoyproxy.svg index 45c995b19603b..a22132d415c40 100644 --- a/src/legacy/core_plugins/kibana/public/home/tutorial_resources/logos/envoyproxy.svg +++ b/src/legacy/core_plugins/kibana/public/home/tutorial_resources/logos/envoyproxy.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/src/legacy/core_plugins/kibana/public/home/tutorial_resources/logos/ibmmq.svg b/src/legacy/core_plugins/kibana/public/home/tutorial_resources/logos/ibmmq.svg index e474d93359beb..396d5a67a20eb 100644 --- a/src/legacy/core_plugins/kibana/public/home/tutorial_resources/logos/ibmmq.svg +++ b/src/legacy/core_plugins/kibana/public/home/tutorial_resources/logos/ibmmq.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/src/legacy/core_plugins/kibana/public/home/tutorial_resources/logos/iis.svg b/src/legacy/core_plugins/kibana/public/home/tutorial_resources/logos/iis.svg new file mode 100644 index 0000000000000..99964448d33c5 --- /dev/null +++ b/src/legacy/core_plugins/kibana/public/home/tutorial_resources/logos/iis.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/legacy/core_plugins/kibana/public/home/tutorial_resources/logos/mssql.svg b/src/legacy/core_plugins/kibana/public/home/tutorial_resources/logos/mssql.svg new file mode 100644 index 0000000000000..738507c5809c0 --- /dev/null +++ b/src/legacy/core_plugins/kibana/public/home/tutorial_resources/logos/mssql.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/legacy/core_plugins/kibana/public/home/tutorial_resources/logos/munin.svg b/src/legacy/core_plugins/kibana/public/home/tutorial_resources/logos/munin.svg new file mode 100644 index 0000000000000..b35a39498c9ec --- /dev/null +++ b/src/legacy/core_plugins/kibana/public/home/tutorial_resources/logos/munin.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/legacy/core_plugins/kibana/public/home/tutorial_resources/logos/nats.svg b/src/legacy/core_plugins/kibana/public/home/tutorial_resources/logos/nats.svg index f7593c51a4c42..5a1d6e9a52f17 100644 --- a/src/legacy/core_plugins/kibana/public/home/tutorial_resources/logos/nats.svg +++ b/src/legacy/core_plugins/kibana/public/home/tutorial_resources/logos/nats.svg @@ -1,102 +1 @@ - - - - - - image/svg+xml - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/src/legacy/core_plugins/kibana/public/home/tutorial_resources/logos/openmetrics.svg b/src/legacy/core_plugins/kibana/public/home/tutorial_resources/logos/openmetrics.svg index feccb88a3f34b..1a00be6ab30a2 100644 --- a/src/legacy/core_plugins/kibana/public/home/tutorial_resources/logos/openmetrics.svg +++ b/src/legacy/core_plugins/kibana/public/home/tutorial_resources/logos/openmetrics.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/src/legacy/core_plugins/kibana/public/home/tutorial_resources/logos/statsd.svg b/src/legacy/core_plugins/kibana/public/home/tutorial_resources/logos/statsd.svg index f4458439fceb4..a745cd71efafe 100644 --- a/src/legacy/core_plugins/kibana/public/home/tutorial_resources/logos/statsd.svg +++ b/src/legacy/core_plugins/kibana/public/home/tutorial_resources/logos/statsd.svg @@ -1,41 +1 @@ - - - - - - - - - - + \ No newline at end of file diff --git a/src/legacy/core_plugins/kibana/public/home/tutorial_resources/logos/suricata.svg b/src/legacy/core_plugins/kibana/public/home/tutorial_resources/logos/suricata.svg new file mode 100644 index 0000000000000..06e627a7e4ba7 --- /dev/null +++ b/src/legacy/core_plugins/kibana/public/home/tutorial_resources/logos/suricata.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/legacy/core_plugins/kibana/public/home/tutorial_resources/logos/system.svg b/src/legacy/core_plugins/kibana/public/home/tutorial_resources/logos/system.svg new file mode 100644 index 0000000000000..0aba96275e24e --- /dev/null +++ b/src/legacy/core_plugins/kibana/public/home/tutorial_resources/logos/system.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/legacy/core_plugins/kibana/public/home/tutorial_resources/logos/traefik.svg b/src/legacy/core_plugins/kibana/public/home/tutorial_resources/logos/traefik.svg index 8ee3448f5626e..10b38261eca5e 100644 --- a/src/legacy/core_plugins/kibana/public/home/tutorial_resources/logos/traefik.svg +++ b/src/legacy/core_plugins/kibana/public/home/tutorial_resources/logos/traefik.svg @@ -1,342 +1 @@ - - - -image/svg+xml \ No newline at end of file + \ No newline at end of file diff --git a/src/legacy/core_plugins/kibana/public/home/tutorial_resources/logos/ubiquiti.svg b/src/legacy/core_plugins/kibana/public/home/tutorial_resources/logos/ubiquiti.svg new file mode 100644 index 0000000000000..99a911e32863e --- /dev/null +++ b/src/legacy/core_plugins/kibana/public/home/tutorial_resources/logos/ubiquiti.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/legacy/core_plugins/kibana/public/home/tutorial_resources/logos/uwsgi.svg b/src/legacy/core_plugins/kibana/public/home/tutorial_resources/logos/uwsgi.svg new file mode 100644 index 0000000000000..43818ab211ee3 --- /dev/null +++ b/src/legacy/core_plugins/kibana/public/home/tutorial_resources/logos/uwsgi.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/legacy/core_plugins/kibana/public/home/tutorial_resources/logos/vsphere.svg b/src/legacy/core_plugins/kibana/public/home/tutorial_resources/logos/vsphere.svg new file mode 100644 index 0000000000000..2a04026e46432 --- /dev/null +++ b/src/legacy/core_plugins/kibana/public/home/tutorial_resources/logos/vsphere.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/legacy/core_plugins/kibana/public/home/tutorial_resources/logos/zeek.svg b/src/legacy/core_plugins/kibana/public/home/tutorial_resources/logos/zeek.svg new file mode 100644 index 0000000000000..0e346f98c7238 --- /dev/null +++ b/src/legacy/core_plugins/kibana/public/home/tutorial_resources/logos/zeek.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/legacy/core_plugins/kibana/public/home/tutorial_resources/logos/zookeeper.svg b/src/legacy/core_plugins/kibana/public/home/tutorial_resources/logos/zookeeper.svg new file mode 100644 index 0000000000000..80db65f670d1d --- /dev/null +++ b/src/legacy/core_plugins/kibana/public/home/tutorial_resources/logos/zookeeper.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/plugins/home/server/tutorials/cisco_logs/index.ts b/src/plugins/home/server/tutorials/cisco_logs/index.ts index 303dbd9a9d856..a694802663171 100644 --- a/src/plugins/home/server/tutorials/cisco_logs/index.ts +++ b/src/plugins/home/server/tutorials/cisco_logs/index.ts @@ -50,7 +50,7 @@ supports the "asa" fileset for Cisco ASA firewall logs received over syslog or r learnMoreLink: '{config.docs.beats.filebeat}/filebeat-module-cisco.html', }, }), - // euiIconType: 'logoCisco', + euiIconType: '/plugins/kibana/home/tutorial_resources/logos/cisco.svg', artifacts: { dashboards: [], application: { diff --git a/src/plugins/home/server/tutorials/envoyproxy_logs/index.ts b/src/plugins/home/server/tutorials/envoyproxy_logs/index.ts index ac2db66dff6b6..53803a9358a14 100644 --- a/src/plugins/home/server/tutorials/envoyproxy_logs/index.ts +++ b/src/plugins/home/server/tutorials/envoyproxy_logs/index.ts @@ -50,7 +50,7 @@ It supports both standalone deployment and Envoy proxy deployment in Kubernetes. learnMoreLink: '{config.docs.beats.filebeat}/filebeat-module-envoyproxy.html', }, }), - // euiIconType: 'logoCisco', + euiIconType: '/plugins/kibana/home/tutorial_resources/logos/envoyproxy.svg', artifacts: { dashboards: [], application: { diff --git a/src/plugins/home/server/tutorials/iis_logs/index.ts b/src/plugins/home/server/tutorials/iis_logs/index.ts index ff9996c1b0187..82ce098018e0b 100644 --- a/src/plugins/home/server/tutorials/iis_logs/index.ts +++ b/src/plugins/home/server/tutorials/iis_logs/index.ts @@ -49,7 +49,7 @@ export function iisLogsSpecProvider(context: TutorialContext): TutorialSchema { learnMoreLink: '{config.docs.beats.filebeat}/filebeat-module-iis.html', }, }), - // euiIconType: 'logoIIS', + euiIconType: '/plugins/kibana/home/tutorial_resources/logos/iis.svg', artifacts: { dashboards: [ { diff --git a/src/plugins/home/server/tutorials/iptables_logs/index.ts b/src/plugins/home/server/tutorials/iptables_logs/index.ts index e3f2124347b6b..b29ab20cb6653 100644 --- a/src/plugins/home/server/tutorials/iptables_logs/index.ts +++ b/src/plugins/home/server/tutorials/iptables_logs/index.ts @@ -52,7 +52,7 @@ number and the action performed on the traffic (allow/deny).. \ learnMoreLink: '{config.docs.beats.filebeat}/filebeat-module-iptables.html', }, }), - // euiIconType: 'logoUbiquiti', + euiIconType: '/plugins/kibana/home/tutorial_resources/logos/ubiquiti.svg', artifacts: { dashboards: [], application: { diff --git a/src/plugins/home/server/tutorials/mssql_metrics/index.ts b/src/plugins/home/server/tutorials/mssql_metrics/index.ts index cea46c3220d5a..a1c994d670a3d 100644 --- a/src/plugins/home/server/tutorials/mssql_metrics/index.ts +++ b/src/plugins/home/server/tutorials/mssql_metrics/index.ts @@ -48,7 +48,7 @@ export function mssqlMetricsSpecProvider(context: TutorialContext): TutorialSche learnMoreLink: '{config.docs.beats.metricbeat}/metricbeat-module-mssql.html', }, }), - // euiIconType: 'logoMSSQL', + euiIconType: '/plugins/kibana/home/tutorial_resources/logos/mssql.svg', isBeta: false, artifacts: { dashboards: [ diff --git a/src/plugins/home/server/tutorials/munin_metrics/index.ts b/src/plugins/home/server/tutorials/munin_metrics/index.ts index e438d3015c77c..90e4ac6026dad 100644 --- a/src/plugins/home/server/tutorials/munin_metrics/index.ts +++ b/src/plugins/home/server/tutorials/munin_metrics/index.ts @@ -36,6 +36,7 @@ export function muninMetricsSpecProvider(context: TutorialContext): TutorialSche name: i18n.translate('home.tutorials.muninMetrics.nameTitle', { defaultMessage: 'Munin metrics', }), + euiIconType: '/plugins/kibana/home/tutorial_resources/logos/munin.svg', isBeta: true, category: TutorialsCategory.METRICS, shortDescription: i18n.translate('home.tutorials.muninMetrics.shortDescription', { diff --git a/src/plugins/home/server/tutorials/suricata_logs/index.ts b/src/plugins/home/server/tutorials/suricata_logs/index.ts index ac19cf0987b84..a3812fda147f5 100644 --- a/src/plugins/home/server/tutorials/suricata_logs/index.ts +++ b/src/plugins/home/server/tutorials/suricata_logs/index.ts @@ -50,7 +50,7 @@ export function suricataLogsSpecProvider(context: TutorialContext): TutorialSche learnMoreLink: '{config.docs.beats.filebeat}/filebeat-module-suricata.html', }, }), - // euiIconType: 'logoSuricata', + euiIconType: '/plugins/kibana/home/tutorial_resources/logos/suricata.svg', artifacts: { dashboards: [ { diff --git a/src/plugins/home/server/tutorials/system_logs/index.ts b/src/plugins/home/server/tutorials/system_logs/index.ts index fc2fa4f49fd5f..ab8184c1b3249 100644 --- a/src/plugins/home/server/tutorials/system_logs/index.ts +++ b/src/plugins/home/server/tutorials/system_logs/index.ts @@ -50,6 +50,7 @@ Unix/Linux based distributions. This module is not available on Windows. \ learnMoreLink: '{config.docs.beats.filebeat}/filebeat-module-system.html', }, }), + euiIconType: '/plugins/kibana/home/tutorial_resources/logos/system.svg', artifacts: { dashboards: [ { diff --git a/src/plugins/home/server/tutorials/system_metrics/index.ts b/src/plugins/home/server/tutorials/system_metrics/index.ts index b0355e1118a96..456804c51f838 100644 --- a/src/plugins/home/server/tutorials/system_metrics/index.ts +++ b/src/plugins/home/server/tutorials/system_metrics/index.ts @@ -49,6 +49,7 @@ It collects system wide statistics and statistics per process and filesystem. \ learnMoreLink: '{config.docs.beats.metricbeat}/metricbeat-module-system.html', }, }), + euiIconType: '/plugins/kibana/home/tutorial_resources/logos/system.svg', artifacts: { dashboards: [ { diff --git a/src/plugins/home/server/tutorials/traefik_logs/index.ts b/src/plugins/home/server/tutorials/traefik_logs/index.ts index 423023a3902e5..56f1d56ea0123 100644 --- a/src/plugins/home/server/tutorials/traefik_logs/index.ts +++ b/src/plugins/home/server/tutorials/traefik_logs/index.ts @@ -49,7 +49,7 @@ export function traefikLogsSpecProvider(context: TutorialContext): TutorialSchem learnMoreLink: '{config.docs.beats.filebeat}/filebeat-module-traefik.html', }, }), - // euiIconType: 'logoTraefik', + euiIconType: '/plugins/kibana/home/tutorial_resources/logos/traefik.svg', artifacts: { dashboards: [ { diff --git a/src/plugins/home/server/tutorials/uwsgi_metrics/index.ts b/src/plugins/home/server/tutorials/uwsgi_metrics/index.ts index fc36cfe869867..a1dfbc64ec244 100644 --- a/src/plugins/home/server/tutorials/uwsgi_metrics/index.ts +++ b/src/plugins/home/server/tutorials/uwsgi_metrics/index.ts @@ -48,7 +48,7 @@ export function uwsgiMetricsSpecProvider(context: TutorialContext): TutorialSche learnMoreLink: '{config.docs.beats.metricbeat}/metricbeat-module-uwsgi.html', }, }), - // euiIconType: 'logouWSGI', + euiIconType: '/plugins/kibana/home/tutorial_resources/logos/uwsgi.svg', isBeta: false, artifacts: { dashboards: [ diff --git a/src/plugins/home/server/tutorials/vsphere_metrics/index.ts b/src/plugins/home/server/tutorials/vsphere_metrics/index.ts index 3ea57cdbc0e44..908b6440f88c6 100644 --- a/src/plugins/home/server/tutorials/vsphere_metrics/index.ts +++ b/src/plugins/home/server/tutorials/vsphere_metrics/index.ts @@ -48,7 +48,7 @@ export function vSphereMetricsSpecProvider(context: TutorialContext): TutorialSc learnMoreLink: '{config.docs.beats.metricbeat}/metricbeat-module-vsphere.html', }, }), - // euiIconType: 'logoVSphere', + euiIconType: '/plugins/kibana/home/tutorial_resources/logos/vsphere.svg', isBeta: true, artifacts: { application: { diff --git a/src/plugins/home/server/tutorials/zeek_logs/index.ts b/src/plugins/home/server/tutorials/zeek_logs/index.ts index c015545046c99..251825147ded1 100644 --- a/src/plugins/home/server/tutorials/zeek_logs/index.ts +++ b/src/plugins/home/server/tutorials/zeek_logs/index.ts @@ -50,7 +50,7 @@ export function zeekLogsSpecProvider(context: TutorialContext): TutorialSchema { learnMoreLink: '{config.docs.beats.filebeat}/filebeat-module-zeek.html', }, }), - // TODO: euiIconType: 'logoZeek', + euiIconType: '/plugins/kibana/home/tutorial_resources/logos/zeek.svg', artifacts: { dashboards: [ { diff --git a/src/plugins/home/server/tutorials/zookeeper_metrics/index.ts b/src/plugins/home/server/tutorials/zookeeper_metrics/index.ts index dcecbb6d4a812..581b4a14a2f38 100644 --- a/src/plugins/home/server/tutorials/zookeeper_metrics/index.ts +++ b/src/plugins/home/server/tutorials/zookeeper_metrics/index.ts @@ -36,6 +36,7 @@ export function zookeeperMetricsSpecProvider(context: TutorialContext): Tutorial name: i18n.translate('home.tutorials.zookeeperMetrics.nameTitle', { defaultMessage: 'Zookeeper metrics', }), + euiIconType: '/plugins/kibana/home/tutorial_resources/logos/zookeeper.svg', isBeta: false, category: TutorialsCategory.METRICS, shortDescription: i18n.translate('home.tutorials.zookeeperMetrics.shortDescription', { diff --git a/x-pack/legacy/plugins/maps/public/angular/map_controller.js b/x-pack/legacy/plugins/maps/public/angular/map_controller.js index a19f8cdf5f7fc..519ba0b1e3d96 100644 --- a/x-pack/legacy/plugins/maps/public/angular/map_controller.js +++ b/x-pack/legacy/plugins/maps/public/angular/map_controller.js @@ -312,12 +312,7 @@ app.controller( const savedLayerList = savedMap.getLayerList(); const oldConfig = savedLayerList ? savedLayerList : initialLayerListConfig; - // savedMap stores layerList as a JSON string using JSON.stringify. - // JSON.stringify removes undefined properties from objects. - // savedMap.getLayerList converts the JSON string back into Javascript array of objects. - // Need to perform the same process for layerListConfigOnly to compare apples to apples - // and avoid undefined properties in layerListConfigOnly triggering unsaved changes. - return !_.isEqual(JSON.parse(JSON.stringify(layerListConfigOnly)), oldConfig); + return !_.isEqual(layerListConfigOnly, oldConfig); } function isOnMapNow() { diff --git a/x-pack/legacy/plugins/maps/public/connected_components/map/features_tooltip/__snapshots__/feature_properties.test.js.snap b/x-pack/legacy/plugins/maps/public/connected_components/map/features_tooltip/__snapshots__/feature_properties.test.js.snap index a52c118bca8cd..3b3d82c92fbb7 100644 --- a/x-pack/legacy/plugins/maps/public/connected_components/map/features_tooltip/__snapshots__/feature_properties.test.js.snap +++ b/x-pack/legacy/plugins/maps/public/connected_components/map/features_tooltip/__snapshots__/feature_properties.test.js.snap @@ -2,7 +2,7 @@ exports[`FeatureProperties should not show filter button 1`] = ` (this._node = node)}> +
(this._node = node)} + > {rows}
); diff --git a/x-pack/legacy/plugins/maps/public/layers/styles/vector/components/color/dynamic_color_form.js b/x-pack/legacy/plugins/maps/public/layers/styles/vector/components/color/dynamic_color_form.js index 5e8f720fcc5e3..a1c15e27c9eb3 100644 --- a/x-pack/legacy/plugins/maps/public/layers/styles/vector/components/color/dynamic_color_form.js +++ b/x-pack/legacy/plugins/maps/public/layers/styles/vector/components/color/dynamic_color_form.js @@ -28,20 +28,12 @@ export function DynamicColorForm({ }; if (type === COLOR_MAP_TYPE.ORDINAL) { newColorOptions.useCustomColorRamp = useCustomColorMap; - if (customColorMap) { - newColorOptions.customColorRamp = customColorMap; - } - if (color) { - newColorOptions.color = color; - } + newColorOptions.customColorRamp = customColorMap; + newColorOptions.color = color; } else { newColorOptions.useCustomColorPalette = useCustomColorMap; - if (customColorMap) { - newColorOptions.customColorPalette = customColorMap; - } - if (color) { - newColorOptions.colorCategory = color; - } + newColorOptions.customColorPalette = customColorMap; + newColorOptions.colorCategory = color; } onDynamicStyleChange(styleProperty.getStyleName(), newColorOptions); diff --git a/x-pack/legacy/plugins/siem/public/containers/case/api.ts b/x-pack/legacy/plugins/siem/public/containers/case/api.ts index e98c258690486..7d5ae53b78ff8 100644 --- a/x-pack/legacy/plugins/siem/public/containers/case/api.ts +++ b/x-pack/legacy/plugins/siem/public/containers/case/api.ts @@ -19,7 +19,9 @@ import { ServiceConnectorCaseResponse, ActionTypeExecutorResult, } from '../../../../../../plugins/case/common/api'; + import { KibanaServices } from '../../lib/kibana'; + import { ActionLicense, AllCases, @@ -30,7 +32,9 @@ import { SortFieldCase, CaseUserActions, } from './types'; + import { CASES_URL } from './constants'; + import { convertToCamelCase, convertAllCasesToCamel, @@ -43,12 +47,17 @@ import { decodeServiceConnectorCaseResponse, } from './utils'; -export const getCase = async (caseId: string, includeComments: boolean = true): Promise => { +export const getCase = async ( + caseId: string, + includeComments: boolean = true, + signal: AbortSignal +): Promise => { const response = await KibanaServices.get().http.fetch(`${CASES_URL}/${caseId}`, { method: 'GET', query: { includeComments, }, + signal, }); return convertToCamelCase(decodeCaseResponse(response)); }; @@ -64,9 +73,10 @@ export const getCasesStatus = async (signal: AbortSignal): Promise return convertToCamelCase(decodeCasesStatusResponse(response)); }; -export const getTags = async (): Promise => { +export const getTags = async (signal: AbortSignal): Promise => { const response = await KibanaServices.get().http.fetch(`${CASES_URL}/tags`, { method: 'GET', + signal, }); return response ?? []; }; @@ -106,6 +116,7 @@ export const getCases = async ({ sortField: SortFieldCase.createdAt, sortOrder: 'desc', }, + signal, }: FetchCasesProps): Promise => { const query = { reporters: filterOptions.reporters.map(r => r.username), @@ -117,14 +128,16 @@ export const getCases = async ({ const response = await KibanaServices.get().http.fetch(`${CASES_URL}/_find`, { method: 'GET', query, + signal, }); return convertAllCasesToCamel(decodeCasesFindResponse(response)); }; -export const postCase = async (newCase: CasePostRequest): Promise => { +export const postCase = async (newCase: CasePostRequest, signal: AbortSignal): Promise => { const response = await KibanaServices.get().http.fetch(CASES_URL, { method: 'POST', body: JSON.stringify(newCase), + signal, }); return convertToCamelCase(decodeCaseResponse(response)); }; @@ -132,29 +145,40 @@ export const postCase = async (newCase: CasePostRequest): Promise => { export const patchCase = async ( caseId: string, updatedCase: Pick, - version: string + version: string, + signal: AbortSignal ): Promise => { const response = await KibanaServices.get().http.fetch(CASES_URL, { method: 'PATCH', body: JSON.stringify({ cases: [{ ...updatedCase, id: caseId, version }] }), + signal, }); return convertToCamelCase(decodeCasesResponse(response)); }; -export const patchCasesStatus = async (cases: BulkUpdateStatus[]): Promise => { +export const patchCasesStatus = async ( + cases: BulkUpdateStatus[], + signal: AbortSignal +): Promise => { const response = await KibanaServices.get().http.fetch(CASES_URL, { method: 'PATCH', body: JSON.stringify({ cases }), + signal, }); return convertToCamelCase(decodeCasesResponse(response)); }; -export const postComment = async (newComment: CommentRequest, caseId: string): Promise => { +export const postComment = async ( + newComment: CommentRequest, + caseId: string, + signal: AbortSignal +): Promise => { const response = await KibanaServices.get().http.fetch( `${CASES_URL}/${caseId}/comments`, { method: 'POST', body: JSON.stringify(newComment), + signal, } ); return convertToCamelCase(decodeCaseResponse(response)); @@ -164,22 +188,25 @@ export const patchComment = async ( caseId: string, commentId: string, commentUpdate: string, - version: string + version: string, + signal: AbortSignal ): Promise => { const response = await KibanaServices.get().http.fetch( `${CASES_URL}/${caseId}/comments`, { method: 'PATCH', body: JSON.stringify({ comment: commentUpdate, id: commentId, version }), + signal, } ); return convertToCamelCase(decodeCaseResponse(response)); }; -export const deleteCases = async (caseIds: string[]): Promise => { +export const deleteCases = async (caseIds: string[], signal: AbortSignal): Promise => { const response = await KibanaServices.get().http.fetch(CASES_URL, { method: 'DELETE', query: { ids: JSON.stringify(caseIds) }, + signal, }); return response === 'true' ? true : false; }; diff --git a/x-pack/legacy/plugins/siem/public/containers/case/types.ts b/x-pack/legacy/plugins/siem/public/containers/case/types.ts index bbbb13788d53a..bb215d6ac271c 100644 --- a/x-pack/legacy/plugins/siem/public/containers/case/types.ts +++ b/x-pack/legacy/plugins/siem/public/containers/case/types.ts @@ -93,7 +93,7 @@ export interface ElasticUser { readonly username: string; } -export interface FetchCasesProps { +export interface FetchCasesProps extends ApiProps { queryParams?: QueryParams; filterOptions?: FilterOptions; } diff --git a/x-pack/legacy/plugins/siem/public/containers/case/use_bulk_update_case.tsx b/x-pack/legacy/plugins/siem/public/containers/case/use_bulk_update_case.tsx index 77d779ab906cf..f1129bae9f537 100644 --- a/x-pack/legacy/plugins/siem/public/containers/case/use_bulk_update_case.tsx +++ b/x-pack/legacy/plugins/siem/public/containers/case/use_bulk_update_case.tsx @@ -66,10 +66,12 @@ export const useUpdateCases = (): UseUpdateCase => { const dispatchUpdateCases = useCallback((cases: BulkUpdateStatus[]) => { let cancel = false; + const abortCtrl = new AbortController(); + const patchData = async () => { try { dispatch({ type: 'FETCH_INIT' }); - await patchCasesStatus(cases); + await patchCasesStatus(cases, abortCtrl.signal); if (!cancel) { dispatch({ type: 'FETCH_SUCCESS', payload: true }); } @@ -87,6 +89,7 @@ export const useUpdateCases = (): UseUpdateCase => { patchData(); return () => { cancel = true; + abortCtrl.abort(); }; }, []); diff --git a/x-pack/legacy/plugins/siem/public/containers/case/use_delete_cases.tsx b/x-pack/legacy/plugins/siem/public/containers/case/use_delete_cases.tsx index d5a3b3cf9314c..b44e01d06acaf 100644 --- a/x-pack/legacy/plugins/siem/public/containers/case/use_delete_cases.tsx +++ b/x-pack/legacy/plugins/siem/public/containers/case/use_delete_cases.tsx @@ -74,10 +74,12 @@ export const useDeleteCases = (): UseDeleteCase => { const dispatchDeleteCases = useCallback((caseIds: string[]) => { let cancel = false; + const abortCtrl = new AbortController(); + const deleteData = async () => { try { dispatch({ type: 'FETCH_INIT' }); - await deleteCases(caseIds); + await deleteCases(caseIds, abortCtrl.signal); if (!cancel) { dispatch({ type: 'FETCH_SUCCESS', payload: true }); } @@ -94,6 +96,7 @@ export const useDeleteCases = (): UseDeleteCase => { }; deleteData(); return () => { + abortCtrl.abort(); cancel = true; }; }, []); diff --git a/x-pack/legacy/plugins/siem/public/containers/case/use_get_case.tsx b/x-pack/legacy/plugins/siem/public/containers/case/use_get_case.tsx index 506be62614c14..835fb7153dc95 100644 --- a/x-pack/legacy/plugins/siem/public/containers/case/use_get_case.tsx +++ b/x-pack/legacy/plugins/siem/public/containers/case/use_get_case.tsx @@ -92,10 +92,12 @@ export const useGetCase = (caseId: string): UseGetCase => { const callFetch = useCallback(async () => { let didCancel = false; + const abortCtrl = new AbortController(); + const fetchData = async () => { dispatch({ type: 'FETCH_INIT' }); try { - const response = await getCase(caseId); + const response = await getCase(caseId, true, abortCtrl.signal); if (!didCancel) { dispatch({ type: 'FETCH_SUCCESS', payload: response }); } @@ -113,6 +115,7 @@ export const useGetCase = (caseId: string): UseGetCase => { fetchData(); return () => { didCancel = true; + abortCtrl.abort(); }; }, [caseId]); diff --git a/x-pack/legacy/plugins/siem/public/containers/case/use_get_cases.tsx b/x-pack/legacy/plugins/siem/public/containers/case/use_get_cases.tsx index ae7b8f3c043fa..323dc23e1b24e 100644 --- a/x-pack/legacy/plugins/siem/public/containers/case/use_get_cases.tsx +++ b/x-pack/legacy/plugins/siem/public/containers/case/use_get_cases.tsx @@ -149,12 +149,15 @@ export const useGetCases = (initialQueryParams?: QueryParams): UseGetCases => { const fetchCases = useCallback((filterOptions: FilterOptions, queryParams: QueryParams) => { let didCancel = false; + const abortCtrl = new AbortController(); + const fetchData = async () => { dispatch({ type: 'FETCH_INIT', payload: 'cases' }); try { const response = await getCases({ filterOptions, queryParams, + signal: abortCtrl.signal, }); if (!didCancel) { dispatch({ @@ -175,6 +178,7 @@ export const useGetCases = (initialQueryParams?: QueryParams): UseGetCases => { }; fetchData(); return () => { + abortCtrl.abort(); didCancel = true; }; }, []); @@ -187,13 +191,17 @@ export const useGetCases = (initialQueryParams?: QueryParams): UseGetCases => { const dispatchUpdateCaseProperty = useCallback( ({ updateKey, updateValue, caseId, refetchCasesStatus, version }: UpdateCase) => { let didCancel = false; + const abortCtrl = new AbortController(); + const fetchData = async () => { dispatch({ type: 'FETCH_INIT', payload: 'caseUpdate' }); try { await patchCase( caseId, { [updateKey]: updateValue }, - version ?? '' // saved object versions are typed as string | undefined, hope that's not true + // saved object versions are typed as string | undefined, hope that's not true + version ?? '', + abortCtrl.signal ); if (!didCancel) { dispatch({ type: 'FETCH_UPDATE_CASE_SUCCESS' }); @@ -209,6 +217,7 @@ export const useGetCases = (initialQueryParams?: QueryParams): UseGetCases => { }; fetchData(); return () => { + abortCtrl.abort(); didCancel = true; }; }, diff --git a/x-pack/legacy/plugins/siem/public/containers/case/use_get_tags.tsx b/x-pack/legacy/plugins/siem/public/containers/case/use_get_tags.tsx index e3657f5b09da9..b41d5aab5c07a 100644 --- a/x-pack/legacy/plugins/siem/public/containers/case/use_get_tags.tsx +++ b/x-pack/legacy/plugins/siem/public/containers/case/use_get_tags.tsx @@ -57,10 +57,12 @@ export const useGetTags = (): TagsState => { useEffect(() => { let didCancel = false; + const abortCtrl = new AbortController(); + const fetchData = async () => { dispatch({ type: 'FETCH_INIT' }); try { - const response = await getTags(); + const response = await getTags(abortCtrl.signal); if (!didCancel) { dispatch({ type: 'FETCH_SUCCESS', payload: response }); } @@ -77,6 +79,7 @@ export const useGetTags = (): TagsState => { }; fetchData(); return () => { + abortCtrl.abort(); didCancel = true; }; }, []); diff --git a/x-pack/legacy/plugins/siem/public/containers/case/use_post_case.tsx b/x-pack/legacy/plugins/siem/public/containers/case/use_post_case.tsx index 2ad7a08473200..0e01364721dc5 100644 --- a/x-pack/legacy/plugins/siem/public/containers/case/use_post_case.tsx +++ b/x-pack/legacy/plugins/siem/public/containers/case/use_post_case.tsx @@ -61,9 +61,11 @@ export const usePostCase = (): UsePostCase => { const postMyCase = useCallback(async (data: CasePostRequest) => { let cancel = false; + const abortCtrl = new AbortController(); + try { dispatch({ type: 'FETCH_INIT' }); - const response = await postCase(data); + const response = await postCase(data, abortCtrl.signal); if (!cancel) { dispatch({ type: 'FETCH_SUCCESS', @@ -81,6 +83,7 @@ export const usePostCase = (): UsePostCase => { } } return () => { + abortCtrl.abort(); cancel = true; }; }, []); diff --git a/x-pack/legacy/plugins/siem/public/containers/case/use_post_comment.tsx b/x-pack/legacy/plugins/siem/public/containers/case/use_post_comment.tsx index 86b7f92ace5ad..207b05814717f 100644 --- a/x-pack/legacy/plugins/siem/public/containers/case/use_post_comment.tsx +++ b/x-pack/legacy/plugins/siem/public/containers/case/use_post_comment.tsx @@ -55,9 +55,11 @@ export const usePostComment = (caseId: string): UsePostComment => { const postMyComment = useCallback( async (data: CommentRequest, updateCase: (newCase: Case) => void) => { let cancel = false; + const abortCtrl = new AbortController(); + try { dispatch({ type: 'FETCH_INIT' }); - const response = await postComment(data, caseId); + const response = await postComment(data, caseId, abortCtrl.signal); if (!cancel) { dispatch({ type: 'FETCH_SUCCESS' }); updateCase(response); @@ -73,6 +75,7 @@ export const usePostComment = (caseId: string): UsePostComment => { } } return () => { + abortCtrl.abort(); cancel = true; }; }, diff --git a/x-pack/legacy/plugins/siem/public/containers/case/use_post_push_to_service.tsx b/x-pack/legacy/plugins/siem/public/containers/case/use_post_push_to_service.tsx index d00755a9f2426..03e10249317ee 100644 --- a/x-pack/legacy/plugins/siem/public/containers/case/use_post_push_to_service.tsx +++ b/x-pack/legacy/plugins/siem/public/containers/case/use_post_push_to_service.tsx @@ -87,7 +87,7 @@ export const usePostPushToService = (): UsePostPushToService => { const abortCtrl = new AbortController(); try { dispatch({ type: 'FETCH_INIT' }); - const casePushData = await getCase(caseId); + const casePushData = await getCase(caseId, true, abortCtrl.signal); const responseService = await pushToService( connectorId, formatServiceRequestData(casePushData), diff --git a/x-pack/legacy/plugins/siem/public/containers/case/use_update_case.tsx b/x-pack/legacy/plugins/siem/public/containers/case/use_update_case.tsx index d1015d3f74250..85ad4fd3fc47a 100644 --- a/x-pack/legacy/plugins/siem/public/containers/case/use_update_case.tsx +++ b/x-pack/legacy/plugins/siem/public/containers/case/use_update_case.tsx @@ -76,9 +76,16 @@ export const useUpdateCase = ({ caseId }: { caseId: string }): UseUpdateCase => const dispatchUpdateCaseProperty = useCallback( async ({ fetchCaseUserActions, updateKey, updateValue, updateCase, version }: UpdateByKey) => { let cancel = false; + const abortCtrl = new AbortController(); + try { dispatch({ type: 'FETCH_INIT', payload: updateKey }); - const response = await patchCase(caseId, { [updateKey]: updateValue }, version); + const response = await patchCase( + caseId, + { [updateKey]: updateValue }, + version, + abortCtrl.signal + ); if (!cancel) { if (fetchCaseUserActions != null) { fetchCaseUserActions(caseId); @@ -100,6 +107,7 @@ export const useUpdateCase = ({ caseId }: { caseId: string }): UseUpdateCase => } return () => { cancel = true; + abortCtrl.abort(); }; }, [] diff --git a/x-pack/legacy/plugins/siem/public/containers/case/use_update_comment.tsx b/x-pack/legacy/plugins/siem/public/containers/case/use_update_comment.tsx index b83ed2c01708a..faf9649a705c5 100644 --- a/x-pack/legacy/plugins/siem/public/containers/case/use_update_comment.tsx +++ b/x-pack/legacy/plugins/siem/public/containers/case/use_update_comment.tsx @@ -81,9 +81,16 @@ export const useUpdateComment = (): UseUpdateComment => { version, }: UpdateComment) => { let cancel = false; + const abortCtrl = new AbortController(); try { dispatch({ type: 'FETCH_INIT', payload: commentId }); - const response = await patchComment(caseId, commentId, commentUpdate, version); + const response = await patchComment( + caseId, + commentId, + commentUpdate, + version, + abortCtrl.signal + ); if (!cancel) { updateCase(response); fetchUserActions(); @@ -101,6 +108,7 @@ export const useUpdateComment = (): UseUpdateComment => { } return () => { cancel = true; + abortCtrl.abort(); }; }, [] diff --git a/x-pack/plugins/case/server/routes/api/cases/comments/delete_all_comments.ts b/x-pack/plugins/case/server/routes/api/cases/comments/delete_all_comments.ts index 941ac90f2e90e..1dfab165eccd7 100644 --- a/x-pack/plugins/case/server/routes/api/cases/comments/delete_all_comments.ts +++ b/x-pack/plugins/case/server/routes/api/cases/comments/delete_all_comments.ts @@ -53,7 +53,7 @@ export function initDeleteAllCommentsApi({ caseService, router, userActionServic ), }); - return response.ok({ body: 'true' }); + return response.noContent(); } catch (error) { return response.customError(wrapError(error)); } diff --git a/x-pack/plugins/case/server/routes/api/cases/comments/delete_comment.test.ts b/x-pack/plugins/case/server/routes/api/cases/comments/delete_comment.test.ts index 8f05fbce391f8..b2022e6dec26d 100644 --- a/x-pack/plugins/case/server/routes/api/cases/comments/delete_comment.test.ts +++ b/x-pack/plugins/case/server/routes/api/cases/comments/delete_comment.test.ts @@ -21,7 +21,7 @@ describe('DELETE comment', () => { beforeAll(async () => { routeHandler = await createRoute(initDeleteCommentApi, 'delete'); }); - it(`deletes the comment. responds with 200`, async () => { + it(`deletes the comment. responds with 204`, async () => { const request = httpServerMock.createKibanaRequest({ path: '/api/cases/{case_id}/comments/{comment_id}', method: 'delete', @@ -39,7 +39,7 @@ describe('DELETE comment', () => { ); const response = await routeHandler(theContext, request, kibanaResponseFactory); - expect(response.status).toEqual(200); + expect(response.status).toEqual(204); }); it(`returns an error when thrown from deleteComment service`, async () => { const request = httpServerMock.createKibanaRequest({ diff --git a/x-pack/plugins/case/server/routes/api/cases/comments/delete_comment.ts b/x-pack/plugins/case/server/routes/api/cases/comments/delete_comment.ts index 44e57fc809e04..ff0729afed96a 100644 --- a/x-pack/plugins/case/server/routes/api/cases/comments/delete_comment.ts +++ b/x-pack/plugins/case/server/routes/api/cases/comments/delete_comment.ts @@ -64,7 +64,7 @@ export function initDeleteCommentApi({ caseService, router, userActionService }: ], }); - return response.ok({ body: 'true' }); + return response.noContent(); } catch (error) { return response.customError(wrapError(error)); } diff --git a/x-pack/plugins/case/server/routes/api/cases/delete_cases.test.ts b/x-pack/plugins/case/server/routes/api/cases/delete_cases.test.ts index cee705694f21d..c5be6f78a1570 100644 --- a/x-pack/plugins/case/server/routes/api/cases/delete_cases.test.ts +++ b/x-pack/plugins/case/server/routes/api/cases/delete_cases.test.ts @@ -22,7 +22,7 @@ describe('DELETE case', () => { beforeAll(async () => { routeHandler = await createRoute(initDeleteCasesApi, 'delete'); }); - it(`deletes the case. responds with 200`, async () => { + it(`deletes the case. responds with 204`, async () => { const request = httpServerMock.createKibanaRequest({ path: '/api/cases', method: 'delete', @@ -39,7 +39,7 @@ describe('DELETE case', () => { ); const response = await routeHandler(theContext, request, kibanaResponseFactory); - expect(response.status).toEqual(200); + expect(response.status).toEqual(204); }); it(`returns an error when thrown from deleteCase service`, async () => { const request = httpServerMock.createKibanaRequest({ diff --git a/x-pack/plugins/case/server/routes/api/cases/delete_cases.ts b/x-pack/plugins/case/server/routes/api/cases/delete_cases.ts index 8b0384c12edce..0214017ae5c29 100644 --- a/x-pack/plugins/case/server/routes/api/cases/delete_cases.ts +++ b/x-pack/plugins/case/server/routes/api/cases/delete_cases.ts @@ -70,7 +70,7 @@ export function initDeleteCasesApi({ caseService, router, userActionService }: R ), }); - return response.ok({ body: 'true' }); + return response.noContent(); } catch (error) { return response.customError(wrapError(error)); } diff --git a/x-pack/plugins/event_log/generated/mappings.json b/x-pack/plugins/event_log/generated/mappings.json index fc1fdb71b0c37..50e7fdd5a9048 100644 --- a/x-pack/plugins/event_log/generated/mappings.json +++ b/x-pack/plugins/event_log/generated/mappings.json @@ -1,12 +1,15 @@ { - "dynamic": "strict", + "dynamic": "false", "properties": { "@timestamp": { "type": "date" }, "tags": { "ignore_above": 1024, - "type": "keyword" + "type": "keyword", + "meta": { + "isArray": true + } }, "message": { "norms": false, @@ -18,8 +21,7 @@ "ignore_above": 1024, "type": "keyword" } - }, - "dynamic": "strict" + } }, "event": { "properties": { @@ -40,8 +42,7 @@ "end": { "type": "date" } - }, - "dynamic": "strict" + } }, "error": { "properties": { @@ -49,8 +50,7 @@ "norms": false, "type": "text" } - }, - "dynamic": "strict" + } }, "user": { "properties": { @@ -58,8 +58,7 @@ "ignore_above": 1024, "type": "keyword" } - }, - "dynamic": "strict" + } }, "kibana": { "properties": { @@ -86,11 +85,9 @@ "ignore_above": 1024 } }, - "type": "nested", - "dynamic": "strict" + "type": "nested" } - }, - "dynamic": "strict" + } } } } \ No newline at end of file diff --git a/x-pack/plugins/event_log/scripts/create_schemas.js b/x-pack/plugins/event_log/scripts/create_schemas.js index 6e9ab00d04d1f..b46f7f295ddc7 100755 --- a/x-pack/plugins/event_log/scripts/create_schemas.js +++ b/x-pack/plugins/event_log/scripts/create_schemas.js @@ -30,11 +30,13 @@ function main() { const exportedProperties = mappings.EcsEventLogProperties; const multiValuedProperties = new Set(mappings.EcsEventLogMultiValuedProperties); + augmentMappings(ecsMappings.mappings, multiValuedProperties); + const elMappings = getEventLogMappings(ecsMappings, exportedProperties); console.log(`generating files in ${PLUGIN_DIR}`); writeEventLogMappings(elMappings); - writeEventLogConfigSchema(elMappings, ecsVersion, multiValuedProperties); + writeEventLogConfigSchema(elMappings, ecsVersion); } // return a stripped down version of the ecs schema, with only exportedProperties @@ -57,7 +59,6 @@ function getEventLogMappings(ecsSchema, exportedProperties) { const elValue = lodash.get(result.mappings.properties, prop); elValue.type = ecsValue.type; - elValue.dynamic = 'strict'; } return result; @@ -86,7 +87,7 @@ function writeEventLogMappings(elSchema) { // fixObjectTypes(elSchema.mappings); const mappings = { - dynamic: 'strict', + dynamic: 'false', properties: elSchema.mappings.properties, }; @@ -94,11 +95,10 @@ function writeEventLogMappings(elSchema) { console.log('generated:', EVENT_LOG_MAPPINGS_FILE); } -function writeEventLogConfigSchema(elSchema, ecsVersion, multiValuedProperties) { +function writeEventLogConfigSchema(elSchema, ecsVersion) { const lineWriter = LineWriter.createLineWriter(); - const elSchemaMappings = augmentMappings(elSchema.mappings, multiValuedProperties); - generateSchemaLines(lineWriter, null, elSchemaMappings); + generateSchemaLines(lineWriter, null, elSchema.mappings); // last line will have an extraneous comma const schemaLines = lineWriter.getContent().replace(/,$/, ''); @@ -113,22 +113,21 @@ const StringTypes = new Set(['string', 'keyword', 'text', 'ip']); const NumberTypes = new Set(['long', 'integer', 'float']); function augmentMappings(mappings, multiValuedProperties) { - // clone the mappings, as we're adding some additional properties - mappings = JSON.parse(JSON.stringify(mappings)); - for (const prop of multiValuedProperties) { const fullProp = replaceDotWithProperties(prop); - lodash.set(mappings.properties, `${fullProp}.multiValued`, true); + const metaPropName = `${fullProp}.meta`; + const meta = lodash.get(mappings.properties, metaPropName) || {}; + meta.isArray = true; + lodash.set(mappings.properties, metaPropName, meta); } - - return mappings; } function generateSchemaLines(lineWriter, prop, mappings) { const propKey = legalPropertyName(prop); + if (mappings == null) return; if (StringTypes.has(mappings.type)) { - if (mappings.multiValued) { + if (mappings.meta && mappings.meta.isArray) { lineWriter.addLine(`${propKey}: ecsStringMulti(),`); } else { lineWriter.addLine(`${propKey}: ecsString(),`); @@ -169,6 +168,7 @@ function generateSchemaLines(lineWriter, prop, mappings) { // write the object properties lineWriter.indent(); for (const prop of Object.keys(mappings.properties)) { + if (prop === 'meta') continue; generateSchemaLines(lineWriter, prop, mappings.properties[prop]); } lineWriter.dedent();