From 165e5a66ec7383d5ad7b13aaceb03869ac517f3c Mon Sep 17 00:00:00 2001
From: DeDe Morton <dede.morton@elastic.co>
Date: Wed, 29 Apr 2020 11:05:55 -0700
Subject: [PATCH] [docs] Refactor heartbeat monitor docs (#18075)

---
 heartbeat/docs/configuring-howto.asciidoc     |   3 +
 heartbeat/docs/heartbeat-options.asciidoc     | 663 +-----------------
 heartbeat/docs/heartbeat-scheduler.asciidoc   |  41 ++
 .../monitors/monitor-common-options.asciidoc  | 143 ++++
 heartbeat/docs/monitors/monitor-http.asciidoc | 246 +++++++
 heartbeat/docs/monitors/monitor-icmp.asciidoc |  39 ++
 heartbeat/docs/monitors/monitor-tcp.asciidoc  | 134 ++++
 7 files changed, 620 insertions(+), 649 deletions(-)
 create mode 100644 heartbeat/docs/heartbeat-scheduler.asciidoc
 create mode 100644 heartbeat/docs/monitors/monitor-common-options.asciidoc
 create mode 100644 heartbeat/docs/monitors/monitor-http.asciidoc
 create mode 100644 heartbeat/docs/monitors/monitor-icmp.asciidoc
 create mode 100644 heartbeat/docs/monitors/monitor-tcp.asciidoc

diff --git a/heartbeat/docs/configuring-howto.asciidoc b/heartbeat/docs/configuring-howto.asciidoc
index 0af33d35fd16..0a2b6fc57297 100644
--- a/heartbeat/docs/configuring-howto.asciidoc
+++ b/heartbeat/docs/configuring-howto.asciidoc
@@ -26,6 +26,7 @@ _Beats Platform Reference_ for more about the structure of the config file.
 The following topics describe how to configure Heartbeat:
 
 * <<configuration-heartbeat-options>>
+* <<monitors-scheduler>>
 * <<configuration-general-options>>
 * <<configuration-path>>
 * <<configuring-output>>
@@ -44,6 +45,8 @@ The following topics describe how to configure Heartbeat:
 
 include::./heartbeat-options.asciidoc[]
 
+include::./heartbeat-scheduler.asciidoc[]
+
 include::./heartbeat-general-options.asciidoc[]
 
 include::{libbeat-dir}/shared-path-config.asciidoc[]
diff --git a/heartbeat/docs/heartbeat-options.asciidoc b/heartbeat/docs/heartbeat-options.asciidoc
index 4e166610a536..23f33c26a3da 100644
--- a/heartbeat/docs/heartbeat-options.asciidoc
+++ b/heartbeat/docs/heartbeat-options.asciidoc
@@ -81,661 +81,26 @@ monitor definitions only, e.g. what is normally under the `heartbeat.monitors` s
 ----------------------------------------------------------------------
 
 [float]
-[[monitor-options]]
-=== Monitor options
+[[monitor-types]]
+=== Monitor types
 
-You can specify the following options when defining a {beatname_uc} monitor in any location.
-These options are the same for all monitors. Each monitor type has additional configuration
-options that are specific to that monitor type.
+You can configure {beatname_uc} to use the following monitor types:
 
-[float]
-[[monitor-type]]
-==== `type`
-
-The type of monitor to run. One of:
-
-* `icmp`: Uses an ICMP (v4 and v6) Echo Request to ping the configured hosts.
-Requires special permissions or root access. See <<monitor-icmp-options>>.
-* `tcp`: Connects via TCP and optionally verifies the endpoint by sending and/or
-receiving a custom payload. See <<monitor-tcp-options>>.
-* `http`: Connects via HTTP and optionally verifies that the host returns the
-expected response. See <<monitor-http-options>>. Will use `Elastic-Heartbeat` as the user agent product.
+*<<monitor-icmp-options,`icmp`>>*:: Uses an ICMP (v4 and v6) Echo Request to ping the configured hosts.
+Requires special permissions or root access.
+*<<monitor-tcp-options,`tcp`>>*:: Connects via TCP and optionally verifies the endpoint by sending and/or
+receiving a custom payload.
+*<<monitor-http-options,`http`>>*:: Connects via HTTP and optionally verifies that the host returns the
+expected response. Will use `Elastic-Heartbeat` as
+the user agent product.
 
 The `tcp` and `http` monitor types both support SSL/TLS and some proxy
 settings.
 
-[float]
-[[monitor-id]]
-==== `id`
-
-A unique identifier for this configuration. This should not change with edits to the monitor configuration
-regardless of changes to any config fields. Examples: `uploader-service`, `http://example.net`, `us-west-loadbalancer`. Note that this uniqueness is only within a given beat instance. If you want to monitor the same endpoint from multiple locations it is recommended that those heartbeat instances use the same IDs so that their results can be correlated. You can use the `host.geo.name` property to disambiguate them.
-
-When querying against indexed monitor data this is the field you will be aggregating with. Appears in the
-<<exported-fields,exported fields>> as `monitor.id`.
-
-If you do not set this explicitly the monitor's config will be hashed and a generated value used. This value will
-change with any options change to this monitor making aggregations over time between changes impossible. For this reason
-it is recommended that you set this manually.
-
-[float]
-[[monitor-name]]
-==== `name`
-
-Optional human readable name for this monitor. This value appears in the <<exported-fields,exported fields>>
-as `monitor.name`.
-
-[float]
-[[monitor-enabled]]
-==== `enabled`
-
-A Boolean value that specifies whether the module is enabled. If the `enabled`
-option is missing from the configuration block, the module is enabled by
-default.
-
-[float]
-[[monitor-schedule]]
-==== `schedule`
-
-A cron-like expression that specifies the task schedule. For example:
-
-* `*/5 * * * * * *` runs the task every 5 seconds (for example, at 10:00:00,
-10:00:05, and so on).
-* `@every 5s` runs the task every 5 seconds from the time when {beatname_uc} was
-started.
-
-The `schedule` option uses a cron-like syntax based on https://github.com/gorhill/cronexpr#implementation[this `cronexpr` implementation],
-but adds the `@every` keyword.
-
-For stats on the execution of scheduled tasks you can enable the HTTP stats server with `http.enabled: true` in heartbeat.yml, then run `curl http://localhost:5066/stats | jq .heartbeat.scheduler` to view the scheduler's stats. Stats are provided for both jobs and tasks. Each time a monitor is scheduled is considered to be a single job, while portions of the work a job does, like DNS lookups and executing network requests are defined as tasks. The stats provided are:
-
-* **jobs.active:** The number of actively running jobs/monitors.
-* **jobs.missed_deadline:** The number of jobs that executed after their scheduled time. This can be caused either by overlong long timeouts from the previous job or high load preventing heartbeat from keeping up with work.
-* **tasks.active:** The number of tasks currently running.
-* **tasks.waiting:** If the global `schedule.limit` option is set, this number will reflect the number of tasks that are ready to execute, but have not been started in order to prevent exceeding `schedule.limit`.
-
-[float]
-[[monitor-ipv4]]
-==== `ipv4`
-
-A Boolean value that specifies whether to ping using the ipv4 protocol if
-hostnames are configured. The default is `true`.
-
-[float]
-[[monitor-ipv6]]
-==== `ipv6`
-
-A Boolean value that specifies whether to ping using the ipv6 protocol
-if hostnames are configured. The default is `true`.
-
-[float]
-[[monitor-mode]]
-==== `mode`
-
-If `mode` is `any`, the monitor pings only one IP address for a hostname. If
-`mode` is `all`, the monitor pings all resolvable IPs for a hostname. The
-`mode: all` setting is useful if you are using a DNS-load balancer and want to
-ping every IP address for the specified hostname. The default is `any`.
-
-[float]
-[[monitor-timeout]]
-==== `timeout`
-
-The total running time for each ping test. This is the total time allowed for
-testing the connection and exchanging data. The default is 16 seconds (16s).
-
-If the timeout is exceeded, {beatname_uc} publishes a `service-down` event. If the
-value specified for `timeout` is greater than `schedule`, intermediate checks
-will not be executed by the scheduler.
-
-[float]
-[[monitor-fields]]
-==== `fields`
-
-Optional fields that you can specify to add additional information to the
-output. For example, you might add fields that you can use for filtering log
-data. Fields can be scalar values, arrays, dictionaries, or any nested
-combination of these. By default, the fields that you specify here will be
-grouped under a `fields` sub-dictionary in the output document. To store the
-custom fields as top-level fields, set the `fields_under_root` option to true.
-If a duplicate field is declared in the general configuration, then its value
-will be overwritten by the value declared here.
-
-[float]
-[[monitor-fields-under-root]]
-==== `fields_under_root`
-
-If this option is set to true, the custom <<monitor-fields,fields>>
-are stored as top-level fields in the output document instead of being grouped
-under a `fields` sub-dictionary. If the custom field names conflict with other
-field names added by {beatname_uc}, then the custom fields overwrite the other
-fields.
-
-[float]
-[[monitor-tags]]
-==== `tags`
-
-A list of tags that will be sent with the monitor event. This setting is optional.
-
-[float]
-[[monitor-processors]]
-==== `processors`
-
-A list of processors to apply to the data generated by the monitor.
-
-See <<filtering-and-enhancing-data>> for information about specifying
-processors in your config.
-
-[float]
-[[monitor-keep-null]]
-==== `keep_null`
-
-If this option is set to true, fields with `null` values will be published in
-the output document. By default, `keep_null` is set to `false`.
-
-[float]
-[[monitor-icmp-options]]
-=== ICMP options
-
-These options configure {beatname_uc} to use ICMP (v4 and v6) Echo Requests to check
-the configured hosts. These options are valid when the <<monitor-type,`type`>> is
-`icmp`. Please note that on most platforms you must execute Heartbeat with elevated permissions
-to perform ICMP pings.
-
-On Linux, regular users may perform pings if the right file capabilities are set. Run
-`sudo setcap cap_net_raw+eip /path/to/heartbeat` to  grant {beatname_uc} ping capabilities on Linux.
-Alternatively, one may grant ping permissions to the user {beatname_uc} runs as. To grant ping permissions
-in this way, run `sudo sysctl -w net.ipv4.ping_group_range='myuserid myuserid'`.
-
-Other platforms may require {beatname_uc} to run as root or administrator to execute pings.
-
-[float]
-[[monitor-icmp-hosts]]
-==== `hosts`
-
-A list of hosts to ping.
-
-[float]
-[[monitor-icmp-wait]]
-==== `wait`
-
-The duration to wait before emitting another ICMP Echo Request. The default is 1
-second (1s).
-
-[float]
-[[monitor-tcp-options]]
-=== TCP options
-
-These options configure {beatname_uc} to connect via TCP and optionally verify the
-endpoint by sending and/or receiving a custom payload. These options are valid when
-the <<monitor-type,`type`>> is `tcp`.
-
-[float]
-[[monitor-tcp-hosts]]
-==== `hosts`
-
-A list of hosts to ping. The entries in the list can be:
-
-* A plain host name, such as `localhost`, or an IP address. If you specify this
-option, you must also specify a value for <<monitor-tcp-ports,`ports`>>.  If the
-monitor is <<configuration-ssl,configured to use SSL>>, {beatname_uc} establishes an
-SSL/TLS-based connection. Otherwise, it establishes a plain TCP connection.
-* A hostname and port, such as `localhost:12345`. {beatname_uc} connects
-to the port on the specified host. If the monitor is
-<<configuration-ssl,configured to use SSL>>, {beatname_uc} establishes an
-SSL/TLS-based connection. Otherwise, it establishes a TCP connection.
-* A full URL using the syntax `scheme://<host>:[port]`, where:
-** `scheme` is one of `tcp`, `plain`, `ssl` or `tls`. If `tcp` or `plain` is
-specified, {beatname_uc} establishes a TCP connection even if the monitor is
-configured to use SSL. If `tls` or `ssl` is specified, {beatname_uc} establishes
-an SSL connection. However, if the monitor is not configured to use SSL, the
-system defaults are used (currently not supported on Windows).
-** `host` is the hostname.
-** `port` is the port number. If `port` is missing in the URL, the
-<<monitor-tcp-ports,`ports`>> setting is required.
-
-[float]
-[[monitor-tcp-ports]]
-==== `ports`
-
-A list of ports to ping if the host specified in <<monitor-tcp-hosts,`hosts`>>
-does not contain a port number. It is generally preferable to use a single value here,
-since each port will be monitored using a separate `id`, with the given `id` value,
-used as a prefix in the Heartbeat data, and the configured `name` shared across events
-sent via this check.
-
-Example configuration:
-
-[source,yaml]
--------------------------------------------------------------------------------
-- type: tcp
-  id: my-host-services
-  name: My Host Services
-  hosts: ["myhost"]
-  ports: [80, 9200, 5044]
-  schedule: '@every 5s'
--------------------------------------------------------------------------------
-
-[float]
-[[monitor-tcp-check]]
-==== `check`
-
-An optional payload string to send to the remote host and the expected answer.
-If no payload is specified, the endpoint is assumed to be available if the
-connection attempt was successful. If `send` is specified without `receive`,
-any response is accepted as OK. If `receive` is specified without `send`, no
-payload is sent, but the client expects to receive a payload in the form of a
-"hello message" or "banner" on connect.
-
-Example configuration:
-
-[source,yaml]
--------------------------------------------------------------------------------
-- type: tcp
-  id: echo-service
-  name: Echo Service
-  hosts: ["myhost"]
-  ports: [7]
-  check.send: 'Hello World'
-  check.receive: 'Hello World'
-  schedule: '@every 5s'
--------------------------------------------------------------------------------
-
-
-[float]
-[[monitor-tcp-proxy-url]]
-==== `proxy_url`
-
-The URL of the SOCKS5 proxy to use when connecting to the server. The value
-must be a URL with a scheme of socks5://.
-
-If the SOCKS5 proxy server requires client authentication, then a username and
-password can be embedded in the URL as shown in the example.
-
-[source,yaml]
--------------------------------------------------------------------------------
-  proxy_url: socks5://user:password@socks5-proxy:2233
--------------------------------------------------------------------------------
-
-When using a proxy, hostnames are resolved on the proxy server instead of on
-the client. You can change this behavior by setting the
-`proxy_use_local_resolver` option.
-
-[float]
-[[monitor-tcp-proxy-use-local-resolver]]
-==== `proxy_use_local_resolver`
-
-A Boolean value that determines whether hostnames are resolved locally instead
-of being resolved on the proxy server. The default value is false, which means
-that name resolution occurs on the proxy server.
-
-[float]
-[[monitor-tcp-tls-ssl]]
-==== `ssl`
-
-The TLS/SSL connection settings.  If the monitor is
-<<configuration-ssl,configured to use SSL>>, it will attempt an SSL
-handshake. If `check` is not configured, the monitor will only check to see if
-it can establish an SSL/TLS connection. This check can fail either at TCP level
-or during certificate validation.
-
-Example configuration:
-
-[source,yaml]
--------------------------------------------------------------------------------
-- type: tcp
-  id: tls-mail
-  name: TLS Mail
-  hosts: ["mail.example.net"]
-  ports: [465]
-  schedule: '@every 5s'
-  ssl:
-    certificate_authorities: ['/etc/ca.crt']
-    supported_protocols: ["TLSv1.0", "TLSv1.1", "TLSv1.2"]
--------------------------------------------------------------------------------
-
-
-Also see <<configuration-ssl>> for a full description of the `ssl` options.
-
-[float]
-[[monitor-http-options]]
-=== HTTP options
-
-These options configure {beatname_uc} to connect via HTTP and optionally verify that
-the host returns the expected response. These options are valid when the
-<<monitor-type,`type`>> is `http`.
-
-[float]
-[[monitor-http-urls]]
-==== `hosts`
-
-A list of URLs to ping.
-
-Example configuration:
-
-[source,yaml]
--------------------------------------------------------------------------------
-- type: http
-  id: myhost
-  name: My HTTP Host
-  schedule: '@every 5s'
-  hosts: ["http://myhost:80"]
--------------------------------------------------------------------------------
-
-[float]
-[[monitor-http-max-redirects]]
-==== `max_redirects`
-
-The total number of redirections Heartbeat will follow. Defaults to 0, meaning heartbeat will not follow redirects,
-but will report the status of the redirect. If set to a number greater than 0 heartbeat will follow that number of redirects.
-
-When this option is set to a value greater than zero the `monitor.ip` field will no longer be reported, as multiple
-DNS requests across multiple IPs may return multiple IPs. Fine grained network timing data will also not be recorded, as with redirects
-that data will span multiple requests. Specifically the fields `http.rtt.content.us`, `http.rtt.response_header.us`,
-`http.rtt.total.us`, `http.rtt.validate.us`, `http.rtt.write_request.us` and `dns.rtt.us` will be omitted.
-
-[float]
-[[monitor-http-proxy-url]]
-==== `proxy_url`
-
-The HTTP proxy URL. This setting is optional. Example `http://proxy.mydomain.com:3128`
-
-[float]
-[[monitor-http-username]]
-==== `username`
-
-The username for authenticating with the server. The credentials are passed
-with the request. This setting is optional.
-
-You need to specify credentials when your `check.response` settings require it.
-For example, you can check for a 403 response (`check.response.status: [403]`)
-without setting credentials.
-
-[float]
-[[monitor-http-password]]
-==== `password`
-
-The password for authenticating with the server. This setting is optional.
-
-[float]
-[[monitor-http-tls-ssl]]
-==== `ssl`
-
-The TLS/SSL connection settings for use with the HTTPS endpoint. If you don't
-specify settings, the system defaults are used.
-
-
-Example configuration:
-
-[source,yaml]
--------------------------------------------------------------------------------
-- type: http
-  id: my-http-service
-  name: My HTTP Service
-  hosts: ["https://myhost:443"]
-  schedule: '@every 5s'
-  ssl:
-    certificate_authorities: ['/etc/ca.crt']
-    supported_protocols: ["TLSv1.0", "TLSv1.1", "TLSv1.2"]
--------------------------------------------------------------------------------
-
-Also see <<configuration-ssl>> for a full description of the `ssl` options.
-
-[float]
-[[monitor-http-response]]
-=== `response`
-
-Controls the indexing of the HTTP response body contents to the `http.response.body.contents` field.
-
-Set `response.include_body` to one of the options listed below.
-
-*`on_error`*:: Include the body if an error is encountered during the check. This is the default.
-*`never`*:: Never include the body.
-*`always`*:: Always include the body with checks.
-
-Set `response.include_body_max_bytes` to control the maximum size of the stored body contents. Defaults to 1024 bytes.
-
-[float]
-[[monitor-http-check]]
-==== `check`
-
-An optional `request` to send to the remote host and the expected `response`.
-
-Example configuration:
-
-[source,yaml]
--------------------------------------------------------------------------------
-- type: http
-  id: my-http-host
-  name: My HTTP Service
-  hosts: ["http://myhost:80"]
-  check.request.method: HEAD
-  check.response.status: [200]
-  schedule: '@every 5s'
--------------------------------------------------------------------------------
-
-
-Under `check.request`, specify these options:
-
-*`method`*:: The HTTP method to use. Valid values are `"HEAD"`, `"GET"` and
-`"POST"`.
-*`headers`*:: A dictionary of additional HTTP headers to send. By default heartbeat
-will set the 'User-Agent' header to identify itself.
-*`body`*:: Optional request body content.
-
-Example configuration:
-This monitor POSTs an `x-www-form-urlencoded` string
-to the endpoint `/demo/add`
-
-[source,yaml]
--------------------------------------------------------------------------------
-- type: http
-  id: demo-service
-  name: Demo Service
-  schedule: '@every 5s'
-  urls: ["http://localhost:8080/demo/add"]
-  check.request:
-    method: POST
-    headers:
-      'Content-Type': 'application/x-www-form-urlencoded'
-    # urlencode the body:
-    body: "name=first&email=someemail%40someemailprovider.com"
-  check.response:
-    status: [200]
-    body:
-      - Saved
-      - saved
--------------------------------------------------------------------------------
-
-Under `check.response`, specify these options:
-
-*`status`*:: A list of expected status codes. 4xx and 5xx codes are considered `down` by default. Other codes are considered `up`.
-*`headers`*:: The required response headers.
-*`body`*:: A list of regular expressions to match the the body output. Only a single expression needs to match. HTTP response
-bodies of up to 100MiB are supported.
-
-Example configuration:
-This monitor examines the
-response body for the strings `saved` or `Saved` and expects 200 or 201 status codes
-
-[source,yaml]
--------------------------------------------------------------------------------
-- type: http
-  id: demo-service
-  name: Demo Service
-  schedule: '@every 5s'
-  urls: ["http://localhost:8080/demo/add"]
-  check.request:
-    method: POST
-    headers:
-      'Content-Type': 'application/x-www-form-urlencoded'
-    # urlencode the body:
-    body: "name=first&email=someemail%40someemailprovider.com"
-  check.response:
-    status: [200, 201]
-    body:
-      - Saved
-      - saved
--------------------------------------------------------------------------------
-
-*`json`*:: A list of <<conditions,condition>> expressions executed against the body when parsed as JSON. Body sizes
-must be less than or equal to 100 MiB.
-
-The following configuration shows how to check the response when the body
-contains JSON:
-
-[source,yaml]
--------------------------------------------------------------------------------
-- type: http
-  id: demo-service
-  name: Demo Service
-  schedule: '@every 5s'
-  hosts: ["https://myhost:80"]
-  check.request:
-    method: GET
-    headers:
-      'X-API-Key': '12345-mykey-67890'
-  check.response:
-    status: [200]
-    json:
-      - description: check status
-        condition:
-          equals:
-            status: ok
--------------------------------------------------------------------------------
-
-The following configuration shows how to check the response for multiple regex
-patterns:
-
-[source,yaml]
--------------------------------------------------------------------------------
-- type: http
-  id: demo-service
-  name: Demo Service
-  schedule: '@every 5s'
-  hosts: ["https://myhost:80"]
-  check.request:
-    method: GET
-    headers:
-      'X-API-Key': '12345-mykey-67890'
-  check.response:
-    status: [200]
-    body:
-      - hello
-      - world
--------------------------------------------------------------------------------
-
-The following configuration shows how to check the response with a multiline
-regex:
-
-[source,yaml]
--------------------------------------------------------------------------------
-- type: http
-  id: demo-service
-  name: Demo Service
-  schedule: '@every 5s'
-  hosts: ["https://myhost:80"]
-  check.request:
-    method: GET
-    headers:
-      'X-API-Key': '12345-mykey-67890'
-  check.response:
-    status: [200]
-    body: '(?s)first.*second.*third'
--------------------------------------------------------------------------------
-
-
-[float]
-[[monitors-scheduler]]
-=== Scheduler options
-
-You specify options under `heartbeat.scheduler` to control the behavior of the task
-scheduler.
-
-Example configuration:
-
-[source,yaml]
--------------------------------------------------------------------------------
-heartbeat.scheduler:
-  limit: 10
-  location: 'UTC-08:00'
--------------------------------------------------------------------------------
-
-In the example, setting `limit` to 10 guarantees that only 10 concurrent
-I/O tasks will be active. An I/O task can be the actual check or resolving an
-address via DNS.
-
-[float]
-[[heartbeat-scheduler-limit]]
-==== `limit`
-
-The number of concurrent I/O tasks that {beatname_uc} is allowed to execute. If set
-to 0, there is no limit. The default is 0.
-
-Most operating systems set a file descriptor limit of 1024. For {beatname_uc} to
-operate correctly and not accidentally block libbeat output, the value that you
-specify for `limit` should be below the configured ulimit.
-
-
-[float]
-[[heartbeat-scheduler-location]]
-==== `location`
-
-The timezone for the scheduler. By default the scheduler uses localtime.
-
-[float]
-[[monitor-watch-poll-file]]
-==== `watch.poll_file`
-
-deprecated:[6.5.0,Replaced by using dynamic reloading via the `heartbeat.config.monitors` option.]
-
-The JSON file to watch for additional monitor configurations. The JSON file can
-contain multiple objects, each of which specifies a different monitor config.
-{beatname_uc} checks this file periodically and starts a new monitor instance for
-each new JSON object added to the file. For example, imagine that you add
-10 new entries to the JSON file, each for a different hostname. When {beatname_uc}
-picks up the changes in the file, it merges the original config
-(`heartbeat.yml`) plus the JSON objects, and starts a monitor for each new host
-that you've configured. If you delete an object from the JSON file and it
-doesn't exist in the main config, {beatname_uc} stops the monitor instance running
-for that object.
-
-Each monitor has a unique ID that's based on parameters like protocol, host,
-and port. If two monitors have the same ID, {beatname_uc} uses the settings that
-are defined in the last JSON object of the merged config. This means that
-you can specify settings in the JSON file that overwrite the settings in
-the main config. In this way, the configuration that you specify for the
-monitor in the main {beatname_uc} config file acts like a default config that you
-can live-reconfigure by specifying additional configurations in the external
-JSON file.
-
-Example configuration:
-
-[source, yaml]
--------------------------------------------------------------------------------
-heartbeat.monitors:
-- type: tcp
-  id: demo-service
-  name: Demo Service
-  schedule: '*/5 * * * * * *'
-  hosts: ["myhost"]
-  watch.poll_file:
-    path: {path.config}/monitors/dynamic.json
-    interval: 5s
--------------------------------------------------------------------------------
+include::monitors/monitor-common-options.asciidoc[]
 
-*`path`*:: Specifies the path to the JSON file to check for updates.
-*`interval`*:: Specifies how often {beatname_uc} checks the file for changes.
+include::monitors/monitor-icmp.asciidoc[]
 
-To reconfigure the settings specified in the example config, you could define
-the following JSON objects in `dynamic.json`:
+include::monitors/monitor-tcp.asciidoc[]
 
-[source, json]
--------------------------------------------------------------------------------
-{"hosts": ["myhost:1234"], "schedule": "*/15 * * * * * *"} <1>
-{"hosts": ["tls://otherhost:479"], "ssl.certificate_authorities": ["path/to/ca/file.pem"]} <2>
--------------------------------------------------------------------------------
-<1> Upon detecting the changes, {beatname_uc} stops the old monitor and then
-restarts it with a schedule of 15 seconds between checks.
-<2> {beatname_uc} starts a new monitor that uses a TLS-based connection with a
-custom CA certificate.
+include::monitors/monitor-http.asciidoc[]
diff --git a/heartbeat/docs/heartbeat-scheduler.asciidoc b/heartbeat/docs/heartbeat-scheduler.asciidoc
new file mode 100644
index 000000000000..ac2f647f6ee5
--- /dev/null
+++ b/heartbeat/docs/heartbeat-scheduler.asciidoc
@@ -0,0 +1,41 @@
+[[monitors-scheduler]]
+== Configure the task scheduler
+
+++++
+<titleabbrev>Task scheduler</titleabbrev>
+++++
+
+You specify options under `heartbeat.scheduler` to control the behavior of the task
+scheduler.
+
+Example configuration:
+
+[source,yaml]
+-------------------------------------------------------------------------------
+heartbeat.scheduler:
+  limit: 10
+  location: 'UTC-08:00'
+-------------------------------------------------------------------------------
+
+In the example, setting `limit` to 10 guarantees that only 10 concurrent
+I/O tasks will be active. An I/O task can be the actual check or resolving an
+address via DNS.
+
+[float]
+[[heartbeat-scheduler-limit]]
+==== `limit`
+
+The number of concurrent I/O tasks that {beatname_uc} is allowed to execute. If set
+to 0, there is no limit. The default is 0.
+
+Most operating systems set a file descriptor limit of 1024. For {beatname_uc} to
+operate correctly and not accidentally block libbeat output, the value that you
+specify for `limit` should be below the configured ulimit.
+
+
+[float]
+[[heartbeat-scheduler-location]]
+==== `location`
+
+The timezone for the scheduler. By default the scheduler uses localtime.
+
diff --git a/heartbeat/docs/monitors/monitor-common-options.asciidoc b/heartbeat/docs/monitors/monitor-common-options.asciidoc
new file mode 100644
index 000000000000..68194b281197
--- /dev/null
+++ b/heartbeat/docs/monitors/monitor-common-options.asciidoc
@@ -0,0 +1,143 @@
+[[monitor-options]]
+=== Common monitor options
+
+You can specify the following options when defining a {beatname_uc} monitor in any location.
+These options are the same for all monitors. Each monitor type has additional configuration
+options that are specific to that monitor type.
+
+[float]
+[[monitor-type]]
+==== `type`
+
+The type of monitor to run. See <<monitor-types>>.
+
+[float]
+[[monitor-id]]
+==== `id`
+
+A unique identifier for this configuration. This should not change with edits to the monitor configuration
+regardless of changes to any config fields. Examples: `uploader-service`, `http://example.net`, `us-west-loadbalancer`. Note that this uniqueness is only within a given beat instance. If you want to monitor the same endpoint from multiple locations it is recommended that those heartbeat instances use the same IDs so that their results can be correlated. You can use the `host.geo.name` property to disambiguate them.
+
+When querying against indexed monitor data this is the field you will be aggregating with. Appears in the
+<<exported-fields,exported fields>> as `monitor.id`.
+
+If you do not set this explicitly the monitor's config will be hashed and a generated value used. This value will
+change with any options change to this monitor making aggregations over time between changes impossible. For this reason
+it is recommended that you set this manually.
+
+[float]
+[[monitor-name]]
+==== `name`
+
+Optional human readable name for this monitor. This value appears in the <<exported-fields,exported fields>>
+as `monitor.name`.
+
+[float]
+[[monitor-enabled]]
+==== `enabled`
+
+A Boolean value that specifies whether the module is enabled. If the `enabled`
+option is missing from the configuration block, the module is enabled by
+default.
+
+[float]
+[[monitor-schedule]]
+==== `schedule`
+
+A cron-like expression that specifies the task schedule. For example:
+
+* `*/5 * * * * * *` runs the task every 5 seconds (for example, at 10:00:00,
+10:00:05, and so on).
+* `@every 5s` runs the task every 5 seconds from the time when {beatname_uc} was
+started.
+
+The `schedule` option uses a cron-like syntax based on https://github.com/gorhill/cronexpr#implementation[this `cronexpr` implementation],
+but adds the `@every` keyword.
+
+For stats on the execution of scheduled tasks you can enable the HTTP stats server with `http.enabled: true` in heartbeat.yml, then run `curl http://localhost:5066/stats | jq .heartbeat.scheduler` to view the scheduler's stats. Stats are provided for both jobs and tasks. Each time a monitor is scheduled is considered to be a single job, while portions of the work a job does, like DNS lookups and executing network requests are defined as tasks. The stats provided are:
+
+* **jobs.active:** The number of actively running jobs/monitors.
+* **jobs.missed_deadline:** The number of jobs that executed after their scheduled time. This can be caused either by overlong long timeouts from the previous job or high load preventing heartbeat from keeping up with work.
+* **tasks.active:** The number of tasks currently running.
+* **tasks.waiting:** If the global `schedule.limit` option is set, this number will reflect the number of tasks that are ready to execute, but have not been started in order to prevent exceeding `schedule.limit`.
+
+Also see the <<monitors-scheduler,task scheduler>> settings.
+
+[float]
+[[monitor-ipv4]]
+==== `ipv4`
+
+A Boolean value that specifies whether to ping using the ipv4 protocol if
+hostnames are configured. The default is `true`.
+
+[float]
+[[monitor-ipv6]]
+==== `ipv6`
+
+A Boolean value that specifies whether to ping using the ipv6 protocol
+if hostnames are configured. The default is `true`.
+
+[float]
+[[monitor-mode]]
+==== `mode`
+
+If `mode` is `any`, the monitor pings only one IP address for a hostname. If
+`mode` is `all`, the monitor pings all resolvable IPs for a hostname. The
+`mode: all` setting is useful if you are using a DNS-load balancer and want to
+ping every IP address for the specified hostname. The default is `any`.
+
+[float]
+[[monitor-timeout]]
+==== `timeout`
+
+The total running time for each ping test. This is the total time allowed for
+testing the connection and exchanging data. The default is 16 seconds (16s).
+
+If the timeout is exceeded, {beatname_uc} publishes a `service-down` event. If the
+value specified for `timeout` is greater than `schedule`, intermediate checks
+will not be executed by the scheduler.
+
+[float]
+[[monitor-fields]]
+==== `fields`
+
+Optional fields that you can specify to add additional information to the
+output. For example, you might add fields that you can use for filtering log
+data. Fields can be scalar values, arrays, dictionaries, or any nested
+combination of these. By default, the fields that you specify here will be
+grouped under a `fields` sub-dictionary in the output document. To store the
+custom fields as top-level fields, set the `fields_under_root` option to true.
+If a duplicate field is declared in the general configuration, then its value
+will be overwritten by the value declared here.
+
+[float]
+[[monitor-fields-under-root]]
+==== `fields_under_root`
+
+If this option is set to true, the custom <<monitor-fields,fields>>
+are stored as top-level fields in the output document instead of being grouped
+under a `fields` sub-dictionary. If the custom field names conflict with other
+field names added by {beatname_uc}, then the custom fields overwrite the other
+fields.
+
+[float]
+[[monitor-tags]]
+==== `tags`
+
+A list of tags that will be sent with the monitor event. This setting is optional.
+
+[float]
+[[monitor-processors]]
+==== `processors`
+
+A list of processors to apply to the data generated by the monitor.
+
+See <<filtering-and-enhancing-data>> for information about specifying
+processors in your config.
+
+[float]
+[[monitor-keep-null]]
+==== `keep_null`
+
+If this option is set to true, fields with `null` values will be published in
+the output document. By default, `keep_null` is set to `false`.
diff --git a/heartbeat/docs/monitors/monitor-http.asciidoc b/heartbeat/docs/monitors/monitor-http.asciidoc
new file mode 100644
index 000000000000..1cea32f662f3
--- /dev/null
+++ b/heartbeat/docs/monitors/monitor-http.asciidoc
@@ -0,0 +1,246 @@
+[[monitor-http-options]]
+=== HTTP options
+
+Also see <<monitor-options>>.
+
+The options described here configure {beatname_uc} to connect via HTTP and
+optionally verify that the host returns the expected response.
+
+Example configuration:
+
+[source,yaml]
+----
+- type: http
+  id: myhost
+  name: My HTTP Host
+  schedule: '@every 5s'
+  hosts: ["http://myhost:80"]
+----
+
+[float]
+[[monitor-http-urls]]
+==== `hosts`
+
+A list of URLs to ping.
+
+[float]
+[[monitor-http-max-redirects]]
+==== `max_redirects`
+
+The total number of redirections Heartbeat will follow. Defaults to 0, meaning heartbeat will not follow redirects,
+but will report the status of the redirect. If set to a number greater than 0 heartbeat will follow that number of redirects.
+
+When this option is set to a value greater than zero the `monitor.ip` field will no longer be reported, as multiple
+DNS requests across multiple IPs may return multiple IPs. Fine grained network timing data will also not be recorded, as with redirects
+that data will span multiple requests. Specifically the fields `http.rtt.content.us`, `http.rtt.response_header.us`,
+`http.rtt.total.us`, `http.rtt.validate.us`, `http.rtt.write_request.us` and `dns.rtt.us` will be omitted.
+
+[float]
+[[monitor-http-proxy-url]]
+==== `proxy_url`
+
+The HTTP proxy URL. This setting is optional. Example `http://proxy.mydomain.com:3128`
+
+[float]
+[[monitor-http-username]]
+==== `username`
+
+The username for authenticating with the server. The credentials are passed
+with the request. This setting is optional.
+
+You need to specify credentials when your `check.response` settings require it.
+For example, you can check for a 403 response (`check.response.status: [403]`)
+without setting credentials.
+
+[float]
+[[monitor-http-password]]
+==== `password`
+
+The password for authenticating with the server. This setting is optional.
+
+[float]
+[[monitor-http-tls-ssl]]
+==== `ssl`
+
+The TLS/SSL connection settings for use with the HTTPS endpoint. If you don't
+specify settings, the system defaults are used.
+
+
+Example configuration:
+
+[source,yaml]
+-------------------------------------------------------------------------------
+- type: http
+  id: my-http-service
+  name: My HTTP Service
+  hosts: ["https://myhost:443"]
+  schedule: '@every 5s'
+  ssl:
+    certificate_authorities: ['/etc/ca.crt']
+    supported_protocols: ["TLSv1.0", "TLSv1.1", "TLSv1.2"]
+-------------------------------------------------------------------------------
+
+Also see <<configuration-ssl>> for a full description of the `ssl` options.
+
+[float]
+[[monitor-http-response]]
+=== `response`
+
+Controls the indexing of the HTTP response body contents to the `http.response.body.contents` field.
+
+Set `response.include_body` to one of the options listed below.
+
+*`on_error`*:: Include the body if an error is encountered during the check. This is the default.
+*`never`*:: Never include the body.
+*`always`*:: Always include the body with checks.
+
+Set `response.include_body_max_bytes` to control the maximum size of the stored body contents. Defaults to 1024 bytes.
+
+[float]
+[[monitor-http-check]]
+==== `check`
+
+An optional `request` to send to the remote host and the expected `response`.
+
+Example configuration:
+
+[source,yaml]
+-------------------------------------------------------------------------------
+- type: http
+  id: my-http-host
+  name: My HTTP Service
+  hosts: ["http://myhost:80"]
+  check.request.method: HEAD
+  check.response.status: [200]
+  schedule: '@every 5s'
+-------------------------------------------------------------------------------
+
+
+Under `check.request`, specify these options:
+
+*`method`*:: The HTTP method to use. Valid values are `"HEAD"`, `"GET"` and
+`"POST"`.
+*`headers`*:: A dictionary of additional HTTP headers to send. By default heartbeat
+will set the 'User-Agent' header to identify itself.
+*`body`*:: Optional request body content.
+
+Example configuration:
+This monitor POSTs an `x-www-form-urlencoded` string
+to the endpoint `/demo/add`
+
+[source,yaml]
+-------------------------------------------------------------------------------
+- type: http
+  id: demo-service
+  name: Demo Service
+  schedule: '@every 5s'
+  urls: ["http://localhost:8080/demo/add"]
+  check.request:
+    method: POST
+    headers:
+      'Content-Type': 'application/x-www-form-urlencoded'
+    # urlencode the body:
+    body: "name=first&email=someemail%40someemailprovider.com"
+  check.response:
+    status: [200]
+    body:
+      - Saved
+      - saved
+-------------------------------------------------------------------------------
+
+Under `check.response`, specify these options:
+
+*`status`*:: A list of expected status codes. 4xx and 5xx codes are considered `down` by default. Other codes are considered `up`.
+*`headers`*:: The required response headers.
+*`body`*:: A list of regular expressions to match the the body output. Only a single expression needs to match. HTTP response
+bodies of up to 100MiB are supported.
+
+Example configuration:
+This monitor examines the
+response body for the strings `saved` or `Saved` and expects 200 or 201 status codes
+
+[source,yaml]
+-------------------------------------------------------------------------------
+- type: http
+  id: demo-service
+  name: Demo Service
+  schedule: '@every 5s'
+  urls: ["http://localhost:8080/demo/add"]
+  check.request:
+    method: POST
+    headers:
+      'Content-Type': 'application/x-www-form-urlencoded'
+    # urlencode the body:
+    body: "name=first&email=someemail%40someemailprovider.com"
+  check.response:
+    status: [200, 201]
+    body:
+      - Saved
+      - saved
+-------------------------------------------------------------------------------
+
+*`json`*:: A list of <<conditions,condition>> expressions executed against the body when parsed as JSON. Body sizes
+must be less than or equal to 100 MiB.
+
+The following configuration shows how to check the response when the body
+contains JSON:
+
+[source,yaml]
+-------------------------------------------------------------------------------
+- type: http
+  id: demo-service
+  name: Demo Service
+  schedule: '@every 5s'
+  hosts: ["https://myhost:80"]
+  check.request:
+    method: GET
+    headers:
+      'X-API-Key': '12345-mykey-67890'
+  check.response:
+    status: [200]
+    json:
+      - description: check status
+        condition:
+          equals:
+            status: ok
+-------------------------------------------------------------------------------
+
+The following configuration shows how to check the response for multiple regex
+patterns:
+
+[source,yaml]
+-------------------------------------------------------------------------------
+- type: http
+  id: demo-service
+  name: Demo Service
+  schedule: '@every 5s'
+  hosts: ["https://myhost:80"]
+  check.request:
+    method: GET
+    headers:
+      'X-API-Key': '12345-mykey-67890'
+  check.response:
+    status: [200]
+    body:
+      - hello
+      - world
+-------------------------------------------------------------------------------
+
+The following configuration shows how to check the response with a multiline
+regex:
+
+[source,yaml]
+-------------------------------------------------------------------------------
+- type: http
+  id: demo-service
+  name: Demo Service
+  schedule: '@every 5s'
+  hosts: ["https://myhost:80"]
+  check.request:
+    method: GET
+    headers:
+      'X-API-Key': '12345-mykey-67890'
+  check.response:
+    status: [200]
+    body: '(?s)first.*second.*third'
+-------------------------------------------------------------------------------
diff --git a/heartbeat/docs/monitors/monitor-icmp.asciidoc b/heartbeat/docs/monitors/monitor-icmp.asciidoc
new file mode 100644
index 000000000000..ccd0ba5f3979
--- /dev/null
+++ b/heartbeat/docs/monitors/monitor-icmp.asciidoc
@@ -0,0 +1,39 @@
+[[monitor-icmp-options]]
+=== ICMP options
+
+Also see <<monitor-options>>.
+
+The options described here configure {beatname_uc} to use ICMP (v4 and v6) Echo
+Requests to check the configured hosts. Please note that on most platforms you
+must execute Heartbeat with elevated permissions to perform ICMP pings.
+
+On Linux, regular users may perform pings if the right file capabilities are set. Run
+`sudo setcap cap_net_raw+eip /path/to/heartbeat` to  grant {beatname_uc} ping capabilities on Linux.
+Alternatively, one may grant ping permissions to the user {beatname_uc} runs as. To grant ping permissions
+in this way, run `sudo sysctl -w net.ipv4.ping_group_range='myuserid myuserid'`.
+
+Other platforms may require {beatname_uc} to run as root or administrator to execute pings.
+
+Example configuration:
+
+[source,yaml]
+----
+- type: icmp
+  id: ping-myhost
+  name: My Host Ping
+  hosts: ["myhost"]
+  schedule: '*/5 * * * * * *'
+----
+
+[float]
+[[monitor-icmp-hosts]]
+==== `hosts`
+
+A list of hosts to ping.
+
+[float]
+[[monitor-icmp-wait]]
+==== `wait`
+
+The duration to wait before emitting another ICMP Echo Request. The default is 1
+second (1s).
diff --git a/heartbeat/docs/monitors/monitor-tcp.asciidoc b/heartbeat/docs/monitors/monitor-tcp.asciidoc
new file mode 100644
index 000000000000..10d39b063026
--- /dev/null
+++ b/heartbeat/docs/monitors/monitor-tcp.asciidoc
@@ -0,0 +1,134 @@
+[[monitor-tcp-options]]
+=== TCP options
+
+Also see <<monitor-options>>.
+
+The options described here configure {beatname_uc} to connect via TCP and
+optionally verify the endpoint by sending and/or receiving a custom payload.
+
+Example configuration:
+
+[source,yaml]
+----
+- type: tcp
+  id: my-host-services
+  name: My Host Services
+  hosts: ["myhost"]
+  ports: [80, 9200, 5044]
+  schedule: '@every 5s'
+----
+
+[float]
+[[monitor-tcp-hosts]]
+==== `hosts`
+
+A list of hosts to ping. The entries in the list can be:
+
+* A plain host name, such as `localhost`, or an IP address. If you specify this
+option, you must also specify a value for <<monitor-tcp-ports,`ports`>>.  If the
+monitor is <<configuration-ssl,configured to use SSL>>, {beatname_uc} establishes an
+SSL/TLS-based connection. Otherwise, it establishes a plain TCP connection.
+* A hostname and port, such as `localhost:12345`. {beatname_uc} connects
+to the port on the specified host. If the monitor is
+<<configuration-ssl,configured to use SSL>>, {beatname_uc} establishes an
+SSL/TLS-based connection. Otherwise, it establishes a TCP connection.
+* A full URL using the syntax `scheme://<host>:[port]`, where:
+** `scheme` is one of `tcp`, `plain`, `ssl` or `tls`. If `tcp` or `plain` is
+specified, {beatname_uc} establishes a TCP connection even if the monitor is
+configured to use SSL. If `tls` or `ssl` is specified, {beatname_uc} establishes
+an SSL connection. However, if the monitor is not configured to use SSL, the
+system defaults are used (currently not supported on Windows).
+** `host` is the hostname.
+** `port` is the port number. If `port` is missing in the URL, the
+<<monitor-tcp-ports,`ports`>> setting is required.
+
+[float]
+[[monitor-tcp-ports]]
+==== `ports`
+
+A list of ports to ping if the host specified in <<monitor-tcp-hosts,`hosts`>>
+does not contain a port number. It is generally preferable to use a single value here,
+since each port will be monitored using a separate `id`, with the given `id` value,
+used as a prefix in the Heartbeat data, and the configured `name` shared across events
+sent via this check.
+
+[float]
+[[monitor-tcp-check]]
+==== `check`
+
+An optional payload string to send to the remote host and the expected answer.
+If no payload is specified, the endpoint is assumed to be available if the
+connection attempt was successful. If `send` is specified without `receive`,
+any response is accepted as OK. If `receive` is specified without `send`, no
+payload is sent, but the client expects to receive a payload in the form of a
+"hello message" or "banner" on connect.
+
+Example configuration:
+
+[source,yaml]
+-------------------------------------------------------------------------------
+- type: tcp
+  id: echo-service
+  name: Echo Service
+  hosts: ["myhost"]
+  ports: [7]
+  check.send: 'Hello World'
+  check.receive: 'Hello World'
+  schedule: '@every 5s'
+-------------------------------------------------------------------------------
+
+
+[float]
+[[monitor-tcp-proxy-url]]
+==== `proxy_url`
+
+The URL of the SOCKS5 proxy to use when connecting to the server. The value
+must be a URL with a scheme of socks5://.
+
+If the SOCKS5 proxy server requires client authentication, then a username and
+password can be embedded in the URL as shown in the example.
+
+[source,yaml]
+-------------------------------------------------------------------------------
+  proxy_url: socks5://user:password@socks5-proxy:2233
+-------------------------------------------------------------------------------
+
+When using a proxy, hostnames are resolved on the proxy server instead of on
+the client. You can change this behavior by setting the
+`proxy_use_local_resolver` option.
+
+[float]
+[[monitor-tcp-proxy-use-local-resolver]]
+==== `proxy_use_local_resolver`
+
+A Boolean value that determines whether hostnames are resolved locally instead
+of being resolved on the proxy server. The default value is false, which means
+that name resolution occurs on the proxy server.
+
+[float]
+[[monitor-tcp-tls-ssl]]
+==== `ssl`
+
+The TLS/SSL connection settings.  If the monitor is
+<<configuration-ssl,configured to use SSL>>, it will attempt an SSL
+handshake. If `check` is not configured, the monitor will only check to see if
+it can establish an SSL/TLS connection. This check can fail either at TCP level
+or during certificate validation.
+
+Example configuration:
+
+[source,yaml]
+-------------------------------------------------------------------------------
+- type: tcp
+  id: tls-mail
+  name: TLS Mail
+  hosts: ["mail.example.net"]
+  ports: [465]
+  schedule: '@every 5s'
+  ssl:
+    certificate_authorities: ['/etc/ca.crt']
+    supported_protocols: ["TLSv1.0", "TLSv1.1", "TLSv1.2"]
+-------------------------------------------------------------------------------
+
+
+Also see <<configuration-ssl>> for a full description of the `ssl` options.